From c4561600a9a4bbb952252f6f89d73006e4c9ccbd Mon Sep 17 00:00:00 2001 From: bicyclering <729921326@qq.com> Date: Sun, 21 Jan 2018 23:11:36 +0800 Subject: [PATCH 001/115] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=88=A0=E6=A0=BC?= =?UTF-8?q?=E5=B8=83=E5=B1=80=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2584802..ebac130 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ ## [V1.5.0](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.5.0)(2017/10/9) #### Added -1. 添加新的布局种类:**栅格布局(MyGridLayout)**。栅格布局是一种将矩形区域划分为多个子矩形区域,并将这个划分一直持续下去的机制,然后再将子视图填充到对应的栅格区域里面的一种布局视图。栅格布局特别适合于动态布局,布局样式可以从服务器动态下发,并且可以用JSON格式的语言来描述这种布局结构,具体请参考新增加的栅格布局和对应的DEMO。以及对应的说明文档:[栅格布局介绍](http://bicyclering.com/2017/09/01/IOS-UIViewLayout-MyLinearLayout/#more) +1. 添加新的布局种类:**栅格布局(MyGridLayout)**。栅格布局是一种将矩形区域划分为多个子矩形区域,并将这个划分一直持续下去的机制,然后再将子视图填充到对应的栅格区域里面的一种布局视图。栅格布局特别适合于动态布局,布局样式可以从服务器动态下发,并且可以用JSON格式的语言来描述这种布局结构,具体请参考新增加的栅格布局和对应的DEMO。以及对应的说明文档:[栅格布局介绍](http://bicyclering.com/2017/09/01/IOS-UIViewLayout-%E5%B8%83%E5%B1%80-MyLinearLayout/#more) 2. 添加了对 **基线对齐baseline**的支持[issue:#43](https://github.com/youngsoft/MyLinearLayout/issues/43),目前只有**水平线性布局(MyLinearLayout)**和**相对布局(MyRelativeLayout)**支持基线对齐。 1. 在**MyGravity**中添加了`MyGravity_Vert_Baseline`的枚举定义来支持线性布局的基线对齐,并且在线性布局中添加了一个属性:`baselineBaseView`来指定某个基线基准视图。同时在布局视图的gravity属性中支持对`MyGravity_Vert_Baseline`的设置。具体例子参考:[LLTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/LLTest1ViewController.m) From 9f10637da5fa8e572a04355b1f6510a0efb9d3f0 Mon Sep 17 00:00:00 2001 From: bicyclering <729921326@qq.com> Date: Sun, 21 Jan 2018 23:16:42 +0800 Subject: [PATCH 002/115] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=88=A0=E6=A0=BC?= =?UTF-8?q?=E5=B8=83=E5=B1=80=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.zh.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.zh.md b/README.zh.md index 6e7d295..2213c5a 100644 --- a/README.zh.md +++ b/README.zh.md @@ -28,7 +28,7 @@ MyLayout是一套iOS界面视图布局框架。MyLayout的内核是基于对UIVi [http://www.jianshu.com/p/fbeb376584ed](http://www.jianshu.com/p/fbeb376584ed) 流式布局 [http://www.jianshu.com/p/0c075f2fdab2](http://www.jianshu.com/p/0c075f2fdab2) 浮动布局 [http://www.jianshu.com/p/4ac229057396](http://www.jianshu.com/p/4ac229057396) 路径布局 -[http://bicyclering.com/2017/09/01/IOS-UIViewLayout-MyLinearLayout/#more](http://bicyclering.com/2017/09/01/IOS-UIViewLayout-MyLinearLayout/#more) 栅格布局 +[http://bicyclering.com/2017/09/01/IOS-UIViewLayout-%E5%B8%83%E5%B1%80-MyLinearLayout/#more](http://bicyclering.com/2017/09/01/IOS-UIViewLayout-%E5%B8%83%E5%B1%80-MyLinearLayout/#more) 栅格布局 ### MyLayout的优势 * MyLayout的实现内核是基于frame的设置,而不是对AutoLayout的封装。因此在使用上不会受到任何操作系统版本的限制。 From baa68bcafc4fab32a9bb4ac9d74edd62e383fcf2 Mon Sep 17 00:00:00 2001 From: gagehuang Date: Mon, 26 Feb 2018 17:34:29 +0800 Subject: [PATCH 003/115] fix MY_USEPREFIXMETHOD bug --- MyLayout/Lib/MyLayoutPos.h | 26 ++++++++++++------------- MyLayout/Lib/MyLayoutSize.h | 33 ++++++++++++++++---------------- MyLayout/Lib/MyLayoutSizeClass.m | 16 +++++++++++----- MyLayout/Lib/MyTableLayout.m | 13 +++++++++++++ 4 files changed, 52 insertions(+), 36 deletions(-) diff --git a/MyLayout/Lib/MyLayoutPos.h b/MyLayout/Lib/MyLayoutPos.h index 6a626b4..133ca26 100644 --- a/MyLayout/Lib/MyLayoutPos.h +++ b/MyLayout/Lib/MyLayoutPos.h @@ -75,20 +75,6 @@ */ @interface MyLayoutPos : NSObject -//because masonry defined macro MAS_SHORTHAND_GLOBALS. the equalTo, offset may conflict with below method. so -//if you used MyLayout and Masonry concurrently and you defined MAS_SHORTHAND_GLOBALS in masonry, then you can define MY_USEPREFIXMETHOD to solve the conflict. -#ifdef MY_USEPREFIXMETHOD --(MyLayoutPos* (^)(id val))myEqualTo; --(MyLayoutPos* (^)(CGFloat val))myOffset; --(MyLayoutPos* (^)(CGFloat val))myMin; --(MyLayoutPos* (^)(id posVal, CGFloat offset))myLBound; --(MyLayoutPos* (^)(CGFloat val))myMax; --(MyLayoutPos* (^)(id posVal, CGFloat offset))myUBound; --(void)myClear; - -#else - - #if UIKIT_DEFINE_AS_PROPERTIES /** @@ -132,6 +118,18 @@ +(CGFloat)safeAreaMargin; #endif +//because masonry defined macro MAS_SHORTHAND_GLOBALS. the equalTo, offset may conflict with below method. so +//if you used MyLayout and Masonry concurrently and you defined MAS_SHORTHAND_GLOBALS in masonry, then you can define MY_USEPREFIXMETHOD to solve the conflict. +#ifdef MY_USEPREFIXMETHOD +-(MyLayoutPos* (^)(id val))myEqualTo; +-(MyLayoutPos* (^)(CGFloat val))myOffset; +-(MyLayoutPos* (^)(CGFloat val))myMin; +-(MyLayoutPos* (^)(id posVal, CGFloat offset))myLBound; +-(MyLayoutPos* (^)(CGFloat val))myMax; +-(MyLayoutPos* (^)(id posVal, CGFloat offset))myUBound; +-(void)myClear; + +#else /** 设置布局位置的值。参数val可以接收下面六种类型的值: diff --git a/MyLayout/Lib/MyLayoutSize.h b/MyLayout/Lib/MyLayoutSize.h index bcf137a..ce13987 100644 --- a/MyLayout/Lib/MyLayoutSize.h +++ b/MyLayout/Lib/MyLayoutSize.h @@ -24,23 +24,6 @@ */ @interface MyLayoutSize : NSObject -//because masonry defined macro MAS_SHORTHAND_GLOBALS. the equalTo, offset may conflict with below method. so -//if you used MyLayout and Masonry concurrently and you defined MAS_SHORTHAND_GLOBALS in masonry, then you can define MY_USEPREFIXMETHOD to solve the conflict. -#ifdef MY_USEPREFIXMETHOD - --(MyLayoutSize* (^)(id val))myEqualTo; --(MyLayoutSize* (^)(CGFloat val))myAdd; --(MyLayoutSize* (^)(CGFloat val))myMultiply; --(MyLayoutSize* (^)(CGFloat val))myMin; --(MyLayoutSize* (^)(id sizeVal, CGFloat addVal, CGFloat multiVal))myLBound; --(MyLayoutSize* (^)(CGFloat val))myMax; --(MyLayoutSize* (^)(id sizeVal, CGFloat addVal, CGFloat multiVal))myUBound; --(void)myClear; - - -#else - - #if UIKIT_DEFINE_AS_PROPERTIES /**特殊的尺寸,表示尺寸由子视图决定或者由内容决定。目前只用在表格布局MyTableLayout和栅格布局MyGridLayout中。*/ @@ -58,6 +41,22 @@ #endif +//because masonry defined macro MAS_SHORTHAND_GLOBALS. the equalTo, offset may conflict with below method. so +//if you used MyLayout and Masonry concurrently and you defined MAS_SHORTHAND_GLOBALS in masonry, then you can define MY_USEPREFIXMETHOD to solve the conflict. +#ifdef MY_USEPREFIXMETHOD + +-(MyLayoutSize* (^)(id val))myEqualTo; +-(MyLayoutSize* (^)(CGFloat val))myAdd; +-(MyLayoutSize* (^)(CGFloat val))myMultiply; +-(MyLayoutSize* (^)(CGFloat val))myMin; +-(MyLayoutSize* (^)(id sizeVal, CGFloat addVal, CGFloat multiVal))myLBound; +-(MyLayoutSize* (^)(CGFloat val))myMax; +-(MyLayoutSize* (^)(id sizeVal, CGFloat addVal, CGFloat multiVal))myUBound; +-(void)myClear; + + +#else + /** 设置尺寸的具体值,这个具体值可以设置为NSNumber, MyLayoutSize以及NSArray数组,UIView和nil值。 diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index 26a9f6d..6a8f720 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -38,10 +38,6 @@ -(id)init return [super init]; } - - - - -(MyLayoutPos*)topPosInner { return _topPos; @@ -438,17 +434,27 @@ -(void)setWrapContentWidth:(BOOL)wrapContentWidth if (wrapContentWidth) { +#ifdef MY_USEPREFIXMETHOD + self.widthSize.myEqualTo(self.widthSize); +#else self.widthSize.equalTo(self.widthSize); +#endif } else { if (self.widthSizeInner.dimeSelfVal != nil) + { +#ifdef MY_USEPREFIXMETHOD + self.widthSizeInner.myEqualTo(nil); +#else self.widthSizeInner.equalTo(nil); +#endif + } } - } } + -(void)setWrapContentHeight:(BOOL)wrapContentHeight { if (self.wrapHeight != wrapContentHeight) diff --git a/MyLayout/Lib/MyTableLayout.m b/MyLayout/Lib/MyTableLayout.m index 4dbcfb3..ee6d7fa 100644 --- a/MyLayout/Lib/MyTableLayout.m +++ b/MyLayout/Lib/MyTableLayout.m @@ -193,9 +193,22 @@ -(void)insertCol:(UIView*)colView atIndexPath:(NSIndexPath*)indexPath { NSUInteger colCount = sColCountTag - rowView.colSize; if (rowsc.orientation == MyOrientation_Horz) + { +#ifdef MY_USEPREFIXMETHOD + colsc.widthSize.myEqualTo(rowView.widthSize).myMultiply(1.0 / colCount).myAdd(-1 * rowView.subviewHSpace * (colCount - 1.0)/ colCount); +#else colsc.widthSize.equalTo(rowView.widthSize).multiply(1.0 / colCount).add(-1 * rowView.subviewHSpace * (colCount - 1.0)/ colCount); +#endif + } else + { +#ifdef MY_USEPREFIXMETHOD + colsc.heightSize.myEqualTo(rowView.heightSize).myMultiply(1.0 / colCount).myAdd(-1 * rowView.subviewVSpace * (colCount - 1.0)/ colCount); +#else colsc.heightSize.equalTo(rowView.heightSize).multiply(1.0 / colCount).add(-1 * rowView.subviewVSpace * (colCount - 1.0)/ colCount); +#endif + } + } else if (rowView.colSize > 0) { From bbe5b27992968c3c65bbb9c05a8a3ea937887edd Mon Sep 17 00:00:00 2001 From: gagehuang Date: Wed, 28 Feb 2018 12:09:23 +0800 Subject: [PATCH 004/115] =?UTF-8?q?=E6=B6=88=E9=99=A4=E6=89=93=E5=BC=80=20?= =?UTF-8?q?CLANG=5FWARN=5FOBJC=5FIMPLICIT=5FRETAIN=5FSELF=20=3D=20YES?= =?UTF-8?q?=E7=AD=89=E7=BC=96=E8=AF=91=E9=80=89=E9=A1=B9=E6=97=B6=E5=80=99?= =?UTF-8?q?=EF=BC=8C=E4=BB=A3=E7=A0=81=E7=BC=96=E8=AF=91=E7=9A=84=E8=AD=A6?= =?UTF-8?q?=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout.xcodeproj/project.pbxproj | 16 ++++++++++++- .../xcshareddata/xcschemes/MyLayout.xcscheme | 4 +++- MyLayout/Lib/MyBaseLayout.h | 4 ++-- MyLayout/Lib/MyMaker.m | 24 +++++++++---------- 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index 5ea6427..617e68a 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -909,7 +909,7 @@ 184082851B2C46E8003F378B /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0820; + LastUpgradeCheck = 0920; ORGANIZATIONNAME = YoungSoft; TargetAttributes = { 181A10B41EDF12CF00996203 = { @@ -1223,6 +1223,7 @@ CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CODE_SIGN_IDENTITY = ""; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; @@ -1250,6 +1251,7 @@ CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CODE_SIGN_IDENTITY = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; @@ -1278,14 +1280,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -1325,14 +1333,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; diff --git a/MyLayout.xcodeproj/xcshareddata/xcschemes/MyLayout.xcscheme b/MyLayout.xcodeproj/xcshareddata/xcschemes/MyLayout.xcscheme index df29ad5..f25ed80 100644 --- a/MyLayout.xcodeproj/xcshareddata/xcschemes/MyLayout.xcscheme +++ b/MyLayout.xcodeproj/xcshareddata/xcschemes/MyLayout.xcscheme @@ -1,6 +1,6 @@ @@ -36,6 +37,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index 1bba083..99717fa 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -845,11 +845,11 @@ /** *设置布局视图在布局开始之前的处理块。系统会在每次布局完成前调用对应的处理块后将处理块清空为nil。系统会在调用layoutSubviews方法前执行beginLayoutBlock。 */ -@property(nonatomic,copy) void (^beginLayoutBlock)(); +@property(nonatomic,copy) void (^beginLayoutBlock)(void); /** *设置布局视图在布局完成之后的处理块。系统会在每次布局完成后调用对应的处理块后将处理块清空为nil。您也可以在endLayoutBlock块内取到所有子视图真实布局后的frame值。系统会在调用layoutSubviews方法后执行endLayoutBlock。 */ -@property(nonatomic,copy) void (^endLayoutBlock)(); +@property(nonatomic,copy) void (^endLayoutBlock)(void); diff --git a/MyLayout/Lib/MyMaker.m b/MyLayout/Lib/MyMaker.m index 6a951f2..5d86b51 100644 --- a/MyLayout/Lib/MyMaker.m +++ b/MyLayout/Lib/MyMaker.m @@ -314,10 +314,10 @@ -(MyMaker*)pagedCount _clear = YES; return ^id(id val) { - for (NSString *key in _keys) + for (NSString *key in self->_keys) { - for (UIView * myView in _myViews) + for (UIView * myView in self->_myViews) { if ([val isKindOfClass:[NSNumber class]]) { @@ -376,9 +376,9 @@ -(MyMaker*)pagedCount return ^id(CGFloat val) { - for (NSString *key in _keys) + for (NSString *key in self->_keys) { - for (UIView *myView in _myViews) + for (UIView *myView in self->_myViews) { [((MyLayoutPos*)[myView valueForKey:key]) __offset:val]; @@ -394,9 +394,9 @@ -(MyMaker*)pagedCount _clear = YES; return ^id(CGFloat val) { - for (NSString *key in _keys) + for (NSString *key in self->_keys) { - for (UIView *myView in _myViews) + for (UIView *myView in self->_myViews) { [((MyLayoutSize*)[myView valueForKey:key]) __multiply:val]; @@ -412,10 +412,10 @@ -(MyMaker*)pagedCount _clear = YES; return ^id(CGFloat val) { - for (NSString *key in _keys) + for (NSString *key in self->_keys) { - for (UIView *myView in _myViews) + for (UIView *myView in self->_myViews) { [((MyLayoutSize*)[myView valueForKey:key]) __add:val]; @@ -431,10 +431,10 @@ -(MyMaker*)pagedCount _clear = YES; return ^id(id val) { - for (NSString *key in _keys) + for (NSString *key in self->_keys) { - for (UIView *myView in _myViews) + for (UIView *myView in self->_myViews) { @@ -465,9 +465,9 @@ -(MyMaker*)pagedCount _clear = YES; return ^id(id val) { - for (NSString *key in _keys) + for (NSString *key in self->_keys) { - for (UIView *myView in _myViews) + for (UIView *myView in self->_myViews) { id val2 = val; if ([val isKindOfClass:[UIView class]]) From 57b1e3175e373dcd9e2c81e44f25f33932b5bc96 Mon Sep 17 00:00:00 2001 From: gagehuang Date: Thu, 15 Mar 2018 16:14:03 +0800 Subject: [PATCH 005/115] =?UTF-8?q?key=E5=8F=AF=E8=83=BD=E4=B8=BA=E7=A9=BA?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E7=9A=84crash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyGridNode.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MyLayout/Lib/MyGridNode.m b/MyLayout/Lib/MyGridNode.m index 04259f6..359b54d 100644 --- a/MyLayout/Lib/MyGridNode.m +++ b/MyLayout/Lib/MyGridNode.m @@ -1229,7 +1229,11 @@ + (void)returnArrayColsRowsGridNode:(id)gridNode result:(NSMutableDi for (id node in gridNode.subGrids) { [temp addObject:[self translateGridNode:node toGridDictionary:[NSMutableDictionary new]]]; } - [result setObject:temp forKey:key]; + + if (key) { + [result setObject:temp forKey:key]; + } + } } From a15cffddf5f12557402aa52878844e6b0f054ee0 Mon Sep 17 00:00:00 2001 From: bicyclering <729921326@qq.com> Date: Tue, 3 Apr 2018 16:04:22 +0800 Subject: [PATCH 006/115] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=85=E6=A0=BC?= =?UTF-8?q?=E5=B8=83=E5=B1=80=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.zh.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.zh.md b/README.zh.md index 2213c5a..3f296e4 100644 --- a/README.zh.md +++ b/README.zh.md @@ -28,7 +28,7 @@ MyLayout是一套iOS界面视图布局框架。MyLayout的内核是基于对UIVi [http://www.jianshu.com/p/fbeb376584ed](http://www.jianshu.com/p/fbeb376584ed) 流式布局 [http://www.jianshu.com/p/0c075f2fdab2](http://www.jianshu.com/p/0c075f2fdab2) 浮动布局 [http://www.jianshu.com/p/4ac229057396](http://www.jianshu.com/p/4ac229057396) 路径布局 -[http://bicyclering.com/2017/09/01/IOS-UIViewLayout-%E5%B8%83%E5%B1%80-MyLinearLayout/#more](http://bicyclering.com/2017/09/01/IOS-UIViewLayout-%E5%B8%83%E5%B1%80-MyLinearLayout/#more) 栅格布局 +[https://bicyclering.github.io/](https://bicyclering.github.io/2017/09/01/IOS/(UIViewLayout)%E5%B8%83%E5%B1%80/MyLinearLayout/#more) 栅格布局 ### MyLayout的优势 * MyLayout的实现内核是基于frame的设置,而不是对AutoLayout的封装。因此在使用上不会受到任何操作系统版本的限制。 From 660d36473479535bbab513802091ebfd1e954e06 Mon Sep 17 00:00:00 2001 From: 111 <111@bogon.dhcp> Date: Mon, 16 Apr 2018 13:17:09 +0800 Subject: [PATCH 007/115] =?UTF-8?q?ori=3D=3Dunknown=E6=83=85=E5=86=B5?= =?UTF-8?q?=E7=9A=84else=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 0 -> 6148 bytes MyLayout/Lib/MyBaseLayout.m | 5 ++++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..73b23931898545e3bdead7864f9b5c9d1aa7ec3e GIT binary patch literal 6148 zcmeHKJxjzu5PfrAabR;;S>_iA*IF${?6kT+pd_M*M}l0y>+&nD{RuV}cD|We^@1r5 z3lW)toj3dOb~g{Qy8}R$UA+M20A?(TqQQu1^Jv#351tam=GdY^hYe2fI5N>+Y|_0S z;R0KnUe z-Pz|P*@EFhflwe62n9lc9R+x2tIZA_!-oQ)Kq&C3fSwNpi(<;yJKE7fXDI+tpV4NF zHJ4CMkuhcL9oa(@rxKkiImHmCv%SdUQpVoV>5!a!NM89Pc@bNk^A|Q8k{rW_0-?ZA zfdjA3_5MHOFEg6t4=GU#1ww&;rhrV#Rk`Fx<-7IU=jmNruw1gJ>9}448sotufE7JQ fj;+)C3ynE0W$Ybw7Hu~=F&+XYNVrho7Zi90 Date: Mon, 23 Apr 2018 08:36:58 +0800 Subject: [PATCH 008/115] Release 1.5.1. The change is in the CHANGELOG.MD --- CHANGELOG.md | 12 + MyLayout.podspec | 2 +- MyLayout.xcodeproj/project.pbxproj | 6 + MyLayout/Lib/MyBaseLayout.h | 154 +--------- MyLayout/Lib/MyBaseLayout.m | 130 +-------- MyLayout/Lib/MyBorderline.h | 2 - MyLayout/Lib/MyFloatLayout.h | 9 - MyLayout/Lib/MyFloatLayout.m | 188 ++++++++++-- MyLayout/Lib/MyFlowLayout.h | 16 +- MyLayout/Lib/MyFlowLayout.m | 39 +-- MyLayout/Lib/MyFrameLayout.h | 20 -- MyLayout/Lib/MyFrameLayout.m | 3 +- MyLayout/Lib/MyGrid.h | 8 +- MyLayout/Lib/MyGridLayout.m | 6 +- MyLayout/Lib/MyLayout.h | 2 +- MyLayout/Lib/MyLayoutDef.h | 160 +++++----- MyLayout/Lib/MyLayoutInner.h | 6 +- MyLayout/Lib/MyLayoutMath.m | 3 +- MyLayout/Lib/MyLayoutPos.h | 6 - MyLayout/Lib/MyLayoutPos.m | 2 +- MyLayout/Lib/MyLayoutSize.h | 8 - MyLayout/Lib/MyLayoutSize.m | 4 +- MyLayout/Lib/MyLinearLayout.h | 17 -- MyLayout/Lib/MyLinearLayout.m | 42 +-- MyLayout/Lib/MyPathLayout.m | 8 +- MyLayout/Lib/MyRelativeLayout.h | 13 - MyLayout/Lib/MyRelativeLayout.m | 30 +- MyLayout/Lib/MyTableLayout.h | 19 +- MyLayout/Lib/MyTableLayout.m | 7 +- MyLayoutDemo/DetailViewController.m | 1 + MyLayoutDemo/FOLTest7ViewController.h | 16 + MyLayoutDemo/FOLTest7ViewController.m | 273 ++++++++++++++++++ MyLayoutDemo/Info.plist | 2 +- MyLayoutDemo/ViewController.m | 5 + .../zh-Hans.lproj/Localizable.strings | 1 + README.md | 2 +- README.zh.md | 2 +- 37 files changed, 596 insertions(+), 628 deletions(-) create mode 100644 MyLayoutDemo/FOLTest7ViewController.h create mode 100644 MyLayoutDemo/FOLTest7ViewController.m diff --git a/CHANGELOG.md b/CHANGELOG.md index ebac130..58cb5ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,18 @@ --- +## [V1.5.1](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.5.1)(2018/04/23) + +#### Added +1. 添加了对浮动布局MyFloatLayout中的子视图的行或者列内对齐方式的设置,您可以借助子视图的myAlignment属性来设置行或者列内的对齐方式,具体的DEMO请参考:[FOLTest7ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/FOLTest7ViewController.m) 中的介绍。 +2. 将所有设置为过期的方法删除。 +3. 修正一些编译上的告警以及一些和Masonry公用时的一些问题。 +4. 修复方向旋转时有可能不调用`rotationToDeviceOrientationBlock`的问题。 +5. 修正一些注释上的提示。 +6. 将网友提交合并的代码一起发布新的版本。 + + + ## [V1.5.0](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.5.0)(2017/10/9) #### Added diff --git a/MyLayout.podspec b/MyLayout.podspec index c820741..ad0ba17 100644 --- a/MyLayout.podspec +++ b/MyLayout.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "MyLayout" - s.version = "1.5.0" + s.version = "1.5.1" s.summary = "MyLayout is an iOS UI framework integrates the functions with Android,AutoLayout,SizeClass,HTML CSS float and flexbox,UIView UITableView." s.description = <<-DESC diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index 617e68a..e193e1d 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -156,6 +156,7 @@ 208157C31F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; 208157C41F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */ = {isa = PBXBuildFile; fileRef = 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */; }; + 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */; }; 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F783551F60399700BE5B31 /* GLTest3ViewController.m */; }; 4411977B1F6AE78E00C22557 /* GridLayoutDemo5.json in Resources */ = {isa = PBXBuildFile; fileRef = 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */; }; 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */; }; @@ -383,6 +384,8 @@ 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutDelegate.h; sourceTree = ""; }; 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutDelegate.m; sourceTree = ""; }; 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo8.gif; sourceTree = ""; }; + 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest7ViewController.h; sourceTree = ""; }; + 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest7ViewController.m; sourceTree = ""; }; 20F783541F60398C00BE5B31 /* GLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest3ViewController.h; sourceTree = ""; }; 20F783551F60399700BE5B31 /* GLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest3ViewController.m; sourceTree = ""; }; 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo5.json; sourceTree = ""; }; @@ -587,6 +590,8 @@ 18D3C9571EDF07F800D3DE43 /* FOLTest5ViewController.m */, 18D3C9581EDF07F800D3DE43 /* FOLTest6ViewController.h */, 18D3C9591EDF07F800D3DE43 /* FOLTest6ViewController.m */, + 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */, + 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */, ); name = FloatLayoutDemo; sourceTree = ""; @@ -1100,6 +1105,7 @@ 18D3C9171EDF074900D3DE43 /* LLTest7ViewController.m in Sources */, 18D3C98A1EDF084000D3DE43 /* AllTest6ViewController.m in Sources */, 18D3C9111EDF074900D3DE43 /* LLTest1ViewController.m in Sources */, + 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */, 18D3C93E1EDF07C000D3DE43 /* FLLTest6ViewController.m in Sources */, 200A26D91FA8A90300B06E7B /* AllTest9ViewController.m in Sources */, 18D3C9281EDF07A700D3DE43 /* RLTest1ViewController.m in Sources */, diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index 99717fa..c77f964 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -554,7 +554,7 @@ /** - 指定子在布局视图上的对齐方式,默认是None表示未指定,这个属性目前只支持框架布局,线性布局,流式布局下的属性设置。 + 指定子在布局视图上的对齐方式,默认是None表示未指定,这个属性目前只支持框架布局,线性布局,流式布局,浮动布局下的属性设置。 1. 在框架布局中支持上、中、下、垂直拉伸和左、中、右、水平拉伸8个设置 @@ -562,9 +562,9 @@ 3. 在水平线性布局中只支持上、中、下、垂直拉伸对齐。(如果父布局视图设置了gravity,子视图设置了这个属性则这个属性优先级最高) - 4. 在垂直流式布局中用来设置一行内的上、中、下、垂直拉伸对齐。(如果父布局视图设置了arrangedGravity,子视图设置了这个属性则这个属性优先级最高) + 4. 在垂直流式布局和垂直浮动布局中用来设置一行内的上、中、下、垂直拉伸对齐。(如果流式父布局视图设置了arrangedGravity,子视图设置了这个属性则这个属性优先级最高) - 5. 在水平流式布局中用来设置一列内的左、中、右、水平拉伸对齐。(如果父布局视图设置了arrangedGravity,子视图时设置了这个属性则这个属性优先级最高) + 5. 在水平流式布局和水平浮动布局中用来设置一列内的左、中、右、水平拉伸对齐。(如果流式父布局视图设置了arrangedGravity,子视图时设置了这个属性则这个属性优先级最高) */ @property(nonatomic, assign) MyGravity myAlignment; @@ -609,69 +609,6 @@ -(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass copyFrom:(MySizeClass)srcSizeClass; -@end - - -@interface UIView(MyLayoutExtDeprecated) - -/** - * 过期的位置和尺寸设置方法,老版本中带Margin后缀就明确为了边距的概念,但是这个和属性定义的概念是不一致的,位置即可表示边距也可以表示间距。所以这些方法将设置为过期。您可以在相应的位置定义宏:#define MY_USEOLDMETHODNOWARNING = 1 则不会出现老方法告警,不过不建议这么做。 - */ - - -/** - *过期属性,请用myLeft - */ -@property(nonatomic, assign) CGFloat myLeftMargin MYMETHODDEPRECATED("use myLeft to instead"); - -/** - *过期属性,请用myTop - */ -@property(nonatomic, assign) CGFloat myTopMargin MYMETHODDEPRECATED("use myTop to instead"); - -/** - *过期属性,请用myRight - */ -@property(nonatomic, assign) CGFloat myRightMargin MYMETHODDEPRECATED("use myRight to instead"); - -/** - *过期属性,请用myBottom - */ -@property(nonatomic, assign) CGFloat myBottomMargin MYMETHODDEPRECATED("use myBottom to instead"); - -/** - *过期属性,请用myCenterX - */ -@property(nonatomic, assign) CGFloat myCenterXOffset MYMETHODDEPRECATED("use myCenterX to instead"); - -/** - *过期属性,请用myCenterY - */ -@property(nonatomic, assign) CGFloat myCenterYOffset MYMETHODDEPRECATED("use myCenterY to instead"); - -/** - *过期属性,请用myCenter - */ -@property(nonatomic, assign) CGPoint myCenterOffset MYMETHODDEPRECATED("use myCenter to instead"); - -/** - *过期属性,请用widthSize - */ -@property(nonatomic, readonly) MyLayoutSize *widthDime MYMETHODDEPRECATED("use widthSize to instead"); - -/** - *过期属性,请用heightSize - */ -@property(nonatomic, readonly) MyLayoutSize *heightDime MYMETHODDEPRECATED("use heightSize to instead"); - - -/** - *过期属性,请用wrapContentHeight - */ -@property(nonatomic, assign, getter=isFlexedHeight) BOOL flexedHeight MYMETHODDEPRECATED("use wrapContentHeight to instead"); - - - @end @@ -686,16 +623,11 @@ */ @interface MyBaseLayout : UIView -#if UIKIT_DEFINE_AS_PROPERTIES - /** 用于实现对阿拉伯国家的布局适配。对于非阿拉伯国家来说,界面布局都是默认从左到右排列。而对于阿拉伯国家来说界面布局则默认是从右往左排列。默认这个属性是NO,您可以将这个属性设置为YES,这样布局里面的所有视图都将从右到左进行排列布局。如果您需要考虑国际化布局的问题,那么您应该用leadingPos来表示头部的位置,而用trailingPos来表示尾部的位置,这样当布局方向是LTR时那么leadingPos就表示的是左边而trailingPos则表示的是右边;而当布局方向是RTL时那么leadingPos表示的是右边而trailingPos则表示的是左边。如果您的界面布局不会考虑到国际化以及不需要考虑RTL时那么您可以用leftPos和rightPos来表示左右而不需要用leadingPos和trailingPos。 */ @property(class, nonatomic, assign) BOOL isRTL; -#else -+(BOOL)isRTL; -+(void)setIsRTL:(BOOL)isRTL; -#endif + /* 布局视图里面的padding属性用来设置布局视图的内边距。内边距是指布局视图里面的子视图离自己距离。外边距则是视图与父视图之间的距离。 @@ -1054,82 +986,4 @@ @end -@interface MyBaseLayout(MyBaseLayoutDeprecated) - -/** - *过期方法,对于间距统一用space来描述,而边距用margin来描述。 - *原先子视图之间的间距属性的命名规范不合理,所以这里将原先的设置间距的属性设置为过期。这里也和TangramKit中的命名统一。 - *您可以在相应的位置定义宏:#define MY_USEOLDMETHODNOWARNING = 1 则不会出现老方法告警,不过不建议这么做。 - */ - -/** -*过期属性,请用subviewVSpace -*/ -@property(nonatomic ,assign, getter=subviewVSpace, setter=setSubviewVSpace:) CGFloat subviewVertMargin MYMETHODDEPRECATED("use subviewVSpace to instead"); - -/** - *过期属性,请用subviewHSpace - */ -@property(nonatomic, assign, getter=subviewHSpace, setter=setSubviewHSpace:) CGFloat subviewHorzMargin MYMETHODDEPRECATED("use subviewHSpace to instead"); - -/** - *过期属性,请用subviewSpace - */ -@property(nonatomic, assign, getter=subviewSpace, setter=setSubviewSpace:) CGFloat subviewMargin MYMETHODDEPRECATED("use subviewSpace to instead"); - -/** - *过期方法, 原先对边界线命名BorderLine不符合规则,Borderline是一个单词不是一个词组。这里也和TangramKit中的命名统一。 - */ - -/** - *过期属性,请用leftBorderline - */ -@property(nonatomic, strong, getter=leftBorderline, setter=setLeftBorderline:) MyBorderline *leftBorderLine MYMETHODDEPRECATED("use leftBorderline to instead"); - -/** - *过期属性,请用rightBorderline - */ -@property(nonatomic, strong, getter=rightBorderline, setter=setRightBorderline:) MyBorderline *rightBorderLine MYMETHODDEPRECATED("use rightBorderline to instead"); - -/** - *过期属性,请用topBorderline - */ -@property(nonatomic, strong, getter=topBorderline, setter=setTopBorderline:) MyBorderline *topBorderLine MYMETHODDEPRECATED("use topBorderline to instead"); - -/** - *过期属性,请用bottomBorderline - */ -@property(nonatomic, strong, getter=bottomBorderline, setter=setBottomBorderline:) MyBorderline *bottomBorderLine MYMETHODDEPRECATED("use bottomBorderline to instead"); - -/** - *过期属性,请用boundBorderline - */ -@property(nonatomic, strong, getter=boundBorderline, setter=setBoundBorderline:) MyBorderline *boundBorderLine MYMETHODDEPRECATED("use boundBorderline to instead"); - -/** - *过期属性,请用intelligentBorderline - */ -@property(nonatomic, strong, getter=intelligentBorderline, setter=setIntelligentBorderline:) MyBorderline *IntelligentBorderLine MYMETHODDEPRECATED("use intelligentBorderline to instead"); - -/** - *过期属性,请用notUseIntelligentBorderline - */ -@property(nonatomic, assign, getter=notUseIntelligentBorderline, setter=setNotUseIntelligentBorderline:) BOOL notUseIntelligentBorderLine MYMETHODDEPRECATED("use notUseIntelligentBorderline to instead"); - - -/** - *这个属性在新版本将失效并且无任何意义了。如果想让子视图隐藏时是否继续占据位置则请参考使用子视图的myVisibility属性来进行单独设置。 - */ -@property(nonatomic, assign) BOOL hideSubviewReLayout MYMETHODDEPRECATED("this property was invalid, please use subview's myVisibility to instead"); - - -/** - *过期方法。请用sizeThatFits方法来代替。 - */ --(CGRect)estimateLayoutRect:(CGSize)size MYMETHODDEPRECATED("this method was invalid, please use sizeThatFits: to instead"); --(CGRect)estimateLayoutRect:(CGSize)size inSizeClass:(MySizeClass)sizeClass MYMETHODDEPRECATED("this method was invalid, please use sizeThatFits:inSizeClass: to instead"); - - -@end - diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index ebd1772..601a90b 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -462,111 +462,6 @@ -(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass copyFrom:(MySizeClass -@end - -@implementation UIView(MyLayoutExtDeprecated) - - - - --(CGFloat)myLeftMargin -{ - return self.myLeft; -} - --(void)setMyLeftMargin:(CGFloat)myLeftMargin -{ - self.myLeft = myLeftMargin; -} - --(CGFloat)myTopMargin -{ - return self.myTop; -} - --(void)setMyTopMargin:(CGFloat)myTopMargin -{ - self.myTop = myTopMargin; -} - --(CGFloat)myRightMargin -{ - return self.myRight; -} - --(void)setMyRightMargin:(CGFloat)myRightMargin -{ - self.myRight = myRightMargin; -} - --(CGFloat)myBottomMargin -{ - return self.myBottom; -} - --(void)setMyBottomMargin:(CGFloat)myBottomMargin -{ - self.myBottom = myBottomMargin; -} - --(MyLayoutSize*)widthDime -{ - return self.widthSize; -} - - - --(MyLayoutSize*)heightDime -{ - return self.heightSize; -} - - --(CGFloat)myCenterXOffset -{ - return self.myCenterX; -} - --(void)setMyCenterXOffset:(CGFloat)myCenterXOffset -{ - self.myCenterX = myCenterXOffset; -} - --(CGFloat)myCenterYOffset -{ - return self.myCenterY; -} - --(void)setMyCenterYOffset:(CGFloat)myCenterYOffset -{ - self.myCenterY = myCenterYOffset; -} - - --(CGPoint)myCenterOffset -{ - return self.myCenter; -} - --(void)setMyCenterOffset:(CGPoint)myCenterOffset -{ - self.myCenter = myCenterOffset; -} - - - --(void)setFlexedHeight:(BOOL)flexedHeight -{ - self.wrapContentHeight = flexedHeight; -} - --(BOOL)isFlexedHeight -{ - return self.wrapContentHeight; -} - - - @end @@ -805,6 +700,9 @@ -(void)dealloc _rotationToDeviceOrientationBlock = nil; } +#pragma mark -- Public Methods + + +(BOOL)isRTL { return [MyViewSizeClass isRTL]; @@ -815,7 +713,6 @@ +(void)setIsRTL:(BOOL)isRTL [MyViewSizeClass setIsRTL:isRTL]; } -#pragma mark -- Public Method -(CGFloat)topPadding @@ -1444,7 +1341,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIView*)object chan } -#pragma mark -- Override Method +#pragma mark -- Override Methods @@ -2184,24 +2081,7 @@ -(void)layoutSubviews } -#pragma mark -- Deprecated Method - --(CGRect)estimateLayoutRect:(CGSize)size -{ - CGRect rect = CGRectZero; - rect.size = [self sizeThatFits:size]; - return rect; -} - --(CGRect)estimateLayoutRect:(CGSize)size inSizeClass:(MySizeClass)sizeClass -{ - CGRect rect = CGRectZero; - rect.size = [self sizeThatFits:size inSizeClass:sizeClass]; - return rect; -} - - -#pragma mark -- Private Method +#pragma mark -- Private Methods diff --git a/MyLayout/Lib/MyBorderline.h b/MyLayout/Lib/MyBorderline.h index db04365..8266d50 100644 --- a/MyLayout/Lib/MyBorderline.h +++ b/MyLayout/Lib/MyBorderline.h @@ -58,7 +58,5 @@ @end -//兼容老版本的类名命名不规则的问题,这样老版本仍然可以用MyBorderLineDraw这个类名。 -typedef MyBorderline MyBorderLineDraw MYMETHODDEPRECATED("use MyBorderline to instead"); diff --git a/MyLayout/Lib/MyFloatLayout.h b/MyLayout/Lib/MyFloatLayout.h index ed9c3f4..9c5490a 100644 --- a/MyLayout/Lib/MyFloatLayout.h +++ b/MyLayout/Lib/MyFloatLayout.h @@ -140,12 +140,3 @@ @end - -@interface MyFloatLayout(MyFloatLayoutDeprecated) - --(void)setSubviewFloatMargin:(CGFloat)subviewSize minMargin:(CGFloat)minMargin MYMETHODDEPRECATED("use method: setSubviews:minSpace:maxSpace to replace"); --(void)setSubviewFloatMargin:(CGFloat)subviewSize minMargin:(CGFloat)minMargin inSizeClass:(MySizeClass)sizeClass MYMETHODDEPRECATED("use method: setSubviews:minSpace:maxSpace:inSizeClass to replace"); - - -@end - diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index d8bb479..a347c63 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -52,6 +52,8 @@ -(BOOL)clearFloat @implementation MyFloatLayout +#pragma mark -- Public Methods + -(instancetype)initWithFrame:(CGRect)frame orientation:(MyOrientation)orientation { self = [super initWithFrame:frame]; @@ -122,32 +124,7 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace: } -#pragma mark -- Deprecated Method - - --(void)setSubviewFloatMargin:(CGFloat)subviewSize minMargin:(CGFloat)minMargin -{ - [self setSubviewsSize:subviewSize minSpace:minMargin maxSpace:CGFLOAT_MAX]; -} - --(void)setSubviewFloatMargin:(CGFloat)subviewSize minMargin:(CGFloat)minMargin inSizeClass:(MySizeClass)sizeClass -{ - [self setSubviewsSize:subviewSize minSpace:minMargin maxSpace:CGFLOAT_MAX inSizeClass:sizeClass]; -} - - - - -/* - // Only override drawRect: if you perform custom drawing. - // An empty implementation adversely affects performance during animation. - - (void)drawRect:(CGRect)rect { - // Drawing code - } - */ - - -#pragma mark -- Override Method +#pragma mark -- Override Methods -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { @@ -226,7 +203,7 @@ -(id)createSizeClassInstance return [MyFloatLayoutViewSizeClass new]; } -#pragma mark -- Private Method +#pragma mark -- Private Methods -(CGPoint)myFindTrailingCandidatePoint:(CGRect)leadingCandidateRect width:(CGFloat)width trailingBoundary:(CGFloat)trailingBoundary trailingCandidateRects:(NSArray*)trailingCandidateRects hasWeight:(BOOL)hasWeight paddingTop:(CGFloat)paddingTop { @@ -534,8 +511,13 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( CGFloat maxHeight = paddingTop; CGFloat maxWidth = paddingLeading; - for (UIView *sbv in sbs) + //记录是否有子视图设置了对齐,如果设置了对齐就会在后面对每行子视图做对齐处理。 + BOOL sbvHasAlignment = NO; + NSMutableArray *lineIndexes = [NSMutableArray new]; + + for (NSInteger idx = 0; idx < sbs.count; idx++) { + UIView *sbv = sbs[idx]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; @@ -545,6 +527,9 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; + //只要有一个子视图设置了对齐,就会做对齐处理,否则不会,这里这样做是为了对后面的对齐计算做优化。 + sbvHasAlignment |= ((sbvsc.myAlignment & MyGravity_Horz_Mask) > MyGravity_Vert_Top); + if (subviewSize != 0) rect.size.width = subviewSize; @@ -723,6 +708,11 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( } + //记录每一行的最大子视图位置的索引值。 + if (trailingLastYOffset != rect.origin.y - topSpace) + { + [lineIndexes addObject:@(idx - 1)]; + } [trailingCandidateRects addObject:[NSValue valueWithCGRect:cRect]]; trailingLastYOffset = rect.origin.y - topSpace; @@ -790,7 +780,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( rect.origin.x = nextPoint.x + leadingSpace; rect.origin.y = _myCGFloatMin(nextPoint.y,maxHeight) + topSpace; - + if (!isEstimate && self.intelligentBorderline != nil) { //优先绘制左边和上边的。绘制左边的和上边的。 @@ -856,6 +846,11 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( } } + //记录每一行的最大子视图位置的索引值。 + if (leadingLastYOffset != rect.origin.y - topSpace) + { + [lineIndexes addObject:@(idx - 1)]; + } [leadingCandidateRects addObject:[NSValue valueWithCGRect:cRect]]; leadingLastYOffset = rect.origin.y - topSpace; @@ -912,6 +907,64 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( } } + + + //如果有子视图设置了对齐属性,那么就要对处在同一行内的子视图进行对齐设置。 + //对齐的规则是以行内最高的子视图作为参考的对象,其他的子视图按照行内最高子视图进行垂直对齐的调整。 + if (sbvHasAlignment) + { + //最后一行。 + if (sbs.count > 0) + { + [lineIndexes addObject:@(sbs.count - 1)]; + } + + NSInteger lineFirstIndex = 0; + for (NSNumber *idxnum in lineIndexes) + { + BOOL lineHasAlignment = NO; + + //计算每行内的最高的子视图,作为行对齐的标准。 + CGFloat lineMaxHeight = 0; + for (NSInteger i = lineFirstIndex; i <= idxnum.integerValue; i++) + { + UIView *sbv = sbs[i]; + MyFrame *sbvmyFrame = sbv.myFrame; + UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + if (sbvmyFrame.height > lineMaxHeight) + lineMaxHeight = sbvmyFrame.height; + + lineHasAlignment |= ((sbvsc.myAlignment & MyGravity_Horz_Mask) > MyGravity_Vert_Top); + } + + //设置行内的对齐 + if (lineHasAlignment) + { + for (NSInteger i = lineFirstIndex; i <= idxnum.integerValue; i++) + { + UIView *sbv = sbs[i]; + MyFrame *sbvmyFrame = sbv.myFrame; + UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + switch (sbvsc.myAlignment & MyGravity_Horz_Mask) { + case MyGravity_Vert_Center: + sbvmyFrame.top += (lineMaxHeight - sbvmyFrame.height) / 2.0; + break; + case MyGravity_Vert_Bottom: + sbvmyFrame.top += (lineMaxHeight - sbvmyFrame.height); + break; + case MyGravity_Vert_Fill: + sbvmyFrame.height = lineMaxHeight; + break; + default: + break; + } + } + } + + lineFirstIndex = idxnum.integerValue + 1; + } + } + return selfSize; } @@ -1037,8 +1090,13 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( CGFloat maxWidth = paddingLeading; CGFloat maxHeight = paddingTop; - for (UIView *sbv in sbs) + //记录是否有子视图设置了对齐,如果设置了对齐就会在后面对每行子视图做对齐处理。 + BOOL sbvHasAlignment = NO; + NSMutableArray *lineIndexes = [NSMutableArray new]; + + for (NSInteger idx = 0; idx < sbs.count; idx++) { + UIView *sbv = sbs[idx]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; @@ -1048,6 +1106,9 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; + //只要有一个子视图设置了对齐,就会做对齐处理,否则不会,这里这样做是为了对后面的对齐计算做优化。 + sbvHasAlignment |= ((sbvsc.myAlignment & MyGravity_Vert_Mask) > MyGravity_Horz_Left); + if (sbvsc.widthSizeInner.dimeNumVal != nil) rect.size.width = sbvsc.widthSizeInner.measure; @@ -1219,6 +1280,12 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( } + //记录每一列的最大子视图位置的索引值。 + if (bottomLastXOffset != rect.origin.x - leadingSpace) + { + [lineIndexes addObject:@(idx - 1)]; + } + [bottomCandidateRects addObject:[NSValue valueWithCGRect:cRect]]; bottomLastXOffset = rect.origin.x - leadingSpace; @@ -1345,6 +1412,11 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( } + //记录每一列的最大子视图位置的索引值。 + if (topLastXOffset != rect.origin.x - leadingSpace) + { + [lineIndexes addObject:@(idx - 1)]; + } [topCandidateRects addObject:[NSValue valueWithCGRect:cRect]]; topLastXOffset = rect.origin.x - leadingSpace; @@ -1404,6 +1476,62 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( } + //如果有子视图设置了对齐属性,那么就要对处在同一列内的子视图进行对齐设置。 + //对齐的规则是以列内最宽的子视图作为参考的对象,其他的子视图按照列内最宽子视图进行水平对齐的调整。 + if (sbvHasAlignment) + { + //最后一列。 + if (sbs.count > 0) + { + [lineIndexes addObject:@(sbs.count - 1)]; + } + + NSInteger lineFirstIndex = 0; + for (NSNumber *idxnum in lineIndexes) + { + BOOL lineHasAlignment = NO; + + //计算每列内的最宽的子视图,作为列对齐的标准。 + CGFloat lineMaxWidth = 0; + for (NSInteger i = lineFirstIndex; i <= idxnum.integerValue; i++) + { + UIView *sbv = sbs[i]; + MyFrame *sbvmyFrame = sbv.myFrame; + UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + if (sbvmyFrame.width > lineMaxWidth) + lineMaxWidth = sbvmyFrame.width; + + lineHasAlignment |= ((sbvsc.myAlignment & MyGravity_Vert_Mask) > MyGravity_Horz_Left); + } + + //设置行内的对齐 + if (lineHasAlignment) + { + for (NSInteger i = lineFirstIndex; i <= idxnum.integerValue; i++) + { + UIView *sbv = sbs[i]; + MyFrame *sbvmyFrame = sbv.myFrame; + UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + switch ([self myConvertLeftRightGravityToLeadingTrailing:sbvsc.myAlignment & MyGravity_Vert_Mask]) { + case MyGravity_Horz_Center: + sbvmyFrame.leading += (lineMaxWidth - sbvmyFrame.width) / 2.0; + break; + case MyGravity_Horz_Trailing: + sbvmyFrame.leading += (lineMaxWidth - sbvmyFrame.width); + break; + case MyGravity_Horz_Fill: + sbvmyFrame.width = lineMaxWidth; + break; + default: + break; + } + } + } + + lineFirstIndex = idxnum.integerValue + 1; + } + } + return selfSize; } diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index b647493..632ea3b 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -185,7 +185,7 @@ /** - *设置流式布局中每排内所有子视图的对齐停靠方式。具体的对齐停靠方式依赖于布局视图的方向: + 设置流式布局中每排内所有子视图的对齐停靠方式。具体的对齐停靠方式依赖于布局视图的方向: 1. 如果是垂直流式布局则表示每排内子视图的上中下对齐方式,这里的对齐基础是以每排中的最高的子视图为基准。这个属性只支持: @code @@ -229,18 +229,4 @@ @end -@interface MyFlowLayout(MyFlowLayoutDeprecated) - -/** - 指定是否均分布局方向上的子视图的宽度或者高度,或者拉伸子视图的尺寸,默认是NO。 - 如果是MyOrientation_Vert则表示每行的子视图的宽度会被均分,这样子视图不需要指定宽度,但是布局视图必须要指定一个明确的宽度值,如果设置为YES则wrapContentWidth会失效。 - 如果是MyOrientation_Horz则表示每列的子视图的高度会被均分,这样子视图不需要指定高度,但是布局视图必须要指定一个明确的高度值,如果设置为YES则wrapContentHeight会失效。 - 内容填充约束流式布局下averageArrange设置为YES时表示拉伸子视图的宽度或者高度以便填充满整个布局视图。 - */ -@property(nonatomic,assign) BOOL averageArrange MYMETHODDEPRECATED("use gravity = MyGravity_Horz_Fill or gravity = MyGravity_Vert_Fill to instead"); - - -@end - - diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index a299060..70db758 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -12,6 +12,7 @@ @implementation MyFlowLayout +#pragma mark -- Public Methods -(instancetype)initWithFrame:(CGRect)frame orientation:(MyOrientation)orientation arrangedCount:(NSInteger)arrangedCount { @@ -134,42 +135,8 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace: [self setNeedsLayout]; } -#pragma mark -- Deprecated Method - --(void)setAverageArrange:(BOOL)averageArrange -{ - MyFlowLayout *lsc = self.myCurrentSizeClass; - - if (lsc.orientation == MyOrientation_Vert) - { - if (averageArrange) - lsc.gravity = (lsc.gravity & MyGravity_Horz_Mask) | MyGravity_Horz_Fill; - else - lsc.gravity = (lsc.gravity & MyGravity_Horz_Mask) | MyGravity_None; - } - else - { - if (averageArrange) - lsc.gravity = (lsc.gravity & MyGravity_Vert_Mask) | MyGravity_Vert_Fill; - else - lsc.gravity = (lsc.gravity & MyGravity_Vert_Mask) | MyGravity_None; - } - -} - --(BOOL)averageArrange -{ - MyFlowLayout *lsc = self.myCurrentSizeClass; - - if (lsc.orientation == MyOrientation_Vert) - return (lsc.gravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill; - else - return (lsc.gravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill; -} - - -#pragma mark -- Override Method +#pragma mark -- Override Methods -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { @@ -266,7 +233,7 @@ -(id)createSizeClassInstance return [MyFlowLayoutViewSizeClass new]; } -#pragma mark -- Private Method +#pragma mark -- Private Methods - (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalWeight:(CGFloat)totalWeight sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count diff --git a/MyLayout/Lib/MyFrameLayout.h b/MyLayout/Lib/MyFrameLayout.h index fb35c7c..5ebb3c9 100644 --- a/MyLayout/Lib/MyFrameLayout.h +++ b/MyLayout/Lib/MyFrameLayout.h @@ -8,26 +8,6 @@ #import "MyBaseLayout.h" -/* -@interface UIView(MyFrameLayoutExt) - -//新版本1.3.3以后的版本将不再提供框架布局对子视图的这个扩展属性的支持。 -@property(nonatomic, assign) MyGravity marginGravity; - - 1.如果您想让子视图右对齐框架布局,则只需要设置myRight = 数值 和宽度即可 不再需要设置marginGravity = MyGravity_Horz_Right - 2.如果您想让子视图底对齐框架布局,则只需要设置myBottom = 数值 和高度即可,不再需要设置marginGravity = MyGravity_Vert_Bottom - 3.如果您想让子视图在框架布局中垂直居中,则只需要设置myCenterY = 数值 和高度即可,不再需要设置marginGravity = MyGravity_Vert_Center - 4.如果您想让子视图在框架布局中水平居中,则只需要设置myCenterX = 数值 和宽度即可,不再需要设置marginGravity = MyGravity_Horz_Center - 5.如果您想让子视图在框架布局中宽度填满,则只需要设置myHorzMargin = 0,不再需要设置marginGravity = MyGravity_Horz_Fill - 6.如果您想让子视图在框架布局中高度填满,则只需要设置myVertMargin = 0, 不再需要设置marginGravity = MyGravity_Vert_Fill - 7.如果你要水平和垂直方向都设置,则请同时设置对应位置对象的值。 - 8.新版本将不再支持让框架布局中的子视图在窗口中居中了。 - - - 请使用了marginGravity属性的代码进行对应的代码变更!!! - -@end -*/ /** 框架布局是一种里面的子视图停靠在父视图特定方位并且可以重叠的布局视图。框架布局里面的子视图的布局位置和添加的顺序无关,框架布局中的所有子视图的约束依赖都只是针对于和父布局视图的。框架布局是一种特殊的相对布局,因此如果某些布局里面的子视图只依赖于父视图的边界时则可以用框架布局来代替,从而加快布局的速度。 diff --git a/MyLayout/Lib/MyFrameLayout.m b/MyLayout/Lib/MyFrameLayout.m index eb354eb..6d70d10 100644 --- a/MyLayout/Lib/MyFrameLayout.m +++ b/MyLayout/Lib/MyFrameLayout.m @@ -22,7 +22,7 @@ - (void)drawRect:(CGRect)rect { */ -#pragma mark -- Override Method +#pragma mark -- Override Methods -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray *)sbs @@ -111,6 +111,7 @@ -(id)createSizeClassInstance } +#pragma mark -- Private Methods -(void)myCalcSubViewRect:(UIView*)sbv diff --git a/MyLayout/Lib/MyGrid.h b/MyLayout/Lib/MyGrid.h index a3c4227..f164c53 100644 --- a/MyLayout/Lib/MyGrid.h +++ b/MyLayout/Lib/MyGrid.h @@ -102,11 +102,15 @@ extern NSString * const vMyGridGravityHeightFill; //对应MyGravity_Vert_Fill @property(nonatomic, weak, readonly) id superGrid; -//得到所有子栅格 +/** + 得到所有子栅格 + */ @property(nonatomic, strong, readonly) NSArray> *subGrids; -//克隆出一个新栅格以及其下的所有子栅格。 +/** + 克隆出一个新栅格以及其下的所有子栅格。 + */ -(id)cloneGrid; diff --git a/MyLayout/Lib/MyGridLayout.m b/MyLayout/Lib/MyGridLayout.m index fa76ded..16ad83a 100644 --- a/MyLayout/Lib/MyGridLayout.m +++ b/MyLayout/Lib/MyGridLayout.m @@ -109,7 +109,7 @@ -(NSMutableDictionary*)tagsDict return _tagsDict; } -#pragma mark -- Public Method +#pragma mark -- Public Methods +(id)createTemplateGrid:(NSInteger)gridTag { @@ -776,7 +776,7 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event -#pragma mark -- Override Method +#pragma mark -- Override Methods -(void)dealloc { @@ -929,7 +929,7 @@ -(id)createSizeClassInstance return [MyGridLayoutViewSizeClass new]; } -#pragma mark -- Private Method +#pragma mark -- Private Methods //遍历位置 -(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigin lsc:(MyGridLayout*)lsc sbvEnumerator:(NSEnumerator*)sbvEnumerator tagViewGroupIndexDict:(NSMutableDictionary*)tagViewGroupIndexDict tagSbvEnumerator:(NSEnumerator*)tagSbvEnumerator isEstimate:(BOOL)isEstimate sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index 9269636..ea5ddba 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -37,7 +37,7 @@ */ -//Current version is 1.5.0, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.5.1, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. #ifndef MyLayout_MyLayout_h diff --git a/MyLayout/Lib/MyLayoutDef.h b/MyLayout/Lib/MyLayoutDef.h index 30d3e2d..0de4f02 100644 --- a/MyLayout/Lib/MyLayoutDef.h +++ b/MyLayout/Lib/MyLayoutDef.h @@ -32,28 +32,24 @@ *布局视图方向的枚举类型定义。用来指定布局内子视图的整体排列布局方向。 */ typedef enum : unsigned char { - MyOrientation_Vert = 0, /**垂直方向,布局视图内所有子视图整体从上到下排列布局*/ - MyOrientation_Horz = 1, /**水平方向,布局视图内所有子视图整体从左到右排列布局*/ - - - //兼容老版本而定义,请使用新的定义值。 - MyLayoutViewOrientation_Vert MYMETHODDEPRECATED("use MyOrientation_Vert to instead") = MyOrientation_Vert, - MyLayoutViewOrientation_Horz MYMETHODDEPRECATED("use MyOrientation_Horz to instead") = MyOrientation_Horz, - + /**垂直方向,布局视图内所有子视图整体从上到下排列布局*/ + MyOrientation_Vert = 0, + /**水平方向,布局视图内所有子视图整体从左到右排列布局*/ + MyOrientation_Horz = 1, } MyOrientation; -//为了兼容老版本而定义 -typedef MyOrientation MyLayoutViewOrientation MYMETHODDEPRECATED("use MyOrientation to instead"); - /** *视图的可见性枚举类型定义。用来指定视图是否在布局中可见,他是对hidden属性的扩展设置。 */ typedef enum : unsigned char { - MyVisibility_Visible, /**视图可见,等价于hidden = false*/ - MyVisibility_Invisible, /**视图隐藏,等价于hidden = true, 但是会在父布局视图中占位空白区域*/ - MyVisibility_Gone /**视图隐藏,等价于hidden = true, 但是不会在父视图中占位空白区域*/ + /**视图可见,等价于hidden = false*/ + MyVisibility_Visible, + /**视图隐藏,等价于hidden = true, 但是会在父布局视图中占位空白区域*/ + MyVisibility_Invisible, + /**视图隐藏,等价于hidden = true, 但是不会在父视图中占位空白区域*/ + MyVisibility_Gone }MyVisibility; @@ -69,66 +65,59 @@ typedef enum : unsigned short { - - MyGravity_None = 0, /**默认值,不停靠、不填充、不对齐。*/ + /**默认值,不停靠、不填充、不对齐。*/ + MyGravity_None = 0, //水平方向 - MyGravity_Horz_Left = 1, /**左边停靠或者左对齐*/ - MyGravity_Horz_Center = 2, /**水平中心停靠或者水平居中对齐*/ - MyGravity_Horz_Right = 4, /**右边停靠或者右对齐*/ - MyGravity_Horz_Window_Center = 8, /**窗口水平中心停靠,表示在屏幕窗口的水平中心停靠*/ - MyGravity_Horz_Between = 16, /**水平间距拉伸*/ - MyGravity_Horz_Leading = 32, /**头部对齐,对于阿拉伯国家来说是和Right等价的,对于非阿拉伯国家则是和Left等价的*/ - MyGravity_Horz_Trailing = 64, /**尾部对齐,对于阿拉伯国家来说是和Left等价的,对于非阿拉伯国家则是和Right等价的*/ - MyGravity_Horz_Fill = MyGravity_Horz_Left | MyGravity_Horz_Center | MyGravity_Horz_Right, /**水平宽度填充*/ - MyGravity_Horz_Mask = 0xFF00, /**水平掩码,用来获取水平方向的枚举值*/ + /**左边停靠或者左对齐*/ + MyGravity_Horz_Left = 1, + /**水平中心停靠或者水平居中对齐*/ + MyGravity_Horz_Center = 2, + /**右边停靠或者右对齐*/ + MyGravity_Horz_Right = 4, + /**窗口水平中心停靠,表示在屏幕窗口的水平中心停靠*/ + MyGravity_Horz_Window_Center = 8, + /**水平间距拉伸*/ + MyGravity_Horz_Between = 16, + /**头部对齐,对于阿拉伯国家来说是和Right等价的,对于非阿拉伯国家则是和Left等价的*/ + MyGravity_Horz_Leading = 32, + /**尾部对齐,对于阿拉伯国家来说是和Left等价的,对于非阿拉伯国家则是和Right等价的*/ + MyGravity_Horz_Trailing = 64, + /**水平宽度填充*/ + MyGravity_Horz_Fill = MyGravity_Horz_Left | MyGravity_Horz_Center | MyGravity_Horz_Right, + /**水平掩码,用来获取水平方向的枚举值*/ + MyGravity_Horz_Mask = 0xFF00, //垂直方向 - MyGravity_Vert_Top = 1 << 8, /**上边停靠或者上对齐*/ - MyGravity_Vert_Center = 2 << 8, /**垂直中心停靠或者垂直居中对齐*/ - MyGravity_Vert_Bottom = 4 << 8, /**下边停靠或者下边对齐*/ - MyGravity_Vert_Window_Center = 8 << 8, /**窗口垂直中心停靠,表示在屏幕窗口的垂直中心停靠*/ - MyGravity_Vert_Between = 16 << 8, /**垂直间距拉伸*/ - MyGravity_Vert_Baseline = 32 << 8, /**基线对齐,只支持水平线性布局,指定基线对齐必须要指定出一个基线标准的子视图*/ - MyGravity_Vert_Fill = MyGravity_Vert_Top | MyGravity_Vert_Center | MyGravity_Vert_Bottom, /**垂直高度填充*/ - MyGravity_Vert_Mask = 0x00FF, /**垂直掩码,用来获取垂直方向的枚举值*/ - - - MyGravity_Center = MyGravity_Horz_Center | MyGravity_Vert_Center, /**整体居中*/ - - - MyGravity_Fill = MyGravity_Horz_Fill | MyGravity_Vert_Fill, /**全部填充*/ - - - MyGravity_Between = MyGravity_Horz_Between | MyGravity_Vert_Between, /**全部拉伸*/ - - - //为了更正确的统一命名规范以及和TangramKit保持一致,下列属性定义设置为过期!!。您在更新版本后只需要统一将MyMarginGravity替换为MyGravity 即可 - MyMarginGravity_None MYMETHODDEPRECATED("use MyGravity_None to instead") = MyGravity_None, - MyMarginGravity_Horz_Left MYMETHODDEPRECATED("use MyGravity_Horz_Left to instead") = MyGravity_Horz_Left, - MyMarginGravity_Horz_Center MYMETHODDEPRECATED("use MyGravity_Horz_Center to instead") = MyGravity_Horz_Center, - MyMarginGravity_Horz_Right MYMETHODDEPRECATED("use MyGravity_Horz_Right to instead") = MyGravity_Horz_Right, - MyMarginGravity_Horz_Window_Center MYMETHODDEPRECATED("use MyGravity_Horz_Window_Center to instead") = MyGravity_Horz_Window_Center, - MyMarginGravity_Horz_Between MYMETHODDEPRECATED("use MyGravity_Horz_Between to instead") = MyGravity_Horz_Between, - MyMarginGravity_Horz_Fill MYMETHODDEPRECATED("use MyGravity_Horz_Fill to instead") = MyGravity_Horz_Fill, - MyMarginGravity_Horz_Mask MYMETHODDEPRECATED("use MyGravity_Horz_Mask to instead") = MyGravity_Horz_Mask, - MyMarginGravity_Vert_Top MYMETHODDEPRECATED("use MyGravity_Vert_Top to instead") = MyGravity_Vert_Top, - MyMarginGravity_Vert_Center MYMETHODDEPRECATED("use MyGravity_Vert_Center to instead") = MyGravity_Vert_Center, - MyMarginGravity_Vert_Bottom MYMETHODDEPRECATED("use MyGravity_Vert_Bottom to instead") = MyGravity_Vert_Bottom, - MyMarginGravity_Vert_Window_Center MYMETHODDEPRECATED("use MyGravity_Vert_Window_Center to instead") = MyGravity_Vert_Window_Center, - MyMarginGravity_Vert_Between MYMETHODDEPRECATED("use MyGravity_Vert_Between to instead") = MyGravity_Vert_Between, - MyMarginGravity_Vert_Fill MYMETHODDEPRECATED("use MyGravity_Vert_Fill to instead") = MyGravity_Vert_Fill, - MyMarginGravity_Vert_Mask MYMETHODDEPRECATED("use MyGravity_Vert_Mask to instead") = MyGravity_Vert_Mask, - MyMarginGravity_Center MYMETHODDEPRECATED("use MyGravity_Center to instead") = MyGravity_Center, - MyMarginGravity_Fill MYMETHODDEPRECATED("use MyGravity_Fill to instead") = MyGravity_Fill, - MyMarginGravity_Between MYMETHODDEPRECATED("use MyGravity_Between to instead") = MyGravity_Between + /**上边停靠或者上对齐*/ + MyGravity_Vert_Top = 1 << 8, + /**垂直中心停靠或者垂直居中对齐*/ + MyGravity_Vert_Center = 2 << 8, + /**下边停靠或者下边对齐*/ + MyGravity_Vert_Bottom = 4 << 8, + /**窗口垂直中心停靠,表示在屏幕窗口的垂直中心停靠*/ + MyGravity_Vert_Window_Center = 8 << 8, + /**垂直间距拉伸*/ + MyGravity_Vert_Between = 16 << 8, + /**基线对齐,只支持水平线性布局,指定基线对齐必须要指定出一个基线标准的子视图*/ + MyGravity_Vert_Baseline = 32 << 8, + /**垂直高度填充*/ + MyGravity_Vert_Fill = MyGravity_Vert_Top | MyGravity_Vert_Center | MyGravity_Vert_Bottom, + /**垂直掩码,用来获取垂直方向的枚举值*/ + MyGravity_Vert_Mask = 0x00FF, + + /**整体居中*/ + MyGravity_Center = MyGravity_Horz_Center | MyGravity_Vert_Center, + + /**全部填充*/ + MyGravity_Fill = MyGravity_Horz_Fill | MyGravity_Vert_Fill, + + /**全部拉伸*/ + MyGravity_Between = MyGravity_Horz_Between | MyGravity_Vert_Between, } MyGravity; -//为了兼容老版本出现告警而定义。 -typedef MyGravity MyMarginGravity MYMETHODDEPRECATED("use MyGravity to instead"); - /** *设置当将布局视图嵌入到UIScrollView以及其派生类时对UIScrollView的contentSize的调整设置模式的枚举类型定义。 @@ -136,34 +125,37 @@ typedef MyGravity MyMarginGravity MYMETHODDEPRECATED("use MyGravity to instead") */ typedef enum :unsigned char { - MyAdjustScrollViewContentSizeModeAuto = 0, /**自动调整,在添加到UIScrollView之前(UITableView, UICollectionView除外)。如果值被设置Auto则在添加到父视图后自动会变为YES。*/ - MyAdjustScrollViewContentSizeModeNo = 1, /**不调整,任何加入到UIScrollView中的布局视图在尺寸变化时都不会调整和设置contentSize的值。*/ - MyAdjustScrollViewContentSizeModeYes = 2, /**会调整,任何加入到UIScrollView中的布局视图在尺寸变化时都会调整和设置contentSize的值。*/ - - - //下面为兼容老版本而定义,请使用新属性 - MyLayoutAdjustScrollViewContentSizeModeAuto MYMETHODDEPRECATED("use MyAdjustScrollViewContentSizeModeAuto to instead") = MyAdjustScrollViewContentSizeModeAuto, - MyLayoutAdjustScrollViewContentSizeModeNo MYMETHODDEPRECATED("use MyAdjustScrollViewContentSizeModeNo to instead") = MyAdjustScrollViewContentSizeModeNo, - MyLayoutAdjustScrollViewContentSizeModeYes MYMETHODDEPRECATED("use MyAdjustScrollViewContentSizeModeYes to instead") = MyAdjustScrollViewContentSizeModeYes, + /**自动调整,在添加到UIScrollView之前(UITableView, UICollectionView除外)。如果值被设置Auto则在添加到父视图后自动会变为YES。*/ + MyAdjustScrollViewContentSizeModeAuto = 0, + /**不调整,任何加入到UIScrollView中的布局视图在尺寸变化时都不会调整和设置contentSize的值。*/ + MyAdjustScrollViewContentSizeModeNo = 1, + /**会调整,任何加入到UIScrollView中的布局视图在尺寸变化时都会调整和设置contentSize的值。*/ + MyAdjustScrollViewContentSizeModeYes = 2, }MyAdjustScrollViewContentSizeMode; -//为兼容老版本而定义 -typedef MyAdjustScrollViewContentSizeMode MyLayoutAdjustScrollViewContentSizeMode MYMETHODDEPRECATED("use MyAdjustScrollViewContentSizeMode to instead"); /** *用来设置当线性布局中的子视图的尺寸大于线性布局的尺寸时的子视图的压缩策略和压缩内容枚举类型定义。请参考线性布局的shrinkType属性的定义。 */ typedef enum : NSUInteger { - MySubviewsShrink_None = 0, /**不压缩。*/ - MySubviewsShrink_Average = 1, /**平均压缩。*/ - MySubviewsShrink_Weight = 2, /**比例压缩。*/ - MySubviewsShrink_Auto = 4, /**自动压缩。这个属性只有在水平线性布局里面并且只有2个子视图的宽度等于自身时才有用。这个属性主要用来实现左右两个子视图根据自身内容来进行缩放,以便实现最佳的宽度空间利用。*/ + /**不压缩。*/ + MySubviewsShrink_None = 0, + /**平均压缩。*/ + MySubviewsShrink_Average = 1, + /**比例压缩。*/ + MySubviewsShrink_Weight = 2, + /**自动压缩。这个属性只有在水平线性布局里面并且只有2个子视图的宽度等于自身时才有用。这个属性主要用来实现左右两个子视图根据自身内容来进行缩放,以便实现最佳的宽度空间利用。*/ + MySubviewsShrink_Auto = 4, //上面部分是压缩的策略,下面部分指定压缩的内容,因此一个shrinkType的指定时上面部分和下面部分的 | 操作。比如让间距平均压缩:MySubviewsShrink_Average | MySubviewsShrink_Space - MySubviewsShrink_Size = 0 << 4, /**只压缩尺寸,因为这里是0所以这部分可以不设置,为默认。*/ - MySubviewsShrink_Space = 1 << 4, /**只压缩间距。*/ - MySubviewsShrink_SizeAndSpace = 2 << 4 /**压缩尺寸和间距。暂时不支持!!!*/ + + /**只压缩尺寸,因为这里是0所以这部分可以不设置,为默认。*/ + MySubviewsShrink_Size = 0 << 4, + /**只压缩间距。*/ + MySubviewsShrink_Space = 1 << 4, + /**压缩尺寸和间距。暂时不支持!!!*/ + MySubviewsShrink_SizeAndSpace = 2 << 4 } MySubviewsShrinkType; diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index 693c116..c2f2728 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -148,12 +148,8 @@ @property(nonatomic, strong,readonly) MyLayoutPos *baselinePosInner; -#if UIKIT_DEFINE_AS_PROPERTIES @property(class, nonatomic, assign) BOOL isRTL; -#else -+(BOOL)isRTL; -+(void)setIsRTL:(BOOL)isRTL; -#endif + @end diff --git a/MyLayout/Lib/MyLayoutMath.m b/MyLayout/Lib/MyLayoutMath.m index fd2b501..c724861 100644 --- a/MyLayout/Lib/MyLayoutMath.m +++ b/MyLayout/Lib/MyLayoutMath.m @@ -112,8 +112,7 @@ CGFloat _myCGFloatRound(CGFloat f) if (scale == 0) scale = [UIScreen mainScreen].scale; - //因为设备点转化为像素时,如果偏移了半个像素点就有可能会产生虚化的效果,因此这里要加上1/4个点的偏移来防止这种虚化现象的产生。 - // floor((f + 0.5 / scale )* scale) 的目的是将设备逻辑点转化为有效的像素。再除以倍数则是转化为有效的设备逻辑点。 + //因为设备点转化为像素时,如果偏移了半个像素点就有可能会产生虚化的效果,因此这里要将设备点先转化为像素点,然后再添加0.5个偏移取整后再除以倍数则是转化为有效的设备逻辑点。 #if CGFLOAT_IS_DOUBLE == 1 if (f < 0) return ceil(fma(f, scale, -0.5)) / scale; diff --git a/MyLayout/Lib/MyLayoutPos.h b/MyLayout/Lib/MyLayoutPos.h index 133ca26..7bdf5c3 100644 --- a/MyLayout/Lib/MyLayoutPos.h +++ b/MyLayout/Lib/MyLayoutPos.h @@ -75,8 +75,6 @@ */ @interface MyLayoutPos : NSObject -#if UIKIT_DEFINE_AS_PROPERTIES - /** 特殊的位置。只用在布局视图和非布局父视图之间的位置约束和没有导航条时的布局视图内子视图的padding设置上。 iOS11以后提出了安全区域的概念,因此对于iOS11以下的版本就需要兼容处理,尤其是在那些没有导航条的情况下。通过将布局视图的边距设置为这个特殊值就可以实现在任何版本中都能完美的实现位置的偏移而且各版本保持统一。比如下面的例子: @@ -113,10 +111,6 @@ */ @property(class, nonatomic, assign,readonly) CGFloat safeAreaMargin; -#else - -+(CGFloat)safeAreaMargin; -#endif //because masonry defined macro MAS_SHORTHAND_GLOBALS. the equalTo, offset may conflict with below method. so //if you used MyLayout and Masonry concurrently and you defined MAS_SHORTHAND_GLOBALS in masonry, then you can define MY_USEPREFIXMETHOD to solve the conflict. diff --git a/MyLayout/Lib/MyLayoutPos.m b/MyLayout/Lib/MyLayoutPos.m index 9f21eef..ff615a3 100644 --- a/MyLayout/Lib/MyLayoutPos.m +++ b/MyLayout/Lib/MyLayoutPos.m @@ -230,7 +230,7 @@ -(id)copyWithZone:(NSZone *)zone } -#pragma mark -- Private Method +#pragma mark -- Private Methods -(NSNumber*)posNumVal diff --git a/MyLayout/Lib/MyLayoutSize.h b/MyLayout/Lib/MyLayoutSize.h index ce13987..590d0d5 100644 --- a/MyLayout/Lib/MyLayoutSize.h +++ b/MyLayout/Lib/MyLayoutSize.h @@ -24,7 +24,6 @@ */ @interface MyLayoutSize : NSObject -#if UIKIT_DEFINE_AS_PROPERTIES /**特殊的尺寸,表示尺寸由子视图决定或者由内容决定。目前只用在表格布局MyTableLayout和栅格布局MyGridLayout中。*/ @property(class, nonatomic, assign,readonly) CGFloat wrap; @@ -33,13 +32,6 @@ /**特殊的尺寸,表示尺寸会均分父视图的剩余空间。目前只用在表格布局MyTableLayout */ @property(class, nonatomic, assign,readonly) CGFloat average; -#else - -+(CGFloat)wrap; -+(CGFloat)fill; -+(CGFloat)average; - -#endif //because masonry defined macro MAS_SHORTHAND_GLOBALS. the equalTo, offset may conflict with below method. so //if you used MyLayout and Masonry concurrently and you defined MAS_SHORTHAND_GLOBALS in masonry, then you can define MY_USEPREFIXMETHOD to solve the conflict. diff --git a/MyLayout/Lib/MyLayoutSize.m b/MyLayout/Lib/MyLayoutSize.m index 3189c57..47aebec 100644 --- a/MyLayout/Lib/MyLayoutSize.m +++ b/MyLayout/Lib/MyLayoutSize.m @@ -261,7 +261,7 @@ -(id)copyWithZone:(NSZone *)zone return self; } -#pragma mark -- Private Method +#pragma mark -- Private Methods -(NSNumber*)dimeNumVal @@ -546,7 +546,7 @@ +(NSString*)dimestrFromDime:(MyLayoutSize*)dimeobj showView:(BOOL)showView } -#pragma mark -- Override Method +#pragma mark -- Override Methods -(NSString*)description { diff --git a/MyLayout/Lib/MyLinearLayout.h b/MyLayout/Lib/MyLinearLayout.h index acf4db1..9ca73f5 100644 --- a/MyLayout/Lib/MyLinearLayout.h +++ b/MyLayout/Lib/MyLinearLayout.h @@ -195,21 +195,4 @@ @end -@interface MyLinearLayout(MyLinearLayoutDeprecated) - -/** - * 过期的方法,这些过期的方法名取名不规范,因此为了和TangramKit统一,这里将这些不规范的方法设置为过期。 - */ --(void)averageSubviews:(BOOL)centered MYMETHODDEPRECATED("use ’equalizeSubviews:(BOOL)centered‘ to instead"); --(void)averageSubviews:(BOOL)centered inSizeClass:(MySizeClass)sizeClass MYMETHODDEPRECATED("use ‘equalizeSubviews:(BOOL)centered inSizeClass:(MySizeClass)sizeClass’ to instead"); - --(void)averageSubviews:(BOOL)centered withMargin:(CGFloat)margin MYMETHODDEPRECATED("use ‘equalizeSubviews:(BOOL)centered withSpace:(CGFloat)space’ to instead"); --(void)averageSubviews:(BOOL)centered withMargin:(CGFloat)margin inSizeClass:(MySizeClass)sizeClass MYMETHODDEPRECATED("use ‘equalizeSubviews:(BOOL)centered withSpace:(CGFloat)space inSizeClass:(MySizeClass)sizeClass’ to instead"); - --(void)averageMargin:(BOOL)centered MYMETHODDEPRECATED("use ‘equalizeSubviewsSpace:(BOOL)centered’ to instead"); --(void)averageMargin:(BOOL)centered inSizeClass:(MySizeClass)sizeClass MYMETHODDEPRECATED("use ‘equalizeSubviewsSpace:(BOOL)centered inSizeClass:(MySizeClass)sizeClass’ to instead"); - - -@end - diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 3f96915..9577ee0 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -11,6 +11,8 @@ @implementation MyLinearLayout +#pragma mark -- Public Methods + -(instancetype)initWithFrame:(CGRect)frame orientation:(MyOrientation)orientation { self = [super initWithFrame:frame]; @@ -138,43 +140,7 @@ -(void)equalizeSubviewsSpace:(BOOL)centered inSizeClass:(MySizeClass)sizeClass } -#pragma mark -- Deprecated Method - --(void)averageSubviews:(BOOL)centered -{ - [self equalizeSubviews:centered]; -} - --(void)averageSubviews:(BOOL)centered inSizeClass:(MySizeClass)sizeClass -{ - [self equalizeSubviews:centered inSizeClass:sizeClass]; -} - - --(void)averageSubviews:(BOOL)centered withMargin:(CGFloat)margin -{ - [self equalizeSubviews:centered withSpace:margin]; -} - --(void)averageSubviews:(BOOL)centered withMargin:(CGFloat)margin inSizeClass:(MySizeClass)sizeClass -{ - [self equalizeSubviews:centered withSpace:margin inSizeClass:sizeClass]; -} - - - --(void)averageMargin:(BOOL)centered -{ - [self equalizeSubviewsSpace:centered]; -} - --(void)averageMargin:(BOOL)centered inSizeClass:(MySizeClass)sizeClass -{ - [self equalizeSubviewsSpace:centered inSizeClass:sizeClass]; -} - - -#pragma mark -- Override Method +#pragma mark -- Override Methods - (void)willMoveToSuperview:(UIView*)newSuperview { @@ -295,7 +261,7 @@ -(id)createSizeClassInstance } -#pragma mark -- Private Method +#pragma mark -- Private Methods //调整子视图的wrapContent设置 - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation:(MyOrientation)orientation gravity:(MyGravity)gravity diff --git a/MyLayout/Lib/MyPathLayout.m b/MyLayout/Lib/MyPathLayout.m index 57963a2..6916d0e 100644 --- a/MyLayout/Lib/MyPathLayout.m +++ b/MyLayout/Lib/MyPathLayout.m @@ -140,11 +140,13 @@ @interface MyPathLayout() @implementation MyPathLayout { - MyCoordinateSetting *_coordinateSetting; BOOL _hasOriginView; + MyCoordinateSetting *_coordinateSetting; MyPathSpace *_spaceType; } +#pragma mark -- Public Methods + /* +(Class)layerClass { @@ -402,7 +404,7 @@ -(CGPathRef)createPath:(NSInteger)subviewCount } -#pragma mark -- Override Method +#pragma mark -- Override Methods - (void)insertSubview:(UIView *)view atIndex:(NSInteger)index { @@ -807,7 +809,7 @@ -(id)createSizeClassInstance -#pragma mark -- Private Method +#pragma mark -- Private Methods -(CGFloat)myCalcDistance:(CGPoint)pt1 with:(CGPoint)pt2 diff --git a/MyLayout/Lib/MyRelativeLayout.h b/MyLayout/Lib/MyRelativeLayout.h index 5457a82..7122321 100644 --- a/MyLayout/Lib/MyRelativeLayout.h +++ b/MyLayout/Lib/MyRelativeLayout.h @@ -17,17 +17,4 @@ */ @interface MyRelativeLayout : MyBaseLayout - -/** - *这个属性已经无效了,请使用子视图自身的扩展属性myVisibility属性来进行子视图的隐藏和显示的定制化处理。 - */ -@property(nonatomic, assign) BOOL flexOtherViewWidthWhenSubviewHidden MYMETHODDEPRECATED("this property was invalid, please use subview's myVisibility to instead"); - -/** - *这个属性已经无效了,请使用子视图自身的扩展属性myVisibility属性来进行子视图的隐藏和显示的定制化处理。 - */ -@property(nonatomic, assign) BOOL flexOtherViewHeightWhenSubviewHidden MYMETHODDEPRECATED("this property was invalid, please use subview's myVisibility to instead"); -; - - @end diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 47032dd..4507a92 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -12,36 +12,8 @@ @implementation MyRelativeLayout -/* - // Only override drawRect: if you perform custom drawing. - // An empty implementation adversely affects performance during animation. - - (void)drawRect:(CGRect)rect { - // Drawing code - } - */ - --(void)setFlexOtherViewWidthWhenSubviewHidden:(BOOL)flexOtherViewWidthWhenSubviewHidden -{ - NSAssert(0, @"oops!, flexOtherViewWidthWhenSubviewHidden is invalid please use subview's myVisibility to instead!!!"); -} - --(BOOL)flexOtherViewWidthWhenSubviewHidden -{ - return NO; -} - --(void)setFlexOtherViewHeightWhenSubviewHidden:(BOOL)flexOtherViewHeightWhenSubviewHidden -{ - NSAssert(0, @"oops!, flexOtherViewHeightWhenSubviewHidden is invalid please use subview's myVisibility to instead!!!"); -} - --(BOOL)flexOtherViewHeightWhenSubviewHidden -{ - return NO; -} - -#pragma mark -- Override Method +#pragma mark -- Override Methods -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { diff --git a/MyLayout/Lib/MyTableLayout.h b/MyLayout/Lib/MyTableLayout.h index 1b743af..8a73cc6 100644 --- a/MyLayout/Lib/MyTableLayout.h +++ b/MyLayout/Lib/MyTableLayout.h @@ -8,12 +8,6 @@ #import "MyLinearLayout.h" -//定义特殊的行列尺寸。主要用于表格布局中。请不要再使用如下的宏,而是改用MyLayoutSize中对应的类属性来代替。 -#define MTLSIZE_AVERAGE MyLayoutSize.average -#define MTLSIZE_WRAPCONTENT MyLayoutSize.wrap -#define MTLSIZE_MATCHPARENT MyLayoutSize.fill - - /** 表格布局行列索引描述扩展对象。 @@ -102,7 +96,7 @@ /** - * 删除一行 + *删除一行 */ -(void)removeRowAt:(NSInteger)rowIndex; @@ -170,15 +164,4 @@ @end -@interface MyTableLayout(MyTableDeprecated) - - -/** - * 不再单独设置表格的行间距和列间距了,而是复用视图的水平间距和垂直间距。原来表格的行间距和列间距会根据不同的表格方向定义不同而不同,现在统一为水平和垂直间距,不管表格的方向如何,水平间距都是定义左右的间距,垂直间距都是定义上下的间距。 - */ -@property(nonatomic ,assign, getter=subviewVSpace, setter=setSubviewVSpace:) CGFloat rowSpacing MYMETHODDEPRECATED("use subviewVSpace to instead"); -@property(nonatomic, assign, getter=subviewHSpace, setter=setSubviewHSpace:) CGFloat colSpacing MYMETHODDEPRECATED("use subviewHSpace to instead"); - - -@end diff --git a/MyLayout/Lib/MyTableLayout.m b/MyLayout/Lib/MyTableLayout.m index ee6d7fa..6b4c6bc 100644 --- a/MyLayout/Lib/MyTableLayout.m +++ b/MyLayout/Lib/MyTableLayout.m @@ -104,6 +104,8 @@ -(NSInteger)col @implementation MyTableLayout +#pragma mark -- Public Methods + +(instancetype)tableLayoutWithOrientation:(MyOrientation)orientation { return [self linearLayoutWithOrientation:orientation]; @@ -282,8 +284,7 @@ -(NSUInteger)countOfColInRow:(NSInteger)rowIndex return [self viewAtRowIndex:rowIndex].subviews.count; } -#pragma mark -- Override Method - +#pragma mark -- Override Methods -(void)setSubviewVSpace:(CGFloat)subviewVSpace @@ -343,7 +344,5 @@ -(id)createSizeClassInstance return [MyTableLayoutViewSizeClass new]; } -#pragma mark -- Deprecated Method - @end diff --git a/MyLayoutDemo/DetailViewController.m b/MyLayoutDemo/DetailViewController.m index a579096..96a5009 100644 --- a/MyLayoutDemo/DetailViewController.m +++ b/MyLayoutDemo/DetailViewController.m @@ -84,6 +84,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N #pragma mark -- UITableViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; UIViewController *demoVC = [[self.demoVCList[indexPath.row][@"class"] alloc] init]; diff --git a/MyLayoutDemo/FOLTest7ViewController.h b/MyLayoutDemo/FOLTest7ViewController.h new file mode 100644 index 0000000..a235526 --- /dev/null +++ b/MyLayoutDemo/FOLTest7ViewController.h @@ -0,0 +1,16 @@ +// +// FOLTest7ViewController.h +// MyLayout +// +// Created by oybq on 16/2/19. +// Copyright © 2016年 YoungSoft. All rights reserved. +// + +#import + +/** + *7.FloatLayout - Alignment + */ +@interface FOLTest7ViewController : UIViewController + +@end diff --git a/MyLayoutDemo/FOLTest7ViewController.m b/MyLayoutDemo/FOLTest7ViewController.m new file mode 100644 index 0000000..9543405 --- /dev/null +++ b/MyLayoutDemo/FOLTest7ViewController.m @@ -0,0 +1,273 @@ +// +// FOLTest7ViewController.m +// MyLayout +// +// Created by oybq on 16/2/19. +// Copyright © 2016年 YoungSoft. All rights reserved. +// + +#import "FOLTest7ViewController.h" +#import "MyLayout.h" +#import "CFTool.h" + +@interface FOLTest7ViewController () + +@end + +@implementation FOLTest7ViewController + + +-(void)loadView +{ + /* + 这个例子主要给大家演示,在浮动布局中也可以支持一行(列)内的子视图的对齐方式的设置了。我们可以借助子视图的myAlignment属性来设置其在浮动布局行(列)内的对齐方式。 + 这里的对齐的标准都是以当前行(列)内最高(宽)的子视图为参考来进行(列)对齐的。 + + 在垂直浮动布局里面的子视图的行内对齐只能设置MyGravity_Vert_Top, MyGravity_Vert_Center, MyGravity_Vert_Bottom, MyGravity_Vert_Fill这几种对齐方式。 + 在水平浮动布局里面的子视图的列内对齐只能设置MyGravity_Horz_Left, MyGravity_Horz_Center, MyGravity_Horz_Right, MyGravity_Horz_Fill这几种对齐方式。 + + */ + + self.edgesForExtendedLayout = UIRectEdgeNone; + + MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + rootLayout.backgroundColor = [UIColor lightGrayColor]; + rootLayout.gravity = MyGravity_Horz_Fill; //所有子视图的宽度都和自己相等。 + rootLayout.subviewVSpace = 10; + self.view = rootLayout; + + MyFloatLayout *vertLayout = [self createVertFloatLayout:rootLayout]; + vertLayout.backgroundColor = [UIColor whiteColor]; + vertLayout.weight = 0.8; //高度占用80% + [rootLayout addSubview:vertLayout]; + + MyFloatLayout *horzLayout = [self createHorzFloatLayout:rootLayout]; + horzLayout.backgroundColor = [UIColor whiteColor]; + horzLayout.weight = 0.2; //高度占用20% + [rootLayout addSubview:horzLayout]; + +} + + +- (void)viewDidLoad { + + [super viewDidLoad]; + + +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +#pragma mark -- Layout Construction + +-(MyFloatLayout*)createVertFloatLayout:(MyLinearLayout*)rootLayout +{ + MyFloatLayout *floatLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; + + UIImageView *logoImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"p1-12"]]; + logoImageView.layer.borderColor = [CFTool color:4].CGColor; + logoImageView.layer.borderWidth = 1; + logoImageView.myAlignment = MyGravity_Vert_Center; //在浮动的一行内垂直居中对齐。 + logoImageView.myMargin = 10; //四周的边距都设置为10. + logoImageView.mySize = CGSizeMake(80, 36); + [floatLayout addSubview:logoImageView]; + + UILabel *brandLabel = [UILabel new]; + brandLabel.text = @"千奈美官方旗舰店"; + [brandLabel sizeToFit]; + brandLabel.myAlignment = MyGravity_Vert_Center; //在浮动的一行内垂直居中对齐。 + brandLabel.myVertMargin = 10; + [floatLayout addSubview:brandLabel]; + + UIButton *attentionButton = [UIButton buttonWithType:UIButtonTypeSystem]; + [attentionButton setTitle:@"关注" forState:UIControlStateNormal]; + [attentionButton sizeToFit]; + attentionButton.reverseFloat = YES; //关注放在右边,所以浮动到右边。 + attentionButton.myMargin = 10; + attentionButton.myAlignment = MyGravity_Vert_Center; //在浮动的一行内垂直居中对齐。 + [floatLayout addSubview:attentionButton]; + + //单独一行。 + UIView *line1 = [UIView new]; + line1.backgroundColor = [CFTool color:5]; + line1.myHeight = 2; + line1.widthSize.equalTo(floatLayout.widthSize); //宽度和父视图一样宽。 + [floatLayout addSubview:line1]; + + + UIImageView *showImageView1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"image2"]]; + showImageView1.myMargin = 10; //四周边距是10 + showImageView1.weight = 0.6; //此时父布局的剩余宽度是屏幕,因此这里的宽度就是屏幕宽度的0.6 + showImageView1.heightSize.equalTo(showImageView1.widthSize); //高度等于宽度。 + [floatLayout addSubview:showImageView1]; + + + //绘制线 + UIView *line2 = [UIView new]; + line2.backgroundColor = [CFTool color:5]; + line2.myWidth = 2; + line2.heightSize.equalTo(showImageView1.heightSize).add(22); //高度和showImageView1高度相等,因为showImageView1还有上下分别为10的边距,还有中间横线的高度2,所以这里要增加22的高度。 + [floatLayout addSubview:line2]; + + + //右边上面的小图。 + UIImageView *showImageView2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"image3"]]; + showImageView2.myMargin = 10; //四周边距是10 + showImageView2.weight = 1.0; //注意这里是剩余宽度的比重,因为这个小图要占用全部的剩余空间,因此这里设置为1。 + showImageView2.heightSize.equalTo(showImageView1.heightSize).multiply(0.5).add(-10); //高度等于大图高度的一半,再减去多余的边距10 + [floatLayout addSubview:showImageView2]; + + + //中间横线。 + UIView *line3 = [UIView new]; + line3.backgroundColor = [CFTool color:5]; + line3.myHeight = 2; + line3.weight = 1.0; + [floatLayout addSubview:line3]; + + //右边下面的小图 + UIImageView *showImageView3 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"image4"]]; + showImageView3.myMargin = 10; + showImageView3.weight = 1.0; + showImageView3.heightSize.equalTo(showImageView1.heightSize).multiply(0.5).add(-10); + [floatLayout addSubview:showImageView3]; + + //绘制下面的横线。 + UIView *line4 = [UIView new]; + line4.backgroundColor = [CFTool color:5]; + line4.myHeight = 2; + line4.weight = 1.0; //因为前面的所有内容都占满一行了,所以这条线是单独一行,这里是占用屏幕的全部空间了。 + line4.myBottom = 10; + [floatLayout addSubview:line4]; + + + UILabel *signatureLabel = [UILabel new]; + signatureLabel.text = @"今日已有137人签到获得好礼"; + signatureLabel.font = [CFTool font:14]; + signatureLabel.textColor = [CFTool color:4]; + [signatureLabel sizeToFit]; + signatureLabel.myHorzMargin = 10; + signatureLabel.myAlignment = MyGravity_Vert_Center; + [floatLayout addSubview:signatureLabel]; + + UIImageView *moreImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"next"]]; + moreImageView.reverseFloat = YES; + moreImageView.myHorzMargin = 10; + moreImageView.myAlignment = MyGravity_Vert_Center; + [floatLayout addSubview:moreImageView]; + + + UILabel *moreLabel = [UILabel new]; + moreLabel.text = @"进店看看"; + [moreLabel sizeToFit]; + moreLabel.reverseFloat = YES; + moreLabel.myAlignment = MyGravity_Vert_Center; + [floatLayout addSubview:moreLabel]; + + + UIView *line5 = [UIView new]; + line5.backgroundColor = [CFTool color:5]; + line5.myHeight = 2; + line5.myVertMargin = 10; + line5.widthSize.equalTo(floatLayout.widthSize); + [floatLayout addSubview:line5]; + + + // + UIImageView *commentImageView1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"minions4"]]; + commentImageView1.myAlignment = MyGravity_Vert_Fill; //这里使用填充对齐,表明会和这行里面高度最高的那个子视图的高度保持一致。 + commentImageView1.myLeft = 10; + [floatLayout addSubview:commentImageView1]; + + UIImageView *commentImageView2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"minions3"]]; + commentImageView2.myAlignment = MyGravity_Vert_Fill; //这里使用填充对齐,表明会和这行里面高度最高的那个子视图的高度保持一致。 + commentImageView2.myLeft = 10; + [floatLayout addSubview:commentImageView2]; + + UIImageView *commentImageView3 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"minions3"]]; + commentImageView3.myLeft = 10; + [floatLayout addSubview:commentImageView3]; + + + for (int i = 0; i < 4; i++) + { + UIImageView *starImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"section2"]]; + starImageView.mySize = CGSizeMake(20, 20); + starImageView.myAlignment = MyGravity_Vert_Bottom; //这里底部对齐,表明子视图和一行内最高的子视图保持底部对齐。 + starImageView.myLeft = 5; + [floatLayout addSubview:starImageView]; + } + + + UIView *line6 = [UIView new]; + line6.backgroundColor = [CFTool color:5]; + line6.myHeight = 2; + line6.widthSize.equalTo(floatLayout.widthSize); + [floatLayout addSubview:line6]; + + + + + return floatLayout; + +} + +-(MyFloatLayout*)createHorzFloatLayout:(MyLinearLayout*)rootLayout +{ + MyFloatLayout *floatLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Horz]; + floatLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); + floatLayout.subviewSpace = 10; + + NSArray *names = @[@"minions1",@"minions3",@"minions2",@"minions4",@"p4-23",@"p4-11"]; + for (int i = 0; i < 6; i++) + { + UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:names[i]]]; + imageView.layer.borderWidth = 0.5; + imageView.layer.borderColor = [CFTool color:6].CGColor; + imageView.heightSize.equalTo(floatLayout.heightSize).multiply(0.5).add(-5); //高度等于父视图的高度的一半,因为设置了每个子视图的间距为10,所以这里要减去5。 + if (i % 2 == 0) + {//这句话的意思一列显示两个子视图,所以当索引下标为偶数时就是换列处理。 + imageView.clearFloat = YES; + } + + //水平填充,每列两个子视图,每列的对齐方式都不一样。 + switch (i) { + case 0: + case 1: + imageView.myAlignment = MyGravity_Horz_Center; + break; + case 2: + case 3: + imageView.myAlignment = MyGravity_Horz_Right; + break; + case 4: + case 5: + imageView.myAlignment = MyGravity_Horz_Fill; + default: + break; + } + + [floatLayout addSubview:imageView]; + + } + + + return floatLayout; + + +} + +@end diff --git a/MyLayoutDemo/Info.plist b/MyLayoutDemo/Info.plist index 141a517..0ef0d7f 100644 --- a/MyLayoutDemo/Info.plist +++ b/MyLayoutDemo/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.5.0 + 1.5.1 CFBundleSignature ???? CFBundleVersion diff --git a/MyLayoutDemo/ViewController.m b/MyLayoutDemo/ViewController.m index d3bc3d3..b8b8b9b 100644 --- a/MyLayoutDemo/ViewController.m +++ b/MyLayoutDemo/ViewController.m @@ -58,6 +58,8 @@ #import "FOLTest4ViewController.h" #import "FOLTest5ViewController.h" #import "FOLTest6ViewController.h" +#import "FOLTest7ViewController.h" + #import "PLTest1ViewController.h" #import "PLTest2ViewController.h" @@ -198,6 +200,9 @@ -(NSArray*)demoTypeList }, @{@"title":NSLocalizedString(@"6.FloatLayout - User Profiles", @""), @"class":[FOLTest6ViewController class] + }, + @{@"title":NSLocalizedString(@"7.FloatLayout - Alignment", @""), + @"class":[FOLTest7ViewController class] } ] }, diff --git a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings index 15c45b3..d843836 100644 --- a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings +++ b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings @@ -38,6 +38,7 @@ "4.FloatLayout - Tag cloud" = "4.浮动布局-标签流"; "5.FloatLayout - Title & Description" = "5.浮动布局-左右排列的文本"; "6.FloatLayout - User Profiles"="6.浮动布局-各种用户配置的实现"; +"7.FloatLayout - Alignment"="7.浮动布局-行内对齐"; "1.PathLayout - Animations" = "1.路径布局-各种动画效果"; "2.PathLayout - Curves"="2.路径布局-各种函数曲线"; "3.PathLayout - Menu in Circle"="3.路径布局-圆环型菜单"; diff --git a/README.md b/README.md index dbd5df4..b9ec76f 100644 --- a/README.md +++ b/README.md @@ -614,7 +614,7 @@ To integrate MyLayout into your Xcode project using CocoaPods, specify it in you source 'https://github.com/CocoaPods/Specs.git' platform :ios, '7.0' -pod 'MyLayout', '~> 1.5.0' +pod 'MyLayout', '~> 1.5.1' ``` Then, run the following command: diff --git a/README.zh.md b/README.zh.md index 3f296e4..1a3bd7d 100644 --- a/README.zh.md +++ b/README.zh.md @@ -622,7 +622,7 @@ $ gem install cocoapods source 'https://github.com/CocoaPods/Specs.git' platform :ios, '7.0' -pod 'MyLayout', '~> 1.5.0' +pod 'MyLayout', '~> 1.5.1' ``` 然后运行如下命令: From 723def92b707fb955295f380cf5c38d7c5bac78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E6=9F=8F=E6=B3=89?= Date: Sun, 6 May 2018 11:57:55 +0800 Subject: [PATCH 009/115] Release V1.5.2 --- MyLayout.xcodeproj/project.pbxproj | 30 +++- MyLayout/Info.plist | 36 ++-- MyLayout/Lib/MyBaseLayout.h | 1 - MyLayout/Lib/MyBaseLayout.m | 36 ++-- MyLayout/Lib/MyFloatLayout.m | 1 - MyLayout/Lib/MyFlowLayout.m | 1 - MyLayout/Lib/MyLayout.h | 2 +- MyLayout/Lib/MyLayoutInner.h | 2 + MyLayout/Lib/MyLinearLayout.m | 1 - MyLayout/Lib/MyPathLayout.h | 6 +- MyLayout/Lib/MyPathLayout.m | 59 +++++-- MyLayout/Lib/MyRelativeLayout.m | 1 - MyLayout/Lib/MyTableLayout.h | 4 +- MyLayout/Lib/MyTableLayout.m | 33 +++- MyLayoutDemo/AllTest3ViewController.m | 1 - MyLayoutDemo/CFTool.m | 2 - MyLayoutDemo/Info.plist | 2 +- MyLayoutDemo/TLTest4ViewController.h | 16 ++ MyLayoutDemo/TLTest4ViewController.m | 158 ++++++++++++++++++ MyLayoutDemo/ViewController.m | 5 + .../zh-Hans.lproj/Localizable.strings | 1 + 21 files changed, 327 insertions(+), 71 deletions(-) create mode 100644 MyLayoutDemo/TLTest4ViewController.h create mode 100644 MyLayoutDemo/TLTest4ViewController.m diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index e193e1d..a7e9dc1 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -138,6 +138,7 @@ 18D684591C4F423400A48BB4 /* MyLayoutTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D684551C4F423400A48BB4 /* MyLayoutTests.m */; }; 200A26D91FA8A90300B06E7B /* AllTest9ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */; }; 200A26DC1FA96B2400B06E7B /* AllTest9CollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */; }; + 204DC321209D5A8700F6CB57 /* TLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */; }; 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */ = {isa = PBXBuildFile; fileRef = 205642841F4CFF9B00E8BDDE /* MyBorderline.h */; }; 205642871F4CFF9B00E8BDDE /* MyBorderline.m in Sources */ = {isa = PBXBuildFile; fileRef = 205642851F4CFF9B00E8BDDE /* MyBorderline.m */; }; 205642881F4CFFB600E8BDDE /* MyBorderline.m in Sources */ = {isa = PBXBuildFile; fileRef = 205642851F4CFF9B00E8BDDE /* MyBorderline.m */; }; @@ -366,6 +367,9 @@ 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest9ViewController.m; sourceTree = ""; }; 200A26DA1FA96B2400B06E7B /* AllTest9CollectionViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AllTest9CollectionViewCell.h; sourceTree = ""; }; 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest9CollectionViewCell.m; sourceTree = ""; }; + 2043D5DB20995DF800276C68 /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = System/Library/Frameworks/CoreBluetooth.framework; sourceTree = SDKROOT; }; + 204DC31F209D5A7C00F6CB57 /* TLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest4ViewController.h; sourceTree = ""; }; + 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLTest4ViewController.m; sourceTree = ""; }; 205642841F4CFF9B00E8BDDE /* MyBorderline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyBorderline.h; sourceTree = ""; }; 205642851F4CFF9B00E8BDDE /* MyBorderline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyBorderline.m; sourceTree = ""; }; 205642891F4D013D00E8BDDE /* MyGrid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyGrid.h; sourceTree = ""; }; @@ -436,6 +440,7 @@ 18D684531C4F423400A48BB4 /* MyLayoutTests */, 18B152321DEDDE5500AD7A1C /* MyLayoutUITests */, 1840828E1B2C46E8003F378B /* Products */, + 2043D5DA20995DF800276C68 /* Frameworks */, ); sourceTree = ""; }; @@ -605,6 +610,8 @@ 18D3C9631EDF080800D3DE43 /* TLTest2ViewController.m */, 18D3C9641EDF080800D3DE43 /* TLTest3ViewController.h */, 18D3C9651EDF080800D3DE43 /* TLTest3ViewController.m */, + 204DC31F209D5A7C00F6CB57 /* TLTest4ViewController.h */, + 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */, ); name = TableLayoutDemo; sourceTree = ""; @@ -787,6 +794,14 @@ path = MyLayoutTests; sourceTree = ""; }; + 2043D5DA20995DF800276C68 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2043D5DB20995DF800276C68 /* CoreBluetooth.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 205CFA8B1F49BCAF00355489 /* GridLayoutDemo */ = { isa = PBXGroup; children = ( @@ -919,6 +934,7 @@ TargetAttributes = { 181A10B41EDF12CF00996203 = { CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = BGQ8WB468K; ProvisioningStyle = Automatic; }; 1840828C1B2C46E8003F378B = { @@ -1118,6 +1134,7 @@ 182225CF1E77E5930081AA4B /* MyFloatLayout.m in Sources */, 18D3C92B1EDF07A700D3DE43 /* RLTest4ViewController.m in Sources */, 18D3C92C1EDF07A700D3DE43 /* RLTest5ViewController.m in Sources */, + 204DC321209D5A8700F6CB57 /* TLTest4ViewController.m in Sources */, 182DB6431EF7876200E2D65D /* MyGridLayout.m in Sources */, 18D3C9871EDF084000D3DE43 /* AllTest3ViewController.m in Sources */, 18D3C9161EDF074900D3DE43 /* LLTest6ViewController.m in Sources */, @@ -1231,9 +1248,11 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = BGQ8WB468K; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -1261,6 +1280,7 @@ CODE_SIGN_IDENTITY = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = BGQ8WB468K; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -1384,14 +1404,17 @@ CLANG_ENABLE_CODE_COVERAGE = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = BGQ8WB468K; GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.mylayout; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutDemo; PRODUCT_NAME = MyLayoutDemo; PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -1403,14 +1426,17 @@ CLANG_ENABLE_CODE_COVERAGE = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = BGQ8WB468K; GCC_PREPROCESSOR_DEFINITIONS = ""; INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.mylayout; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutDemo; PRODUCT_NAME = MyLayoutDemo; PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/MyLayout/Info.plist b/MyLayout/Info.plist index ad93595..32636b1 100644 --- a/MyLayout/Info.plist +++ b/MyLayout/Info.plist @@ -2,23 +2,23 @@ - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.5.0 - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSPrincipalClass - + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.5.2 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index c77f964..0b7d622 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -535,7 +535,6 @@ 指定视图的可见性,默认是visible。这个属性是对视图hidden属性的扩展,布局系统对视图的hidden属性设置后,视图将不再参与布局。但在实际中有些场景我们希望视图隐藏后 仍然会占用空间仍然会参与布局。因此我们可以用这个属性来设置当视图隐藏后是否继续参与布局。 如果您使用了这个属性来对视图进行隐藏和取消隐藏操作则请不要再去操作hidden属性,否则可能出现二者效果不一致的情况。因此建议视图的隐藏和显示用这个属性进行设置。 - 在老版本中布局中的子视图隐藏时要么都参与布局,要么都不参与布局,这是通过布局属性hideSubviewReLayout来设置,新版本中这个属性将会设置为无效了! 属性可以设置的值如下: diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 601a90b..f8156b3 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -951,19 +951,6 @@ -(BOOL)reverseLayout return self.myCurrentSizeClass.reverseLayout; } - - --(void)setHideSubviewReLayout:(BOOL)hideSubviewReLayout -{ - //这个属性已经无效了,请单独设置子视图的myVisibility属性来控制视图的显示与否。 - NSAssert(0, @"oops!, hideSubviewReLayout is invalid please use subview's myVisibility to instead!!!"); -} - --(BOOL)hideSubviewReLayout -{ - return NO; -} - -(void)removeAllSubviews { [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; @@ -1934,14 +1921,28 @@ -(void)layoutSubviews } } - [_borderlineLayerDelegate setNeedsLayoutIn:CGRectMake(0, 0, newSelfSize.width, newSelfSize.height) withLayer:self.layer]; - + //这里只用width判断的原因是如果newSelfSize被计算成功则size中的所有值都不是CGFLOAT_MAX,所以这里选width只是其中一个代表。 if (newSelfSize.width != CGFLOAT_MAX) { UIView *supv = self.superview; + + //更新边界线。 + if (_borderlineLayerDelegate != nil) + { + CGRect borderlineRect = CGRectMake(0, 0, newSelfSize.width, newSelfSize.height); + if ([supv isKindOfClass:[MyBaseLayout class]]) + { + //这里给父布局视图一个机会来可以改变当前布局的borderlineRect的值,也就是显示的边界线有可能会超出当前布局视图本身的区域。 + //比如一些表格或者其他的情况。默认情况下这个函数什么也不做。 + [((MyBaseLayout*)supv) myHookSublayout:self borderlineRect:&borderlineRect]; + } + + [_borderlineLayerDelegate setNeedsLayoutIn:borderlineRect withLayer:self.layer]; + } + //如果自己的父视图是非UIScrollView以及非布局视图。以及自己是wrapContentWidth或者wrapContentHeight时,并且如果设置了在父视图居中或者居下或者居右时要在父视图中更新自己的位置。 if (supv != nil && ![supv isKindOfClass:[MyBaseLayout class]]) { @@ -3182,7 +3183,6 @@ -(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sb if (sbvmyFrame.multiple) { sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为estimateLayoutRect执行后会还原,所以这里要重新设置 - sbvsc = sbvmyFrame.sizeClass; } } } @@ -3331,6 +3331,10 @@ -(void)myCalcSubViewRect:(UIView*)sbv } +-(void)myHookSublayout:(MyBaseLayout *)sublayout borderlineRect:(CGRect *)pRect +{ + //do nothing... +} @end diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index a347c63..651ce38 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -178,7 +178,6 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbvmyFrame.multiple) { sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为sizeThatFits执行后会还原,所以这里要重新设置 - sbvsc = sbvmyFrame.sizeClass; } } } diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 70db758..ebfd188 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -197,7 +197,6 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbvmyFrame.multiple) { sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为sizeThatFits执行后会还原,所以这里要重新设置 - sbvsc = sbvmyFrame.sizeClass; } } } diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index ea5ddba..420bc08 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -37,7 +37,7 @@ */ -//Current version is 1.5.1, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.5.2, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. #ifndef MyLayout_MyLayout_h diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index c2f2728..fd08273 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -126,6 +126,8 @@ -(MySizeClass)myGetGlobalSizeClass; +//给父布局视图机会来更改子布局视图的边界线的显示的rect +-(void)myHookSublayout:(MyBaseLayout*)sublayout borderlineRect:(CGRect*)pRect; @end diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 9577ee0..c01bc58 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -218,7 +218,6 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbvmyFrame.multiple) { sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为sizeThatFits执行后会还原,所以这里要重新设置 - sbvsc = sbvmyFrame.sizeClass; } } } diff --git a/MyLayout/Lib/MyPathLayout.h b/MyLayout/Lib/MyPathLayout.h index 9588a13..0f450d5 100644 --- a/MyLayout/Lib/MyPathLayout.h +++ b/MyLayout/Lib/MyPathLayout.h @@ -26,13 +26,13 @@ typedef enum : NSUInteger { @interface MyPathSpace : NSObject /**浮动距离,根据布局视图的尺寸和子视图的数量动态决定*/ -+(id)flexed; ++(MyPathSpace *)flexed; /**固定距离,len为长度,每个子视图之间的距离都是len*/ -+(id)fixed:(CGFloat)len; ++(MyPathSpace *)fixed:(CGFloat)len; /**数量距离,根据布局视图的尺寸和指定的数量count动态决定。*/ -+(id)count:(NSInteger)count; ++(MyPathSpace *)count:(NSInteger)count; /**距离类型。*/ diff --git a/MyLayout/Lib/MyPathLayout.m b/MyLayout/Lib/MyPathLayout.m index 6916d0e..6a6714a 100644 --- a/MyLayout/Lib/MyPathLayout.m +++ b/MyLayout/Lib/MyPathLayout.m @@ -12,7 +12,7 @@ @implementation MyPathSpace --(id)initWithType:(MyPathSpaceType)type value:(CGFloat)value +-(MyPathSpace *)initWithSpaceType:(MyPathSpaceType)type value:(CGFloat)value { self = [super init]; if (self != nil) @@ -25,21 +25,21 @@ -(id)initWithType:(MyPathSpaceType)type value:(CGFloat)value } //浮动距离,根据布局视图的尺寸和子视图的数量动态决定 -+(id)flexed ++(MyPathSpace *)flexed { - return [[self alloc] initWithType:MyPathSpace_Flexed value:0]; + return [[self alloc] initWithSpaceType:MyPathSpace_Flexed value:0]; } //固定距离,len为长度,每个子视图之间的距离都是len -+(id)fixed:(CGFloat)len ++(MyPathSpace *)fixed:(CGFloat)len { - return [[self alloc] initWithType:MyPathSpace_Fixed value:len]; + return [[self alloc] initWithSpaceType:MyPathSpace_Fixed value:len]; } //数量距离,根据布局视图的尺寸和指定的数量动态决定。 -+(id)count:(NSInteger)count ++(MyPathSpace *)count:(NSInteger)count { - return [[self alloc] initWithType:MyPathSpace_Count value:count]; + return [[self alloc] initWithSpaceType:MyPathSpace_Count value:count]; } @@ -52,7 +52,7 @@ @implementation MyCoordinateSetting __weak MyPathLayout *_pathLayout; } --(id)initWithPathLayout:(MyPathLayout*)pathLayout +-(MyCoordinateSetting *)initWithPathLayout:(MyPathLayout*)pathLayout { self = [super init]; if (self != nil) @@ -348,20 +348,30 @@ -(NSArray*)getSubviewPathPoint:(NSInteger)fromIndex toIndex:(NSInteger)toIndex //要求外界传递进来的索引要考虑原点视图的索引。 NSMutableArray *retPoints = [NSMutableArray new]; - + NSInteger start; + NSInteger end; + NSInteger indexsCount = self.pointIndexs.count; + if (realFromIndex < realToIndex) { - NSInteger start; - NSInteger end; - if (self.pointIndexs == nil) + if (indexsCount == 0) { start = realFromIndex; end = realToIndex; } else { - start = [self.pointIndexs[realFromIndex] integerValue]; - end = [self.pointIndexs[realToIndex] integerValue]; + + if (realFromIndex >= indexsCount) + start = [self.pointIndexs[indexsCount - 1] integerValue]; + else + start = [self.pointIndexs[realFromIndex] integerValue]; + + + if (realToIndex >= indexsCount) + end = [self.pointIndexs[indexsCount - 1] integerValue]; + else + end = [self.pointIndexs[realToIndex] integerValue]; } for (NSInteger i = start; i <= end; i++) @@ -371,8 +381,24 @@ -(NSArray*)getSubviewPathPoint:(NSInteger)fromIndex toIndex:(NSInteger)toIndex } else { - NSInteger end = [self.pointIndexs[realFromIndex] integerValue]; - NSInteger start = [self.pointIndexs[realToIndex] integerValue]; + if (indexsCount == 0) + { + start = realToIndex; + end = realFromIndex; + } + else + { + if (realFromIndex >= indexsCount) + end = [self.pointIndexs[indexsCount - 1] integerValue]; + else + end = [self.pointIndexs[realFromIndex] integerValue]; + + + if (realToIndex >= indexsCount) + start = [self.pointIndexs[indexsCount - 1] integerValue]; + else + start = [self.pointIndexs[realToIndex] integerValue]; + } for (NSInteger i = end; i >= start; i--) { @@ -556,7 +582,6 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbvmyFrame.multiple) { sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为sizeThatFits执行后会还原,所以这里要重新设置 - sbvsc = sbvmyFrame.sizeClass; } } } diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 4507a92..2264900 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -62,7 +62,6 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbvmyFrame.multiple) { sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为sizeThatFits执行后会还原,所以这里要重新设置 - sbvsc = sbvmyFrame.sizeClass; } } } diff --git a/MyLayout/Lib/MyTableLayout.h b/MyLayout/Lib/MyTableLayout.h index 8a73cc6..38b0f44 100644 --- a/MyLayout/Lib/MyTableLayout.h +++ b/MyLayout/Lib/MyTableLayout.h @@ -56,8 +56,8 @@ @note 行能设置的值: - 1. 一般常数尺寸 表示这行的尺寸为这个固定的数值(垂直表格为行高,水平表格为行宽),列子视图不需要设置尺寸(垂直表格为高度,水平表格为宽度)。 - 2. 特殊尺寸MyLayoutSize.wrap 表示由列子视图决定本行尺寸(垂直表格为行高,水平表格为行宽),每个列子视图都需要自己设置尺寸(垂直表格为高度,水平表格为宽度) + 1. 一般常数尺寸: 表示这行的尺寸为这个固定的数值(垂直表格为行高,水平表格为行宽),列子视图不需要设置尺寸(垂直表格为高度,水平表格为宽度)。 + 2. 特殊尺寸MyLayoutSize.wrap: 表示由列子视图决定本行尺寸(垂直表格为行高,水平表格为行宽),每个列子视图都需要自己设置尺寸(垂直表格为高度,水平表格为宽度) 3. 特殊尺寸MyLayoutSize.average 表示均分尺寸(垂直表格为行高 = 总行高/行数,水平表格为行宽 = 总行宽/行数),列子视图不需要设置尺寸(垂直表格为高度,水平表格为宽度) 4. 不能设置为MyLayoutSize.fill。 diff --git a/MyLayout/Lib/MyTableLayout.m b/MyLayout/Lib/MyTableLayout.m index 6b4c6bc..a1e4ec1 100644 --- a/MyLayout/Lib/MyTableLayout.m +++ b/MyLayout/Lib/MyTableLayout.m @@ -14,7 +14,7 @@ @interface MyTableRowLayout : MyLinearLayout -+(id)rowSize:(CGFloat)rowSize colSize:(CGFloat)colSize orientation:(MyOrientation)orientation; ++(MyTableRowLayout *)rowSize:(CGFloat)rowSize colSize:(CGFloat)colSize orientation:(MyOrientation)orientation; @property(nonatomic,assign, readonly) CGFloat rowSize; @property(nonatomic,assign, readonly) CGFloat colSize; @@ -28,7 +28,7 @@ @implementation MyTableRowLayout } --(id)initWith:(CGFloat)rowSize colSize:(CGFloat)colSize orientation:(MyOrientation)orientation +-(instancetype)initWith:(CGFloat)rowSize colSize:(CGFloat)colSize orientation:(MyOrientation)orientation { self = [super initWithOrientation:orientation]; if (self != nil) @@ -78,7 +78,34 @@ -(id)initWith:(CGFloat)rowSize colSize:(CGFloat)colSize orientation:(MyOrientati return self; } -+(id)rowSize:(CGFloat)rowSize colSize:(CGFloat)colSize orientation:(MyOrientation)orientation +-(void)myHookSublayout:(MyBaseLayout *)sublayout borderlineRect:(CGRect *)pRect +{ + /* + 如果行布局是包裹的,那么意味着里面的列子视图都需要自己指定行的尺寸,这样列子视图就会有不同的尺寸,如果是有智能边界线时就会出现每个列子视图的边界线的长度不一致的情况。 + 有时候我们希望列子视图的边界线能够布满整个行(比如垂直表格中,所有列子视图的的高度都和所在行的行高是一致的)因此我们需要将列子视图的边界线的可显示范围进行调整。 + 因此我们重载这个方法来解决这个问题,这个方法可以将列子视图的边界线的区域进行扩充和调整,目的是为了让列子视图的边界线能够布满整个行布局上。 + */ + if (self.rowSize == MyLayoutSize.wrap) + { + if (self.orientation == MyOrientation_Horz) + { + //垂直表格下,行是水平的,所以这里需要将列子视图的y轴的位置和行对齐。 + pRect->origin.y = 0 - sublayout.frame.origin.y; + //垂直表格下,行是水平的,所以这里需要将子视图的边界线的高度和行的高度保持一致。 + pRect->size.height = self.bounds.size.height; + } + else + { + //水平表格下,行是垂直的,所以这里需要将列子视图的x轴的位置和行对齐。 + pRect->origin.x = 0 - sublayout.frame.origin.x; + //水平表格下,行是垂直的,所以这里需要将子视图的边界线的宽度和行的宽度保持一致。 + pRect->size.width = self.bounds.size.width; + } + } +} + + ++(MyTableRowLayout *)rowSize:(CGFloat)rowSize colSize:(CGFloat)colSize orientation:(MyOrientation)orientation { return [[self alloc] initWith:rowSize colSize:colSize orientation:orientation]; } diff --git a/MyLayoutDemo/AllTest3ViewController.m b/MyLayoutDemo/AllTest3ViewController.m index 62b3d67..e7cc966 100644 --- a/MyLayoutDemo/AllTest3ViewController.m +++ b/MyLayoutDemo/AllTest3ViewController.m @@ -299,7 +299,6 @@ -(void)addFlexedWidthLayout:(MyLinearLayout*)contentLayout //添加一个能伸缩的布局 -(void)addShrinkLayout:(MyLinearLayout*)contentLayout { - //下面两个布局用来测试布局视图的hideSubviewReLayout属性。 MyLinearLayout *switchLayout = [self createSwitchLayout:NSLocalizedString(@"show all switch", @"") action:@selector(handleShrinkSwitch:)]; switchLayout.bottomBorderline = [[MyBorderline alloc] initWithColor:[UIColor redColor]]; //底部边界线设置可以缩进 switchLayout.bottomBorderline.headIndent = 10; diff --git a/MyLayoutDemo/CFTool.m b/MyLayoutDemo/CFTool.m index 7977c99..553cfb6 100644 --- a/MyLayoutDemo/CFTool.m +++ b/MyLayoutDemo/CFTool.m @@ -37,8 +37,6 @@ +(UIColor*)color:(NSInteger)idx +(UIFont*)font:(CGFloat)size { - //中文显示平方字体,英文显示ding. - // [NSLocale preferredLanguages] UIFont *font = [UIFont fontWithName:@"STHeitiSC-Light" size:size]; return font; diff --git a/MyLayoutDemo/Info.plist b/MyLayoutDemo/Info.plist index 0ef0d7f..0babf71 100644 --- a/MyLayoutDemo/Info.plist +++ b/MyLayoutDemo/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.5.1 + 1.5.2 CFBundleSignature ???? CFBundleVersion diff --git a/MyLayoutDemo/TLTest4ViewController.h b/MyLayoutDemo/TLTest4ViewController.h new file mode 100644 index 0000000..a6ad9ed --- /dev/null +++ b/MyLayoutDemo/TLTest4ViewController.h @@ -0,0 +1,16 @@ +// +// TLTest4ViewController.h +// MyLayout +// +// Created by oybq on 15/7/18. +// Copyright (c) 2015年 YoungSoft. All rights reserved. +// + +#import + +/** + 4.TableLayout - Style&Alignment + */ +@interface TLTest4ViewController : UIViewController + +@end diff --git a/MyLayoutDemo/TLTest4ViewController.m b/MyLayoutDemo/TLTest4ViewController.m new file mode 100644 index 0000000..ac94d72 --- /dev/null +++ b/MyLayoutDemo/TLTest4ViewController.m @@ -0,0 +1,158 @@ +// +// TLTest4ViewController.m +// MyLayout +// +// Created by oybq on 15/7/18. +// Copyright (c) 2015年 YoungSoft. All rights reserved. +// + +#import "TLTest4ViewController.h" +#import "MyLayout.h" +#import "CFTool.h" + +@interface TLTest4ViewController () + +@end + +@implementation TLTest4ViewController + +-(void)loadView +{ + /* + 这个例子是将表格布局和智能边界线以及对齐和动态高度的综合应用结合,实现一个表格界面。 + + */ + + + UIScrollView *scrollView = [UIScrollView new]; + scrollView.backgroundColor = [UIColor whiteColor]; + scrollView.contentInset = UIEdgeInsetsMake(0, 0, 10, 0); + self.view = scrollView; + + if (@available(iOS 11.0, *)) { + } else { + // Fallback on earlier versions + self.edgesForExtendedLayout = UIRectEdgeNone; + } + + + MyTableLayout *tableLayout = [MyTableLayout tableLayoutWithOrientation:MyOrientation_Vert]; + tableLayout.leadingPos.equalTo(@(MyLayoutPos.safeAreaMargin)).offset(10); + tableLayout.trailingPos.equalTo(@(MyLayoutPos.safeAreaMargin)).offset(10); + tableLayout.topPos.equalTo(@(MyLayoutPos.safeAreaMargin)).offset(10); + tableLayout.boundBorderline = [[MyBorderline alloc] initWithColor:[UIColor blackColor] thick:3]; + tableLayout.intelligentBorderline = [[MyBorderline alloc] initWithColor:[UIColor lightGrayColor]]; + [self.view addSubview:tableLayout]; + + NSArray *titles = @[@"身高(Height)(cm)", @"体重(Weight)(kg)", @"胸围(Bust)(cm)",@"腰围(Waist)(cm)",@"臀围(Hip)(cm)",@"鞋码(Shoes Size)(欧码)"]; + NSArray *values = @[@"177",@"54",@"88",@"88",@"88",@"43"]; + + + //第一行 + MyLinearLayout *row1 = [tableLayout addRow:MyLayoutSize.wrap colCount:titles.count]; + row1.gravity = MyGravity_Vert_Top; + row1.backgroundColor = [CFTool color:8]; + for (NSString *title in titles) + { + [tableLayout addSubview:[self itemFrom:title alignment:NSTextAlignmentCenter isFitWidth:NO]]; + } + + //第二行 + MyLinearLayout *row2 = [tableLayout addRow:MyLayoutSize.wrap colCount:titles.count]; + row2.gravity = MyGravity_Vert_Center; + for (NSString *title in titles) + { + [tableLayout addSubview:[self itemFrom:title alignment:NSTextAlignmentCenter isFitWidth:NO]]; + } + + //第三行 + MyLinearLayout *row3 = [tableLayout addRow:MyLayoutSize.wrap colCount:titles.count]; + row3.gravity = MyGravity_Vert_Bottom; + for (NSString *title in titles) + { + [tableLayout addSubview:[self itemFrom:title alignment:NSTextAlignmentCenter isFitWidth:NO]]; + } + + //第四行 + MyLinearLayout *row4 = [tableLayout addRow:50 colCount:titles.count]; + for (NSString *title in titles) + { + [tableLayout addSubview:[self itemFrom:title alignment:NSTextAlignmentCenter isFitWidth:YES]]; + } + + + //第五行 + MyLinearLayout *row5 = [tableLayout addRow:MyLayoutSize.wrap colCount:values.count]; + for (NSString *value in values) + { + [tableLayout addSubview:[self itemFrom:value alignment:NSTextAlignmentLeft isFitWidth:NO]]; + } + + //第六行 + MyLinearLayout *row6 = [tableLayout addRow:MyLayoutSize.wrap colCount:values.count]; + for (NSString *value in values) + { + [tableLayout addSubview:[self itemFrom:value alignment:NSTextAlignmentCenter isFitWidth:NO]]; + } + + //第7行 + MyLinearLayout *row7 = [tableLayout addRow:MyLayoutSize.wrap colCount:values.count]; + for (NSString *value in values) + { + [tableLayout addSubview:[self itemFrom:value alignment:NSTextAlignmentRight isFitWidth:NO]]; + } +} + + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +#pragma mark -- Layout Construction + +-(MyBaseLayout*)itemFrom:(NSString*)itemString alignment:(NSTextAlignment)alignment isFitWidth:(BOOL)isFitWidth +{ + MyFrameLayout *itemLayout = [MyFrameLayout new]; + itemLayout.topPadding = itemLayout.bottomPadding = 10; + itemLayout.leftPadding = itemLayout.rightPadding = 5; + UILabel *label = [UILabel new]; + label.text = itemString; + label.textAlignment = alignment; + label.textColor = [CFTool color:4]; + [itemLayout addSubview:label]; + + if (isFitWidth) + { + itemLayout.gravity = MyGravity_Fill; + label.adjustsFontSizeToFitWidth = YES; + label.numberOfLines = 0; + } + else + { + itemLayout.gravity = MyGravity_Horz_Fill; + itemLayout.wrapContentHeight = YES; + label.wrapContentHeight = YES; + } + + + return itemLayout; +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/MyLayoutDemo/ViewController.m b/MyLayoutDemo/ViewController.m index b8b8b9b..327139f 100644 --- a/MyLayoutDemo/ViewController.m +++ b/MyLayoutDemo/ViewController.m @@ -32,6 +32,8 @@ #import "TLTest1ViewController.h" #import "TLTest2ViewController.h" #import "TLTest3ViewController.h" +#import "TLTest4ViewController.h" + #import "FLLTest1ViewController.h" #import "FLLTest2ViewController.h" @@ -154,6 +156,9 @@ -(NSArray*)demoTypeList }, @{@"title":NSLocalizedString(@"3.TableLayout - Intelligent Borderline", @""), @"class":[TLTest3ViewController class] + }, + @{@"title":NSLocalizedString(@"4.TableLayout - Style&Alignment", @""), + @"class":[TLTest4ViewController class] } ] }, diff --git a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings index d843836..8f6b804 100644 --- a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings +++ b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings @@ -26,6 +26,7 @@ "1.TableLayout - Vert" = "1.表格布局-垂直表格"; "2.TableLayout - Waterfall(Horz)" = "2.表格布局-水平表格实现瀑布流"; "3.TableLayout - Intelligent Borderline" = "3.表格布局-表格和智能边界线"; +"4.TableLayout - Style&Alignment" = "4.表格布局-多种样式和对齐"; "1.FlowLayout - Regular arrangement" = "1.流式布局-有规律的子视图排列"; "2.FlowLayout - Tag cloud" = "2.流式布局-标签流"; "3.FlowLayout - Drag" = "3.流式布局-子视图的拖拽调整功能"; From 4c0a2dd956603291d1f4fad7d353ea2e08d446c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E6=9F=8F=E6=B3=89?= Date: Sun, 6 May 2018 12:09:09 +0800 Subject: [PATCH 010/115] Release V1.5.2 --- .DS_Store | Bin 6148 -> 6148 bytes CHANGELOG.md | 9 +++++++++ MyLayout.podspec | 2 +- README.md | 2 +- README.zh.md | 2 +- 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.DS_Store b/.DS_Store index 73b23931898545e3bdead7864f9b5c9d1aa7ec3e..d145beada11a3d8d06ae6150c921ef25084395a1 100644 GIT binary patch delta 59 zcmZoMXffE}$jHocZ~f#NMy<(tj2tZ2MYNAhu3|J{12GsFCi5_AOuoa&%fxzN^G8N8 OwuudFo7p-3@&f=rWfJuO delta 59 zcmZoMXffE}$jHq2^~2;EMy<(tj2tZ2em=08T*YX@24XNUOy*(Kn0$wkmx;+?^G8N8 OwuudFo7p-3@&f>mR}|F% diff --git a/CHANGELOG.md b/CHANGELOG.md index 58cb5ba..5407d2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ --- +## [V1.5.2](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.5.2)(2018/05/06) + +#### Fixed +1. 修复路径布局`MyPathLayout`中的方法`getSubviewPathPoint`可能产生数组越界的问题。 +2. 修复路径布局中的`MyPathSpace`的初始化方法和蓝牙框架一起使用时可能会出现编译时错误的问题。 +3. 修复表格布局`MyTableLayout`的行高是MyLayoutSize.wrap时,并且又设置了智能边界线时,列子视图的边界线显示不完整的问题。 +4. 修复了一些编译和分析有可能会产生报警的代码。 + + ## [V1.5.1](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.5.1)(2018/04/23) #### Added diff --git a/MyLayout.podspec b/MyLayout.podspec index ad0ba17..7728c66 100644 --- a/MyLayout.podspec +++ b/MyLayout.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "MyLayout" - s.version = "1.5.1" + s.version = "1.5.2" s.summary = "MyLayout is an iOS UI framework integrates the functions with Android,AutoLayout,SizeClass,HTML CSS float and flexbox,UIView UITableView." s.description = <<-DESC diff --git a/README.md b/README.md index b9ec76f..9daee7b 100644 --- a/README.md +++ b/README.md @@ -614,7 +614,7 @@ To integrate MyLayout into your Xcode project using CocoaPods, specify it in you source 'https://github.com/CocoaPods/Specs.git' platform :ios, '7.0' -pod 'MyLayout', '~> 1.5.1' +pod 'MyLayout' ``` Then, run the following command: diff --git a/README.zh.md b/README.zh.md index 1a3bd7d..7da80d0 100644 --- a/README.zh.md +++ b/README.zh.md @@ -622,7 +622,7 @@ $ gem install cocoapods source 'https://github.com/CocoaPods/Specs.git' platform :ios, '7.0' -pod 'MyLayout', '~> 1.5.1' +pod 'MyLayout' ``` 然后运行如下命令: From 496af65c4aa992112da0ef475f514434a3df42b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E9=98=B3=E5=A4=A7=E5=93=A52013?= Date: Tue, 8 May 2018 22:30:51 +0800 Subject: [PATCH 011/115] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9daee7b..0e18329 100644 --- a/README.md +++ b/README.md @@ -286,7 +286,7 @@ Sample code: S.subviewHSpace = 10; S.subviewVSpace = 10; - [S addRow:MTLSIZE_WRAPCONTENT colSize:MTLSIZE_WRAPCONTENT]; +    [S addRow:MyLayoutSize.wrap colSize:MyLayoutSize.wrap]; UIView *A = [UIView new]; A.mySize = CGSizeMake(50,40); @@ -300,7 +300,7 @@ Sample code: C.mySize = CGSizeMake(30,40); [S addSubview:C]; - [S addRow:MTLSIZE_WRAPCONTENT colSize:MTLSIZE_WRAPCONTENT]; + [S addRow:MyLayoutSize.wrap colSize:MyLayoutSize.wrap]; UIView *D = [UIView new]; D.mySize = CGSizeMake(200,40); From 2bbe44e8c551ec867a8ced19ac42ee1fd10da38f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E6=9F=8F=E6=B3=89?= Date: Thu, 10 May 2018 00:57:09 +0800 Subject: [PATCH 012/115] =?UTF-8?q?Release=20V1.5.3=20=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=B5=81=E5=BC=8F=E5=B8=83=E5=B1=80=E5=AF=B9=E7=80=91?= =?UTF-8?q?=E5=B8=83=E6=B5=81=E7=9A=84=E6=94=AF=E6=8C=81=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 6148 -> 6148 bytes CHANGELOG.md | 19 +- MyLayout.podspec | 2 +- MyLayout.xcodeproj/project.pbxproj | 6 + MyLayout/Info.plist | 2 +- MyLayout/Lib/MyBaseLayout.h | 59 ++--- MyLayout/Lib/MyBaseLayout.m | 69 +++++- MyLayout/Lib/MyFlowLayout.h | 10 +- MyLayout/Lib/MyFlowLayout.m | 219 +++++++++++++++--- MyLayout/Lib/MyLayout.h | 2 +- MyLayout/Lib/MyLayoutInner.h | 6 +- MyLayout/Lib/MyLayoutPos.h | 6 +- MyLayout/Lib/MyLayoutSize.h | 16 +- MyLayoutDemo/AllTest1TableViewCell.m | 6 +- MyLayoutDemo/AllTest9CollectionViewCell.m | 2 +- MyLayoutDemo/FLLTest7ViewController.h | 16 ++ MyLayoutDemo/FLLTest7ViewController.m | 145 ++++++++++++ MyLayoutDemo/Info.plist | 2 +- MyLayoutDemo/ViewController.m | 4 + .../zh-Hans.lproj/Localizable.strings | 1 + 20 files changed, 513 insertions(+), 79 deletions(-) create mode 100644 MyLayoutDemo/FLLTest7ViewController.h create mode 100644 MyLayoutDemo/FLLTest7ViewController.m diff --git a/.DS_Store b/.DS_Store index d145beada11a3d8d06ae6150c921ef25084395a1..4365ec0afd6e5937ca78d46a94675f5da25c610f 100644 GIT binary patch delta 57 zcmV-90LK4>FoZC$K>-5;;G~m$0Vr P@c|YFk$?uX2MGNS{Jjxt delta 57 zcmZoMXffE}$jHocZ~f#NMy<(tjGW9O+D9f=F`BXhX$FSLJd7HX?=bQ*v0m8xkx`6o MVguV|c8CFBundlePackageType FMWK CFBundleShortVersionString - 1.5.2 + 1.5.3 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index 0b7d622..f0a1e17 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -172,100 +172,100 @@ /** - *视图上边的布局位置, 是topPos.equalTo方法的简化版本 + *视图上边的布局位置, 是topPos.equalTo方法的简化版本。此属性只用于赋值不用于读取! */ /** - *Top layout position of the view. Equivalent to topPos.equalTo(NSNumber). + *Top layout position of the view. Equivalent to topPos.equalTo(NSNumber). Only for setting, not for getting. */ @property(nonatomic, assign) IBInspectable CGFloat myTop; /** - *视图头部的布局位置, 是leadingPos.equalTo方法的简化版本 + *视图头部的布局位置, 是leadingPos.equalTo方法的简化版本。此属性只用于赋值不用于读取! */ /** - *Leading layout position of the view. Equivalent to leadingPos.equalTo(NSNumber). + *Leading layout position of the view. Equivalent to leadingPos.equalTo(NSNumber).Only for setting, not for getting. */ @property(nonatomic, assign) IBInspectable CGFloat myLeading; /** - *视图下边的布局位置, 是bottomPos.equalTo方法的简化版本 + *视图下边的布局位置, 是bottomPos.equalTo方法的简化版本。此属性只用于赋值不用于读取! */ /** - *Bottom layout position of the view. Equivalent to bottomPos.equalTo(NSNumber). + *Bottom layout position of the view. Equivalent to bottomPos.equalTo(NSNumber).Only for setting, not for getting. */ @property(nonatomic, assign) IBInspectable CGFloat myBottom; /** - *视图尾部的布局位置, 是trailingPos.equalTo方法的简化版本 + *视图尾部的布局位置, 是trailingPos.equalTo方法的简化版本。此属性只用于赋值不用于读取! */ /** - *Trailing layout position of the view. Equivalent to trailingPos.equalTo(NSNumber). + *Trailing layout position of the view. Equivalent to trailingPos.equalTo(NSNumber).Only for setting, not for getting. */ @property(nonatomic, assign) IBInspectable CGFloat myTrailing; /** - *视图水平中心布局位置, 是centerXPos.equalTo方法的简化版本 + *视图水平中心布局位置, 是centerXPos.equalTo方法的简化版本。此属性只用于赋值不用于读取! */ /** - *Horizontal center layout position of the view. Equivalent to centerXPos.equalTo(NSNumber). + *Horizontal center layout position of the view. Equivalent to centerXPos.equalTo(NSNumber).Only for setting, not for getting. */ @property(nonatomic, assign) IBInspectable CGFloat myCenterX; /** - *视图垂直中心布局位置, 是centerYPos.equalTo方法的简化版本 + *视图垂直中心布局位置, 是centerYPos.equalTo方法的简化版本。此属性只用于赋值不用于读取! */ /** - *Vertical center layout position of the view. Equivalent to centerYPos.equalTo(NSNumber). + *Vertical center layout position of the view. Equivalent to centerYPos.equalTo(NSNumber).Only for setting, not for getting. */ @property(nonatomic, assign) IBInspectable CGFloat myCenterY; /** - *视图中心布局位置, 是myCenterX,myCenterY方法的简化版本 + *视图中心布局位置, 是myCenterX,myCenterY方法的简化版本。此属性只用于赋值不用于读取! */ /** - *Center layout position of the view. Equivalent to set myCenterX and myCenterY . + *Center layout position of the view. Equivalent to set myCenterX and myCenterY .Only for setting, not for getting. */ @property(nonatomic, assign) IBInspectable CGPoint myCenter; /** - *视图左边的布局位置, 是leftPos.equalTo方法的简化版本 + *视图左边的布局位置, 是leftPos.equalTo方法的简化版本。此属性只用于赋值不用于读取! */ /** - *Left layout position of the view. Equivalent to leftPos.equalTo(NSNumber). + *Left layout position of the view. Equivalent to leftPos.equalTo(NSNumber).Only for setting, not for getting. */ @property(nonatomic, assign) IBInspectable CGFloat myLeft; /** - *视图右边的布局位置, 是rightPos.equalTo方法的简化版本 + *视图右边的布局位置, 是rightPos.equalTo方法的简化版本。此属性只用于赋值不用于读取! */ /** - *Right layout position of the view. Equivalent to rightPos.equalTo(NSNumber). + *Right layout position of the view. Equivalent to rightPos.equalTo(NSNumber).Only for setting, not for getting. */ @property(nonatomic, assign) IBInspectable CGFloat myRight; /** - *视图四边的布局位置, 是myLeading,myTop,myTrailing,myBottom的简化版本 + *视图四边的布局位置, 是myLeading,myTop,myTrailing,myBottom的简化版本。此属性只用于赋值不用于读取! */ /** - *Boundary layout position of the view. Equivalent to myLeading,myTop,myTrailing,myBottom set to the same number. + *Boundary layout position of the view. Equivalent to myLeading,myTop,myTrailing,myBottom set to the same number.Only for setting, not for getting. */ @property(nonatomic, assign) IBInspectable CGFloat myMargin; /** - *leading and trailing margin of the view to the superview. Equivalent to myLeading,myTrailing set to the same number + *leading and trailing margin of the view to the superview. Equivalent to myLeading,myTrailing set to the same number.Only for setting, not for getting. */ @property(nonatomic, assign) IBInspectable CGFloat myHorzMargin; /** - *top and bottom margin of the view to the superview. Equivalent to myTop,myBottom set to the same number + *top and bottom margin of the view to the superview. Equivalent to myTop,myBottom set to the same number.Only for setting, not for getting. */ @property(nonatomic, assign) IBInspectable CGFloat myVertMargin; @@ -337,17 +337,17 @@ */ /** - *视图的宽度布局尺寸,是widthSize.equalTo方法的简化版本 + *视图的宽度布局尺寸,是widthSize.equalTo方法的简化版本。此属性只用于赋值不用于读取! */ @property(nonatomic,assign) IBInspectable CGFloat myWidth; /** - *视图的高度布局尺寸,是heightSize.equalTo方法的简化版本 + *视图的高度布局尺寸,是heightSize.equalTo方法的简化版本。此属性只用于赋值不用于读取! */ @property(nonatomic,assign) IBInspectable CGFloat myHeight; /** - *视图的宽度高度布局尺寸,是myWidth,myHeight方法的简化版本 + *视图的宽度高度布局尺寸,是myWidth,myHeight方法的简化版本。此属性只用于赋值不用于读取! */ @property(nonatomic,assign) IBInspectable CGSize mySize; @@ -622,11 +622,15 @@ */ @interface MyBaseLayout : UIView +#if UIKIT_DEFINE_AS_PROPERTIES /** 用于实现对阿拉伯国家的布局适配。对于非阿拉伯国家来说,界面布局都是默认从左到右排列。而对于阿拉伯国家来说界面布局则默认是从右往左排列。默认这个属性是NO,您可以将这个属性设置为YES,这样布局里面的所有视图都将从右到左进行排列布局。如果您需要考虑国际化布局的问题,那么您应该用leadingPos来表示头部的位置,而用trailingPos来表示尾部的位置,这样当布局方向是LTR时那么leadingPos就表示的是左边而trailingPos则表示的是右边;而当布局方向是RTL时那么leadingPos表示的是右边而trailingPos则表示的是左边。如果您的界面布局不会考虑到国际化以及不需要考虑RTL时那么您可以用leftPos和rightPos来表示左右而不需要用leadingPos和trailingPos。 */ @property(class, nonatomic, assign) BOOL isRTL; - +#else ++(BOOL)isRTL; ++(void)setIsRTL:(BOOL)isRTL; +#endif /* 布局视图里面的padding属性用来设置布局视图的内边距。内边距是指布局视图里面的子视图离自己距离。外边距则是视图与父视图之间的距离。 @@ -938,6 +942,9 @@ } @endcode + + @note + 这个属性有可能会造成动态高度计算不正确,请只在UITableviewCell的高度为自适应时使用,其他地方不建议设置这个属性!! */ @property(nonatomic, assign) BOOL cacheEstimatedRect; diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index f8156b3..1d7460c 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -77,6 +77,9 @@ -(MyLayoutPos*)baselinePos -(CGFloat)myTop { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myTop; } @@ -87,6 +90,9 @@ -(void)setMyTop:(CGFloat)myTop -(CGFloat)myLeading { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myLeading; } @@ -98,6 +104,9 @@ -(void)setMyLeading:(CGFloat)myLeading -(CGFloat)myBottom { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myBottom; } @@ -110,6 +119,9 @@ -(void)setMyBottom:(CGFloat)myBottom -(CGFloat)myTrailing { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myTrailing; } @@ -121,6 +133,9 @@ -(void)setMyTrailing:(CGFloat)myTrailing -(CGFloat)myCenterX { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myCenterX; } @@ -131,6 +146,9 @@ -(void)setMyCenterX:(CGFloat)myCenterX -(CGFloat)myCenterY { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myCenterY; } @@ -142,6 +160,9 @@ -(void)setMyCenterY:(CGFloat)myCenterY -(CGPoint)myCenter { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myCenter; } @@ -153,6 +174,9 @@ -(void)setMyCenter:(CGPoint)myCenter -(CGFloat)myLeft { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myLeft; } @@ -163,6 +187,9 @@ -(void)setMyLeft:(CGFloat)myLeft -(CGFloat)myRight { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myRight; } @@ -175,6 +202,9 @@ -(void)setMyRight:(CGFloat)myRight -(CGFloat)myMargin { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myMargin; } @@ -185,6 +215,9 @@ -(void)setMyMargin:(CGFloat)myMargin -(CGFloat)myHorzMargin { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myHorzMargin; } @@ -196,6 +229,9 @@ -(void)setMyHorzMargin:(CGFloat)myHorzMargin -(CGFloat)myVertMargin { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myVertMargin; } @@ -220,6 +256,9 @@ -(MyLayoutSize*)heightSize -(CGFloat)myWidth { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myWidth; } @@ -231,6 +270,9 @@ -(void)setMyWidth:(CGFloat)myWidth -(CGFloat)myHeight { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif return self.myCurrentSizeClass.myHeight; } @@ -241,6 +283,10 @@ -(void)setMyHeight:(CGFloat)myHeight -(CGSize)mySize { +#if DEBUG + NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); +#endif + return self.myCurrentSizeClass.mySize; } @@ -1681,8 +1727,11 @@ -(void)awakeFromNib -(void)safeAreaInsetsDidChange { - [super safeAreaInsetsDidChange]; +#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) + + [super safeAreaInsetsDidChange]; +#endif if (self.superview != nil && ![self.superview isKindOfClass:[MyBaseLayout class]] && (self.leadingPosInner.isSafeAreaPos || @@ -2451,6 +2500,12 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview } + //这里要判断自己的宽度设置了最小和最大宽度依赖于父视图的情况。如果有这种情况,则父视图在变化时也需要调整自身。 + if (lsc.widthSizeInner.lBoundValInner.dimeRelaVal.view == newSuperview || lsc.widthSizeInner.uBoundValInner.dimeRelaVal.view == newSuperview) + { + isAdjust = YES; + } + rectSelf.size.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:rectSelf.size.width sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; if ([MyBaseLayout isRTL]) @@ -2537,6 +2592,12 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview rectSelf.size.height = lsc.heightSizeInner.measure; } + //这里要判断自己的高度设置了最小和最大高度依赖于父视图的情况。如果有这种情况,则父视图在变化时也需要调整自身。 + if (lsc.heightSizeInner.lBoundValInner.dimeRelaVal.view == newSuperview || lsc.heightSizeInner.uBoundValInner.dimeRelaVal.view == newSuperview) + { + isAdjust = YES; + } + rectSelf.size.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:rectSelf.size.height sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; if (lsc.topPosInner.posVal != nil && lsc.bottomPosInner.posVal != nil) @@ -3110,7 +3171,9 @@ -(void)myRemoveSubviewObserver:(UIView*)subview [subview removeObserver:self forKeyPath:@"hidden"]; [subview removeObserver:self forKeyPath:@"frame"]; - if ([subview isKindOfClass:[MyBaseLayout class]]) + //有时候我们可能会把滚动视图加入到布局视图中去,滚动视图的尺寸有可能设置为wrapContent,这样就会调整center。从而需要重新激发滚动视图的布局 + //这也就是为什么只监听center的原因了。布局子视图也是如此。 + if ([subview isKindOfClass:[MyBaseLayout class]] || [subview isKindOfClass:[UIScrollView class]]) { [subview removeObserver:self forKeyPath:@"center"]; } @@ -3134,7 +3197,7 @@ -(void)myAddSubviewObserver:(UIView*)subview sbvmyFrame:(MyFrame*)sbvmyFrame //添加hidden, frame,center的属性通知。 [subview addObserver:self forKeyPath:@"hidden" options:NSKeyValueObservingOptionNew context:_myObserverContextA]; [subview addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:_myObserverContextA]; - if ([subview isKindOfClass:[MyBaseLayout class]]) + if ([subview isKindOfClass:[MyBaseLayout class]] || [subview isKindOfClass:[UIScrollView class]]) { [subview addObserver:self forKeyPath:@"center" options:NSKeyValueObservingOptionNew context:_myObserverContextA]; } diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index 632ea3b..bd7cb06 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -176,10 +176,14 @@ /** - 布局内子视图自动排列。这个属性只有在内容填充约束流式布局下才有用,默认为NO。当设置为YES时则根据子视图的尺寸自动填充,而不是根据加入的顺序来填充,以便保证不会出现多余空隙的情况。 + 布局内子视图自动排列或者让布局内的子视图的排列尽可能的紧凑,默认为NO + 当流式布局是内容填充约束流式布局时,则当设置为YES时则根据子视图的尺寸自动填充,而不是根据加入的顺序来填充,以便保证不会出现多余空隙的情况。 + 当流式布局是数量填充约束流式布局时,则当设置为YES时每个子视图会按顺序找一个最佳的存放地点进行填充。 + + @note - 请在将所有子视图添加完毕并且初始布局完成后再设置这个属性,否则如果预先设置这个属性则在后续添加子视图时可能会非常耗性能。 + 如果在内容填充约束流式布局中使用次属性时,请在将所有子视图添加完毕并且初始布局完成后再设置这个属性,否则如果预先设置这个属性则在后续添加子视图时可能会非常耗性能。 */ @property(nonatomic,assign) IBInspectable BOOL autoArrange; @@ -193,6 +197,7 @@ MyGravity_Vert_Center 垂直居中对齐 MyGravity_Vert_Bottom 底部对齐 MyGravity_Vert_Fill 两端对齐 + MyGravity_Vert_Between 数量约束垂直流式布局有效,子视图会紧凑进行排列,当设置为这个属性值时,子视图的y轴的位置总是从对应列的上一行的结尾开始,而不是上一行的最高位置开始。 @endcode 2. 如果是水平流式布局则表示每排内子视图的左中右对齐方式,这里的对齐基础是以每排中的最宽的子视图为基准。这个属性只支持: @code @@ -200,6 +205,7 @@ MyGravity_Horz_Center 水平居中对齐 MyGravity_Horz_Right 右边对齐 MyGravity_Horz_Fill 两端对齐 + MyGravity_Horz_Between 数量约束垂直流式布局有效,子视图会紧凑进行排列,当设置为这个属性值时,子视图的x轴的位置总是从对应行的上一列的结尾开始,而不是上一列的最宽位置开始。 @endcode @note 如果您想单独设置某个子视图在排内的对齐方式则请使用子视图的扩展属性myAlignment。 diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index ebfd188..134c24d 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -392,10 +392,12 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo } MyGravity sbvVertAlignment = sbvsc.myAlignment & MyGravity_Horz_Mask; - if (sbvVertAlignment != MyGravity_None) - vertAlignment = sbvVertAlignment; + if (sbvVertAlignment == MyGravity_None) + sbvVertAlignment = vertAlignment; + if (vertAlignment == MyGravity_Vert_Between) + sbvVertAlignment = MyGravity_Vert_Between; - if ((vertAlignment != MyGravity_None && vertAlignment != MyGravity_Vert_Top) || _myCGFloatNotEqual(addXPos, 0) || _myCGFloatNotEqual(addXFill, 0)) + if ((sbvVertAlignment != MyGravity_None && sbvVertAlignment != MyGravity_Vert_Top) || _myCGFloatNotEqual(addXPos, 0) || _myCGFloatNotEqual(addXFill, 0)) { sbvmyFrame.leading += addXPos; @@ -419,7 +421,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo } - switch (vertAlignment) { + switch (sbvVertAlignment) { case MyGravity_Vert_Center: { sbvmyFrame.top += (rowMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal - sbvmyFrame.height) / 2; @@ -471,7 +473,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa break; case MyGravity_Vert_Between: { - //总宽度减去最大的宽度。再除以数量表示每个应该扩展的空间。最后一行无效(如果数量和单行的数量相等除外)。 + //总高度减去最大的高度。再除以数量表示每个应该扩展的空间。最后一行无效(如果数量和单行的数量相等除外)。 if ((startIndex != sbs.count || count == lsc.arrangedCount) && count > 1) { addYFill = (selfSize.height - paddingVert - colMaxHeight) / (count - 1); @@ -556,11 +558,14 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa } } - CGFloat sbvHorzAlignment = [self myConvertLeftRightGravityToLeadingTrailing:sbvsc.myAlignment & MyGravity_Vert_Mask]; - if (sbvHorzAlignment != MyGravity_None) - horzAlignment = sbvHorzAlignment; - if ((horzAlignment != MyGravity_None && horzAlignment != MyGravity_Horz_Leading) || _myCGFloatNotEqual(addYPos, 0) || _myCGFloatNotEqual(addYFill, 0) ) + MyGravity sbvHorzAlignment = [self myConvertLeftRightGravityToLeadingTrailing:sbvsc.myAlignment & MyGravity_Vert_Mask]; + if (sbvHorzAlignment == MyGravity_None) + sbvHorzAlignment = horzAlignment; + if (horzAlignment == MyGravity_Horz_Between) + sbvHorzAlignment = MyGravity_Horz_Between; + + if ((sbvHorzAlignment != MyGravity_None && sbvHorzAlignment != MyGravity_Horz_Leading) || _myCGFloatNotEqual(addYPos, 0) || _myCGFloatNotEqual(addYFill, 0) ) { sbvmyFrame.top += addYPos; @@ -581,8 +586,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa sbvmyFrame.top += addYFill * (j - (startIndex - count)); } - - switch (horzAlignment) { + switch (sbvHorzAlignment) { case MyGravity_Horz_Center: { sbvmyFrame.leading += (colMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal - sbvmyFrame.width) / 2; @@ -982,12 +986,14 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst CGFloat paddingHorz = paddingLeading + paddingTrailing; CGFloat paddingVert = paddingTop + paddingBottom; + BOOL autoArrange = lsc.autoArrange; NSInteger arrangedCount = lsc.arrangedCount; CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; CGFloat rowMaxHeight = 0; //某一行的最高值。 CGFloat rowMaxWidth = 0; //某一行的最宽值 CGFloat maxWidth = paddingLeading; //全部行的最宽值 + CGFloat maxHeight = paddingTop; //最大的高度 MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; MyGravity vertAlign = lsc.arrangedGravity & MyGravity_Horz_Mask; @@ -1114,6 +1120,16 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; } + //每列的下一个位置。 + NSMutableArray *nextPointOfRows = nil; + if (autoArrange) + { + nextPointOfRows = [NSMutableArray arrayWithCapacity:arrangedCount]; + for (NSInteger idx = 0; idx < arrangedCount; idx++) + { + [nextPointOfRows addObject:[NSValue valueWithCGPoint:CGPointMake(paddingLeading, paddingTop)]]; + } + } CGFloat pageWidth = 0; //页宽。 CGFloat averageWidth = (selfSize.width - paddingHorz - (arrangedCount - 1) * horzSpace) / arrangedCount; @@ -1203,16 +1219,77 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + //得到最大的行高 + if (_myCGFloatLess(rowMaxHeight, topSpace + bottomSpace + rect.size.height)) + rowMaxHeight = topSpace + bottomSpace + rect.size.height; + + + //自动排列。 + if (autoArrange) + { + //查找能存放当前子视图的最小y轴的位置以及索引。 + CGPoint minPt = CGPointMake(CGFLOAT_MAX, CGFLOAT_MAX); + NSInteger minNextPointIndex = 0; + for (int idx = 0; idx < arrangedCount; idx++) + { + CGPoint pt = nextPointOfRows[idx].CGPointValue; + if (minPt.y > pt.y) + { + minPt = pt; + minNextPointIndex = idx; + } + } + + //找到的minNextPointIndex中的 + xPos = minPt.x; + yPos = minPt.y; + + minPt.y = minPt.y + topSpace + rect.size.height + bottomSpace + vertSpace; + nextPointOfRows[minNextPointIndex] = [NSValue valueWithCGPoint:minPt]; + if (minNextPointIndex + 1 <= arrangedCount - 1) + { + minPt = nextPointOfRows[minNextPointIndex + 1].CGPointValue; + minPt.x = xPos + leadingSpace + rect.size.width + trailingSpace + horzSpace; + nextPointOfRows[minNextPointIndex + 1] = [NSValue valueWithCGPoint:minPt]; + } + + if (_myCGFloatLess(maxHeight, yPos + topSpace + rect.size.height + bottomSpace)) + maxHeight = yPos + topSpace + rect.size.height + bottomSpace; + + } + else if (vertAlign == MyGravity_Vert_Between) + { //当列是紧凑排列时需要特殊处理当前的垂直位置。 + //第0行特殊处理。 + if (i - arrangedCount < 0) + { + yPos = paddingTop; + } + else + { + //取前一行的对应的列的子视图。 + MyFrame *myPrevColSbvFrame = ((UIView*)sbs[i - arrangedCount]).myFrame; + UIView *myPrevColSbvsc = [self myCurrentSizeClassFrom:myPrevColSbvFrame]; + //当前子视图的位置等于前一行对应列的最大y的值 + 前面对应列的底部间距 + 子视图之间的行间距。 + yPos = CGRectGetMaxY(myPrevColSbvFrame.frame)+ myPrevColSbvsc.bottomPosInner.absVal + vertSpace; + } + + if (_myCGFloatLess(maxHeight, yPos + topSpace + rect.size.height + bottomSpace)) + maxHeight = yPos + topSpace + rect.size.height + bottomSpace; + } + else + {//正常排列。 + //这里的最大其实就是最后一个视图的位置加上最高的子视图的尺寸。 + maxHeight = yPos + rowMaxHeight; + } + rect.origin.x = xPos + leadingSpace; rect.origin.y = yPos + topSpace; xPos += leadingSpace + rect.size.width + trailingSpace; - if (arrangedIndex != (arrangedCount - 1)) + if (arrangedIndex != (arrangedCount - 1) && !autoArrange) xPos += horzSpace; - if (_myCGFloatLess(rowMaxHeight, topSpace + bottomSpace + rect.size.height)) - rowMaxHeight = topSpace + bottomSpace + rect.size.height; if (_myCGFloatLess(rowMaxWidth, (xPos - paddingLeading))) rowMaxWidth = (xPos - paddingLeading); @@ -1231,9 +1308,11 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst //最后一行 [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + maxHeight += paddingBottom; + if (lsc.wrapContentHeight) { - selfSize.height = yPos + paddingBottom + rowMaxHeight; + selfSize.height = maxHeight; //只有在父视图为滚动视图,且开启了分页滚动时才会扩充具有包裹设置的布局视图的宽度。 if (isVertPaging && isPagingScroll) @@ -1254,22 +1333,22 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst if (vertGravity == MyGravity_Vert_Center) { - addYPos = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / 2; + addYPos = (selfSize.height - maxHeight) / 2; } else if (vertGravity == MyGravity_Vert_Bottom) { - addYPos = selfSize.height - paddingBottom - rowMaxHeight - yPos; + addYPos = selfSize.height - maxHeight; } else if (vertGravity == MyGravity_Vert_Fill) { if (arranges > 0) - fill = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / arranges; + fill = (selfSize.height - maxHeight) / arranges; } else if (vertGravity == MyGravity_Vert_Between) { if (arranges > 1) - between = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / (arranges - 1); + between = (selfSize.height - maxHeight) / (arranges - 1); } @@ -1611,12 +1690,14 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst CGFloat paddingHorz = paddingLeading + paddingTrailing; CGFloat paddingVert = paddingTop + paddingBottom; + BOOL autoArrange = lsc.autoArrange; NSInteger arrangedCount = lsc.arrangedCount; CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; CGFloat colMaxWidth = 0; //每列的最大宽度 CGFloat colMaxHeight = 0; //每列的最大高度 CGFloat maxHeight = paddingTop; + CGFloat maxWidth = paddingLeading; //最大的宽度。 MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; @@ -1766,7 +1847,17 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - rowTotalFixedHeight totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; } - + //每行的下一个位置。 + NSMutableArray *nextPointOfRows = nil; + if (autoArrange) + { + nextPointOfRows = [NSMutableArray arrayWithCapacity:arrangedCount]; + for (NSInteger idx = 0; idx < arrangedCount; idx++) + { + [nextPointOfRows addObject:[NSValue valueWithCGPoint:CGPointMake(paddingLeading, paddingTop)]]; + } + } + CGFloat pageHeight = 0; //页高 CGFloat averageHeight = (selfSize.height - paddingVert - (arrangedCount - 1) * vertSpace) / arrangedCount; arrangedIndex = 0; @@ -1840,25 +1931,84 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:[sbvsc.widthSizeInner measureWith: rect.size.height ] sbvSize:rect.size selfLayoutSize:selfSize]; } + //得到最大的列宽 + if (_myCGFloatLess(colMaxWidth, leadingSpace + trailingSpace + rect.size.width)) + colMaxWidth = leadingSpace + trailingSpace + rect.size.width; + + //自动排列。 + if (autoArrange) + { + //查找能存放当前子视图的最小x轴的位置以及索引。 + CGPoint minPt = CGPointMake(CGFLOAT_MAX, CGFLOAT_MAX); + NSInteger minNextPointIndex = 0; + for (int idx = 0; idx < arrangedCount; idx++) + { + CGPoint pt = nextPointOfRows[idx].CGPointValue; + if (minPt.x > pt.x) + { + minPt = pt; + minNextPointIndex = idx; + } + } + + //找到的minNextPointIndex中的 + xPos = minPt.x; + yPos = minPt.y; + + minPt.x = minPt.x + leadingSpace + rect.size.width + trailingSpace + horzSpace; + nextPointOfRows[minNextPointIndex] = [NSValue valueWithCGPoint:minPt]; + if (minNextPointIndex + 1 <= arrangedCount - 1) + { + minPt = nextPointOfRows[minNextPointIndex + 1].CGPointValue; + minPt.y = yPos + topSpace + rect.size.height + bottomSpace + vertSpace; + nextPointOfRows[minNextPointIndex + 1] = [NSValue valueWithCGPoint:minPt]; + } + + if (_myCGFloatLess(maxWidth, xPos + leadingSpace + rect.size.width + trailingSpace)) + maxWidth = xPos + leadingSpace + rect.size.width + trailingSpace; + + } + else if (horzAlign == MyGravity_Horz_Between) + { //当列是紧凑排列时需要特殊处理当前的水平位置。 + //第0列特殊处理。 + if (i - arrangedCount < 0) + { + xPos = paddingLeading; + } + else + { + //取前一列的对应的行的子视图。 + MyFrame *myPrevColSbvFrame = ((UIView*)sbs[i - arrangedCount]).myFrame; + UIView *myPrevColSbvsc = [self myCurrentSizeClassFrom:myPrevColSbvFrame]; + //当前子视图的位置等于前一列对应行的最大x的值 + 前面对应行的尾部间距 + 子视图之间的列间距。 + xPos = CGRectGetMaxX(myPrevColSbvFrame.frame)+ myPrevColSbvsc.trailingPosInner.absVal + horzSpace; + } + + if (_myCGFloatLess(maxWidth, xPos + leadingSpace + rect.size.width + trailingSpace)) + maxWidth = xPos + leadingSpace + rect.size.width + trailingSpace; + } + else + {//正常排列。 + //这里的最大其实就是最后一个视图的位置加上最宽的子视图的尺寸。 + maxWidth = xPos + colMaxWidth; + } - rect.origin.y = yPos + topSpace; rect.origin.x = xPos + leadingSpace; + rect.origin.y = yPos + topSpace; yPos += topSpace + rect.size.height + bottomSpace; - if (arrangedIndex != (arrangedCount - 1)) + //不是最后一行以及非自动排列时才添加布局视图设置的行间距。自动排列的情况下上面已经有添加行间距了。 + if (arrangedIndex != (arrangedCount - 1) && !autoArrange) yPos += vertSpace; - if (_myCGFloatLess(colMaxWidth, leadingSpace + trailingSpace + rect.size.width)) - colMaxWidth = leadingSpace + trailingSpace + rect.size.width; - if (_myCGFloatLess(colMaxHeight, (yPos - paddingTop))) colMaxHeight = yPos - paddingTop; if (_myCGFloatLess(maxHeight, yPos)) maxHeight = yPos; - + sbvmyFrame.frame = rect; @@ -1881,13 +2031,14 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst if (_myCGFloatLess(selfSize.height, totalPages * CGRectGetHeight(self.superview.bounds))) selfSize.height = totalPages * CGRectGetHeight(self.superview.bounds); } - - } + + maxWidth += paddingTrailing; + if (lsc.wrapContentWidth) { - selfSize.width = xPos + paddingTrailing + colMaxWidth; + selfSize.width = maxWidth; //只有在父视图为滚动视图,且开启了分页滚动时才会扩充具有包裹设置的布局视图的宽度。 if (isHorzPaging && isPagingScroll) @@ -1905,25 +2056,25 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst CGFloat addXPos = 0; CGFloat between = 0; CGFloat fill = 0; - int arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); + int arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); //列数 if (horzGravity == MyGravity_Horz_Center) { - addXPos = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / 2; + addXPos = (selfSize.width - maxWidth) / 2; } else if (horzGravity == MyGravity_Horz_Trailing) { - addXPos = selfSize.width - paddingTrailing - colMaxWidth - xPos; + addXPos = selfSize.width - maxWidth; } else if (horzGravity == MyGravity_Horz_Fill) { if (arranges > 0) - fill = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / arranges; + fill = (selfSize.width - maxWidth) / arranges; } else if (horzGravity == MyGravity_Horz_Between) { if (arranges > 1) - between = (selfSize.width - paddingLeading - colMaxWidth - xPos) / (arranges - 1); + between = (selfSize.width - maxWidth) / (arranges - 1); } if (addXPos != 0 || between != 0 || fill != 0) diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index 420bc08..55d914c 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -37,7 +37,7 @@ */ -//Current version is 1.5.2, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.5.3, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. #ifndef MyLayout_MyLayout_h diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index fd08273..2656da2 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -149,9 +149,13 @@ @property(nonatomic, strong,readonly) MyLayoutPos *baselinePosInner; +#if UIKIT_DEFINE_AS_PROPERTIES @property(class, nonatomic, assign) BOOL isRTL; - +#else ++(BOOL)isRTL; ++(void)setIsRTL:(BOOL)isRTL; +#endif @end diff --git a/MyLayout/Lib/MyLayoutPos.h b/MyLayout/Lib/MyLayoutPos.h index 7bdf5c3..88bce5a 100644 --- a/MyLayout/Lib/MyLayoutPos.h +++ b/MyLayout/Lib/MyLayoutPos.h @@ -75,6 +75,8 @@ */ @interface MyLayoutPos : NSObject +#if UIKIT_DEFINE_AS_PROPERTIES + /** 特殊的位置。只用在布局视图和非布局父视图之间的位置约束和没有导航条时的布局视图内子视图的padding设置上。 iOS11以后提出了安全区域的概念,因此对于iOS11以下的版本就需要兼容处理,尤其是在那些没有导航条的情况下。通过将布局视图的边距设置为这个特殊值就可以实现在任何版本中都能完美的实现位置的偏移而且各版本保持统一。比如下面的例子: @@ -110,7 +112,9 @@ */ @property(class, nonatomic, assign,readonly) CGFloat safeAreaMargin; - +#else ++(CGFloat)safeAreaMargin; +#endif //because masonry defined macro MAS_SHORTHAND_GLOBALS. the equalTo, offset may conflict with below method. so //if you used MyLayout and Masonry concurrently and you defined MAS_SHORTHAND_GLOBALS in masonry, then you can define MY_USEPREFIXMETHOD to solve the conflict. diff --git a/MyLayout/Lib/MyLayoutSize.h b/MyLayout/Lib/MyLayoutSize.h index 590d0d5..7b63823 100644 --- a/MyLayout/Lib/MyLayoutSize.h +++ b/MyLayout/Lib/MyLayoutSize.h @@ -24,14 +24,26 @@ */ @interface MyLayoutSize : NSObject - +#if UIKIT_DEFINE_AS_PROPERTIES /**特殊的尺寸,表示尺寸由子视图决定或者由内容决定。目前只用在表格布局MyTableLayout和栅格布局MyGridLayout中。*/ @property(class, nonatomic, assign,readonly) CGFloat wrap; +#else ++(CGFloat)wrap; +#endif + +#if UIKIT_DEFINE_AS_PROPERTIES /**特殊的尺寸,表示尺寸会填充满父视图的剩余空间。目前只用在表格布局MyTableLayout和栅格布局MyGridLayout中。*/ @property(class, nonatomic, assign,readonly) CGFloat fill; +#else ++(CGFloat)fill; +#endif + +#if UIKIT_DEFINE_AS_PROPERTIES /**特殊的尺寸,表示尺寸会均分父视图的剩余空间。目前只用在表格布局MyTableLayout */ @property(class, nonatomic, assign,readonly) CGFloat average; - +#else ++(CGFloat)average; +#endif //because masonry defined macro MAS_SHORTHAND_GLOBALS. the equalTo, offset may conflict with below method. so //if you used MyLayout and Masonry concurrently and you defined MAS_SHORTHAND_GLOBALS in masonry, then you can define MY_USEPREFIXMETHOD to solve the conflict. diff --git a/MyLayoutDemo/AllTest1TableViewCell.m b/MyLayoutDemo/AllTest1TableViewCell.m index bcc40c6..57b8346 100644 --- a/MyLayoutDemo/AllTest1TableViewCell.m +++ b/MyLayoutDemo/AllTest1TableViewCell.m @@ -111,7 +111,7 @@ -(void)createLinearRootLayout _rootLayout= [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; _rootLayout.topPadding = 5; _rootLayout.bottomPadding = 5; - _rootLayout.cacheEstimatedRect = YES; + _rootLayout.cacheEstimatedRect = YES; //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! /* 在UITableViewCell中使用MyLayout中的布局时请将布局视图作为contentView的子视图。如果我们的UITableViewCell的高度是动态的,请务必在将布局视图添加到contentView之前进行如下设置: @@ -168,7 +168,7 @@ -(void)createRelativeRootLayout _rootLayout = [MyRelativeLayout new]; _rootLayout.topPadding = 5; _rootLayout.bottomPadding = 5; - _rootLayout.cacheEstimatedRect = YES; + _rootLayout.cacheEstimatedRect = YES; //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! /* 在UITableViewCell中使用MyLayout中的布局时请将布局视图作为contentView的子视图。如果我们的UITableViewCell的高度是动态的,请务必在将布局视图添加到contentView之前进行如下设置: @@ -218,7 +218,7 @@ -(void)createFloatRootLayout _rootLayout= [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; _rootLayout.topPadding = 5; _rootLayout.bottomPadding = 5; - _rootLayout.cacheEstimatedRect = YES; + _rootLayout.cacheEstimatedRect = YES; //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! /* 在UITableViewCell中使用MyLayout中的布局时请将布局视图作为contentView的子视图。如果我们的UITableViewCell的高度是动态的,请务必在将布局视图添加到contentView之前进行如下设置: diff --git a/MyLayoutDemo/AllTest9CollectionViewCell.m b/MyLayoutDemo/AllTest9CollectionViewCell.m index 4f63adf..bd337dd 100644 --- a/MyLayoutDemo/AllTest9CollectionViewCell.m +++ b/MyLayoutDemo/AllTest9CollectionViewCell.m @@ -33,7 +33,7 @@ -(instancetype)initWithFrame:(CGRect)frame _rootLayout.subviewVSpace = 10; _rootLayout.myHorzMargin = 0; _rootLayout.wrapContentHeight = YES; - _rootLayout.cacheEstimatedRect = YES; + _rootLayout.cacheEstimatedRect = YES; //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! [self.contentView addSubview:_rootLayout]; _titleLabel = [UILabel new]; diff --git a/MyLayoutDemo/FLLTest7ViewController.h b/MyLayoutDemo/FLLTest7ViewController.h new file mode 100644 index 0000000..44ef75f --- /dev/null +++ b/MyLayoutDemo/FLLTest7ViewController.h @@ -0,0 +1,16 @@ +// +// FLLTest7ViewController.h +// MyLayout +// +// Created by apple on 17/2/20. +// Copyright © 2017年 YoungSoft. All rights reserved. +// + +#import + +/** + *6.FlowLayout - Auto Arrange + */ +@interface FLLTest7ViewController : UIViewController + +@end diff --git a/MyLayoutDemo/FLLTest7ViewController.m b/MyLayoutDemo/FLLTest7ViewController.m new file mode 100644 index 0000000..359fbe1 --- /dev/null +++ b/MyLayoutDemo/FLLTest7ViewController.m @@ -0,0 +1,145 @@ +// +// FLLTest7ViewController.m +// MyLayout +// +// Created by apple on 17/2/20. +// Copyright © 2017年 YoungSoft. All rights reserved. +// + +#import "FLLTest7ViewController.h" +#import "MyLayout.h" +#import "CFTool.h" + + +@implementation FLLTest7ViewController + + +-(void)createItems:(NSArray*)titles inFlowLayout:(MyFlowLayout*)flowLayout +{ + for (NSString *title in titles) + { + UILabel *label = [UILabel new]; + label.text = title; + label.wrapContentSize = YES; //内容自适应。 + label.backgroundColor = [CFTool color:(random()%14 + 1)]; + label.font = [CFTool font:16]; + [flowLayout addSubview:label]; + } +} + +-(void)loadView +{ + /* + 这个例子主要用来介绍数量约束流式布局的自动排列和紧凑排列的能力,目的是为了实现类似于瀑布流的功能,下面的代码您将能看到水平和垂直两种应用场景。 + 每种应用场景中,我们通过设置autoArrange为YES和arrangedGravity属性为MyGravity_Horz_Between或者MyGravity_Vert_Between来分别实现两种不同的 + 排列策略: + autoArrange: 的策略是让总体的空间达到最高效的利用,但是他会打乱视图添加的顺序。 + arrangedGravity: 的策略则不会打乱视图的添加顺序,因此他的总体空间的利用率可能会不如autoArrange那么高。 + */ + + /* + 需要注意的是,当您的数据量比较小时,我们可以考虑使用流式布局来实现瀑布流,而当你的数据量比较大,并且需要考虑复用,那么为了内存上的考虑建议您还是使用tableView或者collectionView来实现。 + */ + + NSArray *titles = @[@"11111111111111111", @"222222222222222222222222222",@"3333333333333", @"4444444444444444444444", @"55555555", @"6666666666666", @"77777777", @"8888888888888888888888", @"99"]; + + + + self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + + MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + rootLayout.gravity = MyGravity_Horz_Fill; + rootLayout.subviewSpace = 20; + rootLayout.backgroundColor = [UIColor whiteColor]; + self.view = rootLayout; + + //水平瀑布流1。 + UIScrollView *scrollView1 = [UIScrollView new]; + scrollView1.wrapContentHeight = YES; //这里可以设置滚动视图的高度为包裹属性,表示他的高度依赖于布局视图的高度。 + [rootLayout addSubview:scrollView1]; + + MyFlowLayout *flowLayout1 = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:3]; + flowLayout1.backgroundColor = [CFTool color:5]; + flowLayout1.wrapContentSize = YES; //流式布局的尺寸由里面的子视图的整体尺寸决定。 + flowLayout1.widthSize.lBound(scrollView1.widthSize, 0, 1); //虽然尺寸是包裹的,但是最小宽度不能小于父视图的宽度 + flowLayout1.autoArrange = YES; //通过将流式布局的autoArrange属性设置为YES可以实现里面的子视图进行紧凑的自动排列。 + flowLayout1.subviewSpace = 10; + flowLayout1.padding = UIEdgeInsetsMake(10, 10, 10, 10); + [scrollView1 addSubview:flowLayout1]; + [self createItems:titles inFlowLayout:flowLayout1]; + + + //水平瀑布流2。 + UIScrollView *scrollView2 = [UIScrollView new]; + scrollView2.wrapContentHeight = YES; + [rootLayout addSubview:scrollView2]; + + MyFlowLayout *flowLayout2 = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:3]; + flowLayout2.backgroundColor = [CFTool color:6]; + flowLayout2.wrapContentSize = YES; + flowLayout2.widthSize.lBound(scrollView2.widthSize, 0, 1); //虽然尺寸是包裹的,但是最小宽度不能小于父视图的宽度 + flowLayout2.subviewSpace = 10; + flowLayout2.padding = UIEdgeInsetsMake(10, 10, 10, 10); + flowLayout2.arrangedGravity = MyGravity_Horz_Between; //通过将水平流式布局的arrangeGravity属性设置为MyGravity_Horz_Between,我们将得到里面的子视图在每行都会被紧凑的排列。大家可以看到和上面的将autoArrange设置为YES的不同的效果。 + [scrollView2 addSubview:flowLayout2]; + [self createItems:titles inFlowLayout:flowLayout2]; + + + //垂直瀑布流1 + UIScrollView *scrollView3 = [UIScrollView new]; + scrollView3.weight = 0.5; //占用父布局剩余的高度的一半 + [rootLayout addSubview:scrollView3]; + + MyFlowLayout *flowLayout3 = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; + flowLayout3.backgroundColor = [CFTool color:5]; + flowLayout3.wrapContentHeight = YES; + flowLayout3.heightSize.lBound(scrollView3.heightSize, 0, 1); //虽然是包裹尺寸,但是最小不能小于父视图的高度。 + flowLayout3.myHorzMargin = 0; + flowLayout3.gravity = MyGravity_Horz_Fill; //均分宽度。 + flowLayout3.autoArrange = YES; //通过将流式布局的autoArrange属性设置为YES可以实现里面的子视图进行紧凑的自动排列。 + flowLayout3.subviewSpace = 10; + flowLayout3.padding = UIEdgeInsetsMake(10, 10, 10, 10); + [scrollView3 addSubview:flowLayout3]; + [self createItems:titles inFlowLayout:flowLayout3]; + + + //垂直瀑布流2 + UIScrollView *scrollView4 = [UIScrollView new]; + scrollView4.weight = 0.5; //占用父布局剩余的高度的一半 + [rootLayout addSubview:scrollView4]; + + MyFlowLayout *flowLayout4 = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; + flowLayout4.backgroundColor = [CFTool color:6]; + flowLayout4.wrapContentHeight = YES; + flowLayout4.heightSize.lBound(scrollView4.heightSize, 0, 1); + flowLayout4.myHorzMargin = 0; + flowLayout4.gravity = MyGravity_Horz_Fill; //均分宽度。 + flowLayout4.arrangedGravity = MyGravity_Vert_Between; //通过将垂直流式布局的arrangeGravity属性设置为MyGravity_Vert_Between,我们将得到里面的子视图在每列都会被紧凑的排列。大家可以看到和上面的将autoArrange设置为YES的不同的效果。 + flowLayout4.subviewSpace = 10; + flowLayout4.padding = UIEdgeInsetsMake(10, 10, 10, 10); + [scrollView4 addSubview:flowLayout4]; + [self createItems:titles inFlowLayout:flowLayout4]; + +} + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/MyLayoutDemo/Info.plist b/MyLayoutDemo/Info.plist index 0babf71..e0e2348 100644 --- a/MyLayoutDemo/Info.plist +++ b/MyLayoutDemo/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.5.2 + 1.5.3 CFBundleSignature ???? CFBundleVersion diff --git a/MyLayoutDemo/ViewController.m b/MyLayoutDemo/ViewController.m index 327139f..c7745ad 100644 --- a/MyLayoutDemo/ViewController.m +++ b/MyLayoutDemo/ViewController.m @@ -41,6 +41,7 @@ #import "FLLTest4ViewController.h" #import "FLLTest5ViewController.h" #import "FLLTest6ViewController.h" +#import "FLLTest7ViewController.h" #import "AllTest1ViewController.h" @@ -182,6 +183,9 @@ -(NSArray*)demoTypeList }, @{@"title":NSLocalizedString(@"6.FlowLayout - Scroll", @""), @"class":[FLLTest6ViewController class] + }, + @{@"title":NSLocalizedString(@"7.FlowLayout - Auto Arrange", @""), + @"class":[FLLTest7ViewController class] } ] }, diff --git a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings index 8f6b804..ddf4134 100644 --- a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings +++ b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings @@ -33,6 +33,7 @@ "4.FlowLayout - Weight" = "4.流式布局-对线性布局的替代方案"; "5.FlowLayout - Paging" = "5.流式布局-对分页滚动的支持"; "6.FlowLayout - Scroll" = "6.流式布局-不同方向的滚动"; +"7.FlowLayout - Auto Arrange" = "7.流式布局-自动布局和对瀑布流的支持"; "1.FloatLayout - Float" = "1.浮动布局-浮动效果的演示"; "2.FloatLayout - Jagged" = "2.浮动布局-仿天猫淘宝首页实现" ; "3.FloatLayout - Card news" = "3.浮动布局-仿ZAKER今日头条实现"; From b80a821a29d6c5ddbd96588c41d33ee9c93dc522 Mon Sep 17 00:00:00 2001 From: letian <916235259@qq.com> Date: Thu, 10 May 2018 22:02:17 -0600 Subject: [PATCH 013/115] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9C=8B=E5=8F=8B?= =?UTF-8?q?=E5=9C=88=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 6148 -> 6148 bytes MyLayout.xcodeproj/project.pbxproj | 30 ++- .../xcshareddata/IDEWorkspaceChecks.plist | 8 + MyLayoutDemo/AllTest10Cell.h | 15 ++ MyLayoutDemo/AllTest10Cell.m | 91 +++++++ MyLayoutDemo/AllTest10HeaderView.h | 21 ++ MyLayoutDemo/AllTest10HeaderView.m | 237 ++++++++++++++++++ MyLayoutDemo/AllTest10Model.h | 45 ++++ MyLayoutDemo/AllTest10Model.m | 83 ++++++ MyLayoutDemo/AllTest10ViewController.h | 13 + MyLayoutDemo/AllTest10ViewController.m | 151 +++++++++++ MyLayoutDemo/AllTest1ViewController.m | 2 +- .../friend_zan.imageset/Contents.json | 18 ++ .../friend_zan.imageset/friend_zan@2x.png | Bin 0 -> 2040 bytes .../friend_zan.imageset/friend_zan@3x.png | Bin 0 -> 2687 bytes .../interactive_fill.imageset/Contents.json | 18 ++ .../interactive_fill@2x.png | Bin 0 -> 2611 bytes .../interactive_fill@3x.png | Bin 0 -> 3613 bytes .../zan_select.imageset/Contents.json | 18 ++ .../zan_select.imageset/zan_select@2x.png | Bin 0 -> 2205 bytes .../zan_select.imageset/zan_select@3x.png | Bin 0 -> 2901 bytes MyLayoutDemo/LLTest2ViewController.m | 2 +- MyLayoutDemo/ViewController.m | 4 + .../zh-Hans.lproj/Localizable.strings | 1 + 24 files changed, 752 insertions(+), 5 deletions(-) create mode 100644 MyLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 MyLayoutDemo/AllTest10Cell.h create mode 100644 MyLayoutDemo/AllTest10Cell.m create mode 100644 MyLayoutDemo/AllTest10HeaderView.h create mode 100644 MyLayoutDemo/AllTest10HeaderView.m create mode 100644 MyLayoutDemo/AllTest10Model.h create mode 100644 MyLayoutDemo/AllTest10Model.m create mode 100644 MyLayoutDemo/AllTest10ViewController.h create mode 100644 MyLayoutDemo/AllTest10ViewController.m create mode 100644 MyLayoutDemo/Images.xcassets/friend_zan.imageset/Contents.json create mode 100644 MyLayoutDemo/Images.xcassets/friend_zan.imageset/friend_zan@2x.png create mode 100644 MyLayoutDemo/Images.xcassets/friend_zan.imageset/friend_zan@3x.png create mode 100644 MyLayoutDemo/Images.xcassets/interactive_fill.imageset/Contents.json create mode 100644 MyLayoutDemo/Images.xcassets/interactive_fill.imageset/interactive_fill@2x.png create mode 100644 MyLayoutDemo/Images.xcassets/interactive_fill.imageset/interactive_fill@3x.png create mode 100644 MyLayoutDemo/Images.xcassets/zan_select.imageset/Contents.json create mode 100644 MyLayoutDemo/Images.xcassets/zan_select.imageset/zan_select@2x.png create mode 100644 MyLayoutDemo/Images.xcassets/zan_select.imageset/zan_select@3x.png diff --git a/.DS_Store b/.DS_Store index 4365ec0afd6e5937ca78d46a94675f5da25c610f..e83009f53647cbad0187731f40ed2464277b23ee 100644 GIT binary patch delta 79 zcmZoMXfc=|#>CJ*u~2NHo+2aD!~pBb1|lqz`5BFvnWUH|^Dt^mzQf4N#8j~PBcmAG iB&Khh**W+*fI5Ku@640=MGP4kCfo2xZ;laJ!3+RG#T79C delta 118 zcmZoMXfc=|#>B`mu~2NHo+2a5!~pBb0*nnnMvo~o^MfT5do%=c^Icq0N=uR%7_Lj) zh+$xWh^4^9#I#p{#U{StWn#IonUPV3Z8JLuKL^lMAm=;tWPTAt4n_tBh6W(s>>;v; F82}5TAX)$b diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index bc157d0..5bb9cc4 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -164,6 +164,10 @@ 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */; }; 44EBDA8C1F619A6300B47CBD /* GLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */; }; 44EBDA8E1F619C9000B47CBD /* GridLayoutDemo4.json in Resources */ = {isa = PBXBuildFile; fileRef = 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */; }; + 6740E1F820A52D9E00AFBC5A /* AllTest10ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */; }; + 6740E1FB20A52DA900AFBC5A /* AllTest10Model.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */; }; + 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */; }; + 6740E20120A52DC100AFBC5A /* AllTest10Cell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -401,6 +405,14 @@ 44EBDA8A1F619A6300B47CBD /* GLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest4ViewController.h; sourceTree = ""; }; 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest4ViewController.m; sourceTree = ""; }; 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo4.json; sourceTree = ""; }; + 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10ViewController.h; sourceTree = ""; }; + 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10ViewController.m; sourceTree = ""; }; + 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10Model.m; sourceTree = ""; }; + 6740E1FA20A52DA900AFBC5A /* AllTest10Model.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10Model.h; sourceTree = ""; }; + 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10HeaderView.m; sourceTree = ""; }; + 6740E1FD20A52DB000AFBC5A /* AllTest10HeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10HeaderView.h; sourceTree = ""; }; + 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10Cell.m; sourceTree = ""; }; + 6740E20020A52DC100AFBC5A /* AllTest10Cell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10Cell.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -642,6 +654,8 @@ 18D3C9841EDF084000D3DE43 /* AllTest8ViewController.m */, 200A26D71FA8A90300B06E7B /* AllTest9ViewController.h */, 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */, + 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */, + 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */, 18D3C9021EDF068200D3DE43 /* AllTestModel&View */, ); name = IntegratedDemo; @@ -660,6 +674,12 @@ 18D3C9701EDF082800D3DE43 /* AllTestDataModel.m */, 200A26DA1FA96B2400B06E7B /* AllTest9CollectionViewCell.h */, 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */, + 6740E1FA20A52DA900AFBC5A /* AllTest10Model.h */, + 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */, + 6740E1FD20A52DB000AFBC5A /* AllTest10HeaderView.h */, + 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */, + 6740E20020A52DC100AFBC5A /* AllTest10Cell.h */, + 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */, ); name = "AllTestModel&View"; sourceTree = ""; @@ -944,7 +964,7 @@ }; 1840828C1B2C46E8003F378B = { CreatedOnToolsVersion = 6.3.2; - DevelopmentTeam = BGQ8WB468K; + DevelopmentTeam = 2TLR37RWPL; ProvisioningStyle = Automatic; }; 184082A51B2C46E8003F378B = { @@ -1086,6 +1106,7 @@ 18D3C9731EDF082800D3DE43 /* AllTest2TableViewCell.m in Sources */, 18D3C95F1EDF07F800D3DE43 /* FOLTest6ViewController.m in Sources */, 182225D51E77E5930081AA4B /* MyLayoutSize.m in Sources */, + 6740E20120A52DC100AFBC5A /* AllTest10Cell.m in Sources */, 18D3C93A1EDF07C000D3DE43 /* FLLTest2ViewController.m in Sources */, 18D3C95A1EDF07F800D3DE43 /* FOLTest1ViewController.m in Sources */, 182225D01E77E5930081AA4B /* MyLayoutPos.m in Sources */, @@ -1107,6 +1128,7 @@ 18D3C9941EDF08F800D3DE43 /* YYFPSLabel.m in Sources */, 18D3C91D1EDF078200D3DE43 /* FLTest2ViewController.m in Sources */, 18D3C9661EDF080800D3DE43 /* TLTest1ViewController.m in Sources */, + 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */, 18D3C94A1EDF07E700D3DE43 /* PLTest2ViewController.m in Sources */, 205642881F4CFFB600E8BDDE /* MyBorderline.m in Sources */, 18D3C93C1EDF07C000D3DE43 /* FLLTest4ViewController.m in Sources */, @@ -1139,6 +1161,7 @@ 18D3C9711EDF082800D3DE43 /* AllTest1TableViewCell.m in Sources */, 182225CF1E77E5930081AA4B /* MyFloatLayout.m in Sources */, 18D3C92B1EDF07A700D3DE43 /* RLTest4ViewController.m in Sources */, + 6740E1FB20A52DA900AFBC5A /* AllTest10Model.m in Sources */, 18D3C92C1EDF07A700D3DE43 /* RLTest5ViewController.m in Sources */, 204DC321209D5A8700F6CB57 /* TLTest4ViewController.m in Sources */, 182DB6431EF7876200E2D65D /* MyGridLayout.m in Sources */, @@ -1147,6 +1170,7 @@ 18D3C9721EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m in Sources */, 208157C31F5A886400E945B6 /* MyLayoutDelegate.m in Sources */, 18D3C94D1EDF07E700D3DE43 /* PLTest5ViewController.m in Sources */, + 6740E1F820A52D9E00AFBC5A /* AllTest10ViewController.m in Sources */, 18D3C9851EDF084000D3DE43 /* AllTest1ViewController.m in Sources */, 182225D21E77E5930081AA4B /* MyMaker.m in Sources */, 182225C91E77E5930081AA4B /* MyBaseLayout.m in Sources */, @@ -1411,7 +1435,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = BGQ8WB468K; + DEVELOPMENT_TEAM = 2TLR37RWPL; GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1433,7 +1457,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = BGQ8WB468K; + DEVELOPMENT_TEAM = 2TLR37RWPL; GCC_PREPROCESSOR_DEFINITIONS = ""; INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; diff --git a/MyLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/MyLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/MyLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/MyLayoutDemo/AllTest10Cell.h b/MyLayoutDemo/AllTest10Cell.h new file mode 100644 index 0000000..3af7cef --- /dev/null +++ b/MyLayoutDemo/AllTest10Cell.h @@ -0,0 +1,15 @@ +// +// AllTest10Cell.h +// FriendListDemo +// +// Created by bsj_mac_2 on 2018/5/7. +// Copyright © 2018年 bsj_mac_2. All rights reserved. +// + +#import +#import "MyLayout.h" + +@interface AllTest10Cell : UITableViewCell + +- (void)setCommentsText:(NSString *)text; +@end diff --git a/MyLayoutDemo/AllTest10Cell.m b/MyLayoutDemo/AllTest10Cell.m new file mode 100644 index 0000000..12d0152 --- /dev/null +++ b/MyLayoutDemo/AllTest10Cell.m @@ -0,0 +1,91 @@ +// +// AllTest10Cell.m +// FriendListDemo +// +// Created by bsj_mac_2 on 2018/5/7. +// Copyright © 2018年 bsj_mac_2. All rights reserved. +// + +#import "AllTest10Cell.h" + +@interface AllTest10Cell () +@property(nonatomic, strong) UILabel *commentsLabel; +@property (strong, nonatomic) MyLinearLayout *rootLayout; +@end + +@implementation AllTest10Cell + +-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier +{ + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self != nil) + { + [self createLinearRootLayout]; + } + + return self; +} + + +//如果您的最低支持是iOS8,那么你可以重载这个方法来动态的评估cell的高度,Autolayout内部是通过这个方法来评估高度的,因此如果用MyLayout实现的话就不需要调用基类的方法,而是调用根布局视图的sizeThatFits来评估获取动态的高度。 +- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority +{ + /* + 通过布局视图的sizeThatFits方法能够评估出UITableViewCell的动态高度。sizeThatFits并不会进行布局而只是评估布局的尺寸。 + 因为cell的高度是自适应的,因此这里通过调用高度为wrap的布局视图的sizeThatFits来获取真实的高度。 + */ + + if (@available(iOS 11.0, *)) { + //如果你的界面要支持横屏的话,因为iPhoneX的横屏左右有44的安全区域,所以这里要减去左右的安全区域的值,来作为布局宽度尺寸的评估值。 + //如果您的界面不需要支持横屏,或者延伸到安全区域外则不需要做这个特殊处理,而直接使用else部分的代码即可。 + return [self.rootLayout sizeThatFits:CGSizeMake(targetSize.width - self.safeAreaInsets.left - self.safeAreaInsets.right, targetSize.height)]; + } else { + return [self.rootLayout sizeThatFits:targetSize]; //如果使用系统自带的分割线,请记得将返回的高度height+1 + } +} + +#pragma mark -- Layout Construction + +//用线性布局来实现UI界面 +-(void)createLinearRootLayout +{ + _rootLayout= [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + _rootLayout.padding = UIEdgeInsetsMake(0, 65, 0, 10); + _rootLayout.cacheEstimatedRect = YES; + + /* + 在UITableViewCell中使用MyLayout中的布局时请将布局视图作为contentView的子视图。如果我们的UITableViewCell的高度是动态的,请务必在将布局视图添加到contentView之前进行如下设置: + _rootLayout.widthSize.equalTo(self.contentView.widthSize); + _rootLayout.wrapContentHeight = YES; + */ + // _rootLayout.widthSize.equalTo(self.contentView.widthSize); + _rootLayout.myHorzMargin = MyLayoutPos.safeAreaMargin; + _rootLayout.wrapContentHeight = YES; + _rootLayout.wrapContentWidth = NO; + //这里设置其他位置有间隔线而最后一行没有下划线。我们可以借助布局视图本身所提供的边界线来代替掉系统默认的cell之间的间隔线,因为布局视图的边界线所提供的能力要大于默认的间隔线。 + MyBorderline *bld = [[MyBorderline alloc] initWithColor:[UIColor whiteColor]]; + self.rootLayout.bottomBorderline = bld; + [self.contentView addSubview:_rootLayout]; //如果您将布局视图作为子视图添加到UITableViewCell本身,并且同时用了myLeft和myRight来做边界的话,那么有可能最终展示的宽度会不正确。经过试验是因为对UITableViewCell本身的KVO监控所得到的新老尺寸的问题导致的这应该是iOS的一个BUG。所以这里建议最好是把布局视图添加到UITableViewCell的子视图contentView里面去。 + + MyLinearLayout *giveLikeLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + giveLikeLayout.padding = UIEdgeInsetsMake(5, 6, 5, 6); + giveLikeLayout.weight = 1; + giveLikeLayout.myHorzMargin = 0; + giveLikeLayout.backgroundColor = [UIColor colorWithRed:240.0/255 green:240.0/255 blue:240.0/255 alpha:1]; + [self.rootLayout addSubview:giveLikeLayout]; + + _commentsLabel = [UILabel new]; + _commentsLabel.text = @"正文"; + _commentsLabel.textColor = [UIColor blueColor]; + _commentsLabel.font = [UIFont systemFontOfSize:12]; + _commentsLabel.myLeading = 0; + _commentsLabel.myTrailing = 0; //垂直线性布局里面如果同时设置了左右边距则能确定子视图的宽度,这里表示宽度和父视图相等。 + _commentsLabel.wrapContentHeight = YES; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + [giveLikeLayout addSubview:_commentsLabel]; +} + +- (void)setCommentsText:(NSString *)text { + self.commentsLabel.text = text; +} + +@end diff --git a/MyLayoutDemo/AllTest10HeaderView.h b/MyLayoutDemo/AllTest10HeaderView.h new file mode 100644 index 0000000..e3959f6 --- /dev/null +++ b/MyLayoutDemo/AllTest10HeaderView.h @@ -0,0 +1,21 @@ +// +// AllTest10HeaderView.h +// FriendListDemo +// +// Created by 谢海龙 on 2018/5/8. +// Copyright © 2018年 bsj_mac_2. All rights reserved. +// + +#import +#import "MyLayout.h" +@class AllTest10Model; +@class AllTest10HeaderView; +typedef void(^PraiseClickHandler)(AllTest10HeaderView *headerView, AllTest10Model *model); +typedef void(^CommentsClickHandler)(AllTest10HeaderView *headerView, AllTest10Model *model); + +@interface AllTest10HeaderView : UITableViewHeaderFooterView + +@property (strong, nonatomic) AllTest10Model * model; +@property (copy, nonatomic) PraiseClickHandler praiseClickHandler; +@property (copy, nonatomic) CommentsClickHandler commentsClickHandler; +@end diff --git a/MyLayoutDemo/AllTest10HeaderView.m b/MyLayoutDemo/AllTest10HeaderView.m new file mode 100644 index 0000000..f708e6e --- /dev/null +++ b/MyLayoutDemo/AllTest10HeaderView.m @@ -0,0 +1,237 @@ +// +// AllTest10HeaderView.m +// FriendListDemo +// +// Created by 谢海龙 on 2018/5/8. +// Copyright © 2018年 bsj_mac_2. All rights reserved. +// + +#import "AllTest10HeaderView.h" +#import "AllTest10Model.h" + +@interface AllTest10HeaderView () +@property (strong, nonatomic) MyLinearLayout *rootLayout; +@property(nonatomic, strong) UIImageView *headImageView; +@property(nonatomic, strong) UILabel *nickNameLabel; +@property(nonatomic, strong) UILabel *textMessageLabel; +@property(nonatomic, strong) UILabel *timeLabel; +@property(nonatomic, strong) UILabel *browLabel; +@property(nonatomic, strong) UILabel *giveLikeLabel; +@property (strong, nonatomic) NSArray * nineImageViews; +@property (strong, nonatomic) MyFlowLayout * nineFlowLayout; +@property (strong, nonatomic) UIButton * giveLikeButton; +@property (strong, nonatomic) UIButton * commentsButton; +@property (strong, nonatomic) MyLinearLayout *giveLikeLayout; +@end + +@implementation AllTest10HeaderView + +- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier { + if (self = [super initWithReuseIdentifier:reuseIdentifier]) { + [self createLinearRootLayout]; + } + return self; +} + +#pragma mark -- Layout Construction + +//用线性布局来实现UI界面 +-(void)createLinearRootLayout +{ + _rootLayout= [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + _rootLayout.padding = UIEdgeInsetsMake(10, 10, 0.3, 10); +// _rootLayout.cacheEstimatedRect = YES; + _rootLayout.backgroundColor = [UIColor whiteColor]; + /* + 在UITableViewCell中使用MyLayout中的布局时请将布局视图作为contentView的子视图。如果我们的UITableViewCell的高度是动态的,请务必在将布局视图添加到contentView之前进行如下设置: + _rootLayout.widthSize.equalTo(self.contentView.widthSize); + _rootLayout.wrapContentHeight = YES; + */ + // _rootLayout.widthSize.equalTo(self.contentView.widthSize); + _rootLayout.myHorzMargin = MyLayoutPos.safeAreaMargin; + _rootLayout.wrapContentHeight = YES; + _rootLayout.wrapContentWidth = NO; + [self.contentView addSubview:_rootLayout]; //如果您将布局视图作为子视图添加到UITableViewCell本身,并且同时用了myLeft和myRight来做边界的话,那么有可能最终展示的宽度会不正确。经过试验是因为对UITableViewCell本身的KVO监控所得到的新老尺寸的问题导致的这应该是iOS的一个BUG。所以这里建议最好是把布局视图添加到UITableViewCell的子视图contentView里面去。 + + + + /* + 用线性布局实现时,整体用一个水平线性布局:左边是头像,右边是一个垂直的线性布局。垂直线性布局依次加入昵称、文本消息、图片消息。 + */ + + + _headImageView = [UIImageView new]; + _headImageView.myWidth = 50; + _headImageView.myHeight = 50; + _headImageView.backgroundColor = [UIColor colorWithRed:240.0/255 green:240.0/255 blue:240.0/255 alpha:1]; + _headImageView.contentMode = UIViewContentModeScaleAspectFill; + _headImageView.clipsToBounds = YES; + [_rootLayout addSubview:_headImageView]; + + + MyLinearLayout *messageLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + messageLayout.weight = 1; + messageLayout.myLeading = 5; //前面2行代码描述的是垂直布局占用除头像外的所有宽度,并和头像保持5个点的间距。 + messageLayout.subviewVSpace = 5; //垂直布局里面所有子视图都保持5个点的间距。 + [_rootLayout addSubview:messageLayout]; + + _nickNameLabel = [UILabel new]; + _nickNameLabel.text = @""; + _nickNameLabel.font = [UIFont systemFontOfSize:14]; + [messageLayout addSubview:_nickNameLabel]; + + [self.nickNameLabel sizeToFit]; + + _textMessageLabel = [UILabel new]; + _textMessageLabel.text = @""; + _textMessageLabel.myLeading = 0; + _textMessageLabel.myTrailing = 0; //垂直线性布局里面如果同时设置了左右边距则能确定子视图的宽度,这里表示宽度和父视图相等。 + _textMessageLabel.wrapContentHeight = YES; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + [messageLayout addSubview:_textMessageLabel]; + + _nineFlowLayout = [[MyFlowLayout alloc] initWithOrientation:MyOrientation_Vert arrangedCount:3]; + _nineFlowLayout.gravity = MyGravity_Horz_Fill; //所有子视图水平填充,也就是所有子视图的宽度相等。 + _nineFlowLayout.myHorzMargin = 0; + _nineFlowLayout.subviewHSpace = 5; + _nineFlowLayout.subviewVSpace = 5; + _nineFlowLayout.wrapContentHeight = YES; + _nineFlowLayout.wrapContentWidth = NO; + [messageLayout addSubview:_nineFlowLayout]; + + _timeLabel = [UILabel new]; + _timeLabel.text = @""; + _timeLabel.font = [UIFont systemFontOfSize:14]; + [messageLayout addSubview:_timeLabel]; + + MyLinearLayout *hLinearLayout = [[MyLinearLayout alloc] initWithOrientation:MyOrientation_Horz]; + hLinearLayout.wrapContentHeight = YES; + hLinearLayout.gravity = MyGravity_Horz_Between | MyGravity_Vert_Center; + hLinearLayout.myHorzMargin = 0; + [messageLayout addSubview:hLinearLayout]; + + _browLabel = [UILabel new]; + _browLabel.text = @""; + _browLabel.font = [UIFont systemFontOfSize:14]; + _browLabel.wrapContentWidth = YES; + _browLabel.wrapContentHeight = YES; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + [hLinearLayout addSubview:_browLabel]; + + MyLinearLayout *actionshLinearLayout = [[MyLinearLayout alloc] initWithOrientation:MyOrientation_Horz]; + actionshLinearLayout.rightPadding = 5; + actionshLinearLayout.wrapContentHeight = YES; + actionshLinearLayout.gravity = MyGravity_Vert_Center; + actionshLinearLayout.myHorzMargin = 0; + [hLinearLayout addSubview:actionshLinearLayout]; + + _giveLikeButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_giveLikeButton setImage:[UIImage imageNamed:@"friend_zan"] forState:UIControlStateNormal]; + [_giveLikeButton setImage:[UIImage imageNamed:@"zan_select"] forState:UIControlStateSelected]; + _giveLikeButton.mySize = CGSizeMake(30, 30); + [_giveLikeButton addTarget:self action:@selector(praiseClick) forControlEvents:UIControlEventTouchUpInside]; + [_giveLikeButton sizeToFit]; + [actionshLinearLayout addSubview:_giveLikeButton]; + + _commentsButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_commentsButton setImage:[UIImage imageNamed:@"interactive_fill"] forState:UIControlStateNormal]; + [_commentsButton addTarget:self action:@selector(commentsClick) forControlEvents:UIControlEventTouchUpInside]; + _commentsButton.myLeft = 20; + _commentsButton.mySize = CGSizeMake(30, 30); + [_commentsButton sizeToFit]; + [actionshLinearLayout addSubview:_commentsButton]; + + MyLinearLayout *giveLikeLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + giveLikeLayout.padding = UIEdgeInsetsMake(8, 5, 8, 5); + giveLikeLayout.myHorzMargin = 0; + giveLikeLayout.backgroundColor = [UIColor colorWithRed:240.0/255 green:240.0/255 blue:240.0/255 alpha:1]; + [messageLayout addSubview:giveLikeLayout]; + _giveLikeLayout = giveLikeLayout; + _giveLikeLabel = [UILabel new]; + _giveLikeLabel.text = @""; + _giveLikeLabel.textColor = [UIColor blueColor]; + _giveLikeLabel.font = [UIFont systemFontOfSize:12]; + _giveLikeLabel.myHorzMargin = 0; + _giveLikeLabel.wrapContentHeight = YES; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + [giveLikeLayout addSubview:_giveLikeLabel]; + +} + +- (void)praiseClick { + if (self.praiseClickHandler) { + self.praiseClickHandler(self,self.model); + } +} + +- (void)commentsClick { + if (self.commentsClickHandler) { + self.commentsClickHandler(self,self.model); + } +} + +- (void)setCountWithImageArray:(NSArray *)array { + [_nineFlowLayout removeAllSubviews]; + __weak typeof(self) weakSelf = self; + [self.nineImageViews enumerateObjectsUsingBlock:^(UIImageView * _Nonnull imageView, NSUInteger idx, BOOL * _Nonnull stop) { + if (idx < array.count) { + imageView.image = [UIImage imageNamed:array[idx]]; + [weakSelf.nineFlowLayout addSubview:imageView]; + } + }]; +} + +- (void)setModel:(AllTest10Model *)model { + _model = model; + + UIImage *image = [UIImage imageNamed:model.icon]; + _headImageView.image = image; + _giveLikeButton.selected = model.isGiveLike; + _nickNameLabel.text = model.name; + [_nickNameLabel sizeToFit]; + _textMessageLabel.text = model.content; + [_textMessageLabel sizeToFit]; + _timeLabel.text = model.time; + [_timeLabel sizeToFit]; + _browLabel.text = [NSString stringWithFormat:@"浏览%ld次",model.browCount]; + [_browLabel sizeToFit]; + + NSString *giveLikeText = model.giveLikeNames.count > 0 ? [NSString stringWithFormat:@"%@等点了👍",[model.giveLikeNames componentsJoinedByString:@"、"]] : @""; + _giveLikeLayout.myVisibility = model.giveLikeNames.count > 0 ? MyVisibility_Visible : MyVisibility_Gone; + _nineFlowLayout.myVisibility = model.commentsImageUrls.count > 0 ? MyVisibility_Visible : MyVisibility_Gone; + _giveLikeLabel.text = giveLikeText; + [_giveLikeLabel sizeToFit]; + [self setCountWithImageArray:model.commentsImageUrls]; +} + +//如果您的最低支持是iOS8,那么你可以重载这个方法来动态的评估cell的高度,Autolayout内部是通过这个方法来评估高度的,因此如果用MyLayout实现的话就不需要调用基类的方法,而是调用根布局视图的sizeThatFits来评估获取动态的高度。 +- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority +{ + /* + 通过布局视图的sizeThatFits方法能够评估出UITableViewCell的动态高度。sizeThatFits并不会进行布局而只是评估布局的尺寸。 + 因为cell的高度是自适应的,因此这里通过调用高度为wrap的布局视图的sizeThatFits来获取真实的高度。 + */ + + if (@available(iOS 11.0, *)) { + //如果你的界面要支持横屏的话,因为iPhoneX的横屏左右有44的安全区域,所以这里要减去左右的安全区域的值,来作为布局宽度尺寸的评估值。 + //如果您的界面不需要支持横屏,或者延伸到安全区域外则不需要做这个特殊处理,而直接使用else部分的代码即可。 + return [self.rootLayout sizeThatFits:CGSizeMake(targetSize.width - self.safeAreaInsets.left - self.safeAreaInsets.right, targetSize.height)]; + } else { + return [self.rootLayout sizeThatFits:targetSize]; //如果使用系统自带的分割线,请记得将返回的高度height+1 + } +} + +- (NSArray *)nineImageViews { + if (!_nineImageViews) { + NSMutableArray *imageViewArray = [NSMutableArray array]; + for (int i = 0; i<9; i++) { + UIImageView *imageView = [[UIImageView alloc] init]; + imageView.contentMode = UIViewContentModeScaleAspectFill; + imageView.clipsToBounds = YES; + imageView.backgroundColor = [UIColor colorWithRed:240.0/255 green:240.0/255 blue:240.0/255 alpha:1]; + imageView.heightSize.equalTo(imageView.widthSize); + [imageViewArray addObject:imageView]; + } + _nineImageViews = [imageViewArray copy]; + } + return _nineImageViews; +} + +@end diff --git a/MyLayoutDemo/AllTest10Model.h b/MyLayoutDemo/AllTest10Model.h new file mode 100644 index 0000000..a71008e --- /dev/null +++ b/MyLayoutDemo/AllTest10Model.h @@ -0,0 +1,45 @@ +// +// AllTest10Model.h +// FriendListDemo +// +// Created by bsj_mac_2 on 2018/5/9. +// Copyright © 2018年 bsj_mac_2. All rights reserved. +// + +#import + +@interface AllTest10Model : NSObject + +@property (copy, nonatomic) NSString * name; +@property (copy, nonatomic) NSString * icon; +@property (copy, nonatomic) NSString * content; +@property (copy, nonatomic) NSString * time; +@property (strong, nonatomic) NSArray * commentsImageUrls; +/* + 浏览次数 + */ +@property (assign, nonatomic) NSInteger browCount; +/* + 点赞姓名集合(简洁起见,实际开发中转换为对应) + */ +@property (strong, nonatomic) NSMutableArray * giveLikeNames; +/* + 评论集合 + */ +@property (strong, nonatomic) NSMutableArray * comments; +/* + 是否点赞 + */ +@property (assign, nonatomic) BOOL isGiveLike; + +/* + 模拟评论数据 + */ ++ (NSArray*)getRandTestDatasWithNumber:(NSInteger)modelsNumber; + +/* + 返回单挑模拟评论数据 + */ ++ (NSString *)randTestComments; + +@end diff --git a/MyLayoutDemo/AllTest10Model.m b/MyLayoutDemo/AllTest10Model.m new file mode 100644 index 0000000..b983ed5 --- /dev/null +++ b/MyLayoutDemo/AllTest10Model.m @@ -0,0 +1,83 @@ +// +// AllTest10Model.m +// FriendListDemo +// +// Created by bsj_mac_2 on 2018/5/9. +// Copyright © 2018年 bsj_mac_2. All rights reserved. +// + +#import "AllTest10Model.h" + +@implementation AllTest10Model + ++ (NSString *)randTestComments { + NSArray *textMessages = @[NSLocalizedString(@"A single line text", @""), + NSLocalizedString(@"This Demo is used to introduce the solution when use layout view to realize the UITableViewCell's dynamic height. We only need to use the layout view's sizeThatFits method to evaluate the size of the layout view. and you can touch the Cell to shrink the height when the Cell has a picture.", @""), + NSLocalizedString(@"Through layout view's sizeThatFits method can assess a UITableViewCell dynamic height.EstimateLayoutRect just to evaluate layout size but not set the size of the layout. here don't preach the width of 0 is the cause of the above UITableViewCell set the default width is 320 (regardless of any screen), so if we pass the width of 0 will be according to the width of 320 to evaluate UITableViewCell dynamic height, so when in 375 and 375 the width of the assessment of height will not be right, so here you need to specify the real width dimension;And the height is set to 0 mean height is not a fixed value need to evaluate. you can use all type layout view to realize UITableViewCell.", @""), + NSLocalizedString(@"This section not only has text but also hav picture. and picture below at text, text will wrap", @"") + ]; + return textMessages[arc4random_uniform((uint32_t)textMessages.count)]; +} + ++ (NSArray*)getRandTestDatasWithNumber:(NSInteger)modelsNumber { + + NSArray *headImages = @[@"head1", + @"head2", + @"minions1", + @"minions4" + ]; + + NSArray *nickNames = @[@"欧阳大哥", + @"醉里挑灯看键", + @"张三", + @"李四" + ]; + + NSArray *contentTexts = @[@"", + NSLocalizedString(@"A single line text", @""), + NSLocalizedString(@"This Demo is used to introduce the solution when use layout view to realize the UITableViewCell's dynamic height. We only need to use the layout view's sizeThatFits method to evaluate the size of the layout view. and you can touch the Cell to shrink the height when the Cell has a picture.", @""), + NSLocalizedString(@"Through layout view's sizeThatFits method can assess a UITableViewCell dynamic height.EstimateLayoutRect just to evaluate layout size but not set the size of the layout. here don't preach the width of 0 is the cause of the above UITableViewCell set the default width is 320 (regardless of any screen), so if we pass the width of 0 will be according to the width of 320 to evaluate UITableViewCell dynamic height, so when in 375 and 375 the width of the assessment of height will not be right, so here you need to specify the real width dimension;And the height is set to 0 mean height is not a fixed value need to evaluate. you can use all type layout view to realize UITableViewCell.", @""), + NSLocalizedString(@"This section not only has text but also hav picture. and picture below at text, text will wrap", @"") + ]; + + NSArray *textMessages = @[NSLocalizedString(@"A single line text", @""), + NSLocalizedString(@"This Demo is used to introduce the solution when use layout view to realize the UITableViewCell's dynamic height. We only need to use the layout view's sizeThatFits method to evaluate the size of the layout view. and you can touch the Cell to shrink the height when the Cell has a picture.", @""), + NSLocalizedString(@"Through layout view's sizeThatFits method can assess a UITableViewCell dynamic height.EstimateLayoutRect just to evaluate layout size but not set the size of the layout. here don't preach the width of 0 is the cause of the above UITableViewCell set the default width is 320 (regardless of any screen), so if we pass the width of 0 will be according to the width of 320 to evaluate UITableViewCell dynamic height, so when in 375 and 375 the width of the assessment of height will not be right, so here you need to specify the real width dimension;And the height is set to 0 mean height is not a fixed value need to evaluate. you can use all type layout view to realize UITableViewCell.", @""), + NSLocalizedString(@"This section not only has text but also hav picture. and picture below at text, text will wrap", @"") + ]; + + NSArray *commentsImageUrls = @[@"head1",@"head2",@"bk3",@"image1",@"image2",@"image3",@"image4"]; + + NSMutableArray *arrays = [NSMutableArray array]; + for (int i = 0; i + +@interface AllTest10ViewController : UIViewController + +@end diff --git a/MyLayoutDemo/AllTest10ViewController.m b/MyLayoutDemo/AllTest10ViewController.m new file mode 100644 index 0000000..b0a2dd4 --- /dev/null +++ b/MyLayoutDemo/AllTest10ViewController.m @@ -0,0 +1,151 @@ +// +// AllTest10ViewController.m +// FriendListDemo +// +// Created by bsj_mac_2 on 2018/5/7. +// Copyright © 2018年 bsj_mac_2. All rights reserved. +// + +#import "AllTest10ViewController.h" +#import "AllTest10Cell.h" +#import "YYFPSLabel.h" +#import "AllTest10HeaderView.h" +#import "AllTest10Model.h" + +@interface AllTest10ViewController () +@property (strong, nonatomic) NSMutableArray * cellDatas; +@property (strong, nonatomic) UITableView * tableView; +@end + +@implementation AllTest10ViewController + +-(void)loadView +{ + + MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + rootLayout.backgroundColor = [UIColor whiteColor]; + self.view = rootLayout; + + //为了支持iPhoneX的全屏幕适配。我们只需要对根布局视图设置一些扩展的属性,默认情况下是不需要进行特殊设置的,MyLayout自动会对iPhoneX进行适配 + //我们知道iOS11中引入了安全区域的概念,MyLayout中的根布局视图会自动将安全区域叠加到设置的padding中去。这个属性是通过insetsPaddingFromSafeArea来完成的。 + //默认情况下四周的安全区域都会叠加到padding中去,因此您可以根据特殊情况来设置只需要叠加哪一个方向的安全区域。您可以通过如下的方法: + rootLayout.insetsPaddingFromSafeArea = UIRectEdgeAll; //您可以在这里将值改变为UIRectEdge的其他类型然后试试运行的效果。并且在运行时切换横竖屏看看效果 + + //iPhoneX设备中具有一个尺寸为44的刘海区域。当您横屏时为了对齐,左右两边的安全缩进区域都是44。但是有些时候我们希望没有刘海的那一边不需要缩进对齐而是延伸到安全区域以外。这时候您可以通过给根布局视图设置insetLandscapeFringePadding属性来达到效果。 + //注意这个属性只有insetsPaddingFromSafeArea设置了左右都缩进时才有效。 + rootLayout.insetLandscapeFringePadding = NO; //您可以在横屏下将这个属性设置为YES后,然后尝试一下进行左右旋转后查看运行的效果。 + +} + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view from its nib. + [self setNavBar]; + [self setupUI]; + [self loadDatas]; +} + +- (void)setNavBar { + self.navigationItem.titleView = [[YYFPSLabel alloc] initWithFrame:CGRectMake(0, 0, 80, 40)]; + + self.title = @"朋友圈"; +} + +- (void)setupUI { + self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; + self.tableView.myHorzMargin = 0; + self.tableView.heightSize.lBound(self.view.heightSize, 0, 1); + self.tableView.delegate = self; + self.tableView.sectionFooterHeight = 0.0001; + self.tableView.dataSource = self; + self.tableView.backgroundColor = [UIColor whiteColor]; + self.tableView.estimatedRowHeight = 100; + self.tableView.separatorInset = UIEdgeInsetsMake(0, 65, 0, 10); + self.tableView.separatorColor = [UIColor clearColor]; + [self.tableView registerClass:[AllTest10Cell class] forCellReuseIdentifier:@"AllTest10Cell"]; + self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension; + self.tableView.estimatedSectionHeaderHeight = 100; + [self.tableView registerClass:[AllTest10HeaderView class] forHeaderFooterViewReuseIdentifier:@"AllTest10HeaderView"]; + [self.view addSubview:self.tableView]; +} + +- (void)loadDatas { + [self.cellDatas addObjectsFromArray:[AllTest10Model getRandTestDatasWithNumber:60]]; + [self.tableView reloadData]; +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return self.cellDatas.count; +} + +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + AllTest10HeaderView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"AllTest10HeaderView"]; + headerView.model = self.cellDatas[section]; + __weak typeof(self) weakSelf = self; + headerView.praiseClickHandler = ^(AllTest10HeaderView *headerView, AllTest10Model *model) { + model.isGiveLike = !model.isGiveLike; + if (model.isGiveLike) { + [model.giveLikeNames addObject:@"乐天"]; + } else { + [model.giveLikeNames removeObject:@"乐天"]; + } + [weakSelf.tableView reloadData]; + }; + headerView.commentsClickHandler = ^(AllTest10HeaderView *headerView, AllTest10Model *model) { + [model.comments addObject:[AllTest10Model randTestComments]]; + [weakSelf.tableView reloadData]; + }; + return headerView; +} + +- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { + MyBaseLayout *footerView = [[MyBaseLayout alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 10)]; + footerView.backgroundColor = [UIColor whiteColor]; + MyBorderline *bld = [[MyBorderline alloc] initWithColor:[UIColor colorWithRed:216.0/255 green:214.0/255 blue:216.0/255 alpha:1]]; + footerView.bottomBorderline = bld; + return footerView; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { + return 10; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + AllTest10Model *model = self.cellDatas[section]; + return model.comments.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + AllTest10Cell *cell = [tableView dequeueReusableCellWithIdentifier:@"AllTest10Cell"]; + AllTest10Model *model = self.cellDatas[indexPath.section]; + cell.selectionStyle = 0; + [cell setCommentsText:model.comments[indexPath.row]]; + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:@"是否删除此条信息" preferredStyle:UIAlertControllerStyleActionSheet]; + __weak typeof(self) weakSelf = self; + UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"删除" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + AllTest10Model *model = weakSelf.cellDatas[indexPath.section]; + [model.comments removeObjectAtIndex:indexPath.row]; + [UIView performWithoutAnimation:^{ + [weakSelf.tableView reloadData]; + }]; + }]; + UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + + }]; + [alertController addAction:cancleAction]; + [alertController addAction:okAction]; + [self presentViewController:alertController animated:YES completion:nil]; +} + +- (NSMutableArray *)cellDatas { + if (!_cellDatas) { + _cellDatas = [NSMutableArray array]; + } + return _cellDatas; +} + +@end diff --git a/MyLayoutDemo/AllTest1ViewController.m b/MyLayoutDemo/AllTest1ViewController.m index e023486..445c6ba 100644 --- a/MyLayoutDemo/AllTest1ViewController.m +++ b/MyLayoutDemo/AllTest1ViewController.m @@ -49,7 +49,7 @@ -(NSMutableArray*)datas ]; NSArray *textMessages = @[@"", - NSLocalizedString(@"a single line text", @""), + NSLocalizedString(@"A single line text", @""), NSLocalizedString(@"This Demo is used to introduce the solution when use layout view to realize the UITableViewCell's dynamic height. We only need to use the layout view's sizeThatFits method to evaluate the size of the layout view. and you can touch the Cell to shrink the height when the Cell has a picture.", @""), NSLocalizedString(@"Through layout view's sizeThatFits method can assess a UITableViewCell dynamic height.EstimateLayoutRect just to evaluate layout size but not set the size of the layout. here don't preach the width of 0 is the cause of the above UITableViewCell set the default width is 320 (regardless of any screen), so if we pass the width of 0 will be according to the width of 320 to evaluate UITableViewCell dynamic height, so when in 375 and 375 the width of the assessment of height will not be right, so here you need to specify the real width dimension;And the height is set to 0 mean height is not a fixed value need to evaluate. you can use all type layout view to realize UITableViewCell.", @""), NSLocalizedString(@"This section not only has text but also hav picture. and picture below at text, text will wrap", @"") diff --git a/MyLayoutDemo/Images.xcassets/friend_zan.imageset/Contents.json b/MyLayoutDemo/Images.xcassets/friend_zan.imageset/Contents.json new file mode 100644 index 0000000..27282fb --- /dev/null +++ b/MyLayoutDemo/Images.xcassets/friend_zan.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "friend_zan@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "friend_zan@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/MyLayoutDemo/Images.xcassets/friend_zan.imageset/friend_zan@2x.png b/MyLayoutDemo/Images.xcassets/friend_zan.imageset/friend_zan@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4f2fac77d1499f69890900f071359666fe1163db GIT binary patch literal 2040 zcmaJ?Yg7~07LEwY1))?BN+_BJ;X*BWL4ZU9Auov~;bDMuftX1$At59ak^urL3fL=f zi}7*0fTG|75!518M66&CtD*(;Y70JiS@6X}(5ln`+KGzokIS94X3jom?eE*)-sf9u z3L^Qd?QGCCC=|+$8^(%8Rxk5wy#V=E(;n9%i!00)!fPQJoB?P-RHzgZgBY#~NCKll zK$@9)1zd$f&G%9Wgs_koPL)6^9AM7D=~Ws8jY6#o(Q5#S5`-~gFiD}NVaLxJu^5Gv zhK(ch2s{lFlqHJZhFUklmMuyPpIQ1SSTj0{|c9}dzc;fWLq1y3O1NhDt+!&jH7h5@~= zTIVs#zyfs=twIAUAT`F!2#BFHn1)4^zH33H`9Q1Iy&n@YFuWen;E6bbxuw}e9`FCB zs#G7cb#OHJm)`$LtP^BvKzuZ)gVMAT$yJw-(l%SUe&IZ@%2WUH0q|;vjSQ!Me!igZV)<;&?4$?ehBd5){f(&SixP^mm#{ z;`4cc)0Rm}(npsXrLrEhB>#G&Q&f9i{8HA^o;COE$UArG>G#;Jj`*Mcy|6esu_t+X zG>#aBK5adCLnEsM9F zU6y`L|F8L2+ieXExeX)1ZjXxR#auruvdcMFyyg(cg8xaFAU5{(67Sswj8?E}GGh7S zk?ZXWOGVzK`^JKqhZo$K#;ugN)=`(q7>{hPJa>0@h4CNr28FTPQQWS*AD1V@(m%TM zS;^}x%@-$pbn=)&x1u`ie-i4dtHU%jiE+!~N68-bcBHrgC?q1+)9G~PI=V-UFycPl zG}w$Te%jgD>0h*>@_fAWt*&udkxD={#&B5pm}o`i3e}uZY{j+k`owZrG8d*c#q?;s57a_FARATg->_J z4OMI#Ui~;VGxWK|p_a(r2fQ7Tw9aWx&_uX>U(KDGC5Oop?2bye=I~QCuX3}$bS`e2 z;WAcU+;{iL{*wc42Rv8O7j^srlgD)?aNwLagcmnP*PVNI3u`ZTaAb4?mrjk1jqypP zu;tx?(jT(hZy*0I(SBpjwB<(2zWEjRHlbdI#(nq5A3bvLOm&Axi)bIi|L3CBbs}7S zkSWML1U1^Qi4!hMv{xO>DW)GS_oItj8oy_)P zBe;jHZCB;QU2fG4^aHjA2VI}G@AHXumSq?E$`ZbOX0`7!!MNfmB|-MVGXYzI8|p>_)h3(XWO@5z2_QEsB>Us9<})zp!N*Qe7+ql zRhQs-uj;=l>_1Z){CV4NH7RAL7;B(jYCPHZLY{J@Y3VnCNjHT`deNJRUx9Mh-)|+I z6;%DR;M7`}Ke#!!;HMwC8G_AMs?Mam*z>EbdcaQYJasv1IIy(c9V4(BS(7$n+wCLz zy((`@0Ponvo}@;uGStep#^LzB4ec0f!0`2Q{uTN#`Ts}f`-16 z;`jB!Uo literal 0 HcmV?d00001 diff --git a/MyLayoutDemo/Images.xcassets/friend_zan.imageset/friend_zan@3x.png b/MyLayoutDemo/Images.xcassets/friend_zan.imageset/friend_zan@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f04859bbbbde72528ea260feead2c64c994470ba GIT binary patch literal 2687 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 Joc3X4{Rj0xOUM8K literal 0 HcmV?d00001 diff --git a/MyLayoutDemo/Images.xcassets/interactive_fill.imageset/interactive_fill@3x.png b/MyLayoutDemo/Images.xcassets/interactive_fill.imageset/interactive_fill@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..1e6b393b1e69de259690147a7170dfd52a400847 GIT binary patch literal 3613 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 RTc`M8@MieX>pgd-{0BxJhp+$u literal 0 HcmV?d00001 diff --git a/MyLayoutDemo/Images.xcassets/zan_select.imageset/zan_select@3x.png b/MyLayoutDemo/Images.xcassets/zan_select.imageset/zan_select@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..921a80f5efa667f1c804e9b9b73413b9d96bb48f GIT binary patch literal 2901 zcmaJ@dpwi-A75_C^+YrxPa{R_hS*%!Hn-Ezs8%Oswuf!(Vp}$J(L!V#mqMxBuN5f? zA?LVtLv>2@;|Qgkq(mahnND?nfBgDAuh;W@FR#!0{ds>rpZ6b6f{&M*x{AIE1Oid_ za3_#u>*l3bSxNSl5?KSXMNdei2z|LhLJ^e@LU43$AP9J{slgx_q|zh8Zh;OEh`cG& zk0PXywqj{qHk`T?0~fP-GBgC@;4J1*X(6Bx2n2(f97ouj>o;HklkN!HX+uJiczBS( zbdThNzL8#jw8#(|h7NOf0vyCx837vM=762NF+KfPA5GZR)BnpefV38=`>jRTzdfso3ffgS`$n2ZI^WYV!jf*sDv3Q4p>yV{^oL|Y67zr_ws za7DWktdKUY#BW#vm$sh`a)jTo^nbCgKg2HCfz6X;CV+fqI7oNpbJ@U`va!q`Yr+4J z?<7v^AkVm z-%Sej+rG-_L(}|dC)fUuF{8s<5^wH<95n${b;ms{67FZ!ZtDw>n!M0%~#t zhx9N&nrq700|n*p#|Hq)LnRA^_a1oKzrI^NHQE^E@S^DyIrnUMaZC4I(q7qZLsWO& z;9Qre>)`O%r<`SWmcO;p%;nMc5V@4kKlxlcB6PkZXUI}Kk>?aIYKqQils`jIWvD;B zzB4yv?v}pOJj!!EBeyJeU#`*R;<1Mfi6|vF|DJhl_*i&G^UU*O$f`n33wv>Qwp@r_RfZu|vutK) zS>avad3aYyN^z3+3}kD+a<15||Iz-A+vn7)bCUO`?rf=!He;RU!S2G= zsmVRJhvq0rZ-_T)GwJ_XCRxZ%G5oypgg;t3l>e!N5oNsoc;_Ga6}Y-c-6FMarHw=t ziYSF0gDHQpU2L{(juT(_!KFcPel9s%Q+Ivqa9-!s$H`ch&y6LmzoAR+Dhelb=$duMa0CB%D+%cUO22($vggX?`lXXo0N) znJFEmP@6dK%=!JHa+ZaW0l^QthA*>?UIu=ao?P>B*SL65)A}+Y6S#dV<6(7eSiUcX zMbT~l&HMe@9{=q5m?LLx3q;ZHLuMbgxEwQ&UU2`jKGK?0p}XttyGbTOFg)d-rheO% zl%;yDs0t+JJbibRI$x?0XOcxh8&&BNf&!< z@86wlSjM~WU%nhe+4p3qQ#I93Imz0tGiLXRnBp}!?eaOb5jim{w0cgB7CzlL!vAyk z&-3AUJ=cgG;`G&YVktjSf6}zk+{wqLDrzlsn6rIn!`BDZwIBu7vI9i!dY(|Y#E!%qC&ICZBSDTM$;wynMw<} z({oCqu(R4&ZuEes?N(_5tSwVpRM%G!6q}o(HJ*j;Jf+lUb4b~xzAqhZ+gf5Tz}>H| zzmylAIFD+I+Uw>H?DD#DDG)HdM6p{oTJ33@K)oB!iSs_#g}>0*+h-70HT<^U3h9JY zLn~al5{RFGzC-=7UTYlpYc(@mD(Iz;A~w>OjYq%LA4I}0s$eGe9@ai%t1wnJ`N%P+ zUFwffo=a67ZO&olRH(!Tl~Gw8vl!L)?xw6mO|*rNm!Ozy-4{-(kF;<0e^4sD-rZ5F zpiDf8anx&kDcL71KbSG*#FFyYWDki3^k)Sna?ZiAjD(D=rrt}nRW%3rzkAnBy6R3v zq}HjFFJ5baHcs2T^JvGXQ;IgMgoa<(SJ!EMU?K{`4_7rSR4qLd)l<}Zv#%S~IMFud zrdoT@=Fsa+s3(V$)OGVVI5qW(YSRhWhiP(YB=@T@Rucp<+vb Date: Sat, 12 May 2018 00:49:38 +0800 Subject: [PATCH 014/115] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9C=8B=E5=8F=8B?= =?UTF-8?q?=E5=9C=88Demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 6148 -> 6148 bytes MyLayout.xcodeproj/project.pbxproj | 6 +-- .../xcshareddata/IDEWorkspaceChecks.plist | 8 ---- MyLayoutDemo/AllTest10Cell.m | 13 +------ MyLayoutDemo/AllTest10HeaderView.m | 35 ++++-------------- MyLayoutDemo/AllTest10ViewController.m | 2 + MyLayoutDemo/LLTest2ViewController.m | 2 +- 7 files changed, 16 insertions(+), 50 deletions(-) delete mode 100644 MyLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/.DS_Store b/.DS_Store index e83009f53647cbad0187731f40ed2464277b23ee..ad8409f0e75e1096920fdc495e4f97c6d13adaa3 100644 GIT binary patch delta 90 zcmZoMXfc=|#>B`mu~2NHo+2aj!~pBb0*nnnMvobjyurjCjfroBC-$rIlm!>%<>cq3 oGcYhPZf0Z*XWPuq!OsEI3FLfdp3E;|$iWDdYXIWS9wK{~0Z_FTVE_OC delta 76 zcmZoMXfc=|#>CJ*u~2NHo+2aD!~pBb1|lqz`5BFwq?ji2FltQBVHDoHl`)8I@&U$e go7p+|Ie^MHZ)E(=Jegm_kda}s4UhEZ7?Bms02473kpKVy diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index 5bb9cc4..a7bbadc 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -964,7 +964,7 @@ }; 1840828C1B2C46E8003F378B = { CreatedOnToolsVersion = 6.3.2; - DevelopmentTeam = 2TLR37RWPL; + DevelopmentTeam = BGQ8WB468K; ProvisioningStyle = Automatic; }; 184082A51B2C46E8003F378B = { @@ -1435,7 +1435,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 2TLR37RWPL; + DEVELOPMENT_TEAM = BGQ8WB468K; GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1457,7 +1457,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 2TLR37RWPL; + DEVELOPMENT_TEAM = BGQ8WB468K; GCC_PREPROCESSOR_DEFINITIONS = ""; INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; diff --git a/MyLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/MyLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/MyLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/MyLayoutDemo/AllTest10Cell.m b/MyLayoutDemo/AllTest10Cell.m index 12d0152..7498cb2 100644 --- a/MyLayoutDemo/AllTest10Cell.m +++ b/MyLayoutDemo/AllTest10Cell.m @@ -52,21 +52,13 @@ -(void)createLinearRootLayout _rootLayout= [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; _rootLayout.padding = UIEdgeInsetsMake(0, 65, 0, 10); _rootLayout.cacheEstimatedRect = YES; - - /* - 在UITableViewCell中使用MyLayout中的布局时请将布局视图作为contentView的子视图。如果我们的UITableViewCell的高度是动态的,请务必在将布局视图添加到contentView之前进行如下设置: - _rootLayout.widthSize.equalTo(self.contentView.widthSize); - _rootLayout.wrapContentHeight = YES; - */ - // _rootLayout.widthSize.equalTo(self.contentView.widthSize); _rootLayout.myHorzMargin = MyLayoutPos.safeAreaMargin; _rootLayout.wrapContentHeight = YES; _rootLayout.wrapContentWidth = NO; //这里设置其他位置有间隔线而最后一行没有下划线。我们可以借助布局视图本身所提供的边界线来代替掉系统默认的cell之间的间隔线,因为布局视图的边界线所提供的能力要大于默认的间隔线。 MyBorderline *bld = [[MyBorderline alloc] initWithColor:[UIColor whiteColor]]; self.rootLayout.bottomBorderline = bld; - [self.contentView addSubview:_rootLayout]; //如果您将布局视图作为子视图添加到UITableViewCell本身,并且同时用了myLeft和myRight来做边界的话,那么有可能最终展示的宽度会不正确。经过试验是因为对UITableViewCell本身的KVO监控所得到的新老尺寸的问题导致的这应该是iOS的一个BUG。所以这里建议最好是把布局视图添加到UITableViewCell的子视图contentView里面去。 - + [self.contentView addSubview:_rootLayout]; MyLinearLayout *giveLikeLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; giveLikeLayout.padding = UIEdgeInsetsMake(5, 6, 5, 6); giveLikeLayout.weight = 1; @@ -78,8 +70,7 @@ -(void)createLinearRootLayout _commentsLabel.text = @"正文"; _commentsLabel.textColor = [UIColor blueColor]; _commentsLabel.font = [UIFont systemFontOfSize:12]; - _commentsLabel.myLeading = 0; - _commentsLabel.myTrailing = 0; //垂直线性布局里面如果同时设置了左右边距则能确定子视图的宽度,这里表示宽度和父视图相等。 + _commentsLabel.myHorzMargin = 0; _commentsLabel.wrapContentHeight = YES; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 [giveLikeLayout addSubview:_commentsLabel]; } diff --git a/MyLayoutDemo/AllTest10HeaderView.m b/MyLayoutDemo/AllTest10HeaderView.m index f708e6e..c2d88a3 100644 --- a/MyLayoutDemo/AllTest10HeaderView.m +++ b/MyLayoutDemo/AllTest10HeaderView.m @@ -40,25 +40,11 @@ -(void)createLinearRootLayout { _rootLayout= [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; _rootLayout.padding = UIEdgeInsetsMake(10, 10, 0.3, 10); -// _rootLayout.cacheEstimatedRect = YES; _rootLayout.backgroundColor = [UIColor whiteColor]; - /* - 在UITableViewCell中使用MyLayout中的布局时请将布局视图作为contentView的子视图。如果我们的UITableViewCell的高度是动态的,请务必在将布局视图添加到contentView之前进行如下设置: - _rootLayout.widthSize.equalTo(self.contentView.widthSize); - _rootLayout.wrapContentHeight = YES; - */ - // _rootLayout.widthSize.equalTo(self.contentView.widthSize); _rootLayout.myHorzMargin = MyLayoutPos.safeAreaMargin; _rootLayout.wrapContentHeight = YES; _rootLayout.wrapContentWidth = NO; - [self.contentView addSubview:_rootLayout]; //如果您将布局视图作为子视图添加到UITableViewCell本身,并且同时用了myLeft和myRight来做边界的话,那么有可能最终展示的宽度会不正确。经过试验是因为对UITableViewCell本身的KVO监控所得到的新老尺寸的问题导致的这应该是iOS的一个BUG。所以这里建议最好是把布局视图添加到UITableViewCell的子视图contentView里面去。 - - - - /* - 用线性布局实现时,整体用一个水平线性布局:左边是头像,右边是一个垂直的线性布局。垂直线性布局依次加入昵称、文本消息、图片消息。 - */ - + [self.contentView addSubview:_rootLayout]; _headImageView = [UIImageView new]; _headImageView.myWidth = 50; @@ -71,8 +57,8 @@ -(void)createLinearRootLayout MyLinearLayout *messageLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; messageLayout.weight = 1; - messageLayout.myLeading = 5; //前面2行代码描述的是垂直布局占用除头像外的所有宽度,并和头像保持5个点的间距。 - messageLayout.subviewVSpace = 5; //垂直布局里面所有子视图都保持5个点的间距。 + messageLayout.myLeading = 5; + messageLayout.subviewVSpace = 5; [_rootLayout addSubview:messageLayout]; _nickNameLabel = [UILabel new]; @@ -85,12 +71,12 @@ -(void)createLinearRootLayout _textMessageLabel = [UILabel new]; _textMessageLabel.text = @""; _textMessageLabel.myLeading = 0; - _textMessageLabel.myTrailing = 0; //垂直线性布局里面如果同时设置了左右边距则能确定子视图的宽度,这里表示宽度和父视图相等。 - _textMessageLabel.wrapContentHeight = YES; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + _textMessageLabel.myTrailing = 0; + _textMessageLabel.wrapContentHeight = YES; [messageLayout addSubview:_textMessageLabel]; _nineFlowLayout = [[MyFlowLayout alloc] initWithOrientation:MyOrientation_Vert arrangedCount:3]; - _nineFlowLayout.gravity = MyGravity_Horz_Fill; //所有子视图水平填充,也就是所有子视图的宽度相等。 + _nineFlowLayout.gravity = MyGravity_Horz_Fill; _nineFlowLayout.myHorzMargin = 0; _nineFlowLayout.subviewHSpace = 5; _nineFlowLayout.subviewVSpace = 5; @@ -150,7 +136,7 @@ -(void)createLinearRootLayout _giveLikeLabel.textColor = [UIColor blueColor]; _giveLikeLabel.font = [UIFont systemFontOfSize:12]; _giveLikeLabel.myHorzMargin = 0; - _giveLikeLabel.wrapContentHeight = YES; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + _giveLikeLabel.wrapContentHeight = YES; [giveLikeLayout addSubview:_giveLikeLabel]; } @@ -204,17 +190,12 @@ - (void)setModel:(AllTest10Model *)model { //如果您的最低支持是iOS8,那么你可以重载这个方法来动态的评估cell的高度,Autolayout内部是通过这个方法来评估高度的,因此如果用MyLayout实现的话就不需要调用基类的方法,而是调用根布局视图的sizeThatFits来评估获取动态的高度。 - (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority { - /* - 通过布局视图的sizeThatFits方法能够评估出UITableViewCell的动态高度。sizeThatFits并不会进行布局而只是评估布局的尺寸。 - 因为cell的高度是自适应的,因此这里通过调用高度为wrap的布局视图的sizeThatFits来获取真实的高度。 - */ - if (@available(iOS 11.0, *)) { //如果你的界面要支持横屏的话,因为iPhoneX的横屏左右有44的安全区域,所以这里要减去左右的安全区域的值,来作为布局宽度尺寸的评估值。 //如果您的界面不需要支持横屏,或者延伸到安全区域外则不需要做这个特殊处理,而直接使用else部分的代码即可。 return [self.rootLayout sizeThatFits:CGSizeMake(targetSize.width - self.safeAreaInsets.left - self.safeAreaInsets.right, targetSize.height)]; } else { - return [self.rootLayout sizeThatFits:targetSize]; //如果使用系统自带的分割线,请记得将返回的高度height+1 + return [self.rootLayout sizeThatFits:targetSize]; } } diff --git a/MyLayoutDemo/AllTest10ViewController.m b/MyLayoutDemo/AllTest10ViewController.m index b0a2dd4..390d1d3 100644 --- a/MyLayoutDemo/AllTest10ViewController.m +++ b/MyLayoutDemo/AllTest10ViewController.m @@ -60,6 +60,7 @@ - (void)setupUI { self.tableView.dataSource = self; self.tableView.backgroundColor = [UIColor whiteColor]; self.tableView.estimatedRowHeight = 100; + self.tableView.rowHeight = UITableViewAutomaticDimension; self.tableView.separatorInset = UIEdgeInsetsMake(0, 65, 0, 10); self.tableView.separatorColor = [UIColor clearColor]; [self.tableView registerClass:[AllTest10Cell class] forCellReuseIdentifier:@"AllTest10Cell"]; @@ -101,6 +102,7 @@ - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { MyBaseLayout *footerView = [[MyBaseLayout alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 10)]; footerView.backgroundColor = [UIColor whiteColor]; + footerView.myHorzMargin = MyLayoutPos.safeAreaMargin; MyBorderline *bld = [[MyBorderline alloc] initWithColor:[UIColor colorWithRed:216.0/255 green:214.0/255 blue:216.0/255 alpha:1]]; footerView.bottomBorderline = bld; return footerView; diff --git a/MyLayoutDemo/LLTest2ViewController.m b/MyLayoutDemo/LLTest2ViewController.m index 47c2292..4d01695 100644 --- a/MyLayoutDemo/LLTest2ViewController.m +++ b/MyLayoutDemo/LLTest2ViewController.m @@ -38,7 +38,7 @@ -(void)loadView MyLinearLayout *contentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; contentLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); //设置布局内的子视图离自己的边距. contentLayout.myHorzMargin = 0; //同时指定左右边距为0表示宽度和父视图一样宽 - contentLayout.heightSize.lBound(scrollView.heightSize, 0, 1); //高度虽然是wrapContentHeight的。但是最小的高度不能低于父视图的高度加10. + contentLayout.heightSize.lBound(scrollView.heightSize, 10, 1); //高度虽然是wrapContentHeight的。但是最小的高度不能低于父视图的高度加10. [scrollView addSubview:contentLayout]; self.contentLayout = contentLayout; From c8f120ccbfff30cc1b93561a34347ae2e0e902b5 Mon Sep 17 00:00:00 2001 From: letian <916235259@qq.com> Date: Fri, 11 May 2018 23:25:51 -0600 Subject: [PATCH 015/115] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9C=8B=E5=8F=8B?= =?UTF-8?q?=E5=9C=88demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayoutDemo/AllTest10ViewController.m | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/MyLayoutDemo/AllTest10ViewController.m b/MyLayoutDemo/AllTest10ViewController.m index 390d1d3..e9d3edd 100644 --- a/MyLayoutDemo/AllTest10ViewController.m +++ b/MyLayoutDemo/AllTest10ViewController.m @@ -21,20 +21,9 @@ @implementation AllTest10ViewController -(void)loadView { - - MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + MyFrameLayout *rootLayout = [[MyFrameLayout alloc] init]; rootLayout.backgroundColor = [UIColor whiteColor]; self.view = rootLayout; - - //为了支持iPhoneX的全屏幕适配。我们只需要对根布局视图设置一些扩展的属性,默认情况下是不需要进行特殊设置的,MyLayout自动会对iPhoneX进行适配 - //我们知道iOS11中引入了安全区域的概念,MyLayout中的根布局视图会自动将安全区域叠加到设置的padding中去。这个属性是通过insetsPaddingFromSafeArea来完成的。 - //默认情况下四周的安全区域都会叠加到padding中去,因此您可以根据特殊情况来设置只需要叠加哪一个方向的安全区域。您可以通过如下的方法: - rootLayout.insetsPaddingFromSafeArea = UIRectEdgeAll; //您可以在这里将值改变为UIRectEdge的其他类型然后试试运行的效果。并且在运行时切换横竖屏看看效果 - - //iPhoneX设备中具有一个尺寸为44的刘海区域。当您横屏时为了对齐,左右两边的安全缩进区域都是44。但是有些时候我们希望没有刘海的那一边不需要缩进对齐而是延伸到安全区域以外。这时候您可以通过给根布局视图设置insetLandscapeFringePadding属性来达到效果。 - //注意这个属性只有insetsPaddingFromSafeArea设置了左右都缩进时才有效。 - rootLayout.insetLandscapeFringePadding = NO; //您可以在横屏下将这个属性设置为YES后,然后尝试一下进行左右旋转后查看运行的效果。 - } - (void)viewDidLoad { @@ -47,25 +36,23 @@ - (void)viewDidLoad { - (void)setNavBar { self.navigationItem.titleView = [[YYFPSLabel alloc] initWithFrame:CGRectMake(0, 0, 80, 40)]; - self.title = @"朋友圈"; } - (void)setupUI { self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; - self.tableView.myHorzMargin = 0; - self.tableView.heightSize.lBound(self.view.heightSize, 0, 1); + self.tableView.myMargin = 0; self.tableView.delegate = self; - self.tableView.sectionFooterHeight = 0.0001; self.tableView.dataSource = self; - self.tableView.backgroundColor = [UIColor whiteColor]; + self.tableView.sectionFooterHeight = 0.0001; self.tableView.estimatedRowHeight = 100; self.tableView.rowHeight = UITableViewAutomaticDimension; + self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension; + self.tableView.estimatedSectionHeaderHeight = 100; + self.tableView.backgroundColor = [UIColor whiteColor]; self.tableView.separatorInset = UIEdgeInsetsMake(0, 65, 0, 10); self.tableView.separatorColor = [UIColor clearColor]; [self.tableView registerClass:[AllTest10Cell class] forCellReuseIdentifier:@"AllTest10Cell"]; - self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension; - self.tableView.estimatedSectionHeaderHeight = 100; [self.tableView registerClass:[AllTest10HeaderView class] forHeaderFooterViewReuseIdentifier:@"AllTest10HeaderView"]; [self.view addSubview:self.tableView]; } From ff0de1659712636661b67267a8a33df3d4311e4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E6=9F=8F=E6=B3=89?= Date: Sat, 26 May 2018 11:34:32 +0800 Subject: [PATCH 016/115] =?UTF-8?q?=E6=94=AF=E6=8C=81carthage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout.xcodeproj/project.pbxproj | 24 ++++++--- MyLayout/Lib/MyLayoutDef.h | 80 ++++++++++++++++++++++++++++++ MyLayout/Lib/MyLayoutSizeClass.h | 80 ------------------------------ 3 files changed, 96 insertions(+), 88 deletions(-) diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index a7bbadc..2205015 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -25,7 +25,7 @@ 182225D31E77E5930081AA4B /* MyTableLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C31E77E5930081AA4B /* MyTableLayout.m */; }; 182225D41E77E5930081AA4B /* MyDimeScale.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C41E77E5930081AA4B /* MyDimeScale.m */; }; 182225D51E77E5930081AA4B /* MyLayoutSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C51E77E5930081AA4B /* MyLayoutSize.m */; }; - 182DB6421EF7876200E2D65D /* MyGridLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182DB6401EF7876200E2D65D /* MyGridLayout.h */; }; + 182DB6421EF7876200E2D65D /* MyGridLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182DB6401EF7876200E2D65D /* MyGridLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; 182DB6431EF7876200E2D65D /* MyGridLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182DB6411EF7876200E2D65D /* MyGridLayout.m */; }; 182DB6441EF7876200E2D65D /* MyGridLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182DB6411EF7876200E2D65D /* MyGridLayout.m */; }; 1897384F1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 1897384E1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m */; }; @@ -44,7 +44,7 @@ 18C15AF41EDF140400AADEAC /* MyBaseLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AF1E77E5930081AA4B /* MyBaseLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18C15AF51EDF140D00AADEAC /* MyLayoutPos.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B01E77E5930081AA4B /* MyLayoutPos.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18C15AF61EDF141000AADEAC /* MyLayoutSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BC1E77E5930081AA4B /* MyLayoutSize.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF71EDF141600AADEAC /* MyLayoutSizeClass.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF71EDF141600AADEAC /* MyLayoutSizeClass.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */; }; 18C15AF81EDF141A00AADEAC /* MyMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C21E77E5930081AA4B /* MyMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18C15AF91EDF142000AADEAC /* MyDimeScale.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C71E77E5930081AA4B /* MyDimeScale.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18C15AFA1EDF142300AADEAC /* MyLayoutDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B31E77E5930081AA4B /* MyLayoutDef.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -139,7 +139,7 @@ 200A26D91FA8A90300B06E7B /* AllTest9ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */; }; 200A26DC1FA96B2400B06E7B /* AllTest9CollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */; }; 204DC321209D5A8700F6CB57 /* TLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */; }; - 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */ = {isa = PBXBuildFile; fileRef = 205642841F4CFF9B00E8BDDE /* MyBorderline.h */; }; + 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */ = {isa = PBXBuildFile; fileRef = 205642841F4CFF9B00E8BDDE /* MyBorderline.h */; settings = {ATTRIBUTES = (Public, ); }; }; 205642871F4CFF9B00E8BDDE /* MyBorderline.m in Sources */ = {isa = PBXBuildFile; fileRef = 205642851F4CFF9B00E8BDDE /* MyBorderline.m */; }; 205642881F4CFFB600E8BDDE /* MyBorderline.m in Sources */ = {isa = PBXBuildFile; fileRef = 205642851F4CFF9B00E8BDDE /* MyBorderline.m */; }; 2056430A1F4E53CD00E8BDDE /* MyGridNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 205643081F4E53CD00E8BDDE /* MyGridNode.h */; }; @@ -150,11 +150,15 @@ 205643171F55A03000E8BDDE /* MyLayoutMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643151F55A03000E8BDDE /* MyLayoutMath.m */; }; 205643181F55A16400E8BDDE /* MyLayoutMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643151F55A03000E8BDDE /* MyLayoutMath.m */; }; 205CFA8E1F49BD1C00355489 /* GLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */; }; + 205E0C5F20B90347001A8B99 /* MyGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = 205642891F4D013D00E8BDDE /* MyGrid.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 205E0C6020B907CC001A8B99 /* MyLayoutPosInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */; }; + 205E0C6120B907D1001A8B99 /* MyLayoutSizeInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C81E77E5930081AA4B /* MyLayoutSizeInner.h */; }; + 205E0C6220B907DB001A8B99 /* MyLayoutInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B81E77E5930081AA4B /* MyLayoutInner.h */; }; + 205E0C6320B907EC001A8B99 /* MyLayoutDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */; }; 205F9EBA1F7AA5710034732C /* gl.png in Resources */ = {isa = PBXBuildFile; fileRef = 205F9EB91F7AA5710034732C /* gl.png */; }; 205F9EBC1F7AA6510034732C /* all.png in Resources */ = {isa = PBXBuildFile; fileRef = 205F9EBB1F7AA6510034732C /* all.png */; }; 2075CC3220A0B2A400BA6F65 /* FLLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */; }; 208157BD1F586AA700E945B6 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157BC1F586AA700E945B6 /* DetailViewController.m */; }; - 208157C21F5A886300E945B6 /* MyLayoutDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */; }; 208157C31F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; 208157C41F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */ = {isa = PBXBuildFile; fileRef = 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */; }; @@ -854,7 +858,6 @@ 2056430A1F4E53CD00E8BDDE /* MyGridNode.h in Headers */, 18C15AEC1EDF13D700AADEAC /* MyLayout.h in Headers */, 18C15AED1EDF13DE00AADEAC /* MyFlowLayout.h in Headers */, - 208157C21F5A886300E945B6 /* MyLayoutDelegate.h in Headers */, 18C15AEE1EDF13E500AADEAC /* MyLinearLayout.h in Headers */, 18C15AEF1EDF13E900AADEAC /* MyFloatLayout.h in Headers */, 18C15AF01EDF13EF00AADEAC /* MyTableLayout.h in Headers */, @@ -865,12 +868,17 @@ 18C15AF41EDF140400AADEAC /* MyBaseLayout.h in Headers */, 18C15AF51EDF140D00AADEAC /* MyLayoutPos.h in Headers */, 18C15AF61EDF141000AADEAC /* MyLayoutSize.h in Headers */, - 18C15AF71EDF141600AADEAC /* MyLayoutSizeClass.h in Headers */, + 205E0C5F20B90347001A8B99 /* MyGrid.h in Headers */, + 182DB6421EF7876200E2D65D /* MyGridLayout.h in Headers */, + 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */, 18C15AF81EDF141A00AADEAC /* MyMaker.h in Headers */, + 18C15AF71EDF141600AADEAC /* MyLayoutSizeClass.h in Headers */, 18C15AF91EDF142000AADEAC /* MyDimeScale.h in Headers */, - 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */, - 182DB6421EF7876200E2D65D /* MyGridLayout.h in Headers */, 18C15AFA1EDF142300AADEAC /* MyLayoutDef.h in Headers */, + 205E0C6020B907CC001A8B99 /* MyLayoutPosInner.h in Headers */, + 205E0C6120B907D1001A8B99 /* MyLayoutSizeInner.h in Headers */, + 205E0C6220B907DB001A8B99 /* MyLayoutInner.h in Headers */, + 205E0C6320B907EC001A8B99 /* MyLayoutDelegate.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MyLayout/Lib/MyLayoutDef.h b/MyLayout/Lib/MyLayoutDef.h index 0de4f02..23c6a78 100644 --- a/MyLayout/Lib/MyLayoutDef.h +++ b/MyLayout/Lib/MyLayoutDef.h @@ -161,6 +161,86 @@ typedef enum : NSUInteger { +/* + SizeClass的尺寸定义,用于定义苹果设备的各种屏幕的尺寸,对于任意一种设备来说某个纬度的尺寸都可以描述为:Any任意,Compact压缩,Regular常规 + 三种形式,比如下面就列出了苹果各种设备的SizeClass定义: + + iPhone4S,iPhone5/5s,iPhone6 + 竖屏:(w:Compact h:Regular) + 横屏:(w:Compact h:Compact) + iPhone6 Plus + 竖屏:(w:Compact h:Regular) + 横屏:(w:Regular h:Compact) + iPad + 竖屏:(w:Regular h:Regular) + 横屏:(w:Regular h:Regular) + Apple Watch + 竖屏:(w:Compact h:Compact) + 横屏:(w:Compact h:Compact) + + 我们可以专门为某种设备的SizeClass来设置具体的各种子视图和布局的约束,但是为了兼容多种设备,我们提出了SizeClass的继承关系,其中的继承关系如下: + + w:Compact h:Compact 继承 (w:Any h:Compact , w:Compact h:Any , w:Any h:Any) + w:Regular h:Compact 继承 (w:Any h:Compact , w:Regular h:Any , w:Any h:Any) + w:Compact h:Regular 继承 (w:Any h:Regular , w:Compact h:Any , w:Any h:Any) + w:Regular h:Regular 继承 (w:Any h:Regular , w:Regular h:Any , w:Any h:Any) + + + 也就是说设备当前是:w:Compact h:Compact 则会找出某个视图是否定义了这个SizeClass的界面约束布局,如果没有则找w:Any h:Compact。如果找到了 + 则使用,否则继续往上找,直到w:Any h:Any这种尺寸,因为默认所有视图和布局视图的约束设置都是基于w:Any h:Any的。所以总是会找到对应的视图定义的约束的。 + + 在上述的定义中我们发现了2个问题,一个就是没有一个明确来指定横屏和竖屏这种屏幕的情况;另外一个是iPad设备的宽度和高度都是regular,而无法区分横屏和竖屏。因此这里对 + MySizeClass新增加了两个定义:竖屏MySizeClass_Portrait和横屏MySizeClass_Landscape。我们可以用这两个SizeClass来定义全局横屏以及某类设备的横屏和竖屏 + + 在默认情况下现有的布局以及子视图的约束设置都是基于w:Any h:Any的,如果我们要为某种SizeClass设置约束则可以调用视图的扩展方法: + + -(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass; + -(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass copyFrom:(MySizeClass)srcSizeClass; + + + 这两个方法需要传递一个宽度的MySizeClass定义和高度的MySizeClass定义,并通过 | 运算符来组合。 比如: + + 1.想设置所有iPhone设备的横屏的约束 + UIView *lsc = [某视图 fetchLayoutSizeClass:MySizeClass_wAny|MySizeClass_hCompact]; + + 2.想设置所有iPad设备的横屏的约束 + UIView *lsc = [某视图 fetchLayoutSizeClass: MySizeClass_wRegular | MySizeClass_hRegular | MySizeClass_Landscape]; + + 3.想设置iphone6plus下的横屏的约束 + UIView *lsc = [某视图 fetchLayoutSizeClass:MySizeClass_wRegular|MySizeClass_hCompact]; + + 4.想设置ipad下的约束 + UIView *lsc = [某视图 fetchLayoutSizeClass:MySizeClass_wRegular | MySizeClass_hRegular]; + + 5.想设置所有设备下的约束,也是默认的视图的约束 + UIView *lsc = [某视图 fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hAny]; + + 6.所有设备的竖屏约束: + UIView *lsc = [某视图 fetchLayoutSizeClass:MySizeClass_Portrait]; + + 7.所有设备的横屏约束: + UIView *lsc = [某视图 fetchLayoutSizeClass:MySizeClass_Landscape]; + + + + fetchLayoutSizeClass虽然返回的是一个instancetype,但实际得到了一个MyLayoutSizeClass对象或者其派生类,而MyLayoutSizeClass类中又定义了跟UIView一样相同的布局方法,因此虽然是返回视图对象,并设置各种约束,但实际上是设置MyLayoutSizeClass对象的各种约束。 + + */ +typedef enum : unsigned char{ + MySizeClass_wAny = 0, //宽度任意尺寸 + MySizeClass_wCompact = 1, //宽度压缩尺寸,这个属性在iOS8以下不支持 + MySizeClass_wRegular = 2, //宽度常规尺寸,这个属性在iOS8以下不支持 + + MySizeClass_hAny = 0, //高度任意尺寸 + MySizeClass_hCompact = 1 << 2, //高度压缩尺寸,这个属性在iOS8以下不支持 + MySizeClass_hRegular = 2 << 2, //高度常规尺寸,这个属性在iOS8以下不支持 + + MySizeClass_Any = 0x0, //所有设备,等价于MySizeClass_wAny|MySizeClass_hAny + MySizeClass_Portrait = 0x40, //竖屏 + MySizeClass_Landscape = 0x80, //横屏,注意横屏和竖屏不支持 | 运算操作,只能指定一个。 +}MySizeClass; + + //内部使用 typedef enum : unsigned char diff --git a/MyLayout/Lib/MyLayoutSizeClass.h b/MyLayout/Lib/MyLayoutSizeClass.h index f037b10..6fbca6a 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.h +++ b/MyLayout/Lib/MyLayoutSizeClass.h @@ -14,86 +14,6 @@ @class MyBaseLayout; -/* - SizeClass的尺寸定义,用于定义苹果设备的各种屏幕的尺寸,对于任意一种设备来说某个纬度的尺寸都可以描述为:Any任意,Compact压缩,Regular常规 - 三种形式,比如下面就列出了苹果各种设备的SizeClass定义: - - iPhone4S,iPhone5/5s,iPhone6 - 竖屏:(w:Compact h:Regular) - 横屏:(w:Compact h:Compact) - iPhone6 Plus - 竖屏:(w:Compact h:Regular) - 横屏:(w:Regular h:Compact) - iPad - 竖屏:(w:Regular h:Regular) - 横屏:(w:Regular h:Regular) - Apple Watch - 竖屏:(w:Compact h:Compact) - 横屏:(w:Compact h:Compact) - - 我们可以专门为某种设备的SizeClass来设置具体的各种子视图和布局的约束,但是为了兼容多种设备,我们提出了SizeClass的继承关系,其中的继承关系如下: - - w:Compact h:Compact 继承 (w:Any h:Compact , w:Compact h:Any , w:Any h:Any) - w:Regular h:Compact 继承 (w:Any h:Compact , w:Regular h:Any , w:Any h:Any) - w:Compact h:Regular 继承 (w:Any h:Regular , w:Compact h:Any , w:Any h:Any) - w:Regular h:Regular 继承 (w:Any h:Regular , w:Regular h:Any , w:Any h:Any) - - - 也就是说设备当前是:w:Compact h:Compact 则会找出某个视图是否定义了这个SizeClass的界面约束布局,如果没有则找w:Any h:Compact。如果找到了 - 则使用,否则继续往上找,直到w:Any h:Any这种尺寸,因为默认所有视图和布局视图的约束设置都是基于w:Any h:Any的。所以总是会找到对应的视图定义的约束的。 - - 在上述的定义中我们发现了2个问题,一个就是没有一个明确来指定横屏和竖屏这种屏幕的情况;另外一个是iPad设备的宽度和高度都是regular,而无法区分横屏和竖屏。因此这里对 - MySizeClass新增加了两个定义:竖屏MySizeClass_Portrait和横屏MySizeClass_Landscape。我们可以用这两个SizeClass来定义全局横屏以及某类设备的横屏和竖屏 - - 在默认情况下现有的布局以及子视图的约束设置都是基于w:Any h:Any的,如果我们要为某种SizeClass设置约束则可以调用视图的扩展方法: - - -(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass; - -(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass copyFrom:(MySizeClass)srcSizeClass; - - - 这两个方法需要传递一个宽度的MySizeClass定义和高度的MySizeClass定义,并通过 | 运算符来组合。 比如: - - 1.想设置所有iPhone设备的横屏的约束 - UIView *lsc = [某视图 fetchLayoutSizeClass:MySizeClass_wAny|MySizeClass_hCompact]; - - 2.想设置所有iPad设备的横屏的约束 - UIView *lsc = [某视图 fetchLayoutSizeClass: MySizeClass_wRegular | MySizeClass_hRegular | MySizeClass_Landscape]; - - 3.想设置iphone6plus下的横屏的约束 - UIView *lsc = [某视图 fetchLayoutSizeClass:MySizeClass_wRegular|MySizeClass_hCompact]; - - 4.想设置ipad下的约束 - UIView *lsc = [某视图 fetchLayoutSizeClass:MySizeClass_wRegular | MySizeClass_hRegular]; - - 5.想设置所有设备下的约束,也是默认的视图的约束 - UIView *lsc = [某视图 fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hAny]; - - 6.所有设备的竖屏约束: - UIView *lsc = [某视图 fetchLayoutSizeClass:MySizeClass_Portrait]; - - 7.所有设备的横屏约束: - UIView *lsc = [某视图 fetchLayoutSizeClass:MySizeClass_Landscape]; - - - - fetchLayoutSizeClass虽然返回的是一个instancetype,但实际得到了一个MyLayoutSizeClass对象或者其派生类,而MyLayoutSizeClass类中又定义了跟UIView一样相同的布局方法,因此虽然是返回视图对象,并设置各种约束,但实际上是设置MyLayoutSizeClass对象的各种约束。 - - */ -typedef enum : unsigned char{ - MySizeClass_wAny = 0, //宽度任意尺寸 - MySizeClass_wCompact = 1, //宽度压缩尺寸,这个属性在iOS8以下不支持 - MySizeClass_wRegular = 2, //宽度常规尺寸,这个属性在iOS8以下不支持 - - MySizeClass_hAny = 0, //高度任意尺寸 - MySizeClass_hCompact = 1 << 2, //高度压缩尺寸,这个属性在iOS8以下不支持 - MySizeClass_hRegular = 2 << 2, //高度常规尺寸,这个属性在iOS8以下不支持 - - MySizeClass_Any = 0x0, //所有设备,等价于MySizeClass_wAny|MySizeClass_hAny - MySizeClass_Portrait = 0x40, //竖屏 - MySizeClass_Landscape = 0x80, //横屏,注意横屏和竖屏不支持 | 运算操作,只能指定一个。 -}MySizeClass; - - /* 布局的尺寸类型类,这个类的功能用来支持类似于iOS的Size Class机制用来实现各种屏幕下的视图的约束。 From 8bad98bedb2522fe6f403f6f8aa1e71b7c839b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E6=9F=8F=E6=B3=89?= Date: Sat, 26 May 2018 11:38:39 +0800 Subject: [PATCH 017/115] support for carthage --- MyLayout/Lib/MyBaseLayout.h | 1 - 1 file changed, 1 deletion(-) diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index f0a1e17..dd59bc9 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -9,7 +9,6 @@ #import "MyLayoutDef.h" #import "MyLayoutPos.h" #import "MyLayoutSize.h" -#import "MyLayoutSizeClass.h" #import "MyBorderline.h" /* From 6c4840673b74cf84ff067d363be3a69b5502f884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E6=9F=8F=E6=B3=89?= Date: Sat, 26 May 2018 11:49:16 +0800 Subject: [PATCH 018/115] support carthage --- MyLayout.xcodeproj/project.pbxproj | 3122 ++++++++++++++-------------- 1 file changed, 1561 insertions(+), 1561 deletions(-) diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index 2205015..ebaa23d 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -1,1606 +1,1606 @@ // !$*UTF8*$! { - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { /* Begin PBXBuildFile section */ - 180BD8A11EA9EF9A00C6980B /* MyFrameLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 180BD8A01EA9EF9A00C6980B /* MyFrameLayoutTestCase.m */; }; - 1810AC221EB966D30022CBFF /* MyLayoutPerformanceTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */; }; - 181836951EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 181836941EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m */; }; - 181A10AA1EDF11FF00996203 /* FLLTest2ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 181A10A81EDF11FF00996203 /* FLLTest2ViewController.xib */; }; - 181A10AE1EDF123800996203 /* FOLTest1ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 181A10AC1EDF123800996203 /* FOLTest1ViewController.xib */; }; - 182225C91E77E5930081AA4B /* MyBaseLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B11E77E5930081AA4B /* MyBaseLayout.m */; }; - 182225CA1E77E5930081AA4B /* MyLinearLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B21E77E5930081AA4B /* MyLinearLayout.m */; }; - 182225CB1E77E5930081AA4B /* MyFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B41E77E5930081AA4B /* MyFlowLayout.m */; }; - 182225CC1E77E5930081AA4B /* MyRelativeLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B51E77E5930081AA4B /* MyRelativeLayout.m */; }; - 182225CD1E77E5930081AA4B /* MyPathLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B61E77E5930081AA4B /* MyPathLayout.m */; }; - 182225CE1E77E5930081AA4B /* MyFrameLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B71E77E5930081AA4B /* MyFrameLayout.m */; }; - 182225CF1E77E5930081AA4B /* MyFloatLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B91E77E5930081AA4B /* MyFloatLayout.m */; }; - 182225D01E77E5930081AA4B /* MyLayoutPos.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BB1E77E5930081AA4B /* MyLayoutPos.m */; }; - 182225D11E77E5930081AA4B /* MyLayoutSizeClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */; }; - 182225D21E77E5930081AA4B /* MyMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C11E77E5930081AA4B /* MyMaker.m */; }; - 182225D31E77E5930081AA4B /* MyTableLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C31E77E5930081AA4B /* MyTableLayout.m */; }; - 182225D41E77E5930081AA4B /* MyDimeScale.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C41E77E5930081AA4B /* MyDimeScale.m */; }; - 182225D51E77E5930081AA4B /* MyLayoutSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C51E77E5930081AA4B /* MyLayoutSize.m */; }; - 182DB6421EF7876200E2D65D /* MyGridLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182DB6401EF7876200E2D65D /* MyGridLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 182DB6431EF7876200E2D65D /* MyGridLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182DB6411EF7876200E2D65D /* MyGridLayout.m */; }; - 182DB6441EF7876200E2D65D /* MyGridLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182DB6411EF7876200E2D65D /* MyGridLayout.m */; }; - 1897384F1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 1897384E1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m */; }; - 189738511E16330B004F80D6 /* MyLayoutTestCaseBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 189738501E16330B004F80D6 /* MyLayoutTestCaseBase.m */; }; - 18B152341DEDDE5500AD7A1C /* MyLayoutUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */; }; - 18B2CCE81EAF5066001AE0E1 /* MyLinearLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */; }; - 18B2CCEA1EB046AC001AE0E1 /* MyFloatLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */; }; - 18C15AEC1EDF13D700AADEAC /* MyLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 18D684001C4F421400A48BB4 /* MyLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AED1EDF13DE00AADEAC /* MyFlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AB1E77E5930081AA4B /* MyFlowLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AEE1EDF13E500AADEAC /* MyLinearLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AC1E77E5930081AA4B /* MyLinearLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AEF1EDF13E900AADEAC /* MyFloatLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AD1E77E5930081AA4B /* MyFloatLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF01EDF13EF00AADEAC /* MyTableLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AE1E77E5930081AA4B /* MyTableLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF11EDF13F300AADEAC /* MyRelativeLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BE1E77E5930081AA4B /* MyRelativeLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF21EDF13F900AADEAC /* MyPathLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BD1E77E5930081AA4B /* MyPathLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF31EDF13FF00AADEAC /* MyFrameLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BA1E77E5930081AA4B /* MyFrameLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF41EDF140400AADEAC /* MyBaseLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AF1E77E5930081AA4B /* MyBaseLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF51EDF140D00AADEAC /* MyLayoutPos.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B01E77E5930081AA4B /* MyLayoutPos.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF61EDF141000AADEAC /* MyLayoutSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BC1E77E5930081AA4B /* MyLayoutSize.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF71EDF141600AADEAC /* MyLayoutSizeClass.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */; }; - 18C15AF81EDF141A00AADEAC /* MyMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C21E77E5930081AA4B /* MyMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF91EDF142000AADEAC /* MyDimeScale.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C71E77E5930081AA4B /* MyDimeScale.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AFA1EDF142300AADEAC /* MyLayoutDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B31E77E5930081AA4B /* MyLayoutDef.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AFB1EDF144B00AADEAC /* MyFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B41E77E5930081AA4B /* MyFlowLayout.m */; }; - 18C15AFC1EDF144B00AADEAC /* MyLinearLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B21E77E5930081AA4B /* MyLinearLayout.m */; }; - 18C15AFD1EDF144B00AADEAC /* MyFloatLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B91E77E5930081AA4B /* MyFloatLayout.m */; }; - 18C15AFE1EDF144B00AADEAC /* MyTableLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C31E77E5930081AA4B /* MyTableLayout.m */; }; - 18C15AFF1EDF144B00AADEAC /* MyRelativeLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B51E77E5930081AA4B /* MyRelativeLayout.m */; }; - 18C15B001EDF144B00AADEAC /* MyPathLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B61E77E5930081AA4B /* MyPathLayout.m */; }; - 18C15B011EDF144B00AADEAC /* MyFrameLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B71E77E5930081AA4B /* MyFrameLayout.m */; }; - 18C15B021EDF144B00AADEAC /* MyBaseLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B11E77E5930081AA4B /* MyBaseLayout.m */; }; - 18C15B031EDF144B00AADEAC /* MyLayoutPos.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BB1E77E5930081AA4B /* MyLayoutPos.m */; }; - 18C15B041EDF144B00AADEAC /* MyLayoutSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C51E77E5930081AA4B /* MyLayoutSize.m */; }; - 18C15B051EDF144B00AADEAC /* MyLayoutSizeClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */; }; - 18C15B061EDF144B00AADEAC /* MyMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C11E77E5930081AA4B /* MyMaker.m */; }; - 18C15B071EDF144B00AADEAC /* MyDimeScale.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C41E77E5930081AA4B /* MyDimeScale.m */; }; - 18D3C9111EDF074900D3DE43 /* LLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9041EDF074900D3DE43 /* LLTest1ViewController.m */; }; - 18D3C9121EDF074900D3DE43 /* LLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9061EDF074900D3DE43 /* LLTest2ViewController.m */; }; - 18D3C9131EDF074900D3DE43 /* LLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9081EDF074900D3DE43 /* LLTest3ViewController.m */; }; - 18D3C9141EDF074900D3DE43 /* LLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C90A1EDF074900D3DE43 /* LLTest4ViewController.m */; }; - 18D3C9151EDF074900D3DE43 /* LLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C90C1EDF074900D3DE43 /* LLTest5ViewController.m */; }; - 18D3C9161EDF074900D3DE43 /* LLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C90E1EDF074900D3DE43 /* LLTest6ViewController.m */; }; - 18D3C9171EDF074900D3DE43 /* LLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9101EDF074900D3DE43 /* LLTest7ViewController.m */; }; - 18D3C91C1EDF078200D3DE43 /* FLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9191EDF078200D3DE43 /* FLTest1ViewController.m */; }; - 18D3C91D1EDF078200D3DE43 /* FLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C91B1EDF078200D3DE43 /* FLTest2ViewController.m */; }; - 18D3C9281EDF07A700D3DE43 /* RLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C91F1EDF07A700D3DE43 /* RLTest1ViewController.m */; }; - 18D3C9291EDF07A700D3DE43 /* RLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9211EDF07A700D3DE43 /* RLTest2ViewController.m */; }; - 18D3C92A1EDF07A700D3DE43 /* RLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9231EDF07A700D3DE43 /* RLTest3ViewController.m */; }; - 18D3C92B1EDF07A700D3DE43 /* RLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9251EDF07A700D3DE43 /* RLTest4ViewController.m */; }; - 18D3C92C1EDF07A700D3DE43 /* RLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9271EDF07A700D3DE43 /* RLTest5ViewController.m */; }; - 18D3C9391EDF07C000D3DE43 /* FLLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C92E1EDF07C000D3DE43 /* FLLTest1ViewController.m */; }; - 18D3C93A1EDF07C000D3DE43 /* FLLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9301EDF07C000D3DE43 /* FLLTest2ViewController.m */; }; - 18D3C93B1EDF07C000D3DE43 /* FLLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9321EDF07C000D3DE43 /* FLLTest3ViewController.m */; }; - 18D3C93C1EDF07C000D3DE43 /* FLLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9341EDF07C000D3DE43 /* FLLTest4ViewController.m */; }; - 18D3C93D1EDF07C000D3DE43 /* FLLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9361EDF07C000D3DE43 /* FLLTest5ViewController.m */; }; - 18D3C93E1EDF07C000D3DE43 /* FLLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9381EDF07C000D3DE43 /* FLLTest6ViewController.m */; }; - 18D3C9491EDF07E700D3DE43 /* PLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9401EDF07E700D3DE43 /* PLTest1ViewController.m */; }; - 18D3C94A1EDF07E700D3DE43 /* PLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9421EDF07E700D3DE43 /* PLTest2ViewController.m */; }; - 18D3C94B1EDF07E700D3DE43 /* PLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9441EDF07E700D3DE43 /* PLTest3ViewController.m */; }; - 18D3C94C1EDF07E700D3DE43 /* PLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9461EDF07E700D3DE43 /* PLTest4ViewController.m */; }; - 18D3C94D1EDF07E700D3DE43 /* PLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9481EDF07E700D3DE43 /* PLTest5ViewController.m */; }; - 18D3C95A1EDF07F800D3DE43 /* FOLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C94F1EDF07F800D3DE43 /* FOLTest1ViewController.m */; }; - 18D3C95B1EDF07F800D3DE43 /* FOLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9511EDF07F800D3DE43 /* FOLTest2ViewController.m */; }; - 18D3C95C1EDF07F800D3DE43 /* FOLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9531EDF07F800D3DE43 /* FOLTest3ViewController.m */; }; - 18D3C95D1EDF07F800D3DE43 /* FOLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9551EDF07F800D3DE43 /* FOLTest4ViewController.m */; }; - 18D3C95E1EDF07F800D3DE43 /* FOLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9571EDF07F800D3DE43 /* FOLTest5ViewController.m */; }; - 18D3C95F1EDF07F800D3DE43 /* FOLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9591EDF07F800D3DE43 /* FOLTest6ViewController.m */; }; - 18D3C9661EDF080800D3DE43 /* TLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9611EDF080800D3DE43 /* TLTest1ViewController.m */; }; - 18D3C9671EDF080800D3DE43 /* TLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9631EDF080800D3DE43 /* TLTest2ViewController.m */; }; - 18D3C9681EDF080800D3DE43 /* TLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9651EDF080800D3DE43 /* TLTest3ViewController.m */; }; - 18D3C9711EDF082800D3DE43 /* AllTest1TableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C96A1EDF082800D3DE43 /* AllTest1TableViewCell.m */; }; - 18D3C9721EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C96C1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m */; }; - 18D3C9731EDF082800D3DE43 /* AllTest2TableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C96E1EDF082800D3DE43 /* AllTest2TableViewCell.m */; }; - 18D3C9741EDF082800D3DE43 /* AllTestDataModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9701EDF082800D3DE43 /* AllTestDataModel.m */; }; - 18D3C9851EDF084000D3DE43 /* AllTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9761EDF084000D3DE43 /* AllTest1ViewController.m */; }; - 18D3C9861EDF084000D3DE43 /* AllTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9781EDF084000D3DE43 /* AllTest2ViewController.m */; }; - 18D3C9871EDF084000D3DE43 /* AllTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C97A1EDF084000D3DE43 /* AllTest3ViewController.m */; }; - 18D3C9881EDF084000D3DE43 /* AllTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C97C1EDF084000D3DE43 /* AllTest4ViewController.m */; }; - 18D3C9891EDF084000D3DE43 /* AllTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C97E1EDF084000D3DE43 /* AllTest5ViewController.m */; }; - 18D3C98A1EDF084000D3DE43 /* AllTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9801EDF084000D3DE43 /* AllTest6ViewController.m */; }; - 18D3C98B1EDF084000D3DE43 /* AllTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9821EDF084000D3DE43 /* AllTest7ViewController.m */; }; - 18D3C98C1EDF084000D3DE43 /* AllTest8ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9841EDF084000D3DE43 /* AllTest8ViewController.m */; }; - 18D3C9931EDF08F800D3DE43 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C98E1EDF08F800D3DE43 /* ViewController.m */; }; - 18D3C9941EDF08F800D3DE43 /* YYFPSLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9901EDF08F800D3DE43 /* YYFPSLabel.m */; }; - 18D3C9951EDF08F800D3DE43 /* YYWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9921EDF08F800D3DE43 /* YYWeakProxy.m */; }; - 18D3C99B1EDF09BE00D3DE43 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9981EDF09BE00D3DE43 /* AppDelegate.m */; }; - 18D3C99C1EDF09BE00D3DE43 /* CFTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C99A1EDF09BE00D3DE43 /* CFTool.m */; }; - 18D3C9B41EDF0A5A00D3DE43 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9A21EDF0A5A00D3DE43 /* LaunchScreen.xib */; }; - 18D3C9B51EDF0A5A00D3DE43 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9A41EDF0A5A00D3DE43 /* Localizable.strings */; }; - 18D3C9B61EDF0A5A00D3DE43 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9A61EDF0A5A00D3DE43 /* Images.xcassets */; }; - 18D3C9B81EDF0A5A00D3DE43 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9A81EDF0A5A00D3DE43 /* main.m */; }; - 18D3C9BB1EDF0A5A00D3DE43 /* LaunchScreen.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9AE1EDF0A5A00D3DE43 /* LaunchScreen.strings */; }; - 18D3C9BC1EDF0A5A00D3DE43 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9B01EDF0A5A00D3DE43 /* Localizable.strings */; }; - 18D3C9CF1EDF0AB500D3DE43 /* fl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9BE1EDF0AB500D3DE43 /* fl.png */; }; - 18D3C9D01EDF0AB500D3DE43 /* fll.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9BF1EDF0AB500D3DE43 /* fll.png */; }; - 18D3C9D11EDF0AB500D3DE43 /* flo.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C01EDF0AB500D3DE43 /* flo.png */; }; - 18D3C9D21EDF0AB500D3DE43 /* layoutdemo1.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C11EDF0AB500D3DE43 /* layoutdemo1.gif */; }; - 18D3C9D31EDF0AB500D3DE43 /* layoutdemo2.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C21EDF0AB500D3DE43 /* layoutdemo2.gif */; }; - 18D3C9D41EDF0AB500D3DE43 /* layoutdemo3.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C31EDF0AB500D3DE43 /* layoutdemo3.gif */; }; - 18D3C9D51EDF0AB500D3DE43 /* layoutdemo4.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C41EDF0AB500D3DE43 /* layoutdemo4.gif */; }; - 18D3C9D61EDF0AB500D3DE43 /* layoutdemo5.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C51EDF0AB500D3DE43 /* layoutdemo5.gif */; }; - 18D3C9D71EDF0AB500D3DE43 /* layoutdemo6.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C61EDF0AB500D3DE43 /* layoutdemo6.gif */; }; - 18D3C9D81EDF0AB500D3DE43 /* layoutdemo7.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C71EDF0AB500D3DE43 /* layoutdemo7.gif */; }; - 18D3C9D91EDF0AB500D3DE43 /* ll.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C81EDF0AB500D3DE43 /* ll.png */; }; - 18D3C9DA1EDF0AB500D3DE43 /* MyLayout.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C91EDF0AB500D3DE43 /* MyLayout.png */; }; - 18D3C9DB1EDF0AB500D3DE43 /* MyLayoutClass.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CA1EDF0AB500D3DE43 /* MyLayoutClass.png */; }; - 18D3C9DC1EDF0AB500D3DE43 /* MyLayoutP.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CB1EDF0AB500D3DE43 /* MyLayoutP.png */; }; - 18D3C9DD1EDF0AB500D3DE43 /* pl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CC1EDF0AB500D3DE43 /* pl.png */; }; - 18D3C9DE1EDF0AB500D3DE43 /* rl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CD1EDF0AB500D3DE43 /* rl.png */; }; - 18D3C9DF1EDF0AB500D3DE43 /* tl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CE1EDF0AB500D3DE43 /* tl.png */; }; - 18D684591C4F423400A48BB4 /* MyLayoutTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D684551C4F423400A48BB4 /* MyLayoutTests.m */; }; - 200A26D91FA8A90300B06E7B /* AllTest9ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */; }; - 200A26DC1FA96B2400B06E7B /* AllTest9CollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */; }; - 204DC321209D5A8700F6CB57 /* TLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */; }; - 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */ = {isa = PBXBuildFile; fileRef = 205642841F4CFF9B00E8BDDE /* MyBorderline.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 205642871F4CFF9B00E8BDDE /* MyBorderline.m in Sources */ = {isa = PBXBuildFile; fileRef = 205642851F4CFF9B00E8BDDE /* MyBorderline.m */; }; - 205642881F4CFFB600E8BDDE /* MyBorderline.m in Sources */ = {isa = PBXBuildFile; fileRef = 205642851F4CFF9B00E8BDDE /* MyBorderline.m */; }; - 2056430A1F4E53CD00E8BDDE /* MyGridNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 205643081F4E53CD00E8BDDE /* MyGridNode.h */; }; - 2056430B1F4E53CD00E8BDDE /* MyGridNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643091F4E53CD00E8BDDE /* MyGridNode.m */; }; - 2056430C1F4E8B1E00E8BDDE /* MyGridNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643091F4E53CD00E8BDDE /* MyGridNode.m */; }; - 205643131F51C7EB00E8BDDE /* GLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643121F51C7EB00E8BDDE /* GLTest2ViewController.m */; }; - 205643161F55A03000E8BDDE /* MyLayoutMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 205643141F55A03000E8BDDE /* MyLayoutMath.h */; }; - 205643171F55A03000E8BDDE /* MyLayoutMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643151F55A03000E8BDDE /* MyLayoutMath.m */; }; - 205643181F55A16400E8BDDE /* MyLayoutMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643151F55A03000E8BDDE /* MyLayoutMath.m */; }; - 205CFA8E1F49BD1C00355489 /* GLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */; }; - 205E0C5F20B90347001A8B99 /* MyGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = 205642891F4D013D00E8BDDE /* MyGrid.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 205E0C6020B907CC001A8B99 /* MyLayoutPosInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */; }; - 205E0C6120B907D1001A8B99 /* MyLayoutSizeInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C81E77E5930081AA4B /* MyLayoutSizeInner.h */; }; - 205E0C6220B907DB001A8B99 /* MyLayoutInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B81E77E5930081AA4B /* MyLayoutInner.h */; }; - 205E0C6320B907EC001A8B99 /* MyLayoutDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */; }; - 205F9EBA1F7AA5710034732C /* gl.png in Resources */ = {isa = PBXBuildFile; fileRef = 205F9EB91F7AA5710034732C /* gl.png */; }; - 205F9EBC1F7AA6510034732C /* all.png in Resources */ = {isa = PBXBuildFile; fileRef = 205F9EBB1F7AA6510034732C /* all.png */; }; - 2075CC3220A0B2A400BA6F65 /* FLLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */; }; - 208157BD1F586AA700E945B6 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157BC1F586AA700E945B6 /* DetailViewController.m */; }; - 208157C31F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; - 208157C41F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; - 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */ = {isa = PBXBuildFile; fileRef = 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */; }; - 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */; }; - 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F783551F60399700BE5B31 /* GLTest3ViewController.m */; }; - 4411977B1F6AE78E00C22557 /* GridLayoutDemo5.json in Resources */ = {isa = PBXBuildFile; fileRef = 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */; }; - 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */; }; - 44EBDA8C1F619A6300B47CBD /* GLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */; }; - 44EBDA8E1F619C9000B47CBD /* GridLayoutDemo4.json in Resources */ = {isa = PBXBuildFile; fileRef = 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */; }; - 6740E1F820A52D9E00AFBC5A /* AllTest10ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */; }; - 6740E1FB20A52DA900AFBC5A /* AllTest10Model.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */; }; - 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */; }; - 6740E20120A52DC100AFBC5A /* AllTest10Cell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */; }; + 180BD8A11EA9EF9A00C6980B /* MyFrameLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 180BD8A01EA9EF9A00C6980B /* MyFrameLayoutTestCase.m */; }; + 1810AC221EB966D30022CBFF /* MyLayoutPerformanceTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */; }; + 181836951EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 181836941EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m */; }; + 181A10AA1EDF11FF00996203 /* FLLTest2ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 181A10A81EDF11FF00996203 /* FLLTest2ViewController.xib */; }; + 181A10AE1EDF123800996203 /* FOLTest1ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 181A10AC1EDF123800996203 /* FOLTest1ViewController.xib */; }; + 182225C91E77E5930081AA4B /* MyBaseLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B11E77E5930081AA4B /* MyBaseLayout.m */; }; + 182225CA1E77E5930081AA4B /* MyLinearLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B21E77E5930081AA4B /* MyLinearLayout.m */; }; + 182225CB1E77E5930081AA4B /* MyFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B41E77E5930081AA4B /* MyFlowLayout.m */; }; + 182225CC1E77E5930081AA4B /* MyRelativeLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B51E77E5930081AA4B /* MyRelativeLayout.m */; }; + 182225CD1E77E5930081AA4B /* MyPathLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B61E77E5930081AA4B /* MyPathLayout.m */; }; + 182225CE1E77E5930081AA4B /* MyFrameLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B71E77E5930081AA4B /* MyFrameLayout.m */; }; + 182225CF1E77E5930081AA4B /* MyFloatLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B91E77E5930081AA4B /* MyFloatLayout.m */; }; + 182225D01E77E5930081AA4B /* MyLayoutPos.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BB1E77E5930081AA4B /* MyLayoutPos.m */; }; + 182225D11E77E5930081AA4B /* MyLayoutSizeClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */; }; + 182225D21E77E5930081AA4B /* MyMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C11E77E5930081AA4B /* MyMaker.m */; }; + 182225D31E77E5930081AA4B /* MyTableLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C31E77E5930081AA4B /* MyTableLayout.m */; }; + 182225D41E77E5930081AA4B /* MyDimeScale.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C41E77E5930081AA4B /* MyDimeScale.m */; }; + 182225D51E77E5930081AA4B /* MyLayoutSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C51E77E5930081AA4B /* MyLayoutSize.m */; }; + 182DB6421EF7876200E2D65D /* MyGridLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182DB6401EF7876200E2D65D /* MyGridLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 182DB6431EF7876200E2D65D /* MyGridLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182DB6411EF7876200E2D65D /* MyGridLayout.m */; }; + 182DB6441EF7876200E2D65D /* MyGridLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182DB6411EF7876200E2D65D /* MyGridLayout.m */; }; + 1897384F1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 1897384E1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m */; }; + 189738511E16330B004F80D6 /* MyLayoutTestCaseBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 189738501E16330B004F80D6 /* MyLayoutTestCaseBase.m */; }; + 18B152341DEDDE5500AD7A1C /* MyLayoutUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */; }; + 18B2CCE81EAF5066001AE0E1 /* MyLinearLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */; }; + 18B2CCEA1EB046AC001AE0E1 /* MyFloatLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */; }; + 18C15AEC1EDF13D700AADEAC /* MyLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 18D684001C4F421400A48BB4 /* MyLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AED1EDF13DE00AADEAC /* MyFlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AB1E77E5930081AA4B /* MyFlowLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AEE1EDF13E500AADEAC /* MyLinearLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AC1E77E5930081AA4B /* MyLinearLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AEF1EDF13E900AADEAC /* MyFloatLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AD1E77E5930081AA4B /* MyFloatLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF01EDF13EF00AADEAC /* MyTableLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AE1E77E5930081AA4B /* MyTableLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF11EDF13F300AADEAC /* MyRelativeLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BE1E77E5930081AA4B /* MyRelativeLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF21EDF13F900AADEAC /* MyPathLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BD1E77E5930081AA4B /* MyPathLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF31EDF13FF00AADEAC /* MyFrameLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BA1E77E5930081AA4B /* MyFrameLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF41EDF140400AADEAC /* MyBaseLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AF1E77E5930081AA4B /* MyBaseLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF51EDF140D00AADEAC /* MyLayoutPos.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B01E77E5930081AA4B /* MyLayoutPos.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF61EDF141000AADEAC /* MyLayoutSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BC1E77E5930081AA4B /* MyLayoutSize.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF71EDF141600AADEAC /* MyLayoutSizeClass.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */; }; + 18C15AF81EDF141A00AADEAC /* MyMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C21E77E5930081AA4B /* MyMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF91EDF142000AADEAC /* MyDimeScale.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C71E77E5930081AA4B /* MyDimeScale.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AFA1EDF142300AADEAC /* MyLayoutDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B31E77E5930081AA4B /* MyLayoutDef.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AFB1EDF144B00AADEAC /* MyFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B41E77E5930081AA4B /* MyFlowLayout.m */; }; + 18C15AFC1EDF144B00AADEAC /* MyLinearLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B21E77E5930081AA4B /* MyLinearLayout.m */; }; + 18C15AFD1EDF144B00AADEAC /* MyFloatLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B91E77E5930081AA4B /* MyFloatLayout.m */; }; + 18C15AFE1EDF144B00AADEAC /* MyTableLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C31E77E5930081AA4B /* MyTableLayout.m */; }; + 18C15AFF1EDF144B00AADEAC /* MyRelativeLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B51E77E5930081AA4B /* MyRelativeLayout.m */; }; + 18C15B001EDF144B00AADEAC /* MyPathLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B61E77E5930081AA4B /* MyPathLayout.m */; }; + 18C15B011EDF144B00AADEAC /* MyFrameLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B71E77E5930081AA4B /* MyFrameLayout.m */; }; + 18C15B021EDF144B00AADEAC /* MyBaseLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B11E77E5930081AA4B /* MyBaseLayout.m */; }; + 18C15B031EDF144B00AADEAC /* MyLayoutPos.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BB1E77E5930081AA4B /* MyLayoutPos.m */; }; + 18C15B041EDF144B00AADEAC /* MyLayoutSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C51E77E5930081AA4B /* MyLayoutSize.m */; }; + 18C15B051EDF144B00AADEAC /* MyLayoutSizeClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */; }; + 18C15B061EDF144B00AADEAC /* MyMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C11E77E5930081AA4B /* MyMaker.m */; }; + 18C15B071EDF144B00AADEAC /* MyDimeScale.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C41E77E5930081AA4B /* MyDimeScale.m */; }; + 18D3C9111EDF074900D3DE43 /* LLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9041EDF074900D3DE43 /* LLTest1ViewController.m */; }; + 18D3C9121EDF074900D3DE43 /* LLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9061EDF074900D3DE43 /* LLTest2ViewController.m */; }; + 18D3C9131EDF074900D3DE43 /* LLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9081EDF074900D3DE43 /* LLTest3ViewController.m */; }; + 18D3C9141EDF074900D3DE43 /* LLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C90A1EDF074900D3DE43 /* LLTest4ViewController.m */; }; + 18D3C9151EDF074900D3DE43 /* LLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C90C1EDF074900D3DE43 /* LLTest5ViewController.m */; }; + 18D3C9161EDF074900D3DE43 /* LLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C90E1EDF074900D3DE43 /* LLTest6ViewController.m */; }; + 18D3C9171EDF074900D3DE43 /* LLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9101EDF074900D3DE43 /* LLTest7ViewController.m */; }; + 18D3C91C1EDF078200D3DE43 /* FLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9191EDF078200D3DE43 /* FLTest1ViewController.m */; }; + 18D3C91D1EDF078200D3DE43 /* FLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C91B1EDF078200D3DE43 /* FLTest2ViewController.m */; }; + 18D3C9281EDF07A700D3DE43 /* RLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C91F1EDF07A700D3DE43 /* RLTest1ViewController.m */; }; + 18D3C9291EDF07A700D3DE43 /* RLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9211EDF07A700D3DE43 /* RLTest2ViewController.m */; }; + 18D3C92A1EDF07A700D3DE43 /* RLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9231EDF07A700D3DE43 /* RLTest3ViewController.m */; }; + 18D3C92B1EDF07A700D3DE43 /* RLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9251EDF07A700D3DE43 /* RLTest4ViewController.m */; }; + 18D3C92C1EDF07A700D3DE43 /* RLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9271EDF07A700D3DE43 /* RLTest5ViewController.m */; }; + 18D3C9391EDF07C000D3DE43 /* FLLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C92E1EDF07C000D3DE43 /* FLLTest1ViewController.m */; }; + 18D3C93A1EDF07C000D3DE43 /* FLLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9301EDF07C000D3DE43 /* FLLTest2ViewController.m */; }; + 18D3C93B1EDF07C000D3DE43 /* FLLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9321EDF07C000D3DE43 /* FLLTest3ViewController.m */; }; + 18D3C93C1EDF07C000D3DE43 /* FLLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9341EDF07C000D3DE43 /* FLLTest4ViewController.m */; }; + 18D3C93D1EDF07C000D3DE43 /* FLLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9361EDF07C000D3DE43 /* FLLTest5ViewController.m */; }; + 18D3C93E1EDF07C000D3DE43 /* FLLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9381EDF07C000D3DE43 /* FLLTest6ViewController.m */; }; + 18D3C9491EDF07E700D3DE43 /* PLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9401EDF07E700D3DE43 /* PLTest1ViewController.m */; }; + 18D3C94A1EDF07E700D3DE43 /* PLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9421EDF07E700D3DE43 /* PLTest2ViewController.m */; }; + 18D3C94B1EDF07E700D3DE43 /* PLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9441EDF07E700D3DE43 /* PLTest3ViewController.m */; }; + 18D3C94C1EDF07E700D3DE43 /* PLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9461EDF07E700D3DE43 /* PLTest4ViewController.m */; }; + 18D3C94D1EDF07E700D3DE43 /* PLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9481EDF07E700D3DE43 /* PLTest5ViewController.m */; }; + 18D3C95A1EDF07F800D3DE43 /* FOLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C94F1EDF07F800D3DE43 /* FOLTest1ViewController.m */; }; + 18D3C95B1EDF07F800D3DE43 /* FOLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9511EDF07F800D3DE43 /* FOLTest2ViewController.m */; }; + 18D3C95C1EDF07F800D3DE43 /* FOLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9531EDF07F800D3DE43 /* FOLTest3ViewController.m */; }; + 18D3C95D1EDF07F800D3DE43 /* FOLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9551EDF07F800D3DE43 /* FOLTest4ViewController.m */; }; + 18D3C95E1EDF07F800D3DE43 /* FOLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9571EDF07F800D3DE43 /* FOLTest5ViewController.m */; }; + 18D3C95F1EDF07F800D3DE43 /* FOLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9591EDF07F800D3DE43 /* FOLTest6ViewController.m */; }; + 18D3C9661EDF080800D3DE43 /* TLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9611EDF080800D3DE43 /* TLTest1ViewController.m */; }; + 18D3C9671EDF080800D3DE43 /* TLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9631EDF080800D3DE43 /* TLTest2ViewController.m */; }; + 18D3C9681EDF080800D3DE43 /* TLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9651EDF080800D3DE43 /* TLTest3ViewController.m */; }; + 18D3C9711EDF082800D3DE43 /* AllTest1TableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C96A1EDF082800D3DE43 /* AllTest1TableViewCell.m */; }; + 18D3C9721EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C96C1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m */; }; + 18D3C9731EDF082800D3DE43 /* AllTest2TableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C96E1EDF082800D3DE43 /* AllTest2TableViewCell.m */; }; + 18D3C9741EDF082800D3DE43 /* AllTestDataModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9701EDF082800D3DE43 /* AllTestDataModel.m */; }; + 18D3C9851EDF084000D3DE43 /* AllTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9761EDF084000D3DE43 /* AllTest1ViewController.m */; }; + 18D3C9861EDF084000D3DE43 /* AllTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9781EDF084000D3DE43 /* AllTest2ViewController.m */; }; + 18D3C9871EDF084000D3DE43 /* AllTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C97A1EDF084000D3DE43 /* AllTest3ViewController.m */; }; + 18D3C9881EDF084000D3DE43 /* AllTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C97C1EDF084000D3DE43 /* AllTest4ViewController.m */; }; + 18D3C9891EDF084000D3DE43 /* AllTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C97E1EDF084000D3DE43 /* AllTest5ViewController.m */; }; + 18D3C98A1EDF084000D3DE43 /* AllTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9801EDF084000D3DE43 /* AllTest6ViewController.m */; }; + 18D3C98B1EDF084000D3DE43 /* AllTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9821EDF084000D3DE43 /* AllTest7ViewController.m */; }; + 18D3C98C1EDF084000D3DE43 /* AllTest8ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9841EDF084000D3DE43 /* AllTest8ViewController.m */; }; + 18D3C9931EDF08F800D3DE43 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C98E1EDF08F800D3DE43 /* ViewController.m */; }; + 18D3C9941EDF08F800D3DE43 /* YYFPSLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9901EDF08F800D3DE43 /* YYFPSLabel.m */; }; + 18D3C9951EDF08F800D3DE43 /* YYWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9921EDF08F800D3DE43 /* YYWeakProxy.m */; }; + 18D3C99B1EDF09BE00D3DE43 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9981EDF09BE00D3DE43 /* AppDelegate.m */; }; + 18D3C99C1EDF09BE00D3DE43 /* CFTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C99A1EDF09BE00D3DE43 /* CFTool.m */; }; + 18D3C9B41EDF0A5A00D3DE43 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9A21EDF0A5A00D3DE43 /* LaunchScreen.xib */; }; + 18D3C9B51EDF0A5A00D3DE43 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9A41EDF0A5A00D3DE43 /* Localizable.strings */; }; + 18D3C9B61EDF0A5A00D3DE43 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9A61EDF0A5A00D3DE43 /* Images.xcassets */; }; + 18D3C9B81EDF0A5A00D3DE43 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9A81EDF0A5A00D3DE43 /* main.m */; }; + 18D3C9BB1EDF0A5A00D3DE43 /* LaunchScreen.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9AE1EDF0A5A00D3DE43 /* LaunchScreen.strings */; }; + 18D3C9BC1EDF0A5A00D3DE43 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9B01EDF0A5A00D3DE43 /* Localizable.strings */; }; + 18D3C9CF1EDF0AB500D3DE43 /* fl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9BE1EDF0AB500D3DE43 /* fl.png */; }; + 18D3C9D01EDF0AB500D3DE43 /* fll.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9BF1EDF0AB500D3DE43 /* fll.png */; }; + 18D3C9D11EDF0AB500D3DE43 /* flo.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C01EDF0AB500D3DE43 /* flo.png */; }; + 18D3C9D21EDF0AB500D3DE43 /* layoutdemo1.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C11EDF0AB500D3DE43 /* layoutdemo1.gif */; }; + 18D3C9D31EDF0AB500D3DE43 /* layoutdemo2.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C21EDF0AB500D3DE43 /* layoutdemo2.gif */; }; + 18D3C9D41EDF0AB500D3DE43 /* layoutdemo3.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C31EDF0AB500D3DE43 /* layoutdemo3.gif */; }; + 18D3C9D51EDF0AB500D3DE43 /* layoutdemo4.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C41EDF0AB500D3DE43 /* layoutdemo4.gif */; }; + 18D3C9D61EDF0AB500D3DE43 /* layoutdemo5.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C51EDF0AB500D3DE43 /* layoutdemo5.gif */; }; + 18D3C9D71EDF0AB500D3DE43 /* layoutdemo6.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C61EDF0AB500D3DE43 /* layoutdemo6.gif */; }; + 18D3C9D81EDF0AB500D3DE43 /* layoutdemo7.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C71EDF0AB500D3DE43 /* layoutdemo7.gif */; }; + 18D3C9D91EDF0AB500D3DE43 /* ll.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C81EDF0AB500D3DE43 /* ll.png */; }; + 18D3C9DA1EDF0AB500D3DE43 /* MyLayout.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C91EDF0AB500D3DE43 /* MyLayout.png */; }; + 18D3C9DB1EDF0AB500D3DE43 /* MyLayoutClass.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CA1EDF0AB500D3DE43 /* MyLayoutClass.png */; }; + 18D3C9DC1EDF0AB500D3DE43 /* MyLayoutP.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CB1EDF0AB500D3DE43 /* MyLayoutP.png */; }; + 18D3C9DD1EDF0AB500D3DE43 /* pl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CC1EDF0AB500D3DE43 /* pl.png */; }; + 18D3C9DE1EDF0AB500D3DE43 /* rl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CD1EDF0AB500D3DE43 /* rl.png */; }; + 18D3C9DF1EDF0AB500D3DE43 /* tl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CE1EDF0AB500D3DE43 /* tl.png */; }; + 18D684591C4F423400A48BB4 /* MyLayoutTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D684551C4F423400A48BB4 /* MyLayoutTests.m */; }; + 200A26D91FA8A90300B06E7B /* AllTest9ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */; }; + 200A26DC1FA96B2400B06E7B /* AllTest9CollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */; }; + 204DC321209D5A8700F6CB57 /* TLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */; }; + 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */ = {isa = PBXBuildFile; fileRef = 205642841F4CFF9B00E8BDDE /* MyBorderline.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 205642871F4CFF9B00E8BDDE /* MyBorderline.m in Sources */ = {isa = PBXBuildFile; fileRef = 205642851F4CFF9B00E8BDDE /* MyBorderline.m */; }; + 205642881F4CFFB600E8BDDE /* MyBorderline.m in Sources */ = {isa = PBXBuildFile; fileRef = 205642851F4CFF9B00E8BDDE /* MyBorderline.m */; }; + 2056430A1F4E53CD00E8BDDE /* MyGridNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 205643081F4E53CD00E8BDDE /* MyGridNode.h */; }; + 2056430B1F4E53CD00E8BDDE /* MyGridNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643091F4E53CD00E8BDDE /* MyGridNode.m */; }; + 2056430C1F4E8B1E00E8BDDE /* MyGridNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643091F4E53CD00E8BDDE /* MyGridNode.m */; }; + 205643131F51C7EB00E8BDDE /* GLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643121F51C7EB00E8BDDE /* GLTest2ViewController.m */; }; + 205643161F55A03000E8BDDE /* MyLayoutMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 205643141F55A03000E8BDDE /* MyLayoutMath.h */; }; + 205643171F55A03000E8BDDE /* MyLayoutMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643151F55A03000E8BDDE /* MyLayoutMath.m */; }; + 205643181F55A16400E8BDDE /* MyLayoutMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643151F55A03000E8BDDE /* MyLayoutMath.m */; }; + 205CFA8E1F49BD1C00355489 /* GLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */; }; + 205E0C5F20B90347001A8B99 /* MyGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = 205642891F4D013D00E8BDDE /* MyGrid.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 205E0C6020B907CC001A8B99 /* MyLayoutPosInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */; }; + 205E0C6120B907D1001A8B99 /* MyLayoutSizeInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C81E77E5930081AA4B /* MyLayoutSizeInner.h */; }; + 205E0C6220B907DB001A8B99 /* MyLayoutInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B81E77E5930081AA4B /* MyLayoutInner.h */; }; + 205E0C6320B907EC001A8B99 /* MyLayoutDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */; }; + 205F9EBA1F7AA5710034732C /* gl.png in Resources */ = {isa = PBXBuildFile; fileRef = 205F9EB91F7AA5710034732C /* gl.png */; }; + 205F9EBC1F7AA6510034732C /* all.png in Resources */ = {isa = PBXBuildFile; fileRef = 205F9EBB1F7AA6510034732C /* all.png */; }; + 2075CC3220A0B2A400BA6F65 /* FLLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */; }; + 208157BD1F586AA700E945B6 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157BC1F586AA700E945B6 /* DetailViewController.m */; }; + 208157C31F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; + 208157C41F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; + 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */ = {isa = PBXBuildFile; fileRef = 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */; }; + 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */; }; + 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F783551F60399700BE5B31 /* GLTest3ViewController.m */; }; + 4411977B1F6AE78E00C22557 /* GridLayoutDemo5.json in Resources */ = {isa = PBXBuildFile; fileRef = 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */; }; + 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */; }; + 44EBDA8C1F619A6300B47CBD /* GLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */; }; + 44EBDA8E1F619C9000B47CBD /* GridLayoutDemo4.json in Resources */ = {isa = PBXBuildFile; fileRef = 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */; }; + 6740E1F820A52D9E00AFBC5A /* AllTest10ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */; }; + 6740E1FB20A52DA900AFBC5A /* AllTest10Model.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */; }; + 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */; }; + 6740E20120A52DC100AFBC5A /* AllTest10Cell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 184082A71B2C46E8003F378B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 184082851B2C46E8003F378B /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1840828C1B2C46E8003F378B; - remoteInfo = MyLinearLayoutDemo; - }; - 18B152361DEDDE5500AD7A1C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 184082851B2C46E8003F378B /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1840828C1B2C46E8003F378B; - remoteInfo = MyLayout; - }; + 184082A71B2C46E8003F378B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 184082851B2C46E8003F378B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1840828C1B2C46E8003F378B; + remoteInfo = MyLinearLayoutDemo; + }; + 18B152361DEDDE5500AD7A1C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 184082851B2C46E8003F378B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1840828C1B2C46E8003F378B; + remoteInfo = MyLayout; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 180BD8A01EA9EF9A00C6980B /* MyFrameLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyFrameLayoutTestCase.m; sourceTree = ""; }; - 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutPerformanceTestCase.m; sourceTree = ""; }; - 181836941EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyNoLayoutSuperviewTestCase.m; sourceTree = ""; }; - 181A10A91EDF11FF00996203 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/FLLTest2ViewController.xib; sourceTree = ""; }; - 181A10AB1EDF120E00996203 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "zh-Hans"; path = "zh-Hans.lproj/FLLTest2ViewController.xib"; sourceTree = ""; }; - 181A10AD1EDF123800996203 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/FOLTest1ViewController.xib; sourceTree = ""; }; - 181A10AF1EDF124400996203 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "zh-Hans"; path = "zh-Hans.lproj/FOLTest1ViewController.xib"; sourceTree = ""; }; - 181A10B51EDF12CF00996203 /* MyLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MyLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 182225AB1E77E5930081AA4B /* MyFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyFlowLayout.h; sourceTree = ""; }; - 182225AC1E77E5930081AA4B /* MyLinearLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLinearLayout.h; sourceTree = ""; }; - 182225AD1E77E5930081AA4B /* MyFloatLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyFloatLayout.h; sourceTree = ""; }; - 182225AE1E77E5930081AA4B /* MyTableLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MyTableLayout.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 182225AF1E77E5930081AA4B /* MyBaseLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MyBaseLayout.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 182225B01E77E5930081AA4B /* MyLayoutPos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutPos.h; sourceTree = ""; }; - 182225B11E77E5930081AA4B /* MyBaseLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyBaseLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 182225B21E77E5930081AA4B /* MyLinearLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyLinearLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 182225B31E77E5930081AA4B /* MyLayoutDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutDef.h; sourceTree = ""; }; - 182225B41E77E5930081AA4B /* MyFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFlowLayout.m; sourceTree = ""; }; - 182225B51E77E5930081AA4B /* MyRelativeLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyRelativeLayout.m; sourceTree = ""; }; - 182225B61E77E5930081AA4B /* MyPathLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyPathLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 182225B71E77E5930081AA4B /* MyFrameLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFrameLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 182225B81E77E5930081AA4B /* MyLayoutInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutInner.h; sourceTree = ""; }; - 182225B91E77E5930081AA4B /* MyFloatLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFloatLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 182225BA1E77E5930081AA4B /* MyFrameLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyFrameLayout.h; sourceTree = ""; }; - 182225BB1E77E5930081AA4B /* MyLayoutPos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutPos.m; sourceTree = ""; }; - 182225BC1E77E5930081AA4B /* MyLayoutSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutSize.h; sourceTree = ""; }; - 182225BD1E77E5930081AA4B /* MyPathLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyPathLayout.h; sourceTree = ""; }; - 182225BE1E77E5930081AA4B /* MyRelativeLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyRelativeLayout.h; sourceTree = ""; }; - 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyLayoutSizeClass.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutSizeClass.h; sourceTree = ""; }; - 182225C11E77E5930081AA4B /* MyMaker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyMaker.m; sourceTree = ""; }; - 182225C21E77E5930081AA4B /* MyMaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyMaker.h; sourceTree = ""; }; - 182225C31E77E5930081AA4B /* MyTableLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyTableLayout.m; sourceTree = ""; }; - 182225C41E77E5930081AA4B /* MyDimeScale.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyDimeScale.m; sourceTree = ""; }; - 182225C51E77E5930081AA4B /* MyLayoutSize.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutSize.m; sourceTree = ""; }; - 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutPosInner.h; sourceTree = ""; }; - 182225C71E77E5930081AA4B /* MyDimeScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyDimeScale.h; sourceTree = ""; }; - 182225C81E77E5930081AA4B /* MyLayoutSizeInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutSizeInner.h; sourceTree = ""; }; - 182DB6401EF7876200E2D65D /* MyGridLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyGridLayout.h; sourceTree = ""; }; - 182DB6411EF7876200E2D65D /* MyGridLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyGridLayout.m; sourceTree = ""; }; - 1840828D1B2C46E8003F378B /* MyLayoutDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MyLayoutDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 184082A61B2C46E8003F378B /* MyLayout.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MyLayout.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 1897384E1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyRelativeLayoutTestCase.m; sourceTree = ""; }; - 189738501E16330B004F80D6 /* MyLayoutTestCaseBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutTestCaseBase.m; sourceTree = ""; }; - 189738521E16340D004F80D6 /* MyLayoutTestCaseBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyLayoutTestCaseBase.h; sourceTree = ""; }; - 18B152311DEDDE5500AD7A1C /* MyLayoutUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MyLayoutUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyLayoutUITests.m; sourceTree = ""; }; - 18B152351DEDDE5500AD7A1C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLinearLayoutTestCase.m; sourceTree = ""; }; - 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyFloatLayoutTestCase.m; sourceTree = ""; }; - 18C15AEA1EDF133200AADEAC /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 18D3C9031EDF074900D3DE43 /* LLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest1ViewController.h; sourceTree = ""; }; - 18D3C9041EDF074900D3DE43 /* LLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest1ViewController.m; sourceTree = ""; }; - 18D3C9051EDF074900D3DE43 /* LLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest2ViewController.h; sourceTree = ""; }; - 18D3C9061EDF074900D3DE43 /* LLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest2ViewController.m; sourceTree = ""; }; - 18D3C9071EDF074900D3DE43 /* LLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest3ViewController.h; sourceTree = ""; }; - 18D3C9081EDF074900D3DE43 /* LLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest3ViewController.m; sourceTree = ""; }; - 18D3C9091EDF074900D3DE43 /* LLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest4ViewController.h; sourceTree = ""; }; - 18D3C90A1EDF074900D3DE43 /* LLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest4ViewController.m; sourceTree = ""; }; - 18D3C90B1EDF074900D3DE43 /* LLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest5ViewController.h; sourceTree = ""; }; - 18D3C90C1EDF074900D3DE43 /* LLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest5ViewController.m; sourceTree = ""; }; - 18D3C90D1EDF074900D3DE43 /* LLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest6ViewController.h; sourceTree = ""; }; - 18D3C90E1EDF074900D3DE43 /* LLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest6ViewController.m; sourceTree = ""; }; - 18D3C90F1EDF074900D3DE43 /* LLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest7ViewController.h; sourceTree = ""; }; - 18D3C9101EDF074900D3DE43 /* LLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = LLTest7ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C9181EDF078200D3DE43 /* FLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLTest1ViewController.h; sourceTree = ""; }; - 18D3C9191EDF078200D3DE43 /* FLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLTest1ViewController.m; sourceTree = ""; }; - 18D3C91A1EDF078200D3DE43 /* FLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLTest2ViewController.h; sourceTree = ""; }; - 18D3C91B1EDF078200D3DE43 /* FLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLTest2ViewController.m; sourceTree = ""; }; - 18D3C91E1EDF07A700D3DE43 /* RLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest1ViewController.h; sourceTree = ""; }; - 18D3C91F1EDF07A700D3DE43 /* RLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest1ViewController.m; sourceTree = ""; }; - 18D3C9201EDF07A700D3DE43 /* RLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest2ViewController.h; sourceTree = ""; }; - 18D3C9211EDF07A700D3DE43 /* RLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest2ViewController.m; sourceTree = ""; }; - 18D3C9221EDF07A700D3DE43 /* RLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest3ViewController.h; sourceTree = ""; }; - 18D3C9231EDF07A700D3DE43 /* RLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest3ViewController.m; sourceTree = ""; }; - 18D3C9241EDF07A700D3DE43 /* RLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest4ViewController.h; sourceTree = ""; }; - 18D3C9251EDF07A700D3DE43 /* RLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest4ViewController.m; sourceTree = ""; }; - 18D3C9261EDF07A700D3DE43 /* RLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest5ViewController.h; sourceTree = ""; }; - 18D3C9271EDF07A700D3DE43 /* RLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest5ViewController.m; sourceTree = ""; }; - 18D3C92D1EDF07C000D3DE43 /* FLLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest1ViewController.h; sourceTree = ""; }; - 18D3C92E1EDF07C000D3DE43 /* FLLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest1ViewController.m; sourceTree = ""; }; - 18D3C92F1EDF07C000D3DE43 /* FLLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest2ViewController.h; sourceTree = ""; }; - 18D3C9301EDF07C000D3DE43 /* FLLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest2ViewController.m; sourceTree = ""; }; - 18D3C9311EDF07C000D3DE43 /* FLLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest3ViewController.h; sourceTree = ""; }; - 18D3C9321EDF07C000D3DE43 /* FLLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest3ViewController.m; sourceTree = ""; }; - 18D3C9331EDF07C000D3DE43 /* FLLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest4ViewController.h; sourceTree = ""; }; - 18D3C9341EDF07C000D3DE43 /* FLLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest4ViewController.m; sourceTree = ""; }; - 18D3C9351EDF07C000D3DE43 /* FLLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest5ViewController.h; sourceTree = ""; }; - 18D3C9361EDF07C000D3DE43 /* FLLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest5ViewController.m; sourceTree = ""; }; - 18D3C9371EDF07C000D3DE43 /* FLLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest6ViewController.h; sourceTree = ""; }; - 18D3C9381EDF07C000D3DE43 /* FLLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest6ViewController.m; sourceTree = ""; }; - 18D3C93F1EDF07E700D3DE43 /* PLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest1ViewController.h; sourceTree = ""; }; - 18D3C9401EDF07E700D3DE43 /* PLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest1ViewController.m; sourceTree = ""; }; - 18D3C9411EDF07E700D3DE43 /* PLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest2ViewController.h; sourceTree = ""; }; - 18D3C9421EDF07E700D3DE43 /* PLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest2ViewController.m; sourceTree = ""; }; - 18D3C9431EDF07E700D3DE43 /* PLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest3ViewController.h; sourceTree = ""; }; - 18D3C9441EDF07E700D3DE43 /* PLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest3ViewController.m; sourceTree = ""; }; - 18D3C9451EDF07E700D3DE43 /* PLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest4ViewController.h; sourceTree = ""; }; - 18D3C9461EDF07E700D3DE43 /* PLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = PLTest4ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C9471EDF07E700D3DE43 /* PLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest5ViewController.h; sourceTree = ""; }; - 18D3C9481EDF07E700D3DE43 /* PLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest5ViewController.m; sourceTree = ""; }; - 18D3C94E1EDF07F800D3DE43 /* FOLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest1ViewController.h; sourceTree = ""; }; - 18D3C94F1EDF07F800D3DE43 /* FOLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest1ViewController.m; sourceTree = ""; }; - 18D3C9501EDF07F800D3DE43 /* FOLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest2ViewController.h; sourceTree = ""; }; - 18D3C9511EDF07F800D3DE43 /* FOLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest2ViewController.m; sourceTree = ""; }; - 18D3C9521EDF07F800D3DE43 /* FOLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest3ViewController.h; sourceTree = ""; }; - 18D3C9531EDF07F800D3DE43 /* FOLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest3ViewController.m; sourceTree = ""; }; - 18D3C9541EDF07F800D3DE43 /* FOLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest4ViewController.h; sourceTree = ""; }; - 18D3C9551EDF07F800D3DE43 /* FOLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest4ViewController.m; sourceTree = ""; }; - 18D3C9561EDF07F800D3DE43 /* FOLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest5ViewController.h; sourceTree = ""; }; - 18D3C9571EDF07F800D3DE43 /* FOLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest5ViewController.m; sourceTree = ""; }; - 18D3C9581EDF07F800D3DE43 /* FOLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest6ViewController.h; sourceTree = ""; }; - 18D3C9591EDF07F800D3DE43 /* FOLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest6ViewController.m; sourceTree = ""; }; - 18D3C9601EDF080800D3DE43 /* TLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest1ViewController.h; sourceTree = ""; }; - 18D3C9611EDF080800D3DE43 /* TLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = TLTest1ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C9621EDF080800D3DE43 /* TLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest2ViewController.h; sourceTree = ""; }; - 18D3C9631EDF080800D3DE43 /* TLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = TLTest2ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C9641EDF080800D3DE43 /* TLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest3ViewController.h; sourceTree = ""; }; - 18D3C9651EDF080800D3DE43 /* TLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLTest3ViewController.m; sourceTree = ""; }; - 18D3C9691EDF082800D3DE43 /* AllTest1TableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1TableViewCell.h; sourceTree = ""; }; - 18D3C96A1EDF082800D3DE43 /* AllTest1TableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1TableViewCell.m; sourceTree = ""; }; - 18D3C96B1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1TableViewHeaderFooterView.h; sourceTree = ""; }; - 18D3C96C1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1TableViewHeaderFooterView.m; sourceTree = ""; }; - 18D3C96D1EDF082800D3DE43 /* AllTest2TableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest2TableViewCell.h; sourceTree = ""; }; - 18D3C96E1EDF082800D3DE43 /* AllTest2TableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AllTest2TableViewCell.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C96F1EDF082800D3DE43 /* AllTestDataModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTestDataModel.h; sourceTree = ""; }; - 18D3C9701EDF082800D3DE43 /* AllTestDataModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTestDataModel.m; sourceTree = ""; }; - 18D3C9751EDF084000D3DE43 /* AllTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1ViewController.h; sourceTree = ""; }; - 18D3C9761EDF084000D3DE43 /* AllTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1ViewController.m; sourceTree = ""; }; - 18D3C9771EDF084000D3DE43 /* AllTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest2ViewController.h; sourceTree = ""; }; - 18D3C9781EDF084000D3DE43 /* AllTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest2ViewController.m; sourceTree = ""; }; - 18D3C9791EDF084000D3DE43 /* AllTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest3ViewController.h; sourceTree = ""; }; - 18D3C97A1EDF084000D3DE43 /* AllTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AllTest3ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C97B1EDF084000D3DE43 /* AllTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest4ViewController.h; sourceTree = ""; }; - 18D3C97C1EDF084000D3DE43 /* AllTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest4ViewController.m; sourceTree = ""; }; - 18D3C97D1EDF084000D3DE43 /* AllTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest5ViewController.h; sourceTree = ""; }; - 18D3C97E1EDF084000D3DE43 /* AllTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest5ViewController.m; sourceTree = ""; }; - 18D3C97F1EDF084000D3DE43 /* AllTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest6ViewController.h; sourceTree = ""; }; - 18D3C9801EDF084000D3DE43 /* AllTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest6ViewController.m; sourceTree = ""; }; - 18D3C9811EDF084000D3DE43 /* AllTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest7ViewController.h; sourceTree = ""; }; - 18D3C9821EDF084000D3DE43 /* AllTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AllTest7ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C9831EDF084000D3DE43 /* AllTest8ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest8ViewController.h; sourceTree = ""; }; - 18D3C9841EDF084000D3DE43 /* AllTest8ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest8ViewController.m; sourceTree = ""; }; - 18D3C98D1EDF08F800D3DE43 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; - 18D3C98E1EDF08F800D3DE43 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; - 18D3C98F1EDF08F800D3DE43 /* YYFPSLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYFPSLabel.h; sourceTree = ""; }; - 18D3C9901EDF08F800D3DE43 /* YYFPSLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYFPSLabel.m; sourceTree = ""; }; - 18D3C9911EDF08F800D3DE43 /* YYWeakProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWeakProxy.h; sourceTree = ""; }; - 18D3C9921EDF08F800D3DE43 /* YYWeakProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWeakProxy.m; sourceTree = ""; }; - 18D3C9971EDF09BE00D3DE43 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 18D3C9981EDF09BE00D3DE43 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 18D3C9991EDF09BE00D3DE43 /* CFTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFTool.h; sourceTree = ""; }; - 18D3C99A1EDF09BE00D3DE43 /* CFTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CFTool.m; sourceTree = ""; }; - 18D3C9A31EDF0A5A00D3DE43 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = LaunchScreen.xib; sourceTree = ""; }; - 18D3C9A51EDF0A5A00D3DE43 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Localizable.strings; sourceTree = ""; }; - 18D3C9A61EDF0A5A00D3DE43 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 18D3C9A71EDF0A5A00D3DE43 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 18D3C9A81EDF0A5A00D3DE43 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 18D3C9AF1EDF0A5A00D3DE43 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = LaunchScreen.strings; sourceTree = ""; }; - 18D3C9B11EDF0A5A00D3DE43 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = Localizable.strings; sourceTree = ""; }; - 18D3C9BE1EDF0AB500D3DE43 /* fl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = fl.png; sourceTree = ""; }; - 18D3C9BF1EDF0AB500D3DE43 /* fll.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = fll.png; sourceTree = ""; }; - 18D3C9C01EDF0AB500D3DE43 /* flo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flo.png; sourceTree = ""; }; - 18D3C9C11EDF0AB500D3DE43 /* layoutdemo1.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo1.gif; sourceTree = ""; }; - 18D3C9C21EDF0AB500D3DE43 /* layoutdemo2.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo2.gif; sourceTree = ""; }; - 18D3C9C31EDF0AB500D3DE43 /* layoutdemo3.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo3.gif; sourceTree = ""; }; - 18D3C9C41EDF0AB500D3DE43 /* layoutdemo4.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo4.gif; sourceTree = ""; }; - 18D3C9C51EDF0AB500D3DE43 /* layoutdemo5.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo5.gif; sourceTree = ""; }; - 18D3C9C61EDF0AB500D3DE43 /* layoutdemo6.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo6.gif; sourceTree = ""; }; - 18D3C9C71EDF0AB500D3DE43 /* layoutdemo7.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo7.gif; sourceTree = ""; }; - 18D3C9C81EDF0AB500D3DE43 /* ll.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ll.png; sourceTree = ""; }; - 18D3C9C91EDF0AB500D3DE43 /* MyLayout.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MyLayout.png; sourceTree = ""; }; - 18D3C9CA1EDF0AB500D3DE43 /* MyLayoutClass.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MyLayoutClass.png; sourceTree = ""; }; - 18D3C9CB1EDF0AB500D3DE43 /* MyLayoutP.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MyLayoutP.png; sourceTree = ""; }; - 18D3C9CC1EDF0AB500D3DE43 /* pl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = pl.png; sourceTree = ""; }; - 18D3C9CD1EDF0AB500D3DE43 /* rl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = rl.png; sourceTree = ""; }; - 18D3C9CE1EDF0AB500D3DE43 /* tl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tl.png; sourceTree = ""; }; - 18D684001C4F421400A48BB4 /* MyLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayout.h; sourceTree = ""; }; - 18D684541C4F423400A48BB4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 18D684551C4F423400A48BB4 /* MyLayoutTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutTests.m; sourceTree = ""; }; - 200A26D71FA8A90300B06E7B /* AllTest9ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AllTest9ViewController.h; sourceTree = ""; }; - 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest9ViewController.m; sourceTree = ""; }; - 200A26DA1FA96B2400B06E7B /* AllTest9CollectionViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AllTest9CollectionViewCell.h; sourceTree = ""; }; - 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest9CollectionViewCell.m; sourceTree = ""; }; - 2043D5DB20995DF800276C68 /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = System/Library/Frameworks/CoreBluetooth.framework; sourceTree = SDKROOT; }; - 204DC31F209D5A7C00F6CB57 /* TLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest4ViewController.h; sourceTree = ""; }; - 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLTest4ViewController.m; sourceTree = ""; }; - 205642841F4CFF9B00E8BDDE /* MyBorderline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyBorderline.h; sourceTree = ""; }; - 205642851F4CFF9B00E8BDDE /* MyBorderline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyBorderline.m; sourceTree = ""; }; - 205642891F4D013D00E8BDDE /* MyGrid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyGrid.h; sourceTree = ""; }; - 205643081F4E53CD00E8BDDE /* MyGridNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyGridNode.h; sourceTree = ""; }; - 205643091F4E53CD00E8BDDE /* MyGridNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyGridNode.m; sourceTree = ""; }; - 205643111F51C7DF00E8BDDE /* GLTest2ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GLTest2ViewController.h; sourceTree = ""; }; - 205643121F51C7EB00E8BDDE /* GLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GLTest2ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 205643141F55A03000E8BDDE /* MyLayoutMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutMath.h; sourceTree = ""; }; - 205643151F55A03000E8BDDE /* MyLayoutMath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutMath.m; sourceTree = ""; }; - 205CFA8C1F49BD1C00355489 /* GLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest1ViewController.h; sourceTree = ""; }; - 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GLTest1ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 205F9EB91F7AA5710034732C /* gl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = gl.png; sourceTree = ""; }; - 205F9EBB1F7AA6510034732C /* all.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = all.png; sourceTree = ""; }; - 2075CC3020A0B29700BA6F65 /* FLLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest7ViewController.h; sourceTree = ""; }; - 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest7ViewController.m; sourceTree = ""; }; - 208157BB1F586A9900E945B6 /* DetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = ""; }; - 208157BC1F586AA700E945B6 /* DetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; - 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutDelegate.h; sourceTree = ""; }; - 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutDelegate.m; sourceTree = ""; }; - 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo8.gif; sourceTree = ""; }; - 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest7ViewController.h; sourceTree = ""; }; - 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest7ViewController.m; sourceTree = ""; }; - 20F783541F60398C00BE5B31 /* GLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest3ViewController.h; sourceTree = ""; }; - 20F783551F60399700BE5B31 /* GLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest3ViewController.m; sourceTree = ""; }; - 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo5.json; sourceTree = ""; }; - 444B718F1F6A3E3F00331872 /* GLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest5ViewController.h; sourceTree = ""; }; - 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest5ViewController.m; sourceTree = ""; }; - 44EBDA8A1F619A6300B47CBD /* GLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest4ViewController.h; sourceTree = ""; }; - 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest4ViewController.m; sourceTree = ""; }; - 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo4.json; sourceTree = ""; }; - 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10ViewController.h; sourceTree = ""; }; - 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10ViewController.m; sourceTree = ""; }; - 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10Model.m; sourceTree = ""; }; - 6740E1FA20A52DA900AFBC5A /* AllTest10Model.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10Model.h; sourceTree = ""; }; - 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10HeaderView.m; sourceTree = ""; }; - 6740E1FD20A52DB000AFBC5A /* AllTest10HeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10HeaderView.h; sourceTree = ""; }; - 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10Cell.m; sourceTree = ""; }; - 6740E20020A52DC100AFBC5A /* AllTest10Cell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10Cell.h; sourceTree = ""; }; + 180BD8A01EA9EF9A00C6980B /* MyFrameLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyFrameLayoutTestCase.m; sourceTree = ""; }; + 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutPerformanceTestCase.m; sourceTree = ""; }; + 181836941EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyNoLayoutSuperviewTestCase.m; sourceTree = ""; }; + 181A10A91EDF11FF00996203 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/FLLTest2ViewController.xib; sourceTree = ""; }; + 181A10AB1EDF120E00996203 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "zh-Hans"; path = "zh-Hans.lproj/FLLTest2ViewController.xib"; sourceTree = ""; }; + 181A10AD1EDF123800996203 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/FOLTest1ViewController.xib; sourceTree = ""; }; + 181A10AF1EDF124400996203 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "zh-Hans"; path = "zh-Hans.lproj/FOLTest1ViewController.xib"; sourceTree = ""; }; + 181A10B51EDF12CF00996203 /* MyLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MyLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 182225AB1E77E5930081AA4B /* MyFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyFlowLayout.h; sourceTree = ""; }; + 182225AC1E77E5930081AA4B /* MyLinearLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLinearLayout.h; sourceTree = ""; }; + 182225AD1E77E5930081AA4B /* MyFloatLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyFloatLayout.h; sourceTree = ""; }; + 182225AE1E77E5930081AA4B /* MyTableLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MyTableLayout.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 182225AF1E77E5930081AA4B /* MyBaseLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MyBaseLayout.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 182225B01E77E5930081AA4B /* MyLayoutPos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutPos.h; sourceTree = ""; }; + 182225B11E77E5930081AA4B /* MyBaseLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyBaseLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225B21E77E5930081AA4B /* MyLinearLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyLinearLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225B31E77E5930081AA4B /* MyLayoutDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutDef.h; sourceTree = ""; }; + 182225B41E77E5930081AA4B /* MyFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFlowLayout.m; sourceTree = ""; }; + 182225B51E77E5930081AA4B /* MyRelativeLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyRelativeLayout.m; sourceTree = ""; }; + 182225B61E77E5930081AA4B /* MyPathLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyPathLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225B71E77E5930081AA4B /* MyFrameLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFrameLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225B81E77E5930081AA4B /* MyLayoutInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutInner.h; sourceTree = ""; }; + 182225B91E77E5930081AA4B /* MyFloatLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFloatLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225BA1E77E5930081AA4B /* MyFrameLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyFrameLayout.h; sourceTree = ""; }; + 182225BB1E77E5930081AA4B /* MyLayoutPos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutPos.m; sourceTree = ""; }; + 182225BC1E77E5930081AA4B /* MyLayoutSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutSize.h; sourceTree = ""; }; + 182225BD1E77E5930081AA4B /* MyPathLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyPathLayout.h; sourceTree = ""; }; + 182225BE1E77E5930081AA4B /* MyRelativeLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyRelativeLayout.h; sourceTree = ""; }; + 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyLayoutSizeClass.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutSizeClass.h; sourceTree = ""; }; + 182225C11E77E5930081AA4B /* MyMaker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyMaker.m; sourceTree = ""; }; + 182225C21E77E5930081AA4B /* MyMaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyMaker.h; sourceTree = ""; }; + 182225C31E77E5930081AA4B /* MyTableLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyTableLayout.m; sourceTree = ""; }; + 182225C41E77E5930081AA4B /* MyDimeScale.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyDimeScale.m; sourceTree = ""; }; + 182225C51E77E5930081AA4B /* MyLayoutSize.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutSize.m; sourceTree = ""; }; + 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutPosInner.h; sourceTree = ""; }; + 182225C71E77E5930081AA4B /* MyDimeScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyDimeScale.h; sourceTree = ""; }; + 182225C81E77E5930081AA4B /* MyLayoutSizeInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutSizeInner.h; sourceTree = ""; }; + 182DB6401EF7876200E2D65D /* MyGridLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyGridLayout.h; sourceTree = ""; }; + 182DB6411EF7876200E2D65D /* MyGridLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyGridLayout.m; sourceTree = ""; }; + 1840828D1B2C46E8003F378B /* MyLayoutDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MyLayoutDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 184082A61B2C46E8003F378B /* MyLayout.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MyLayout.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1897384E1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyRelativeLayoutTestCase.m; sourceTree = ""; }; + 189738501E16330B004F80D6 /* MyLayoutTestCaseBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutTestCaseBase.m; sourceTree = ""; }; + 189738521E16340D004F80D6 /* MyLayoutTestCaseBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyLayoutTestCaseBase.h; sourceTree = ""; }; + 18B152311DEDDE5500AD7A1C /* MyLayoutUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MyLayoutUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyLayoutUITests.m; sourceTree = ""; }; + 18B152351DEDDE5500AD7A1C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLinearLayoutTestCase.m; sourceTree = ""; }; + 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyFloatLayoutTestCase.m; sourceTree = ""; }; + 18C15AEA1EDF133200AADEAC /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 18D3C9031EDF074900D3DE43 /* LLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest1ViewController.h; sourceTree = ""; }; + 18D3C9041EDF074900D3DE43 /* LLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest1ViewController.m; sourceTree = ""; }; + 18D3C9051EDF074900D3DE43 /* LLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest2ViewController.h; sourceTree = ""; }; + 18D3C9061EDF074900D3DE43 /* LLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest2ViewController.m; sourceTree = ""; }; + 18D3C9071EDF074900D3DE43 /* LLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest3ViewController.h; sourceTree = ""; }; + 18D3C9081EDF074900D3DE43 /* LLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest3ViewController.m; sourceTree = ""; }; + 18D3C9091EDF074900D3DE43 /* LLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest4ViewController.h; sourceTree = ""; }; + 18D3C90A1EDF074900D3DE43 /* LLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest4ViewController.m; sourceTree = ""; }; + 18D3C90B1EDF074900D3DE43 /* LLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest5ViewController.h; sourceTree = ""; }; + 18D3C90C1EDF074900D3DE43 /* LLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest5ViewController.m; sourceTree = ""; }; + 18D3C90D1EDF074900D3DE43 /* LLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest6ViewController.h; sourceTree = ""; }; + 18D3C90E1EDF074900D3DE43 /* LLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest6ViewController.m; sourceTree = ""; }; + 18D3C90F1EDF074900D3DE43 /* LLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest7ViewController.h; sourceTree = ""; }; + 18D3C9101EDF074900D3DE43 /* LLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = LLTest7ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C9181EDF078200D3DE43 /* FLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLTest1ViewController.h; sourceTree = ""; }; + 18D3C9191EDF078200D3DE43 /* FLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLTest1ViewController.m; sourceTree = ""; }; + 18D3C91A1EDF078200D3DE43 /* FLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLTest2ViewController.h; sourceTree = ""; }; + 18D3C91B1EDF078200D3DE43 /* FLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLTest2ViewController.m; sourceTree = ""; }; + 18D3C91E1EDF07A700D3DE43 /* RLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest1ViewController.h; sourceTree = ""; }; + 18D3C91F1EDF07A700D3DE43 /* RLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest1ViewController.m; sourceTree = ""; }; + 18D3C9201EDF07A700D3DE43 /* RLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest2ViewController.h; sourceTree = ""; }; + 18D3C9211EDF07A700D3DE43 /* RLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest2ViewController.m; sourceTree = ""; }; + 18D3C9221EDF07A700D3DE43 /* RLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest3ViewController.h; sourceTree = ""; }; + 18D3C9231EDF07A700D3DE43 /* RLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest3ViewController.m; sourceTree = ""; }; + 18D3C9241EDF07A700D3DE43 /* RLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest4ViewController.h; sourceTree = ""; }; + 18D3C9251EDF07A700D3DE43 /* RLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest4ViewController.m; sourceTree = ""; }; + 18D3C9261EDF07A700D3DE43 /* RLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest5ViewController.h; sourceTree = ""; }; + 18D3C9271EDF07A700D3DE43 /* RLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest5ViewController.m; sourceTree = ""; }; + 18D3C92D1EDF07C000D3DE43 /* FLLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest1ViewController.h; sourceTree = ""; }; + 18D3C92E1EDF07C000D3DE43 /* FLLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest1ViewController.m; sourceTree = ""; }; + 18D3C92F1EDF07C000D3DE43 /* FLLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest2ViewController.h; sourceTree = ""; }; + 18D3C9301EDF07C000D3DE43 /* FLLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest2ViewController.m; sourceTree = ""; }; + 18D3C9311EDF07C000D3DE43 /* FLLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest3ViewController.h; sourceTree = ""; }; + 18D3C9321EDF07C000D3DE43 /* FLLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest3ViewController.m; sourceTree = ""; }; + 18D3C9331EDF07C000D3DE43 /* FLLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest4ViewController.h; sourceTree = ""; }; + 18D3C9341EDF07C000D3DE43 /* FLLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest4ViewController.m; sourceTree = ""; }; + 18D3C9351EDF07C000D3DE43 /* FLLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest5ViewController.h; sourceTree = ""; }; + 18D3C9361EDF07C000D3DE43 /* FLLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest5ViewController.m; sourceTree = ""; }; + 18D3C9371EDF07C000D3DE43 /* FLLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest6ViewController.h; sourceTree = ""; }; + 18D3C9381EDF07C000D3DE43 /* FLLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest6ViewController.m; sourceTree = ""; }; + 18D3C93F1EDF07E700D3DE43 /* PLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest1ViewController.h; sourceTree = ""; }; + 18D3C9401EDF07E700D3DE43 /* PLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest1ViewController.m; sourceTree = ""; }; + 18D3C9411EDF07E700D3DE43 /* PLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest2ViewController.h; sourceTree = ""; }; + 18D3C9421EDF07E700D3DE43 /* PLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest2ViewController.m; sourceTree = ""; }; + 18D3C9431EDF07E700D3DE43 /* PLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest3ViewController.h; sourceTree = ""; }; + 18D3C9441EDF07E700D3DE43 /* PLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest3ViewController.m; sourceTree = ""; }; + 18D3C9451EDF07E700D3DE43 /* PLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest4ViewController.h; sourceTree = ""; }; + 18D3C9461EDF07E700D3DE43 /* PLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = PLTest4ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C9471EDF07E700D3DE43 /* PLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest5ViewController.h; sourceTree = ""; }; + 18D3C9481EDF07E700D3DE43 /* PLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest5ViewController.m; sourceTree = ""; }; + 18D3C94E1EDF07F800D3DE43 /* FOLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest1ViewController.h; sourceTree = ""; }; + 18D3C94F1EDF07F800D3DE43 /* FOLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest1ViewController.m; sourceTree = ""; }; + 18D3C9501EDF07F800D3DE43 /* FOLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest2ViewController.h; sourceTree = ""; }; + 18D3C9511EDF07F800D3DE43 /* FOLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest2ViewController.m; sourceTree = ""; }; + 18D3C9521EDF07F800D3DE43 /* FOLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest3ViewController.h; sourceTree = ""; }; + 18D3C9531EDF07F800D3DE43 /* FOLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest3ViewController.m; sourceTree = ""; }; + 18D3C9541EDF07F800D3DE43 /* FOLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest4ViewController.h; sourceTree = ""; }; + 18D3C9551EDF07F800D3DE43 /* FOLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest4ViewController.m; sourceTree = ""; }; + 18D3C9561EDF07F800D3DE43 /* FOLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest5ViewController.h; sourceTree = ""; }; + 18D3C9571EDF07F800D3DE43 /* FOLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest5ViewController.m; sourceTree = ""; }; + 18D3C9581EDF07F800D3DE43 /* FOLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest6ViewController.h; sourceTree = ""; }; + 18D3C9591EDF07F800D3DE43 /* FOLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest6ViewController.m; sourceTree = ""; }; + 18D3C9601EDF080800D3DE43 /* TLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest1ViewController.h; sourceTree = ""; }; + 18D3C9611EDF080800D3DE43 /* TLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = TLTest1ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C9621EDF080800D3DE43 /* TLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest2ViewController.h; sourceTree = ""; }; + 18D3C9631EDF080800D3DE43 /* TLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = TLTest2ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C9641EDF080800D3DE43 /* TLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest3ViewController.h; sourceTree = ""; }; + 18D3C9651EDF080800D3DE43 /* TLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLTest3ViewController.m; sourceTree = ""; }; + 18D3C9691EDF082800D3DE43 /* AllTest1TableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1TableViewCell.h; sourceTree = ""; }; + 18D3C96A1EDF082800D3DE43 /* AllTest1TableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1TableViewCell.m; sourceTree = ""; }; + 18D3C96B1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1TableViewHeaderFooterView.h; sourceTree = ""; }; + 18D3C96C1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1TableViewHeaderFooterView.m; sourceTree = ""; }; + 18D3C96D1EDF082800D3DE43 /* AllTest2TableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest2TableViewCell.h; sourceTree = ""; }; + 18D3C96E1EDF082800D3DE43 /* AllTest2TableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AllTest2TableViewCell.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C96F1EDF082800D3DE43 /* AllTestDataModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTestDataModel.h; sourceTree = ""; }; + 18D3C9701EDF082800D3DE43 /* AllTestDataModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTestDataModel.m; sourceTree = ""; }; + 18D3C9751EDF084000D3DE43 /* AllTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1ViewController.h; sourceTree = ""; }; + 18D3C9761EDF084000D3DE43 /* AllTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1ViewController.m; sourceTree = ""; }; + 18D3C9771EDF084000D3DE43 /* AllTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest2ViewController.h; sourceTree = ""; }; + 18D3C9781EDF084000D3DE43 /* AllTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest2ViewController.m; sourceTree = ""; }; + 18D3C9791EDF084000D3DE43 /* AllTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest3ViewController.h; sourceTree = ""; }; + 18D3C97A1EDF084000D3DE43 /* AllTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AllTest3ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C97B1EDF084000D3DE43 /* AllTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest4ViewController.h; sourceTree = ""; }; + 18D3C97C1EDF084000D3DE43 /* AllTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest4ViewController.m; sourceTree = ""; }; + 18D3C97D1EDF084000D3DE43 /* AllTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest5ViewController.h; sourceTree = ""; }; + 18D3C97E1EDF084000D3DE43 /* AllTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest5ViewController.m; sourceTree = ""; }; + 18D3C97F1EDF084000D3DE43 /* AllTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest6ViewController.h; sourceTree = ""; }; + 18D3C9801EDF084000D3DE43 /* AllTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest6ViewController.m; sourceTree = ""; }; + 18D3C9811EDF084000D3DE43 /* AllTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest7ViewController.h; sourceTree = ""; }; + 18D3C9821EDF084000D3DE43 /* AllTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AllTest7ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C9831EDF084000D3DE43 /* AllTest8ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest8ViewController.h; sourceTree = ""; }; + 18D3C9841EDF084000D3DE43 /* AllTest8ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest8ViewController.m; sourceTree = ""; }; + 18D3C98D1EDF08F800D3DE43 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 18D3C98E1EDF08F800D3DE43 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + 18D3C98F1EDF08F800D3DE43 /* YYFPSLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYFPSLabel.h; sourceTree = ""; }; + 18D3C9901EDF08F800D3DE43 /* YYFPSLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYFPSLabel.m; sourceTree = ""; }; + 18D3C9911EDF08F800D3DE43 /* YYWeakProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWeakProxy.h; sourceTree = ""; }; + 18D3C9921EDF08F800D3DE43 /* YYWeakProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWeakProxy.m; sourceTree = ""; }; + 18D3C9971EDF09BE00D3DE43 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 18D3C9981EDF09BE00D3DE43 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 18D3C9991EDF09BE00D3DE43 /* CFTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFTool.h; sourceTree = ""; }; + 18D3C99A1EDF09BE00D3DE43 /* CFTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CFTool.m; sourceTree = ""; }; + 18D3C9A31EDF0A5A00D3DE43 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = LaunchScreen.xib; sourceTree = ""; }; + 18D3C9A51EDF0A5A00D3DE43 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Localizable.strings; sourceTree = ""; }; + 18D3C9A61EDF0A5A00D3DE43 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 18D3C9A71EDF0A5A00D3DE43 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 18D3C9A81EDF0A5A00D3DE43 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 18D3C9AF1EDF0A5A00D3DE43 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = LaunchScreen.strings; sourceTree = ""; }; + 18D3C9B11EDF0A5A00D3DE43 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = Localizable.strings; sourceTree = ""; }; + 18D3C9BE1EDF0AB500D3DE43 /* fl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = fl.png; sourceTree = ""; }; + 18D3C9BF1EDF0AB500D3DE43 /* fll.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = fll.png; sourceTree = ""; }; + 18D3C9C01EDF0AB500D3DE43 /* flo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flo.png; sourceTree = ""; }; + 18D3C9C11EDF0AB500D3DE43 /* layoutdemo1.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo1.gif; sourceTree = ""; }; + 18D3C9C21EDF0AB500D3DE43 /* layoutdemo2.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo2.gif; sourceTree = ""; }; + 18D3C9C31EDF0AB500D3DE43 /* layoutdemo3.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo3.gif; sourceTree = ""; }; + 18D3C9C41EDF0AB500D3DE43 /* layoutdemo4.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo4.gif; sourceTree = ""; }; + 18D3C9C51EDF0AB500D3DE43 /* layoutdemo5.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo5.gif; sourceTree = ""; }; + 18D3C9C61EDF0AB500D3DE43 /* layoutdemo6.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo6.gif; sourceTree = ""; }; + 18D3C9C71EDF0AB500D3DE43 /* layoutdemo7.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo7.gif; sourceTree = ""; }; + 18D3C9C81EDF0AB500D3DE43 /* ll.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ll.png; sourceTree = ""; }; + 18D3C9C91EDF0AB500D3DE43 /* MyLayout.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MyLayout.png; sourceTree = ""; }; + 18D3C9CA1EDF0AB500D3DE43 /* MyLayoutClass.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MyLayoutClass.png; sourceTree = ""; }; + 18D3C9CB1EDF0AB500D3DE43 /* MyLayoutP.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MyLayoutP.png; sourceTree = ""; }; + 18D3C9CC1EDF0AB500D3DE43 /* pl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = pl.png; sourceTree = ""; }; + 18D3C9CD1EDF0AB500D3DE43 /* rl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = rl.png; sourceTree = ""; }; + 18D3C9CE1EDF0AB500D3DE43 /* tl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tl.png; sourceTree = ""; }; + 18D684001C4F421400A48BB4 /* MyLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayout.h; sourceTree = ""; }; + 18D684541C4F423400A48BB4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 18D684551C4F423400A48BB4 /* MyLayoutTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutTests.m; sourceTree = ""; }; + 200A26D71FA8A90300B06E7B /* AllTest9ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AllTest9ViewController.h; sourceTree = ""; }; + 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest9ViewController.m; sourceTree = ""; }; + 200A26DA1FA96B2400B06E7B /* AllTest9CollectionViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AllTest9CollectionViewCell.h; sourceTree = ""; }; + 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest9CollectionViewCell.m; sourceTree = ""; }; + 2043D5DB20995DF800276C68 /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = System/Library/Frameworks/CoreBluetooth.framework; sourceTree = SDKROOT; }; + 204DC31F209D5A7C00F6CB57 /* TLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest4ViewController.h; sourceTree = ""; }; + 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLTest4ViewController.m; sourceTree = ""; }; + 205642841F4CFF9B00E8BDDE /* MyBorderline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyBorderline.h; sourceTree = ""; }; + 205642851F4CFF9B00E8BDDE /* MyBorderline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyBorderline.m; sourceTree = ""; }; + 205642891F4D013D00E8BDDE /* MyGrid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyGrid.h; sourceTree = ""; }; + 205643081F4E53CD00E8BDDE /* MyGridNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyGridNode.h; sourceTree = ""; }; + 205643091F4E53CD00E8BDDE /* MyGridNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyGridNode.m; sourceTree = ""; }; + 205643111F51C7DF00E8BDDE /* GLTest2ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GLTest2ViewController.h; sourceTree = ""; }; + 205643121F51C7EB00E8BDDE /* GLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GLTest2ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 205643141F55A03000E8BDDE /* MyLayoutMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutMath.h; sourceTree = ""; }; + 205643151F55A03000E8BDDE /* MyLayoutMath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutMath.m; sourceTree = ""; }; + 205CFA8C1F49BD1C00355489 /* GLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest1ViewController.h; sourceTree = ""; }; + 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GLTest1ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 205F9EB91F7AA5710034732C /* gl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = gl.png; sourceTree = ""; }; + 205F9EBB1F7AA6510034732C /* all.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = all.png; sourceTree = ""; }; + 2075CC3020A0B29700BA6F65 /* FLLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest7ViewController.h; sourceTree = ""; }; + 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest7ViewController.m; sourceTree = ""; }; + 208157BB1F586A9900E945B6 /* DetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = ""; }; + 208157BC1F586AA700E945B6 /* DetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; + 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutDelegate.h; sourceTree = ""; }; + 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutDelegate.m; sourceTree = ""; }; + 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo8.gif; sourceTree = ""; }; + 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest7ViewController.h; sourceTree = ""; }; + 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest7ViewController.m; sourceTree = ""; }; + 20F783541F60398C00BE5B31 /* GLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest3ViewController.h; sourceTree = ""; }; + 20F783551F60399700BE5B31 /* GLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest3ViewController.m; sourceTree = ""; }; + 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo5.json; sourceTree = ""; }; + 444B718F1F6A3E3F00331872 /* GLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest5ViewController.h; sourceTree = ""; }; + 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest5ViewController.m; sourceTree = ""; }; + 44EBDA8A1F619A6300B47CBD /* GLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest4ViewController.h; sourceTree = ""; }; + 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest4ViewController.m; sourceTree = ""; }; + 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo4.json; sourceTree = ""; }; + 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10ViewController.h; sourceTree = ""; }; + 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10ViewController.m; sourceTree = ""; }; + 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10Model.m; sourceTree = ""; }; + 6740E1FA20A52DA900AFBC5A /* AllTest10Model.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10Model.h; sourceTree = ""; }; + 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10HeaderView.m; sourceTree = ""; }; + 6740E1FD20A52DB000AFBC5A /* AllTest10HeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10HeaderView.h; sourceTree = ""; }; + 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10Cell.m; sourceTree = ""; }; + 6740E20020A52DC100AFBC5A /* AllTest10Cell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10Cell.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 181A10B11EDF12CF00996203 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1840828A1B2C46E8003F378B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 184082A31B2C46E8003F378B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18B1522E1DEDDE5500AD7A1C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; + 181A10B11EDF12CF00996203 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1840828A1B2C46E8003F378B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 184082A31B2C46E8003F378B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18B1522E1DEDDE5500AD7A1C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 184082841B2C46E8003F378B = { - isa = PBXGroup; - children = ( - 18D3C8F91EDF04E000D3DE43 /* MyLayoutDemo */, - 18D683E61C4F421400A48BB4 /* MyLayout */, - 18D684531C4F423400A48BB4 /* MyLayoutTests */, - 18B152321DEDDE5500AD7A1C /* MyLayoutUITests */, - 1840828E1B2C46E8003F378B /* Products */, - 2043D5DA20995DF800276C68 /* Frameworks */, - ); - sourceTree = ""; - }; - 1840828E1B2C46E8003F378B /* Products */ = { - isa = PBXGroup; - children = ( - 1840828D1B2C46E8003F378B /* MyLayoutDemo.app */, - 184082A61B2C46E8003F378B /* MyLayout.xctest */, - 18B152311DEDDE5500AD7A1C /* MyLayoutUITests.xctest */, - 181A10B51EDF12CF00996203 /* MyLayout.framework */, - ); - name = Products; - sourceTree = ""; - }; - 18B152321DEDDE5500AD7A1C /* MyLayoutUITests */ = { - isa = PBXGroup; - children = ( - 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */, - 18B152351DEDDE5500AD7A1C /* Info.plist */, - ); - path = MyLayoutUITests; - sourceTree = ""; - }; - 18D3C8F91EDF04E000D3DE43 /* MyLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C9971EDF09BE00D3DE43 /* AppDelegate.h */, - 18D3C9981EDF09BE00D3DE43 /* AppDelegate.m */, - 18D3C98D1EDF08F800D3DE43 /* ViewController.h */, - 18D3C98E1EDF08F800D3DE43 /* ViewController.m */, - 208157BB1F586A9900E945B6 /* DetailViewController.h */, - 208157BC1F586AA700E945B6 /* DetailViewController.m */, - 18D3C9991EDF09BE00D3DE43 /* CFTool.h */, - 18D3C99A1EDF09BE00D3DE43 /* CFTool.m */, - 18D3C98F1EDF08F800D3DE43 /* YYFPSLabel.h */, - 18D3C9901EDF08F800D3DE43 /* YYFPSLabel.m */, - 18D3C9911EDF08F800D3DE43 /* YYWeakProxy.h */, - 18D3C9921EDF08F800D3DE43 /* YYWeakProxy.m */, - 18D3C9961EDF091B00D3DE43 /* Supporting Files */, - 18D3C8FA1EDF051000D3DE43 /* LinearLayoutDemo */, - 18D3C8FB1EDF052300D3DE43 /* FrameLayoutDemo */, - 18D3C8FC1EDF053000D3DE43 /* RelativeLayoutDemo */, - 18D3C9001EDF056900D3DE43 /* TableLayoutDemo */, - 18D3C8FD1EDF053D00D3DE43 /* FlowLayoutDemo */, - 18D3C8FF1EDF055C00D3DE43 /* FloatLayoutDemo */, - 205CFA8B1F49BCAF00355489 /* GridLayoutDemo */, - 18D3C8FE1EDF055000D3DE43 /* PathLayoutDemo */, - 18D3C9011EDF059600D3DE43 /* IntegratedDemo */, - ); - path = MyLayoutDemo; - sourceTree = ""; - }; - 18D3C8FA1EDF051000D3DE43 /* LinearLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C9031EDF074900D3DE43 /* LLTest1ViewController.h */, - 18D3C9041EDF074900D3DE43 /* LLTest1ViewController.m */, - 18D3C9051EDF074900D3DE43 /* LLTest2ViewController.h */, - 18D3C9061EDF074900D3DE43 /* LLTest2ViewController.m */, - 18D3C9071EDF074900D3DE43 /* LLTest3ViewController.h */, - 18D3C9081EDF074900D3DE43 /* LLTest3ViewController.m */, - 18D3C9091EDF074900D3DE43 /* LLTest4ViewController.h */, - 18D3C90A1EDF074900D3DE43 /* LLTest4ViewController.m */, - 18D3C90B1EDF074900D3DE43 /* LLTest5ViewController.h */, - 18D3C90C1EDF074900D3DE43 /* LLTest5ViewController.m */, - 18D3C90D1EDF074900D3DE43 /* LLTest6ViewController.h */, - 18D3C90E1EDF074900D3DE43 /* LLTest6ViewController.m */, - 18D3C90F1EDF074900D3DE43 /* LLTest7ViewController.h */, - 18D3C9101EDF074900D3DE43 /* LLTest7ViewController.m */, - ); - name = LinearLayoutDemo; - sourceTree = ""; - }; - 18D3C8FB1EDF052300D3DE43 /* FrameLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C9181EDF078200D3DE43 /* FLTest1ViewController.h */, - 18D3C9191EDF078200D3DE43 /* FLTest1ViewController.m */, - 18D3C91A1EDF078200D3DE43 /* FLTest2ViewController.h */, - 18D3C91B1EDF078200D3DE43 /* FLTest2ViewController.m */, - ); - name = FrameLayoutDemo; - sourceTree = ""; - }; - 18D3C8FC1EDF053000D3DE43 /* RelativeLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C91E1EDF07A700D3DE43 /* RLTest1ViewController.h */, - 18D3C91F1EDF07A700D3DE43 /* RLTest1ViewController.m */, - 18D3C9201EDF07A700D3DE43 /* RLTest2ViewController.h */, - 18D3C9211EDF07A700D3DE43 /* RLTest2ViewController.m */, - 18D3C9221EDF07A700D3DE43 /* RLTest3ViewController.h */, - 18D3C9231EDF07A700D3DE43 /* RLTest3ViewController.m */, - 18D3C9241EDF07A700D3DE43 /* RLTest4ViewController.h */, - 18D3C9251EDF07A700D3DE43 /* RLTest4ViewController.m */, - 18D3C9261EDF07A700D3DE43 /* RLTest5ViewController.h */, - 18D3C9271EDF07A700D3DE43 /* RLTest5ViewController.m */, - ); - name = RelativeLayoutDemo; - sourceTree = ""; - }; - 18D3C8FD1EDF053D00D3DE43 /* FlowLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C92D1EDF07C000D3DE43 /* FLLTest1ViewController.h */, - 18D3C92E1EDF07C000D3DE43 /* FLLTest1ViewController.m */, - 18D3C92F1EDF07C000D3DE43 /* FLLTest2ViewController.h */, - 18D3C9301EDF07C000D3DE43 /* FLLTest2ViewController.m */, - 181A10A81EDF11FF00996203 /* FLLTest2ViewController.xib */, - 18D3C9311EDF07C000D3DE43 /* FLLTest3ViewController.h */, - 18D3C9321EDF07C000D3DE43 /* FLLTest3ViewController.m */, - 18D3C9331EDF07C000D3DE43 /* FLLTest4ViewController.h */, - 18D3C9341EDF07C000D3DE43 /* FLLTest4ViewController.m */, - 18D3C9351EDF07C000D3DE43 /* FLLTest5ViewController.h */, - 18D3C9361EDF07C000D3DE43 /* FLLTest5ViewController.m */, - 18D3C9371EDF07C000D3DE43 /* FLLTest6ViewController.h */, - 18D3C9381EDF07C000D3DE43 /* FLLTest6ViewController.m */, - 2075CC3020A0B29700BA6F65 /* FLLTest7ViewController.h */, - 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */, - ); - name = FlowLayoutDemo; - sourceTree = ""; - }; - 18D3C8FE1EDF055000D3DE43 /* PathLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C93F1EDF07E700D3DE43 /* PLTest1ViewController.h */, - 18D3C9401EDF07E700D3DE43 /* PLTest1ViewController.m */, - 18D3C9411EDF07E700D3DE43 /* PLTest2ViewController.h */, - 18D3C9421EDF07E700D3DE43 /* PLTest2ViewController.m */, - 18D3C9431EDF07E700D3DE43 /* PLTest3ViewController.h */, - 18D3C9441EDF07E700D3DE43 /* PLTest3ViewController.m */, - 18D3C9451EDF07E700D3DE43 /* PLTest4ViewController.h */, - 18D3C9461EDF07E700D3DE43 /* PLTest4ViewController.m */, - 18D3C9471EDF07E700D3DE43 /* PLTest5ViewController.h */, - 18D3C9481EDF07E700D3DE43 /* PLTest5ViewController.m */, - ); - name = PathLayoutDemo; - sourceTree = ""; - }; - 18D3C8FF1EDF055C00D3DE43 /* FloatLayoutDemo */ = { - isa = PBXGroup; - children = ( - 181A10AC1EDF123800996203 /* FOLTest1ViewController.xib */, - 18D3C94E1EDF07F800D3DE43 /* FOLTest1ViewController.h */, - 18D3C94F1EDF07F800D3DE43 /* FOLTest1ViewController.m */, - 18D3C9501EDF07F800D3DE43 /* FOLTest2ViewController.h */, - 18D3C9511EDF07F800D3DE43 /* FOLTest2ViewController.m */, - 18D3C9521EDF07F800D3DE43 /* FOLTest3ViewController.h */, - 18D3C9531EDF07F800D3DE43 /* FOLTest3ViewController.m */, - 18D3C9541EDF07F800D3DE43 /* FOLTest4ViewController.h */, - 18D3C9551EDF07F800D3DE43 /* FOLTest4ViewController.m */, - 18D3C9561EDF07F800D3DE43 /* FOLTest5ViewController.h */, - 18D3C9571EDF07F800D3DE43 /* FOLTest5ViewController.m */, - 18D3C9581EDF07F800D3DE43 /* FOLTest6ViewController.h */, - 18D3C9591EDF07F800D3DE43 /* FOLTest6ViewController.m */, - 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */, - 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */, - ); - name = FloatLayoutDemo; - sourceTree = ""; - }; - 18D3C9001EDF056900D3DE43 /* TableLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C9601EDF080800D3DE43 /* TLTest1ViewController.h */, - 18D3C9611EDF080800D3DE43 /* TLTest1ViewController.m */, - 18D3C9621EDF080800D3DE43 /* TLTest2ViewController.h */, - 18D3C9631EDF080800D3DE43 /* TLTest2ViewController.m */, - 18D3C9641EDF080800D3DE43 /* TLTest3ViewController.h */, - 18D3C9651EDF080800D3DE43 /* TLTest3ViewController.m */, - 204DC31F209D5A7C00F6CB57 /* TLTest4ViewController.h */, - 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */, - ); - name = TableLayoutDemo; - sourceTree = ""; - }; - 18D3C9011EDF059600D3DE43 /* IntegratedDemo */ = { - isa = PBXGroup; - children = ( - 18D3C9751EDF084000D3DE43 /* AllTest1ViewController.h */, - 18D3C9761EDF084000D3DE43 /* AllTest1ViewController.m */, - 18D3C9771EDF084000D3DE43 /* AllTest2ViewController.h */, - 18D3C9781EDF084000D3DE43 /* AllTest2ViewController.m */, - 18D3C9791EDF084000D3DE43 /* AllTest3ViewController.h */, - 18D3C97A1EDF084000D3DE43 /* AllTest3ViewController.m */, - 18D3C97B1EDF084000D3DE43 /* AllTest4ViewController.h */, - 18D3C97C1EDF084000D3DE43 /* AllTest4ViewController.m */, - 18D3C97D1EDF084000D3DE43 /* AllTest5ViewController.h */, - 18D3C97E1EDF084000D3DE43 /* AllTest5ViewController.m */, - 18D3C97F1EDF084000D3DE43 /* AllTest6ViewController.h */, - 18D3C9801EDF084000D3DE43 /* AllTest6ViewController.m */, - 18D3C9811EDF084000D3DE43 /* AllTest7ViewController.h */, - 18D3C9821EDF084000D3DE43 /* AllTest7ViewController.m */, - 18D3C9831EDF084000D3DE43 /* AllTest8ViewController.h */, - 18D3C9841EDF084000D3DE43 /* AllTest8ViewController.m */, - 200A26D71FA8A90300B06E7B /* AllTest9ViewController.h */, - 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */, - 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */, - 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */, - 18D3C9021EDF068200D3DE43 /* AllTestModel&View */, - ); - name = IntegratedDemo; - sourceTree = ""; - }; - 18D3C9021EDF068200D3DE43 /* AllTestModel&View */ = { - isa = PBXGroup; - children = ( - 18D3C9691EDF082800D3DE43 /* AllTest1TableViewCell.h */, - 18D3C96A1EDF082800D3DE43 /* AllTest1TableViewCell.m */, - 18D3C96B1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.h */, - 18D3C96C1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m */, - 18D3C96D1EDF082800D3DE43 /* AllTest2TableViewCell.h */, - 18D3C96E1EDF082800D3DE43 /* AllTest2TableViewCell.m */, - 18D3C96F1EDF082800D3DE43 /* AllTestDataModel.h */, - 18D3C9701EDF082800D3DE43 /* AllTestDataModel.m */, - 200A26DA1FA96B2400B06E7B /* AllTest9CollectionViewCell.h */, - 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */, - 6740E1FA20A52DA900AFBC5A /* AllTest10Model.h */, - 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */, - 6740E1FD20A52DB000AFBC5A /* AllTest10HeaderView.h */, - 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */, - 6740E20020A52DC100AFBC5A /* AllTest10Cell.h */, - 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */, - ); - name = "AllTestModel&View"; - sourceTree = ""; - }; - 18D3C9961EDF091B00D3DE43 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 18D3C9A91EDF0A5A00D3DE43 /* zh-Hans.lproj */, - 18D3C99D1EDF0A5A00D3DE43 /* Base.lproj */, - 18D3C9A61EDF0A5A00D3DE43 /* Images.xcassets */, - 18D3C9A71EDF0A5A00D3DE43 /* Info.plist */, - 18D3C9A81EDF0A5A00D3DE43 /* main.m */, - 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */, - 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 18D3C99D1EDF0A5A00D3DE43 /* Base.lproj */ = { - isa = PBXGroup; - children = ( - 18D3C9A21EDF0A5A00D3DE43 /* LaunchScreen.xib */, - 18D3C9A41EDF0A5A00D3DE43 /* Localizable.strings */, - ); - path = Base.lproj; - sourceTree = ""; - }; - 18D3C9A91EDF0A5A00D3DE43 /* zh-Hans.lproj */ = { - isa = PBXGroup; - children = ( - 18D3C9AE1EDF0A5A00D3DE43 /* LaunchScreen.strings */, - 18D3C9B01EDF0A5A00D3DE43 /* Localizable.strings */, - ); - path = "zh-Hans.lproj"; - sourceTree = ""; - }; - 18D3C9BD1EDF0A7900D3DE43 /* Images */ = { - isa = PBXGroup; - children = ( - 205F9EBB1F7AA6510034732C /* all.png */, - 205F9EB91F7AA5710034732C /* gl.png */, - 18D3C9BE1EDF0AB500D3DE43 /* fl.png */, - 18D3C9BF1EDF0AB500D3DE43 /* fll.png */, - 18D3C9C01EDF0AB500D3DE43 /* flo.png */, - 18D3C9C11EDF0AB500D3DE43 /* layoutdemo1.gif */, - 18D3C9C21EDF0AB500D3DE43 /* layoutdemo2.gif */, - 18D3C9C31EDF0AB500D3DE43 /* layoutdemo3.gif */, - 18D3C9C41EDF0AB500D3DE43 /* layoutdemo4.gif */, - 18D3C9C51EDF0AB500D3DE43 /* layoutdemo5.gif */, - 18D3C9C61EDF0AB500D3DE43 /* layoutdemo6.gif */, - 18D3C9C71EDF0AB500D3DE43 /* layoutdemo7.gif */, - 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */, - 18D3C9C81EDF0AB500D3DE43 /* ll.png */, - 18D3C9C91EDF0AB500D3DE43 /* MyLayout.png */, - 18D3C9CA1EDF0AB500D3DE43 /* MyLayoutClass.png */, - 18D3C9CB1EDF0AB500D3DE43 /* MyLayoutP.png */, - 18D3C9CC1EDF0AB500D3DE43 /* pl.png */, - 18D3C9CD1EDF0AB500D3DE43 /* rl.png */, - 18D3C9CE1EDF0AB500D3DE43 /* tl.png */, - ); - name = Images; - sourceTree = ""; - }; - 18D683E61C4F421400A48BB4 /* MyLayout */ = { - isa = PBXGroup; - children = ( - 18C15AEA1EDF133200AADEAC /* Info.plist */, - 18D3C9BD1EDF0A7900D3DE43 /* Images */, - 18D683FB1C4F421400A48BB4 /* Lib */, - ); - path = MyLayout; - sourceTree = ""; - }; - 18D683FB1C4F421400A48BB4 /* Lib */ = { - isa = PBXGroup; - children = ( - 18D684001C4F421400A48BB4 /* MyLayout.h */, - 182225AB1E77E5930081AA4B /* MyFlowLayout.h */, - 182225B41E77E5930081AA4B /* MyFlowLayout.m */, - 182225AC1E77E5930081AA4B /* MyLinearLayout.h */, - 182225B21E77E5930081AA4B /* MyLinearLayout.m */, - 182225AD1E77E5930081AA4B /* MyFloatLayout.h */, - 182225B91E77E5930081AA4B /* MyFloatLayout.m */, - 182225AE1E77E5930081AA4B /* MyTableLayout.h */, - 182225C31E77E5930081AA4B /* MyTableLayout.m */, - 182225BE1E77E5930081AA4B /* MyRelativeLayout.h */, - 182225B51E77E5930081AA4B /* MyRelativeLayout.m */, - 182225BD1E77E5930081AA4B /* MyPathLayout.h */, - 182225B61E77E5930081AA4B /* MyPathLayout.m */, - 182225BA1E77E5930081AA4B /* MyFrameLayout.h */, - 182225B71E77E5930081AA4B /* MyFrameLayout.m */, - 182225AF1E77E5930081AA4B /* MyBaseLayout.h */, - 182225B11E77E5930081AA4B /* MyBaseLayout.m */, - 182225B01E77E5930081AA4B /* MyLayoutPos.h */, - 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */, - 182225BB1E77E5930081AA4B /* MyLayoutPos.m */, - 182225BC1E77E5930081AA4B /* MyLayoutSize.h */, - 182225C81E77E5930081AA4B /* MyLayoutSizeInner.h */, - 182225C51E77E5930081AA4B /* MyLayoutSize.m */, - 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */, - 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */, - 182225C21E77E5930081AA4B /* MyMaker.h */, - 182225C11E77E5930081AA4B /* MyMaker.m */, - 182225C71E77E5930081AA4B /* MyDimeScale.h */, - 182225C41E77E5930081AA4B /* MyDimeScale.m */, - 182225B81E77E5930081AA4B /* MyLayoutInner.h */, - 182225B31E77E5930081AA4B /* MyLayoutDef.h */, - 205642891F4D013D00E8BDDE /* MyGrid.h */, - 182DB6401EF7876200E2D65D /* MyGridLayout.h */, - 182DB6411EF7876200E2D65D /* MyGridLayout.m */, - 205642841F4CFF9B00E8BDDE /* MyBorderline.h */, - 205642851F4CFF9B00E8BDDE /* MyBorderline.m */, - 205643081F4E53CD00E8BDDE /* MyGridNode.h */, - 205643091F4E53CD00E8BDDE /* MyGridNode.m */, - 205643141F55A03000E8BDDE /* MyLayoutMath.h */, - 205643151F55A03000E8BDDE /* MyLayoutMath.m */, - 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */, - 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */, - ); - path = Lib; - sourceTree = ""; - }; - 18D684531C4F423400A48BB4 /* MyLayoutTests */ = { - isa = PBXGroup; - children = ( - 18D684541C4F423400A48BB4 /* Info.plist */, - 18D684551C4F423400A48BB4 /* MyLayoutTests.m */, - 189738501E16330B004F80D6 /* MyLayoutTestCaseBase.m */, - 189738521E16340D004F80D6 /* MyLayoutTestCaseBase.h */, - 1897384E1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m */, - 180BD8A01EA9EF9A00C6980B /* MyFrameLayoutTestCase.m */, - 181836941EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m */, - 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */, - 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */, - 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */, - ); - path = MyLayoutTests; - sourceTree = ""; - }; - 2043D5DA20995DF800276C68 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 2043D5DB20995DF800276C68 /* CoreBluetooth.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 205CFA8B1F49BCAF00355489 /* GridLayoutDemo */ = { - isa = PBXGroup; - children = ( - 205CFA8C1F49BD1C00355489 /* GLTest1ViewController.h */, - 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */, - 205643111F51C7DF00E8BDDE /* GLTest2ViewController.h */, - 205643121F51C7EB00E8BDDE /* GLTest2ViewController.m */, - 20F783541F60398C00BE5B31 /* GLTest3ViewController.h */, - 20F783551F60399700BE5B31 /* GLTest3ViewController.m */, - 44EBDA8A1F619A6300B47CBD /* GLTest4ViewController.h */, - 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */, - 444B718F1F6A3E3F00331872 /* GLTest5ViewController.h */, - 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */, - ); - name = GridLayoutDemo; - sourceTree = ""; - }; + 184082841B2C46E8003F378B = { + isa = PBXGroup; + children = ( + 18D3C8F91EDF04E000D3DE43 /* MyLayoutDemo */, + 18D683E61C4F421400A48BB4 /* MyLayout */, + 18D684531C4F423400A48BB4 /* MyLayoutTests */, + 18B152321DEDDE5500AD7A1C /* MyLayoutUITests */, + 1840828E1B2C46E8003F378B /* Products */, + 2043D5DA20995DF800276C68 /* Frameworks */, + ); + sourceTree = ""; + }; + 1840828E1B2C46E8003F378B /* Products */ = { + isa = PBXGroup; + children = ( + 1840828D1B2C46E8003F378B /* MyLayoutDemo.app */, + 184082A61B2C46E8003F378B /* MyLayout.xctest */, + 18B152311DEDDE5500AD7A1C /* MyLayoutUITests.xctest */, + 181A10B51EDF12CF00996203 /* MyLayout.framework */, + ); + name = Products; + sourceTree = ""; + }; + 18B152321DEDDE5500AD7A1C /* MyLayoutUITests */ = { + isa = PBXGroup; + children = ( + 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */, + 18B152351DEDDE5500AD7A1C /* Info.plist */, + ); + path = MyLayoutUITests; + sourceTree = ""; + }; + 18D3C8F91EDF04E000D3DE43 /* MyLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C9971EDF09BE00D3DE43 /* AppDelegate.h */, + 18D3C9981EDF09BE00D3DE43 /* AppDelegate.m */, + 18D3C98D1EDF08F800D3DE43 /* ViewController.h */, + 18D3C98E1EDF08F800D3DE43 /* ViewController.m */, + 208157BB1F586A9900E945B6 /* DetailViewController.h */, + 208157BC1F586AA700E945B6 /* DetailViewController.m */, + 18D3C9991EDF09BE00D3DE43 /* CFTool.h */, + 18D3C99A1EDF09BE00D3DE43 /* CFTool.m */, + 18D3C98F1EDF08F800D3DE43 /* YYFPSLabel.h */, + 18D3C9901EDF08F800D3DE43 /* YYFPSLabel.m */, + 18D3C9911EDF08F800D3DE43 /* YYWeakProxy.h */, + 18D3C9921EDF08F800D3DE43 /* YYWeakProxy.m */, + 18D3C9961EDF091B00D3DE43 /* Supporting Files */, + 18D3C8FA1EDF051000D3DE43 /* LinearLayoutDemo */, + 18D3C8FB1EDF052300D3DE43 /* FrameLayoutDemo */, + 18D3C8FC1EDF053000D3DE43 /* RelativeLayoutDemo */, + 18D3C9001EDF056900D3DE43 /* TableLayoutDemo */, + 18D3C8FD1EDF053D00D3DE43 /* FlowLayoutDemo */, + 18D3C8FF1EDF055C00D3DE43 /* FloatLayoutDemo */, + 205CFA8B1F49BCAF00355489 /* GridLayoutDemo */, + 18D3C8FE1EDF055000D3DE43 /* PathLayoutDemo */, + 18D3C9011EDF059600D3DE43 /* IntegratedDemo */, + ); + path = MyLayoutDemo; + sourceTree = ""; + }; + 18D3C8FA1EDF051000D3DE43 /* LinearLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C9031EDF074900D3DE43 /* LLTest1ViewController.h */, + 18D3C9041EDF074900D3DE43 /* LLTest1ViewController.m */, + 18D3C9051EDF074900D3DE43 /* LLTest2ViewController.h */, + 18D3C9061EDF074900D3DE43 /* LLTest2ViewController.m */, + 18D3C9071EDF074900D3DE43 /* LLTest3ViewController.h */, + 18D3C9081EDF074900D3DE43 /* LLTest3ViewController.m */, + 18D3C9091EDF074900D3DE43 /* LLTest4ViewController.h */, + 18D3C90A1EDF074900D3DE43 /* LLTest4ViewController.m */, + 18D3C90B1EDF074900D3DE43 /* LLTest5ViewController.h */, + 18D3C90C1EDF074900D3DE43 /* LLTest5ViewController.m */, + 18D3C90D1EDF074900D3DE43 /* LLTest6ViewController.h */, + 18D3C90E1EDF074900D3DE43 /* LLTest6ViewController.m */, + 18D3C90F1EDF074900D3DE43 /* LLTest7ViewController.h */, + 18D3C9101EDF074900D3DE43 /* LLTest7ViewController.m */, + ); + name = LinearLayoutDemo; + sourceTree = ""; + }; + 18D3C8FB1EDF052300D3DE43 /* FrameLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C9181EDF078200D3DE43 /* FLTest1ViewController.h */, + 18D3C9191EDF078200D3DE43 /* FLTest1ViewController.m */, + 18D3C91A1EDF078200D3DE43 /* FLTest2ViewController.h */, + 18D3C91B1EDF078200D3DE43 /* FLTest2ViewController.m */, + ); + name = FrameLayoutDemo; + sourceTree = ""; + }; + 18D3C8FC1EDF053000D3DE43 /* RelativeLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C91E1EDF07A700D3DE43 /* RLTest1ViewController.h */, + 18D3C91F1EDF07A700D3DE43 /* RLTest1ViewController.m */, + 18D3C9201EDF07A700D3DE43 /* RLTest2ViewController.h */, + 18D3C9211EDF07A700D3DE43 /* RLTest2ViewController.m */, + 18D3C9221EDF07A700D3DE43 /* RLTest3ViewController.h */, + 18D3C9231EDF07A700D3DE43 /* RLTest3ViewController.m */, + 18D3C9241EDF07A700D3DE43 /* RLTest4ViewController.h */, + 18D3C9251EDF07A700D3DE43 /* RLTest4ViewController.m */, + 18D3C9261EDF07A700D3DE43 /* RLTest5ViewController.h */, + 18D3C9271EDF07A700D3DE43 /* RLTest5ViewController.m */, + ); + name = RelativeLayoutDemo; + sourceTree = ""; + }; + 18D3C8FD1EDF053D00D3DE43 /* FlowLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C92D1EDF07C000D3DE43 /* FLLTest1ViewController.h */, + 18D3C92E1EDF07C000D3DE43 /* FLLTest1ViewController.m */, + 18D3C92F1EDF07C000D3DE43 /* FLLTest2ViewController.h */, + 18D3C9301EDF07C000D3DE43 /* FLLTest2ViewController.m */, + 181A10A81EDF11FF00996203 /* FLLTest2ViewController.xib */, + 18D3C9311EDF07C000D3DE43 /* FLLTest3ViewController.h */, + 18D3C9321EDF07C000D3DE43 /* FLLTest3ViewController.m */, + 18D3C9331EDF07C000D3DE43 /* FLLTest4ViewController.h */, + 18D3C9341EDF07C000D3DE43 /* FLLTest4ViewController.m */, + 18D3C9351EDF07C000D3DE43 /* FLLTest5ViewController.h */, + 18D3C9361EDF07C000D3DE43 /* FLLTest5ViewController.m */, + 18D3C9371EDF07C000D3DE43 /* FLLTest6ViewController.h */, + 18D3C9381EDF07C000D3DE43 /* FLLTest6ViewController.m */, + 2075CC3020A0B29700BA6F65 /* FLLTest7ViewController.h */, + 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */, + ); + name = FlowLayoutDemo; + sourceTree = ""; + }; + 18D3C8FE1EDF055000D3DE43 /* PathLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C93F1EDF07E700D3DE43 /* PLTest1ViewController.h */, + 18D3C9401EDF07E700D3DE43 /* PLTest1ViewController.m */, + 18D3C9411EDF07E700D3DE43 /* PLTest2ViewController.h */, + 18D3C9421EDF07E700D3DE43 /* PLTest2ViewController.m */, + 18D3C9431EDF07E700D3DE43 /* PLTest3ViewController.h */, + 18D3C9441EDF07E700D3DE43 /* PLTest3ViewController.m */, + 18D3C9451EDF07E700D3DE43 /* PLTest4ViewController.h */, + 18D3C9461EDF07E700D3DE43 /* PLTest4ViewController.m */, + 18D3C9471EDF07E700D3DE43 /* PLTest5ViewController.h */, + 18D3C9481EDF07E700D3DE43 /* PLTest5ViewController.m */, + ); + name = PathLayoutDemo; + sourceTree = ""; + }; + 18D3C8FF1EDF055C00D3DE43 /* FloatLayoutDemo */ = { + isa = PBXGroup; + children = ( + 181A10AC1EDF123800996203 /* FOLTest1ViewController.xib */, + 18D3C94E1EDF07F800D3DE43 /* FOLTest1ViewController.h */, + 18D3C94F1EDF07F800D3DE43 /* FOLTest1ViewController.m */, + 18D3C9501EDF07F800D3DE43 /* FOLTest2ViewController.h */, + 18D3C9511EDF07F800D3DE43 /* FOLTest2ViewController.m */, + 18D3C9521EDF07F800D3DE43 /* FOLTest3ViewController.h */, + 18D3C9531EDF07F800D3DE43 /* FOLTest3ViewController.m */, + 18D3C9541EDF07F800D3DE43 /* FOLTest4ViewController.h */, + 18D3C9551EDF07F800D3DE43 /* FOLTest4ViewController.m */, + 18D3C9561EDF07F800D3DE43 /* FOLTest5ViewController.h */, + 18D3C9571EDF07F800D3DE43 /* FOLTest5ViewController.m */, + 18D3C9581EDF07F800D3DE43 /* FOLTest6ViewController.h */, + 18D3C9591EDF07F800D3DE43 /* FOLTest6ViewController.m */, + 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */, + 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */, + ); + name = FloatLayoutDemo; + sourceTree = ""; + }; + 18D3C9001EDF056900D3DE43 /* TableLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C9601EDF080800D3DE43 /* TLTest1ViewController.h */, + 18D3C9611EDF080800D3DE43 /* TLTest1ViewController.m */, + 18D3C9621EDF080800D3DE43 /* TLTest2ViewController.h */, + 18D3C9631EDF080800D3DE43 /* TLTest2ViewController.m */, + 18D3C9641EDF080800D3DE43 /* TLTest3ViewController.h */, + 18D3C9651EDF080800D3DE43 /* TLTest3ViewController.m */, + 204DC31F209D5A7C00F6CB57 /* TLTest4ViewController.h */, + 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */, + ); + name = TableLayoutDemo; + sourceTree = ""; + }; + 18D3C9011EDF059600D3DE43 /* IntegratedDemo */ = { + isa = PBXGroup; + children = ( + 18D3C9751EDF084000D3DE43 /* AllTest1ViewController.h */, + 18D3C9761EDF084000D3DE43 /* AllTest1ViewController.m */, + 18D3C9771EDF084000D3DE43 /* AllTest2ViewController.h */, + 18D3C9781EDF084000D3DE43 /* AllTest2ViewController.m */, + 18D3C9791EDF084000D3DE43 /* AllTest3ViewController.h */, + 18D3C97A1EDF084000D3DE43 /* AllTest3ViewController.m */, + 18D3C97B1EDF084000D3DE43 /* AllTest4ViewController.h */, + 18D3C97C1EDF084000D3DE43 /* AllTest4ViewController.m */, + 18D3C97D1EDF084000D3DE43 /* AllTest5ViewController.h */, + 18D3C97E1EDF084000D3DE43 /* AllTest5ViewController.m */, + 18D3C97F1EDF084000D3DE43 /* AllTest6ViewController.h */, + 18D3C9801EDF084000D3DE43 /* AllTest6ViewController.m */, + 18D3C9811EDF084000D3DE43 /* AllTest7ViewController.h */, + 18D3C9821EDF084000D3DE43 /* AllTest7ViewController.m */, + 18D3C9831EDF084000D3DE43 /* AllTest8ViewController.h */, + 18D3C9841EDF084000D3DE43 /* AllTest8ViewController.m */, + 200A26D71FA8A90300B06E7B /* AllTest9ViewController.h */, + 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */, + 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */, + 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */, + 18D3C9021EDF068200D3DE43 /* AllTestModel&View */, + ); + name = IntegratedDemo; + sourceTree = ""; + }; + 18D3C9021EDF068200D3DE43 /* AllTestModel&View */ = { + isa = PBXGroup; + children = ( + 18D3C9691EDF082800D3DE43 /* AllTest1TableViewCell.h */, + 18D3C96A1EDF082800D3DE43 /* AllTest1TableViewCell.m */, + 18D3C96B1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.h */, + 18D3C96C1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m */, + 18D3C96D1EDF082800D3DE43 /* AllTest2TableViewCell.h */, + 18D3C96E1EDF082800D3DE43 /* AllTest2TableViewCell.m */, + 18D3C96F1EDF082800D3DE43 /* AllTestDataModel.h */, + 18D3C9701EDF082800D3DE43 /* AllTestDataModel.m */, + 200A26DA1FA96B2400B06E7B /* AllTest9CollectionViewCell.h */, + 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */, + 6740E1FA20A52DA900AFBC5A /* AllTest10Model.h */, + 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */, + 6740E1FD20A52DB000AFBC5A /* AllTest10HeaderView.h */, + 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */, + 6740E20020A52DC100AFBC5A /* AllTest10Cell.h */, + 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */, + ); + name = "AllTestModel&View"; + sourceTree = ""; + }; + 18D3C9961EDF091B00D3DE43 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 18D3C9A91EDF0A5A00D3DE43 /* zh-Hans.lproj */, + 18D3C99D1EDF0A5A00D3DE43 /* Base.lproj */, + 18D3C9A61EDF0A5A00D3DE43 /* Images.xcassets */, + 18D3C9A71EDF0A5A00D3DE43 /* Info.plist */, + 18D3C9A81EDF0A5A00D3DE43 /* main.m */, + 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */, + 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 18D3C99D1EDF0A5A00D3DE43 /* Base.lproj */ = { + isa = PBXGroup; + children = ( + 18D3C9A21EDF0A5A00D3DE43 /* LaunchScreen.xib */, + 18D3C9A41EDF0A5A00D3DE43 /* Localizable.strings */, + ); + path = Base.lproj; + sourceTree = ""; + }; + 18D3C9A91EDF0A5A00D3DE43 /* zh-Hans.lproj */ = { + isa = PBXGroup; + children = ( + 18D3C9AE1EDF0A5A00D3DE43 /* LaunchScreen.strings */, + 18D3C9B01EDF0A5A00D3DE43 /* Localizable.strings */, + ); + path = "zh-Hans.lproj"; + sourceTree = ""; + }; + 18D3C9BD1EDF0A7900D3DE43 /* Images */ = { + isa = PBXGroup; + children = ( + 205F9EBB1F7AA6510034732C /* all.png */, + 205F9EB91F7AA5710034732C /* gl.png */, + 18D3C9BE1EDF0AB500D3DE43 /* fl.png */, + 18D3C9BF1EDF0AB500D3DE43 /* fll.png */, + 18D3C9C01EDF0AB500D3DE43 /* flo.png */, + 18D3C9C11EDF0AB500D3DE43 /* layoutdemo1.gif */, + 18D3C9C21EDF0AB500D3DE43 /* layoutdemo2.gif */, + 18D3C9C31EDF0AB500D3DE43 /* layoutdemo3.gif */, + 18D3C9C41EDF0AB500D3DE43 /* layoutdemo4.gif */, + 18D3C9C51EDF0AB500D3DE43 /* layoutdemo5.gif */, + 18D3C9C61EDF0AB500D3DE43 /* layoutdemo6.gif */, + 18D3C9C71EDF0AB500D3DE43 /* layoutdemo7.gif */, + 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */, + 18D3C9C81EDF0AB500D3DE43 /* ll.png */, + 18D3C9C91EDF0AB500D3DE43 /* MyLayout.png */, + 18D3C9CA1EDF0AB500D3DE43 /* MyLayoutClass.png */, + 18D3C9CB1EDF0AB500D3DE43 /* MyLayoutP.png */, + 18D3C9CC1EDF0AB500D3DE43 /* pl.png */, + 18D3C9CD1EDF0AB500D3DE43 /* rl.png */, + 18D3C9CE1EDF0AB500D3DE43 /* tl.png */, + ); + name = Images; + sourceTree = ""; + }; + 18D683E61C4F421400A48BB4 /* MyLayout */ = { + isa = PBXGroup; + children = ( + 18C15AEA1EDF133200AADEAC /* Info.plist */, + 18D3C9BD1EDF0A7900D3DE43 /* Images */, + 18D683FB1C4F421400A48BB4 /* Lib */, + ); + path = MyLayout; + sourceTree = ""; + }; + 18D683FB1C4F421400A48BB4 /* Lib */ = { + isa = PBXGroup; + children = ( + 18D684001C4F421400A48BB4 /* MyLayout.h */, + 182225AB1E77E5930081AA4B /* MyFlowLayout.h */, + 182225B41E77E5930081AA4B /* MyFlowLayout.m */, + 182225AC1E77E5930081AA4B /* MyLinearLayout.h */, + 182225B21E77E5930081AA4B /* MyLinearLayout.m */, + 182225AD1E77E5930081AA4B /* MyFloatLayout.h */, + 182225B91E77E5930081AA4B /* MyFloatLayout.m */, + 182225AE1E77E5930081AA4B /* MyTableLayout.h */, + 182225C31E77E5930081AA4B /* MyTableLayout.m */, + 182225BE1E77E5930081AA4B /* MyRelativeLayout.h */, + 182225B51E77E5930081AA4B /* MyRelativeLayout.m */, + 182225BD1E77E5930081AA4B /* MyPathLayout.h */, + 182225B61E77E5930081AA4B /* MyPathLayout.m */, + 182225BA1E77E5930081AA4B /* MyFrameLayout.h */, + 182225B71E77E5930081AA4B /* MyFrameLayout.m */, + 182225AF1E77E5930081AA4B /* MyBaseLayout.h */, + 182225B11E77E5930081AA4B /* MyBaseLayout.m */, + 182225B01E77E5930081AA4B /* MyLayoutPos.h */, + 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */, + 182225BB1E77E5930081AA4B /* MyLayoutPos.m */, + 182225BC1E77E5930081AA4B /* MyLayoutSize.h */, + 182225C81E77E5930081AA4B /* MyLayoutSizeInner.h */, + 182225C51E77E5930081AA4B /* MyLayoutSize.m */, + 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */, + 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */, + 182225C21E77E5930081AA4B /* MyMaker.h */, + 182225C11E77E5930081AA4B /* MyMaker.m */, + 182225C71E77E5930081AA4B /* MyDimeScale.h */, + 182225C41E77E5930081AA4B /* MyDimeScale.m */, + 182225B81E77E5930081AA4B /* MyLayoutInner.h */, + 182225B31E77E5930081AA4B /* MyLayoutDef.h */, + 205642891F4D013D00E8BDDE /* MyGrid.h */, + 182DB6401EF7876200E2D65D /* MyGridLayout.h */, + 182DB6411EF7876200E2D65D /* MyGridLayout.m */, + 205642841F4CFF9B00E8BDDE /* MyBorderline.h */, + 205642851F4CFF9B00E8BDDE /* MyBorderline.m */, + 205643081F4E53CD00E8BDDE /* MyGridNode.h */, + 205643091F4E53CD00E8BDDE /* MyGridNode.m */, + 205643141F55A03000E8BDDE /* MyLayoutMath.h */, + 205643151F55A03000E8BDDE /* MyLayoutMath.m */, + 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */, + 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */, + ); + path = Lib; + sourceTree = ""; + }; + 18D684531C4F423400A48BB4 /* MyLayoutTests */ = { + isa = PBXGroup; + children = ( + 18D684541C4F423400A48BB4 /* Info.plist */, + 18D684551C4F423400A48BB4 /* MyLayoutTests.m */, + 189738501E16330B004F80D6 /* MyLayoutTestCaseBase.m */, + 189738521E16340D004F80D6 /* MyLayoutTestCaseBase.h */, + 1897384E1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m */, + 180BD8A01EA9EF9A00C6980B /* MyFrameLayoutTestCase.m */, + 181836941EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m */, + 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */, + 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */, + 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */, + ); + path = MyLayoutTests; + sourceTree = ""; + }; + 2043D5DA20995DF800276C68 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2043D5DB20995DF800276C68 /* CoreBluetooth.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 205CFA8B1F49BCAF00355489 /* GridLayoutDemo */ = { + isa = PBXGroup; + children = ( + 205CFA8C1F49BD1C00355489 /* GLTest1ViewController.h */, + 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */, + 205643111F51C7DF00E8BDDE /* GLTest2ViewController.h */, + 205643121F51C7EB00E8BDDE /* GLTest2ViewController.m */, + 20F783541F60398C00BE5B31 /* GLTest3ViewController.h */, + 20F783551F60399700BE5B31 /* GLTest3ViewController.m */, + 44EBDA8A1F619A6300B47CBD /* GLTest4ViewController.h */, + 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */, + 444B718F1F6A3E3F00331872 /* GLTest5ViewController.h */, + 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */, + ); + name = GridLayoutDemo; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 181A10B21EDF12CF00996203 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 2056430A1F4E53CD00E8BDDE /* MyGridNode.h in Headers */, - 18C15AEC1EDF13D700AADEAC /* MyLayout.h in Headers */, - 18C15AED1EDF13DE00AADEAC /* MyFlowLayout.h in Headers */, - 18C15AEE1EDF13E500AADEAC /* MyLinearLayout.h in Headers */, - 18C15AEF1EDF13E900AADEAC /* MyFloatLayout.h in Headers */, - 18C15AF01EDF13EF00AADEAC /* MyTableLayout.h in Headers */, - 18C15AF11EDF13F300AADEAC /* MyRelativeLayout.h in Headers */, - 18C15AF21EDF13F900AADEAC /* MyPathLayout.h in Headers */, - 205643161F55A03000E8BDDE /* MyLayoutMath.h in Headers */, - 18C15AF31EDF13FF00AADEAC /* MyFrameLayout.h in Headers */, - 18C15AF41EDF140400AADEAC /* MyBaseLayout.h in Headers */, - 18C15AF51EDF140D00AADEAC /* MyLayoutPos.h in Headers */, - 18C15AF61EDF141000AADEAC /* MyLayoutSize.h in Headers */, - 205E0C5F20B90347001A8B99 /* MyGrid.h in Headers */, - 182DB6421EF7876200E2D65D /* MyGridLayout.h in Headers */, - 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */, - 18C15AF81EDF141A00AADEAC /* MyMaker.h in Headers */, - 18C15AF71EDF141600AADEAC /* MyLayoutSizeClass.h in Headers */, - 18C15AF91EDF142000AADEAC /* MyDimeScale.h in Headers */, - 18C15AFA1EDF142300AADEAC /* MyLayoutDef.h in Headers */, - 205E0C6020B907CC001A8B99 /* MyLayoutPosInner.h in Headers */, - 205E0C6120B907D1001A8B99 /* MyLayoutSizeInner.h in Headers */, - 205E0C6220B907DB001A8B99 /* MyLayoutInner.h in Headers */, - 205E0C6320B907EC001A8B99 /* MyLayoutDelegate.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; + 181A10B21EDF12CF00996203 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2056430A1F4E53CD00E8BDDE /* MyGridNode.h in Headers */, + 18C15AEC1EDF13D700AADEAC /* MyLayout.h in Headers */, + 18C15AED1EDF13DE00AADEAC /* MyFlowLayout.h in Headers */, + 18C15AEE1EDF13E500AADEAC /* MyLinearLayout.h in Headers */, + 18C15AEF1EDF13E900AADEAC /* MyFloatLayout.h in Headers */, + 18C15AF01EDF13EF00AADEAC /* MyTableLayout.h in Headers */, + 18C15AF11EDF13F300AADEAC /* MyRelativeLayout.h in Headers */, + 18C15AF21EDF13F900AADEAC /* MyPathLayout.h in Headers */, + 205643161F55A03000E8BDDE /* MyLayoutMath.h in Headers */, + 18C15AF31EDF13FF00AADEAC /* MyFrameLayout.h in Headers */, + 18C15AF41EDF140400AADEAC /* MyBaseLayout.h in Headers */, + 18C15AF51EDF140D00AADEAC /* MyLayoutPos.h in Headers */, + 18C15AF61EDF141000AADEAC /* MyLayoutSize.h in Headers */, + 205E0C5F20B90347001A8B99 /* MyGrid.h in Headers */, + 182DB6421EF7876200E2D65D /* MyGridLayout.h in Headers */, + 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */, + 18C15AF81EDF141A00AADEAC /* MyMaker.h in Headers */, + 18C15AF71EDF141600AADEAC /* MyLayoutSizeClass.h in Headers */, + 18C15AF91EDF142000AADEAC /* MyDimeScale.h in Headers */, + 18C15AFA1EDF142300AADEAC /* MyLayoutDef.h in Headers */, + 205E0C6020B907CC001A8B99 /* MyLayoutPosInner.h in Headers */, + 205E0C6120B907D1001A8B99 /* MyLayoutSizeInner.h in Headers */, + 205E0C6220B907DB001A8B99 /* MyLayoutInner.h in Headers */, + 205E0C6320B907EC001A8B99 /* MyLayoutDelegate.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 181A10B41EDF12CF00996203 /* MyLayout */ = { - isa = PBXNativeTarget; - buildConfigurationList = 181A10BA1EDF12CF00996203 /* Build configuration list for PBXNativeTarget "MyLayout" */; - buildPhases = ( - 181A10B01EDF12CF00996203 /* Sources */, - 181A10B11EDF12CF00996203 /* Frameworks */, - 181A10B21EDF12CF00996203 /* Headers */, - 181A10B31EDF12CF00996203 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = MyLayout; - productName = MyLayout; - productReference = 181A10B51EDF12CF00996203 /* MyLayout.framework */; - productType = "com.apple.product-type.framework"; - }; - 1840828C1B2C46E8003F378B /* MyLayoutDemo */ = { - isa = PBXNativeTarget; - buildConfigurationList = 184082B01B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutDemo" */; - buildPhases = ( - 184082891B2C46E8003F378B /* Sources */, - 1840828A1B2C46E8003F378B /* Frameworks */, - 1840828B1B2C46E8003F378B /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = MyLayoutDemo; - productName = MyLayout; - productReference = 1840828D1B2C46E8003F378B /* MyLayoutDemo.app */; - productType = "com.apple.product-type.application"; - }; - 184082A51B2C46E8003F378B /* MyLayoutTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 184082B31B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutTests" */; - buildPhases = ( - 184082A21B2C46E8003F378B /* Sources */, - 184082A31B2C46E8003F378B /* Frameworks */, - 184082A41B2C46E8003F378B /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 184082A81B2C46E8003F378B /* PBXTargetDependency */, - ); - name = MyLayoutTests; - productName = MyLayoutTests; - productReference = 184082A61B2C46E8003F378B /* MyLayout.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 18B152301DEDDE5500AD7A1C /* MyLayoutUITests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 18B1523A1DEDDE5500AD7A1C /* Build configuration list for PBXNativeTarget "MyLayoutUITests" */; - buildPhases = ( - 18B1522D1DEDDE5500AD7A1C /* Sources */, - 18B1522E1DEDDE5500AD7A1C /* Frameworks */, - 18B1522F1DEDDE5500AD7A1C /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 18B152371DEDDE5500AD7A1C /* PBXTargetDependency */, - ); - name = MyLayoutUITests; - productName = MyLayoutUITests; - productReference = 18B152311DEDDE5500AD7A1C /* MyLayoutUITests.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; + 181A10B41EDF12CF00996203 /* MyLayout */ = { + isa = PBXNativeTarget; + buildConfigurationList = 181A10BA1EDF12CF00996203 /* Build configuration list for PBXNativeTarget "MyLayout" */; + buildPhases = ( + 181A10B01EDF12CF00996203 /* Sources */, + 181A10B11EDF12CF00996203 /* Frameworks */, + 181A10B21EDF12CF00996203 /* Headers */, + 181A10B31EDF12CF00996203 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MyLayout; + productName = MyLayout; + productReference = 181A10B51EDF12CF00996203 /* MyLayout.framework */; + productType = "com.apple.product-type.framework"; + }; + 1840828C1B2C46E8003F378B /* MyLayoutDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 184082B01B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutDemo" */; + buildPhases = ( + 184082891B2C46E8003F378B /* Sources */, + 1840828A1B2C46E8003F378B /* Frameworks */, + 1840828B1B2C46E8003F378B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MyLayoutDemo; + productName = MyLayout; + productReference = 1840828D1B2C46E8003F378B /* MyLayoutDemo.app */; + productType = "com.apple.product-type.application"; + }; + 184082A51B2C46E8003F378B /* MyLayoutTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 184082B31B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutTests" */; + buildPhases = ( + 184082A21B2C46E8003F378B /* Sources */, + 184082A31B2C46E8003F378B /* Frameworks */, + 184082A41B2C46E8003F378B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 184082A81B2C46E8003F378B /* PBXTargetDependency */, + ); + name = MyLayoutTests; + productName = MyLayoutTests; + productReference = 184082A61B2C46E8003F378B /* MyLayout.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 18B152301DEDDE5500AD7A1C /* MyLayoutUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18B1523A1DEDDE5500AD7A1C /* Build configuration list for PBXNativeTarget "MyLayoutUITests" */; + buildPhases = ( + 18B1522D1DEDDE5500AD7A1C /* Sources */, + 18B1522E1DEDDE5500AD7A1C /* Frameworks */, + 18B1522F1DEDDE5500AD7A1C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 18B152371DEDDE5500AD7A1C /* PBXTargetDependency */, + ); + name = MyLayoutUITests; + productName = MyLayoutUITests; + productReference = 18B152311DEDDE5500AD7A1C /* MyLayoutUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 184082851B2C46E8003F378B /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0920; - ORGANIZATIONNAME = YoungSoft; - TargetAttributes = { - 181A10B41EDF12CF00996203 = { - CreatedOnToolsVersion = 8.3.2; - DevelopmentTeam = BGQ8WB468K; - ProvisioningStyle = Automatic; - }; - 1840828C1B2C46E8003F378B = { - CreatedOnToolsVersion = 6.3.2; - DevelopmentTeam = BGQ8WB468K; - ProvisioningStyle = Automatic; - }; - 184082A51B2C46E8003F378B = { - CreatedOnToolsVersion = 6.3.2; - DevelopmentTeam = Q5MFLFRY64; - TestTargetID = 1840828C1B2C46E8003F378B; - }; - 18B152301DEDDE5500AD7A1C = { - CreatedOnToolsVersion = 8.1; - ProvisioningStyle = Automatic; - TestTargetID = 1840828C1B2C46E8003F378B; - }; - }; - }; - buildConfigurationList = 184082881B2C46E8003F378B /* Build configuration list for PBXProject "MyLayout" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - Base, - "zh-Hans", - ); - mainGroup = 184082841B2C46E8003F378B; - productRefGroup = 1840828E1B2C46E8003F378B /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 1840828C1B2C46E8003F378B /* MyLayoutDemo */, - 184082A51B2C46E8003F378B /* MyLayoutTests */, - 18B152301DEDDE5500AD7A1C /* MyLayoutUITests */, - 181A10B41EDF12CF00996203 /* MyLayout */, - ); - }; + 184082851B2C46E8003F378B /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0920; + ORGANIZATIONNAME = YoungSoft; + TargetAttributes = { + 181A10B41EDF12CF00996203 = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = BGQ8WB468K; + ProvisioningStyle = Automatic; + }; + 1840828C1B2C46E8003F378B = { + CreatedOnToolsVersion = 6.3.2; + DevelopmentTeam = BGQ8WB468K; + ProvisioningStyle = Automatic; + }; + 184082A51B2C46E8003F378B = { + CreatedOnToolsVersion = 6.3.2; + DevelopmentTeam = Q5MFLFRY64; + TestTargetID = 1840828C1B2C46E8003F378B; + }; + 18B152301DEDDE5500AD7A1C = { + CreatedOnToolsVersion = 8.1; + ProvisioningStyle = Automatic; + TestTargetID = 1840828C1B2C46E8003F378B; + }; + }; + }; + buildConfigurationList = 184082881B2C46E8003F378B /* Build configuration list for PBXProject "MyLayout" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + "zh-Hans", + ); + mainGroup = 184082841B2C46E8003F378B; + productRefGroup = 1840828E1B2C46E8003F378B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1840828C1B2C46E8003F378B /* MyLayoutDemo */, + 184082A51B2C46E8003F378B /* MyLayoutTests */, + 18B152301DEDDE5500AD7A1C /* MyLayoutUITests */, + 181A10B41EDF12CF00996203 /* MyLayout */, + ); + }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 181A10B31EDF12CF00996203 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1840828B1B2C46E8003F378B /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 181A10AA1EDF11FF00996203 /* FLLTest2ViewController.xib in Resources */, - 18D3C9D01EDF0AB500D3DE43 /* fll.png in Resources */, - 18D3C9DB1EDF0AB500D3DE43 /* MyLayoutClass.png in Resources */, - 18D3C9CF1EDF0AB500D3DE43 /* fl.png in Resources */, - 18D3C9DC1EDF0AB500D3DE43 /* MyLayoutP.png in Resources */, - 18D3C9D31EDF0AB500D3DE43 /* layoutdemo2.gif in Resources */, - 18D3C9DF1EDF0AB500D3DE43 /* tl.png in Resources */, - 18D3C9B61EDF0A5A00D3DE43 /* Images.xcassets in Resources */, - 4411977B1F6AE78E00C22557 /* GridLayoutDemo5.json in Resources */, - 18D3C9D91EDF0AB500D3DE43 /* ll.png in Resources */, - 18D3C9D11EDF0AB500D3DE43 /* flo.png in Resources */, - 18D3C9D41EDF0AB500D3DE43 /* layoutdemo3.gif in Resources */, - 18D3C9DE1EDF0AB500D3DE43 /* rl.png in Resources */, - 181A10AE1EDF123800996203 /* FOLTest1ViewController.xib in Resources */, - 18D3C9BB1EDF0A5A00D3DE43 /* LaunchScreen.strings in Resources */, - 205F9EBC1F7AA6510034732C /* all.png in Resources */, - 18D3C9B51EDF0A5A00D3DE43 /* Localizable.strings in Resources */, - 18D3C9DD1EDF0AB500D3DE43 /* pl.png in Resources */, - 44EBDA8E1F619C9000B47CBD /* GridLayoutDemo4.json in Resources */, - 18D3C9D71EDF0AB500D3DE43 /* layoutdemo6.gif in Resources */, - 18D3C9D81EDF0AB500D3DE43 /* layoutdemo7.gif in Resources */, - 18D3C9BC1EDF0A5A00D3DE43 /* Localizable.strings in Resources */, - 18D3C9D21EDF0AB500D3DE43 /* layoutdemo1.gif in Resources */, - 18D3C9D61EDF0AB500D3DE43 /* layoutdemo5.gif in Resources */, - 18D3C9DA1EDF0AB500D3DE43 /* MyLayout.png in Resources */, - 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */, - 18D3C9B41EDF0A5A00D3DE43 /* LaunchScreen.xib in Resources */, - 18D3C9D51EDF0AB500D3DE43 /* layoutdemo4.gif in Resources */, - 205F9EBA1F7AA5710034732C /* gl.png in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 184082A41B2C46E8003F378B /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18B1522F1DEDDE5500AD7A1C /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; + 181A10B31EDF12CF00996203 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1840828B1B2C46E8003F378B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 181A10AA1EDF11FF00996203 /* FLLTest2ViewController.xib in Resources */, + 18D3C9D01EDF0AB500D3DE43 /* fll.png in Resources */, + 18D3C9DB1EDF0AB500D3DE43 /* MyLayoutClass.png in Resources */, + 18D3C9CF1EDF0AB500D3DE43 /* fl.png in Resources */, + 18D3C9DC1EDF0AB500D3DE43 /* MyLayoutP.png in Resources */, + 18D3C9D31EDF0AB500D3DE43 /* layoutdemo2.gif in Resources */, + 18D3C9DF1EDF0AB500D3DE43 /* tl.png in Resources */, + 18D3C9B61EDF0A5A00D3DE43 /* Images.xcassets in Resources */, + 4411977B1F6AE78E00C22557 /* GridLayoutDemo5.json in Resources */, + 18D3C9D91EDF0AB500D3DE43 /* ll.png in Resources */, + 18D3C9D11EDF0AB500D3DE43 /* flo.png in Resources */, + 18D3C9D41EDF0AB500D3DE43 /* layoutdemo3.gif in Resources */, + 18D3C9DE1EDF0AB500D3DE43 /* rl.png in Resources */, + 181A10AE1EDF123800996203 /* FOLTest1ViewController.xib in Resources */, + 18D3C9BB1EDF0A5A00D3DE43 /* LaunchScreen.strings in Resources */, + 205F9EBC1F7AA6510034732C /* all.png in Resources */, + 18D3C9B51EDF0A5A00D3DE43 /* Localizable.strings in Resources */, + 18D3C9DD1EDF0AB500D3DE43 /* pl.png in Resources */, + 44EBDA8E1F619C9000B47CBD /* GridLayoutDemo4.json in Resources */, + 18D3C9D71EDF0AB500D3DE43 /* layoutdemo6.gif in Resources */, + 18D3C9D81EDF0AB500D3DE43 /* layoutdemo7.gif in Resources */, + 18D3C9BC1EDF0A5A00D3DE43 /* Localizable.strings in Resources */, + 18D3C9D21EDF0AB500D3DE43 /* layoutdemo1.gif in Resources */, + 18D3C9D61EDF0AB500D3DE43 /* layoutdemo5.gif in Resources */, + 18D3C9DA1EDF0AB500D3DE43 /* MyLayout.png in Resources */, + 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */, + 18D3C9B41EDF0A5A00D3DE43 /* LaunchScreen.xib in Resources */, + 18D3C9D51EDF0AB500D3DE43 /* layoutdemo4.gif in Resources */, + 205F9EBA1F7AA5710034732C /* gl.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 184082A41B2C46E8003F378B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18B1522F1DEDDE5500AD7A1C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 181A10B01EDF12CF00996203 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 18C15AFB1EDF144B00AADEAC /* MyFlowLayout.m in Sources */, - 205642871F4CFF9B00E8BDDE /* MyBorderline.m in Sources */, - 18C15AFC1EDF144B00AADEAC /* MyLinearLayout.m in Sources */, - 18C15AFD1EDF144B00AADEAC /* MyFloatLayout.m in Sources */, - 18C15AFE1EDF144B00AADEAC /* MyTableLayout.m in Sources */, - 2056430B1F4E53CD00E8BDDE /* MyGridNode.m in Sources */, - 205643171F55A03000E8BDDE /* MyLayoutMath.m in Sources */, - 18C15AFF1EDF144B00AADEAC /* MyRelativeLayout.m in Sources */, - 182DB6441EF7876200E2D65D /* MyGridLayout.m in Sources */, - 18C15B001EDF144B00AADEAC /* MyPathLayout.m in Sources */, - 18C15B011EDF144B00AADEAC /* MyFrameLayout.m in Sources */, - 18C15B021EDF144B00AADEAC /* MyBaseLayout.m in Sources */, - 18C15B031EDF144B00AADEAC /* MyLayoutPos.m in Sources */, - 18C15B041EDF144B00AADEAC /* MyLayoutSize.m in Sources */, - 208157C41F5A886400E945B6 /* MyLayoutDelegate.m in Sources */, - 18C15B051EDF144B00AADEAC /* MyLayoutSizeClass.m in Sources */, - 18C15B061EDF144B00AADEAC /* MyMaker.m in Sources */, - 18C15B071EDF144B00AADEAC /* MyDimeScale.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 184082891B2C46E8003F378B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 205643131F51C7EB00E8BDDE /* GLTest2ViewController.m in Sources */, - 18D3C9B81EDF0A5A00D3DE43 /* main.m in Sources */, - 18D3C94B1EDF07E700D3DE43 /* PLTest3ViewController.m in Sources */, - 18D3C9391EDF07C000D3DE43 /* FLLTest1ViewController.m in Sources */, - 18D3C9681EDF080800D3DE43 /* TLTest3ViewController.m in Sources */, - 182225CB1E77E5930081AA4B /* MyFlowLayout.m in Sources */, - 182225D31E77E5930081AA4B /* MyTableLayout.m in Sources */, - 18D3C95B1EDF07F800D3DE43 /* FOLTest2ViewController.m in Sources */, - 18D3C9121EDF074900D3DE43 /* LLTest2ViewController.m in Sources */, - 182225D41E77E5930081AA4B /* MyDimeScale.m in Sources */, - 18D3C92A1EDF07A700D3DE43 /* RLTest3ViewController.m in Sources */, - 208157BD1F586AA700E945B6 /* DetailViewController.m in Sources */, - 18D3C9861EDF084000D3DE43 /* AllTest2ViewController.m in Sources */, - 18D3C9731EDF082800D3DE43 /* AllTest2TableViewCell.m in Sources */, - 18D3C95F1EDF07F800D3DE43 /* FOLTest6ViewController.m in Sources */, - 182225D51E77E5930081AA4B /* MyLayoutSize.m in Sources */, - 6740E20120A52DC100AFBC5A /* AllTest10Cell.m in Sources */, - 18D3C93A1EDF07C000D3DE43 /* FLLTest2ViewController.m in Sources */, - 18D3C95A1EDF07F800D3DE43 /* FOLTest1ViewController.m in Sources */, - 182225D01E77E5930081AA4B /* MyLayoutPos.m in Sources */, - 18D3C98B1EDF084000D3DE43 /* AllTest7ViewController.m in Sources */, - 200A26DC1FA96B2400B06E7B /* AllTest9CollectionViewCell.m in Sources */, - 18D3C9881EDF084000D3DE43 /* AllTest4ViewController.m in Sources */, - 18D3C9131EDF074900D3DE43 /* LLTest3ViewController.m in Sources */, - 18D3C95E1EDF07F800D3DE43 /* FOLTest5ViewController.m in Sources */, - 18D3C99C1EDF09BE00D3DE43 /* CFTool.m in Sources */, - 18D3C9141EDF074900D3DE43 /* LLTest4ViewController.m in Sources */, - 18D3C9931EDF08F800D3DE43 /* ViewController.m in Sources */, - 18D3C93B1EDF07C000D3DE43 /* FLLTest3ViewController.m in Sources */, - 205643181F55A16400E8BDDE /* MyLayoutMath.m in Sources */, - 18D3C95C1EDF07F800D3DE43 /* FOLTest3ViewController.m in Sources */, - 18D3C9491EDF07E700D3DE43 /* PLTest1ViewController.m in Sources */, - 18D3C95D1EDF07F800D3DE43 /* FOLTest4ViewController.m in Sources */, - 2075CC3220A0B2A400BA6F65 /* FLLTest7ViewController.m in Sources */, - 182225CE1E77E5930081AA4B /* MyFrameLayout.m in Sources */, - 18D3C9941EDF08F800D3DE43 /* YYFPSLabel.m in Sources */, - 18D3C91D1EDF078200D3DE43 /* FLTest2ViewController.m in Sources */, - 18D3C9661EDF080800D3DE43 /* TLTest1ViewController.m in Sources */, - 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */, - 18D3C94A1EDF07E700D3DE43 /* PLTest2ViewController.m in Sources */, - 205642881F4CFFB600E8BDDE /* MyBorderline.m in Sources */, - 18D3C93C1EDF07C000D3DE43 /* FLLTest4ViewController.m in Sources */, - 18D3C98C1EDF084000D3DE43 /* AllTest8ViewController.m in Sources */, - 18D3C93D1EDF07C000D3DE43 /* FLLTest5ViewController.m in Sources */, - 18D3C9671EDF080800D3DE43 /* TLTest2ViewController.m in Sources */, - 18D3C99B1EDF09BE00D3DE43 /* AppDelegate.m in Sources */, - 18D3C9291EDF07A700D3DE43 /* RLTest2ViewController.m in Sources */, - 18D3C9151EDF074900D3DE43 /* LLTest5ViewController.m in Sources */, - 18D3C9891EDF084000D3DE43 /* AllTest5ViewController.m in Sources */, - 182225CC1E77E5930081AA4B /* MyRelativeLayout.m in Sources */, - 18D3C94C1EDF07E700D3DE43 /* PLTest4ViewController.m in Sources */, - 2056430C1F4E8B1E00E8BDDE /* MyGridNode.m in Sources */, - 182225D11E77E5930081AA4B /* MyLayoutSizeClass.m in Sources */, - 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */, - 18D3C9741EDF082800D3DE43 /* AllTestDataModel.m in Sources */, - 205CFA8E1F49BD1C00355489 /* GLTest1ViewController.m in Sources */, - 18D3C9171EDF074900D3DE43 /* LLTest7ViewController.m in Sources */, - 18D3C98A1EDF084000D3DE43 /* AllTest6ViewController.m in Sources */, - 18D3C9111EDF074900D3DE43 /* LLTest1ViewController.m in Sources */, - 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */, - 18D3C93E1EDF07C000D3DE43 /* FLLTest6ViewController.m in Sources */, - 200A26D91FA8A90300B06E7B /* AllTest9ViewController.m in Sources */, - 18D3C9281EDF07A700D3DE43 /* RLTest1ViewController.m in Sources */, - 182225CA1E77E5930081AA4B /* MyLinearLayout.m in Sources */, - 18D3C91C1EDF078200D3DE43 /* FLTest1ViewController.m in Sources */, - 18D3C9951EDF08F800D3DE43 /* YYWeakProxy.m in Sources */, - 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */, - 44EBDA8C1F619A6300B47CBD /* GLTest4ViewController.m in Sources */, - 18D3C9711EDF082800D3DE43 /* AllTest1TableViewCell.m in Sources */, - 182225CF1E77E5930081AA4B /* MyFloatLayout.m in Sources */, - 18D3C92B1EDF07A700D3DE43 /* RLTest4ViewController.m in Sources */, - 6740E1FB20A52DA900AFBC5A /* AllTest10Model.m in Sources */, - 18D3C92C1EDF07A700D3DE43 /* RLTest5ViewController.m in Sources */, - 204DC321209D5A8700F6CB57 /* TLTest4ViewController.m in Sources */, - 182DB6431EF7876200E2D65D /* MyGridLayout.m in Sources */, - 18D3C9871EDF084000D3DE43 /* AllTest3ViewController.m in Sources */, - 18D3C9161EDF074900D3DE43 /* LLTest6ViewController.m in Sources */, - 18D3C9721EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m in Sources */, - 208157C31F5A886400E945B6 /* MyLayoutDelegate.m in Sources */, - 18D3C94D1EDF07E700D3DE43 /* PLTest5ViewController.m in Sources */, - 6740E1F820A52D9E00AFBC5A /* AllTest10ViewController.m in Sources */, - 18D3C9851EDF084000D3DE43 /* AllTest1ViewController.m in Sources */, - 182225D21E77E5930081AA4B /* MyMaker.m in Sources */, - 182225C91E77E5930081AA4B /* MyBaseLayout.m in Sources */, - 182225CD1E77E5930081AA4B /* MyPathLayout.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 184082A21B2C46E8003F378B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 18B2CCE81EAF5066001AE0E1 /* MyLinearLayoutTestCase.m in Sources */, - 18D684591C4F423400A48BB4 /* MyLayoutTests.m in Sources */, - 1810AC221EB966D30022CBFF /* MyLayoutPerformanceTestCase.m in Sources */, - 181836951EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m in Sources */, - 180BD8A11EA9EF9A00C6980B /* MyFrameLayoutTestCase.m in Sources */, - 1897384F1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m in Sources */, - 189738511E16330B004F80D6 /* MyLayoutTestCaseBase.m in Sources */, - 18B2CCEA1EB046AC001AE0E1 /* MyFloatLayoutTestCase.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18B1522D1DEDDE5500AD7A1C /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 18B152341DEDDE5500AD7A1C /* MyLayoutUITests.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; + 181A10B01EDF12CF00996203 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18C15AFB1EDF144B00AADEAC /* MyFlowLayout.m in Sources */, + 205642871F4CFF9B00E8BDDE /* MyBorderline.m in Sources */, + 18C15AFC1EDF144B00AADEAC /* MyLinearLayout.m in Sources */, + 18C15AFD1EDF144B00AADEAC /* MyFloatLayout.m in Sources */, + 18C15AFE1EDF144B00AADEAC /* MyTableLayout.m in Sources */, + 2056430B1F4E53CD00E8BDDE /* MyGridNode.m in Sources */, + 205643171F55A03000E8BDDE /* MyLayoutMath.m in Sources */, + 18C15AFF1EDF144B00AADEAC /* MyRelativeLayout.m in Sources */, + 182DB6441EF7876200E2D65D /* MyGridLayout.m in Sources */, + 18C15B001EDF144B00AADEAC /* MyPathLayout.m in Sources */, + 18C15B011EDF144B00AADEAC /* MyFrameLayout.m in Sources */, + 18C15B021EDF144B00AADEAC /* MyBaseLayout.m in Sources */, + 18C15B031EDF144B00AADEAC /* MyLayoutPos.m in Sources */, + 18C15B041EDF144B00AADEAC /* MyLayoutSize.m in Sources */, + 208157C41F5A886400E945B6 /* MyLayoutDelegate.m in Sources */, + 18C15B051EDF144B00AADEAC /* MyLayoutSizeClass.m in Sources */, + 18C15B061EDF144B00AADEAC /* MyMaker.m in Sources */, + 18C15B071EDF144B00AADEAC /* MyDimeScale.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 184082891B2C46E8003F378B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 205643131F51C7EB00E8BDDE /* GLTest2ViewController.m in Sources */, + 18D3C9B81EDF0A5A00D3DE43 /* main.m in Sources */, + 18D3C94B1EDF07E700D3DE43 /* PLTest3ViewController.m in Sources */, + 18D3C9391EDF07C000D3DE43 /* FLLTest1ViewController.m in Sources */, + 18D3C9681EDF080800D3DE43 /* TLTest3ViewController.m in Sources */, + 182225CB1E77E5930081AA4B /* MyFlowLayout.m in Sources */, + 182225D31E77E5930081AA4B /* MyTableLayout.m in Sources */, + 18D3C95B1EDF07F800D3DE43 /* FOLTest2ViewController.m in Sources */, + 18D3C9121EDF074900D3DE43 /* LLTest2ViewController.m in Sources */, + 182225D41E77E5930081AA4B /* MyDimeScale.m in Sources */, + 18D3C92A1EDF07A700D3DE43 /* RLTest3ViewController.m in Sources */, + 208157BD1F586AA700E945B6 /* DetailViewController.m in Sources */, + 18D3C9861EDF084000D3DE43 /* AllTest2ViewController.m in Sources */, + 18D3C9731EDF082800D3DE43 /* AllTest2TableViewCell.m in Sources */, + 18D3C95F1EDF07F800D3DE43 /* FOLTest6ViewController.m in Sources */, + 182225D51E77E5930081AA4B /* MyLayoutSize.m in Sources */, + 6740E20120A52DC100AFBC5A /* AllTest10Cell.m in Sources */, + 18D3C93A1EDF07C000D3DE43 /* FLLTest2ViewController.m in Sources */, + 18D3C95A1EDF07F800D3DE43 /* FOLTest1ViewController.m in Sources */, + 182225D01E77E5930081AA4B /* MyLayoutPos.m in Sources */, + 18D3C98B1EDF084000D3DE43 /* AllTest7ViewController.m in Sources */, + 200A26DC1FA96B2400B06E7B /* AllTest9CollectionViewCell.m in Sources */, + 18D3C9881EDF084000D3DE43 /* AllTest4ViewController.m in Sources */, + 18D3C9131EDF074900D3DE43 /* LLTest3ViewController.m in Sources */, + 18D3C95E1EDF07F800D3DE43 /* FOLTest5ViewController.m in Sources */, + 18D3C99C1EDF09BE00D3DE43 /* CFTool.m in Sources */, + 18D3C9141EDF074900D3DE43 /* LLTest4ViewController.m in Sources */, + 18D3C9931EDF08F800D3DE43 /* ViewController.m in Sources */, + 18D3C93B1EDF07C000D3DE43 /* FLLTest3ViewController.m in Sources */, + 205643181F55A16400E8BDDE /* MyLayoutMath.m in Sources */, + 18D3C95C1EDF07F800D3DE43 /* FOLTest3ViewController.m in Sources */, + 18D3C9491EDF07E700D3DE43 /* PLTest1ViewController.m in Sources */, + 18D3C95D1EDF07F800D3DE43 /* FOLTest4ViewController.m in Sources */, + 2075CC3220A0B2A400BA6F65 /* FLLTest7ViewController.m in Sources */, + 182225CE1E77E5930081AA4B /* MyFrameLayout.m in Sources */, + 18D3C9941EDF08F800D3DE43 /* YYFPSLabel.m in Sources */, + 18D3C91D1EDF078200D3DE43 /* FLTest2ViewController.m in Sources */, + 18D3C9661EDF080800D3DE43 /* TLTest1ViewController.m in Sources */, + 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */, + 18D3C94A1EDF07E700D3DE43 /* PLTest2ViewController.m in Sources */, + 205642881F4CFFB600E8BDDE /* MyBorderline.m in Sources */, + 18D3C93C1EDF07C000D3DE43 /* FLLTest4ViewController.m in Sources */, + 18D3C98C1EDF084000D3DE43 /* AllTest8ViewController.m in Sources */, + 18D3C93D1EDF07C000D3DE43 /* FLLTest5ViewController.m in Sources */, + 18D3C9671EDF080800D3DE43 /* TLTest2ViewController.m in Sources */, + 18D3C99B1EDF09BE00D3DE43 /* AppDelegate.m in Sources */, + 18D3C9291EDF07A700D3DE43 /* RLTest2ViewController.m in Sources */, + 18D3C9151EDF074900D3DE43 /* LLTest5ViewController.m in Sources */, + 18D3C9891EDF084000D3DE43 /* AllTest5ViewController.m in Sources */, + 182225CC1E77E5930081AA4B /* MyRelativeLayout.m in Sources */, + 18D3C94C1EDF07E700D3DE43 /* PLTest4ViewController.m in Sources */, + 2056430C1F4E8B1E00E8BDDE /* MyGridNode.m in Sources */, + 182225D11E77E5930081AA4B /* MyLayoutSizeClass.m in Sources */, + 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */, + 18D3C9741EDF082800D3DE43 /* AllTestDataModel.m in Sources */, + 205CFA8E1F49BD1C00355489 /* GLTest1ViewController.m in Sources */, + 18D3C9171EDF074900D3DE43 /* LLTest7ViewController.m in Sources */, + 18D3C98A1EDF084000D3DE43 /* AllTest6ViewController.m in Sources */, + 18D3C9111EDF074900D3DE43 /* LLTest1ViewController.m in Sources */, + 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */, + 18D3C93E1EDF07C000D3DE43 /* FLLTest6ViewController.m in Sources */, + 200A26D91FA8A90300B06E7B /* AllTest9ViewController.m in Sources */, + 18D3C9281EDF07A700D3DE43 /* RLTest1ViewController.m in Sources */, + 182225CA1E77E5930081AA4B /* MyLinearLayout.m in Sources */, + 18D3C91C1EDF078200D3DE43 /* FLTest1ViewController.m in Sources */, + 18D3C9951EDF08F800D3DE43 /* YYWeakProxy.m in Sources */, + 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */, + 44EBDA8C1F619A6300B47CBD /* GLTest4ViewController.m in Sources */, + 18D3C9711EDF082800D3DE43 /* AllTest1TableViewCell.m in Sources */, + 182225CF1E77E5930081AA4B /* MyFloatLayout.m in Sources */, + 18D3C92B1EDF07A700D3DE43 /* RLTest4ViewController.m in Sources */, + 6740E1FB20A52DA900AFBC5A /* AllTest10Model.m in Sources */, + 18D3C92C1EDF07A700D3DE43 /* RLTest5ViewController.m in Sources */, + 204DC321209D5A8700F6CB57 /* TLTest4ViewController.m in Sources */, + 182DB6431EF7876200E2D65D /* MyGridLayout.m in Sources */, + 18D3C9871EDF084000D3DE43 /* AllTest3ViewController.m in Sources */, + 18D3C9161EDF074900D3DE43 /* LLTest6ViewController.m in Sources */, + 18D3C9721EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m in Sources */, + 208157C31F5A886400E945B6 /* MyLayoutDelegate.m in Sources */, + 18D3C94D1EDF07E700D3DE43 /* PLTest5ViewController.m in Sources */, + 6740E1F820A52D9E00AFBC5A /* AllTest10ViewController.m in Sources */, + 18D3C9851EDF084000D3DE43 /* AllTest1ViewController.m in Sources */, + 182225D21E77E5930081AA4B /* MyMaker.m in Sources */, + 182225C91E77E5930081AA4B /* MyBaseLayout.m in Sources */, + 182225CD1E77E5930081AA4B /* MyPathLayout.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 184082A21B2C46E8003F378B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18B2CCE81EAF5066001AE0E1 /* MyLinearLayoutTestCase.m in Sources */, + 18D684591C4F423400A48BB4 /* MyLayoutTests.m in Sources */, + 1810AC221EB966D30022CBFF /* MyLayoutPerformanceTestCase.m in Sources */, + 181836951EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m in Sources */, + 180BD8A11EA9EF9A00C6980B /* MyFrameLayoutTestCase.m in Sources */, + 1897384F1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m in Sources */, + 189738511E16330B004F80D6 /* MyLayoutTestCaseBase.m in Sources */, + 18B2CCEA1EB046AC001AE0E1 /* MyFloatLayoutTestCase.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18B1522D1DEDDE5500AD7A1C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18B152341DEDDE5500AD7A1C /* MyLayoutUITests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 184082A81B2C46E8003F378B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1840828C1B2C46E8003F378B /* MyLayoutDemo */; - targetProxy = 184082A71B2C46E8003F378B /* PBXContainerItemProxy */; - }; - 18B152371DEDDE5500AD7A1C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1840828C1B2C46E8003F378B /* MyLayoutDemo */; - targetProxy = 18B152361DEDDE5500AD7A1C /* PBXContainerItemProxy */; - }; + 184082A81B2C46E8003F378B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1840828C1B2C46E8003F378B /* MyLayoutDemo */; + targetProxy = 184082A71B2C46E8003F378B /* PBXContainerItemProxy */; + }; + 18B152371DEDDE5500AD7A1C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1840828C1B2C46E8003F378B /* MyLayoutDemo */; + targetProxy = 18B152361DEDDE5500AD7A1C /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - 181A10A81EDF11FF00996203 /* FLLTest2ViewController.xib */ = { - isa = PBXVariantGroup; - children = ( - 181A10A91EDF11FF00996203 /* Base */, - 181A10AB1EDF120E00996203 /* zh-Hans */, - ); - name = FLLTest2ViewController.xib; - sourceTree = ""; - }; - 181A10AC1EDF123800996203 /* FOLTest1ViewController.xib */ = { - isa = PBXVariantGroup; - children = ( - 181A10AD1EDF123800996203 /* Base */, - 181A10AF1EDF124400996203 /* zh-Hans */, - ); - name = FOLTest1ViewController.xib; - sourceTree = ""; - }; - 18D3C9A21EDF0A5A00D3DE43 /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 18D3C9A31EDF0A5A00D3DE43 /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; - 18D3C9A41EDF0A5A00D3DE43 /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - 18D3C9A51EDF0A5A00D3DE43 /* Base */, - ); - name = Localizable.strings; - sourceTree = ""; - }; - 18D3C9AE1EDF0A5A00D3DE43 /* LaunchScreen.strings */ = { - isa = PBXVariantGroup; - children = ( - 18D3C9AF1EDF0A5A00D3DE43 /* zh-Hans */, - ); - name = LaunchScreen.strings; - sourceTree = ""; - }; - 18D3C9B01EDF0A5A00D3DE43 /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - 18D3C9B11EDF0A5A00D3DE43 /* zh-Hans */, - ); - name = Localizable.strings; - sourceTree = ""; - }; + 181A10A81EDF11FF00996203 /* FLLTest2ViewController.xib */ = { + isa = PBXVariantGroup; + children = ( + 181A10A91EDF11FF00996203 /* Base */, + 181A10AB1EDF120E00996203 /* zh-Hans */, + ); + name = FLLTest2ViewController.xib; + sourceTree = ""; + }; + 181A10AC1EDF123800996203 /* FOLTest1ViewController.xib */ = { + isa = PBXVariantGroup; + children = ( + 181A10AD1EDF123800996203 /* Base */, + 181A10AF1EDF124400996203 /* zh-Hans */, + ); + name = FOLTest1ViewController.xib; + sourceTree = ""; + }; + 18D3C9A21EDF0A5A00D3DE43 /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 18D3C9A31EDF0A5A00D3DE43 /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; + 18D3C9A41EDF0A5A00D3DE43 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 18D3C9A51EDF0A5A00D3DE43 /* Base */, + ); + name = Localizable.strings; + sourceTree = ""; + }; + 18D3C9AE1EDF0A5A00D3DE43 /* LaunchScreen.strings */ = { + isa = PBXVariantGroup; + children = ( + 18D3C9AF1EDF0A5A00D3DE43 /* zh-Hans */, + ); + name = LaunchScreen.strings; + sourceTree = ""; + }; + 18D3C9B01EDF0A5A00D3DE43 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 18D3C9B11EDF0A5A00D3DE43 /* zh-Hans */, + ); + name = Localizable.strings; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - 181A10BB1EDF12CF00996203 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = BGQ8WB468K; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = MyLayout/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayout; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 181A10BC1EDF12CF00996203 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CODE_SIGN_IDENTITY = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = BGQ8WB468K; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = MyLayout/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayout; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 184082AE1B2C46E8003F378B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = ""; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 184082AF1B2C46E8003F378B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 184082B11B2C46E8003F378B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_CODE_COVERAGE = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = BGQ8WB468K; - GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; - INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutDemo; - PRODUCT_NAME = MyLayoutDemo; - PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = ""; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 184082B21B2C46E8003F378B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_CODE_COVERAGE = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = BGQ8WB468K; - GCC_PREPROCESSOR_DEFINITIONS = ""; - INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutDemo; - PRODUCT_NAME = MyLayoutDemo; - PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = ""; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 184082B41B2C46E8003F378B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - DEVELOPMENT_TEAM = Q5MFLFRY64; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = MyLayoutTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.youngsoft.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = MyLayout; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MyLayoutDemo.app/MyLayoutDemo"; - }; - name = Debug; - }; - 184082B51B2C46E8003F378B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - DEVELOPMENT_TEAM = Q5MFLFRY64; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - INFOPLIST_FILE = MyLayoutTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.youngsoft.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = MyLayout; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MyLayoutDemo.app/MyLayoutDemo"; - }; - name = Release; - }; - 18B152381DEDDE5500AD7A1C /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_SUSPICIOUS_MOVES = YES; - DEBUG_INFORMATION_FORMAT = dwarf; - INFOPLIST_FILE = MyLayoutUITests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "4bac08b2-6788-4e38-8e3e-241ebd7fba1e"; - TEST_TARGET_NAME = MyLayout; - }; - name = Debug; - }; - 18B152391DEDDE5500AD7A1C /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_SUSPICIOUS_MOVES = YES; - INFOPLIST_FILE = MyLayoutUITests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "4bac08b2-6788-4e38-8e3e-241ebd7fba1e"; - TEST_TARGET_NAME = MyLayout; - }; - name = Release; - }; + 181A10BB1EDF12CF00996203 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = BGQ8WB468K; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = MyLayout/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + OTHER_LDFLAGS = ""; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayout; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 181A10BC1EDF12CF00996203 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CODE_SIGN_IDENTITY = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = BGQ8WB468K; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = MyLayout/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + OTHER_LDFLAGS = ""; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayout; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 184082AE1B2C46E8003F378B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ""; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 184082AF1B2C46E8003F378B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 184082B11B2C46E8003F378B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_CODE_COVERAGE = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = BGQ8WB468K; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; + INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutDemo; + PRODUCT_NAME = MyLayoutDemo; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 184082B21B2C46E8003F378B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_CODE_COVERAGE = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = BGQ8WB468K; + GCC_PREPROCESSOR_DEFINITIONS = ""; + INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutDemo; + PRODUCT_NAME = MyLayoutDemo; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 184082B41B2C46E8003F378B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + DEVELOPMENT_TEAM = Q5MFLFRY64; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = MyLayoutTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.youngsoft.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = MyLayout; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MyLayoutDemo.app/MyLayoutDemo"; + }; + name = Debug; + }; + 184082B51B2C46E8003F378B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + DEVELOPMENT_TEAM = Q5MFLFRY64; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = MyLayoutTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.youngsoft.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = MyLayout; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MyLayoutDemo.app/MyLayoutDemo"; + }; + name = Release; + }; + 18B152381DEDDE5500AD7A1C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + INFOPLIST_FILE = MyLayoutUITests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "4bac08b2-6788-4e38-8e3e-241ebd7fba1e"; + TEST_TARGET_NAME = MyLayout; + }; + name = Debug; + }; + 18B152391DEDDE5500AD7A1C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + INFOPLIST_FILE = MyLayoutUITests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "4bac08b2-6788-4e38-8e3e-241ebd7fba1e"; + TEST_TARGET_NAME = MyLayout; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 181A10BA1EDF12CF00996203 /* Build configuration list for PBXNativeTarget "MyLayout" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 181A10BB1EDF12CF00996203 /* Debug */, - 181A10BC1EDF12CF00996203 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 184082881B2C46E8003F378B /* Build configuration list for PBXProject "MyLayout" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 184082AE1B2C46E8003F378B /* Debug */, - 184082AF1B2C46E8003F378B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 184082B01B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 184082B11B2C46E8003F378B /* Debug */, - 184082B21B2C46E8003F378B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 184082B31B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 184082B41B2C46E8003F378B /* Debug */, - 184082B51B2C46E8003F378B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 18B1523A1DEDDE5500AD7A1C /* Build configuration list for PBXNativeTarget "MyLayoutUITests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 18B152381DEDDE5500AD7A1C /* Debug */, - 18B152391DEDDE5500AD7A1C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; + 181A10BA1EDF12CF00996203 /* Build configuration list for PBXNativeTarget "MyLayout" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 181A10BB1EDF12CF00996203 /* Debug */, + 181A10BC1EDF12CF00996203 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 184082881B2C46E8003F378B /* Build configuration list for PBXProject "MyLayout" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 184082AE1B2C46E8003F378B /* Debug */, + 184082AF1B2C46E8003F378B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 184082B01B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 184082B11B2C46E8003F378B /* Debug */, + 184082B21B2C46E8003F378B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 184082B31B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 184082B41B2C46E8003F378B /* Debug */, + 184082B51B2C46E8003F378B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18B1523A1DEDDE5500AD7A1C /* Build configuration list for PBXNativeTarget "MyLayoutUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18B152381DEDDE5500AD7A1C /* Debug */, + 18B152391DEDDE5500AD7A1C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ - }; - rootObject = 184082851B2C46E8003F378B /* Project object */; + }; + rootObject = 184082851B2C46E8003F378B /* Project object */; } From 3519b04a246650d94fabfec2e07c06153b677386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E6=9F=8F=E6=B3=89?= Date: Sat, 26 May 2018 11:55:15 +0800 Subject: [PATCH 019/115] support for carthage --- MyLayout.xcodeproj/project.pbxproj | 3122 ++++++++++++++-------------- MyLayout/Info.plist | 2 +- MyLayout/Lib/MyLayout.h | 2 +- MyLayoutDemo/Info.plist | 2 +- 4 files changed, 1564 insertions(+), 1564 deletions(-) diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index ebaa23d..2205015 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -1,1606 +1,1606 @@ // !$*UTF8*$! { - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { /* Begin PBXBuildFile section */ - 180BD8A11EA9EF9A00C6980B /* MyFrameLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 180BD8A01EA9EF9A00C6980B /* MyFrameLayoutTestCase.m */; }; - 1810AC221EB966D30022CBFF /* MyLayoutPerformanceTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */; }; - 181836951EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 181836941EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m */; }; - 181A10AA1EDF11FF00996203 /* FLLTest2ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 181A10A81EDF11FF00996203 /* FLLTest2ViewController.xib */; }; - 181A10AE1EDF123800996203 /* FOLTest1ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 181A10AC1EDF123800996203 /* FOLTest1ViewController.xib */; }; - 182225C91E77E5930081AA4B /* MyBaseLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B11E77E5930081AA4B /* MyBaseLayout.m */; }; - 182225CA1E77E5930081AA4B /* MyLinearLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B21E77E5930081AA4B /* MyLinearLayout.m */; }; - 182225CB1E77E5930081AA4B /* MyFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B41E77E5930081AA4B /* MyFlowLayout.m */; }; - 182225CC1E77E5930081AA4B /* MyRelativeLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B51E77E5930081AA4B /* MyRelativeLayout.m */; }; - 182225CD1E77E5930081AA4B /* MyPathLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B61E77E5930081AA4B /* MyPathLayout.m */; }; - 182225CE1E77E5930081AA4B /* MyFrameLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B71E77E5930081AA4B /* MyFrameLayout.m */; }; - 182225CF1E77E5930081AA4B /* MyFloatLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B91E77E5930081AA4B /* MyFloatLayout.m */; }; - 182225D01E77E5930081AA4B /* MyLayoutPos.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BB1E77E5930081AA4B /* MyLayoutPos.m */; }; - 182225D11E77E5930081AA4B /* MyLayoutSizeClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */; }; - 182225D21E77E5930081AA4B /* MyMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C11E77E5930081AA4B /* MyMaker.m */; }; - 182225D31E77E5930081AA4B /* MyTableLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C31E77E5930081AA4B /* MyTableLayout.m */; }; - 182225D41E77E5930081AA4B /* MyDimeScale.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C41E77E5930081AA4B /* MyDimeScale.m */; }; - 182225D51E77E5930081AA4B /* MyLayoutSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C51E77E5930081AA4B /* MyLayoutSize.m */; }; - 182DB6421EF7876200E2D65D /* MyGridLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182DB6401EF7876200E2D65D /* MyGridLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 182DB6431EF7876200E2D65D /* MyGridLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182DB6411EF7876200E2D65D /* MyGridLayout.m */; }; - 182DB6441EF7876200E2D65D /* MyGridLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182DB6411EF7876200E2D65D /* MyGridLayout.m */; }; - 1897384F1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 1897384E1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m */; }; - 189738511E16330B004F80D6 /* MyLayoutTestCaseBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 189738501E16330B004F80D6 /* MyLayoutTestCaseBase.m */; }; - 18B152341DEDDE5500AD7A1C /* MyLayoutUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */; }; - 18B2CCE81EAF5066001AE0E1 /* MyLinearLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */; }; - 18B2CCEA1EB046AC001AE0E1 /* MyFloatLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */; }; - 18C15AEC1EDF13D700AADEAC /* MyLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 18D684001C4F421400A48BB4 /* MyLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AED1EDF13DE00AADEAC /* MyFlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AB1E77E5930081AA4B /* MyFlowLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AEE1EDF13E500AADEAC /* MyLinearLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AC1E77E5930081AA4B /* MyLinearLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AEF1EDF13E900AADEAC /* MyFloatLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AD1E77E5930081AA4B /* MyFloatLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF01EDF13EF00AADEAC /* MyTableLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AE1E77E5930081AA4B /* MyTableLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF11EDF13F300AADEAC /* MyRelativeLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BE1E77E5930081AA4B /* MyRelativeLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF21EDF13F900AADEAC /* MyPathLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BD1E77E5930081AA4B /* MyPathLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF31EDF13FF00AADEAC /* MyFrameLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BA1E77E5930081AA4B /* MyFrameLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF41EDF140400AADEAC /* MyBaseLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AF1E77E5930081AA4B /* MyBaseLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF51EDF140D00AADEAC /* MyLayoutPos.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B01E77E5930081AA4B /* MyLayoutPos.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF61EDF141000AADEAC /* MyLayoutSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BC1E77E5930081AA4B /* MyLayoutSize.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF71EDF141600AADEAC /* MyLayoutSizeClass.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */; }; - 18C15AF81EDF141A00AADEAC /* MyMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C21E77E5930081AA4B /* MyMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AF91EDF142000AADEAC /* MyDimeScale.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C71E77E5930081AA4B /* MyDimeScale.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AFA1EDF142300AADEAC /* MyLayoutDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B31E77E5930081AA4B /* MyLayoutDef.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C15AFB1EDF144B00AADEAC /* MyFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B41E77E5930081AA4B /* MyFlowLayout.m */; }; - 18C15AFC1EDF144B00AADEAC /* MyLinearLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B21E77E5930081AA4B /* MyLinearLayout.m */; }; - 18C15AFD1EDF144B00AADEAC /* MyFloatLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B91E77E5930081AA4B /* MyFloatLayout.m */; }; - 18C15AFE1EDF144B00AADEAC /* MyTableLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C31E77E5930081AA4B /* MyTableLayout.m */; }; - 18C15AFF1EDF144B00AADEAC /* MyRelativeLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B51E77E5930081AA4B /* MyRelativeLayout.m */; }; - 18C15B001EDF144B00AADEAC /* MyPathLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B61E77E5930081AA4B /* MyPathLayout.m */; }; - 18C15B011EDF144B00AADEAC /* MyFrameLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B71E77E5930081AA4B /* MyFrameLayout.m */; }; - 18C15B021EDF144B00AADEAC /* MyBaseLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B11E77E5930081AA4B /* MyBaseLayout.m */; }; - 18C15B031EDF144B00AADEAC /* MyLayoutPos.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BB1E77E5930081AA4B /* MyLayoutPos.m */; }; - 18C15B041EDF144B00AADEAC /* MyLayoutSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C51E77E5930081AA4B /* MyLayoutSize.m */; }; - 18C15B051EDF144B00AADEAC /* MyLayoutSizeClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */; }; - 18C15B061EDF144B00AADEAC /* MyMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C11E77E5930081AA4B /* MyMaker.m */; }; - 18C15B071EDF144B00AADEAC /* MyDimeScale.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C41E77E5930081AA4B /* MyDimeScale.m */; }; - 18D3C9111EDF074900D3DE43 /* LLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9041EDF074900D3DE43 /* LLTest1ViewController.m */; }; - 18D3C9121EDF074900D3DE43 /* LLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9061EDF074900D3DE43 /* LLTest2ViewController.m */; }; - 18D3C9131EDF074900D3DE43 /* LLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9081EDF074900D3DE43 /* LLTest3ViewController.m */; }; - 18D3C9141EDF074900D3DE43 /* LLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C90A1EDF074900D3DE43 /* LLTest4ViewController.m */; }; - 18D3C9151EDF074900D3DE43 /* LLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C90C1EDF074900D3DE43 /* LLTest5ViewController.m */; }; - 18D3C9161EDF074900D3DE43 /* LLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C90E1EDF074900D3DE43 /* LLTest6ViewController.m */; }; - 18D3C9171EDF074900D3DE43 /* LLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9101EDF074900D3DE43 /* LLTest7ViewController.m */; }; - 18D3C91C1EDF078200D3DE43 /* FLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9191EDF078200D3DE43 /* FLTest1ViewController.m */; }; - 18D3C91D1EDF078200D3DE43 /* FLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C91B1EDF078200D3DE43 /* FLTest2ViewController.m */; }; - 18D3C9281EDF07A700D3DE43 /* RLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C91F1EDF07A700D3DE43 /* RLTest1ViewController.m */; }; - 18D3C9291EDF07A700D3DE43 /* RLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9211EDF07A700D3DE43 /* RLTest2ViewController.m */; }; - 18D3C92A1EDF07A700D3DE43 /* RLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9231EDF07A700D3DE43 /* RLTest3ViewController.m */; }; - 18D3C92B1EDF07A700D3DE43 /* RLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9251EDF07A700D3DE43 /* RLTest4ViewController.m */; }; - 18D3C92C1EDF07A700D3DE43 /* RLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9271EDF07A700D3DE43 /* RLTest5ViewController.m */; }; - 18D3C9391EDF07C000D3DE43 /* FLLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C92E1EDF07C000D3DE43 /* FLLTest1ViewController.m */; }; - 18D3C93A1EDF07C000D3DE43 /* FLLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9301EDF07C000D3DE43 /* FLLTest2ViewController.m */; }; - 18D3C93B1EDF07C000D3DE43 /* FLLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9321EDF07C000D3DE43 /* FLLTest3ViewController.m */; }; - 18D3C93C1EDF07C000D3DE43 /* FLLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9341EDF07C000D3DE43 /* FLLTest4ViewController.m */; }; - 18D3C93D1EDF07C000D3DE43 /* FLLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9361EDF07C000D3DE43 /* FLLTest5ViewController.m */; }; - 18D3C93E1EDF07C000D3DE43 /* FLLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9381EDF07C000D3DE43 /* FLLTest6ViewController.m */; }; - 18D3C9491EDF07E700D3DE43 /* PLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9401EDF07E700D3DE43 /* PLTest1ViewController.m */; }; - 18D3C94A1EDF07E700D3DE43 /* PLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9421EDF07E700D3DE43 /* PLTest2ViewController.m */; }; - 18D3C94B1EDF07E700D3DE43 /* PLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9441EDF07E700D3DE43 /* PLTest3ViewController.m */; }; - 18D3C94C1EDF07E700D3DE43 /* PLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9461EDF07E700D3DE43 /* PLTest4ViewController.m */; }; - 18D3C94D1EDF07E700D3DE43 /* PLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9481EDF07E700D3DE43 /* PLTest5ViewController.m */; }; - 18D3C95A1EDF07F800D3DE43 /* FOLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C94F1EDF07F800D3DE43 /* FOLTest1ViewController.m */; }; - 18D3C95B1EDF07F800D3DE43 /* FOLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9511EDF07F800D3DE43 /* FOLTest2ViewController.m */; }; - 18D3C95C1EDF07F800D3DE43 /* FOLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9531EDF07F800D3DE43 /* FOLTest3ViewController.m */; }; - 18D3C95D1EDF07F800D3DE43 /* FOLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9551EDF07F800D3DE43 /* FOLTest4ViewController.m */; }; - 18D3C95E1EDF07F800D3DE43 /* FOLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9571EDF07F800D3DE43 /* FOLTest5ViewController.m */; }; - 18D3C95F1EDF07F800D3DE43 /* FOLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9591EDF07F800D3DE43 /* FOLTest6ViewController.m */; }; - 18D3C9661EDF080800D3DE43 /* TLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9611EDF080800D3DE43 /* TLTest1ViewController.m */; }; - 18D3C9671EDF080800D3DE43 /* TLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9631EDF080800D3DE43 /* TLTest2ViewController.m */; }; - 18D3C9681EDF080800D3DE43 /* TLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9651EDF080800D3DE43 /* TLTest3ViewController.m */; }; - 18D3C9711EDF082800D3DE43 /* AllTest1TableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C96A1EDF082800D3DE43 /* AllTest1TableViewCell.m */; }; - 18D3C9721EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C96C1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m */; }; - 18D3C9731EDF082800D3DE43 /* AllTest2TableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C96E1EDF082800D3DE43 /* AllTest2TableViewCell.m */; }; - 18D3C9741EDF082800D3DE43 /* AllTestDataModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9701EDF082800D3DE43 /* AllTestDataModel.m */; }; - 18D3C9851EDF084000D3DE43 /* AllTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9761EDF084000D3DE43 /* AllTest1ViewController.m */; }; - 18D3C9861EDF084000D3DE43 /* AllTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9781EDF084000D3DE43 /* AllTest2ViewController.m */; }; - 18D3C9871EDF084000D3DE43 /* AllTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C97A1EDF084000D3DE43 /* AllTest3ViewController.m */; }; - 18D3C9881EDF084000D3DE43 /* AllTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C97C1EDF084000D3DE43 /* AllTest4ViewController.m */; }; - 18D3C9891EDF084000D3DE43 /* AllTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C97E1EDF084000D3DE43 /* AllTest5ViewController.m */; }; - 18D3C98A1EDF084000D3DE43 /* AllTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9801EDF084000D3DE43 /* AllTest6ViewController.m */; }; - 18D3C98B1EDF084000D3DE43 /* AllTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9821EDF084000D3DE43 /* AllTest7ViewController.m */; }; - 18D3C98C1EDF084000D3DE43 /* AllTest8ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9841EDF084000D3DE43 /* AllTest8ViewController.m */; }; - 18D3C9931EDF08F800D3DE43 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C98E1EDF08F800D3DE43 /* ViewController.m */; }; - 18D3C9941EDF08F800D3DE43 /* YYFPSLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9901EDF08F800D3DE43 /* YYFPSLabel.m */; }; - 18D3C9951EDF08F800D3DE43 /* YYWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9921EDF08F800D3DE43 /* YYWeakProxy.m */; }; - 18D3C99B1EDF09BE00D3DE43 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9981EDF09BE00D3DE43 /* AppDelegate.m */; }; - 18D3C99C1EDF09BE00D3DE43 /* CFTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C99A1EDF09BE00D3DE43 /* CFTool.m */; }; - 18D3C9B41EDF0A5A00D3DE43 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9A21EDF0A5A00D3DE43 /* LaunchScreen.xib */; }; - 18D3C9B51EDF0A5A00D3DE43 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9A41EDF0A5A00D3DE43 /* Localizable.strings */; }; - 18D3C9B61EDF0A5A00D3DE43 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9A61EDF0A5A00D3DE43 /* Images.xcassets */; }; - 18D3C9B81EDF0A5A00D3DE43 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9A81EDF0A5A00D3DE43 /* main.m */; }; - 18D3C9BB1EDF0A5A00D3DE43 /* LaunchScreen.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9AE1EDF0A5A00D3DE43 /* LaunchScreen.strings */; }; - 18D3C9BC1EDF0A5A00D3DE43 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9B01EDF0A5A00D3DE43 /* Localizable.strings */; }; - 18D3C9CF1EDF0AB500D3DE43 /* fl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9BE1EDF0AB500D3DE43 /* fl.png */; }; - 18D3C9D01EDF0AB500D3DE43 /* fll.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9BF1EDF0AB500D3DE43 /* fll.png */; }; - 18D3C9D11EDF0AB500D3DE43 /* flo.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C01EDF0AB500D3DE43 /* flo.png */; }; - 18D3C9D21EDF0AB500D3DE43 /* layoutdemo1.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C11EDF0AB500D3DE43 /* layoutdemo1.gif */; }; - 18D3C9D31EDF0AB500D3DE43 /* layoutdemo2.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C21EDF0AB500D3DE43 /* layoutdemo2.gif */; }; - 18D3C9D41EDF0AB500D3DE43 /* layoutdemo3.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C31EDF0AB500D3DE43 /* layoutdemo3.gif */; }; - 18D3C9D51EDF0AB500D3DE43 /* layoutdemo4.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C41EDF0AB500D3DE43 /* layoutdemo4.gif */; }; - 18D3C9D61EDF0AB500D3DE43 /* layoutdemo5.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C51EDF0AB500D3DE43 /* layoutdemo5.gif */; }; - 18D3C9D71EDF0AB500D3DE43 /* layoutdemo6.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C61EDF0AB500D3DE43 /* layoutdemo6.gif */; }; - 18D3C9D81EDF0AB500D3DE43 /* layoutdemo7.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C71EDF0AB500D3DE43 /* layoutdemo7.gif */; }; - 18D3C9D91EDF0AB500D3DE43 /* ll.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C81EDF0AB500D3DE43 /* ll.png */; }; - 18D3C9DA1EDF0AB500D3DE43 /* MyLayout.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C91EDF0AB500D3DE43 /* MyLayout.png */; }; - 18D3C9DB1EDF0AB500D3DE43 /* MyLayoutClass.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CA1EDF0AB500D3DE43 /* MyLayoutClass.png */; }; - 18D3C9DC1EDF0AB500D3DE43 /* MyLayoutP.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CB1EDF0AB500D3DE43 /* MyLayoutP.png */; }; - 18D3C9DD1EDF0AB500D3DE43 /* pl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CC1EDF0AB500D3DE43 /* pl.png */; }; - 18D3C9DE1EDF0AB500D3DE43 /* rl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CD1EDF0AB500D3DE43 /* rl.png */; }; - 18D3C9DF1EDF0AB500D3DE43 /* tl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CE1EDF0AB500D3DE43 /* tl.png */; }; - 18D684591C4F423400A48BB4 /* MyLayoutTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D684551C4F423400A48BB4 /* MyLayoutTests.m */; }; - 200A26D91FA8A90300B06E7B /* AllTest9ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */; }; - 200A26DC1FA96B2400B06E7B /* AllTest9CollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */; }; - 204DC321209D5A8700F6CB57 /* TLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */; }; - 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */ = {isa = PBXBuildFile; fileRef = 205642841F4CFF9B00E8BDDE /* MyBorderline.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 205642871F4CFF9B00E8BDDE /* MyBorderline.m in Sources */ = {isa = PBXBuildFile; fileRef = 205642851F4CFF9B00E8BDDE /* MyBorderline.m */; }; - 205642881F4CFFB600E8BDDE /* MyBorderline.m in Sources */ = {isa = PBXBuildFile; fileRef = 205642851F4CFF9B00E8BDDE /* MyBorderline.m */; }; - 2056430A1F4E53CD00E8BDDE /* MyGridNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 205643081F4E53CD00E8BDDE /* MyGridNode.h */; }; - 2056430B1F4E53CD00E8BDDE /* MyGridNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643091F4E53CD00E8BDDE /* MyGridNode.m */; }; - 2056430C1F4E8B1E00E8BDDE /* MyGridNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643091F4E53CD00E8BDDE /* MyGridNode.m */; }; - 205643131F51C7EB00E8BDDE /* GLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643121F51C7EB00E8BDDE /* GLTest2ViewController.m */; }; - 205643161F55A03000E8BDDE /* MyLayoutMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 205643141F55A03000E8BDDE /* MyLayoutMath.h */; }; - 205643171F55A03000E8BDDE /* MyLayoutMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643151F55A03000E8BDDE /* MyLayoutMath.m */; }; - 205643181F55A16400E8BDDE /* MyLayoutMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643151F55A03000E8BDDE /* MyLayoutMath.m */; }; - 205CFA8E1F49BD1C00355489 /* GLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */; }; - 205E0C5F20B90347001A8B99 /* MyGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = 205642891F4D013D00E8BDDE /* MyGrid.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 205E0C6020B907CC001A8B99 /* MyLayoutPosInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */; }; - 205E0C6120B907D1001A8B99 /* MyLayoutSizeInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C81E77E5930081AA4B /* MyLayoutSizeInner.h */; }; - 205E0C6220B907DB001A8B99 /* MyLayoutInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B81E77E5930081AA4B /* MyLayoutInner.h */; }; - 205E0C6320B907EC001A8B99 /* MyLayoutDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */; }; - 205F9EBA1F7AA5710034732C /* gl.png in Resources */ = {isa = PBXBuildFile; fileRef = 205F9EB91F7AA5710034732C /* gl.png */; }; - 205F9EBC1F7AA6510034732C /* all.png in Resources */ = {isa = PBXBuildFile; fileRef = 205F9EBB1F7AA6510034732C /* all.png */; }; - 2075CC3220A0B2A400BA6F65 /* FLLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */; }; - 208157BD1F586AA700E945B6 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157BC1F586AA700E945B6 /* DetailViewController.m */; }; - 208157C31F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; - 208157C41F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; - 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */ = {isa = PBXBuildFile; fileRef = 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */; }; - 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */; }; - 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F783551F60399700BE5B31 /* GLTest3ViewController.m */; }; - 4411977B1F6AE78E00C22557 /* GridLayoutDemo5.json in Resources */ = {isa = PBXBuildFile; fileRef = 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */; }; - 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */; }; - 44EBDA8C1F619A6300B47CBD /* GLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */; }; - 44EBDA8E1F619C9000B47CBD /* GridLayoutDemo4.json in Resources */ = {isa = PBXBuildFile; fileRef = 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */; }; - 6740E1F820A52D9E00AFBC5A /* AllTest10ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */; }; - 6740E1FB20A52DA900AFBC5A /* AllTest10Model.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */; }; - 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */; }; - 6740E20120A52DC100AFBC5A /* AllTest10Cell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */; }; + 180BD8A11EA9EF9A00C6980B /* MyFrameLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 180BD8A01EA9EF9A00C6980B /* MyFrameLayoutTestCase.m */; }; + 1810AC221EB966D30022CBFF /* MyLayoutPerformanceTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */; }; + 181836951EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 181836941EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m */; }; + 181A10AA1EDF11FF00996203 /* FLLTest2ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 181A10A81EDF11FF00996203 /* FLLTest2ViewController.xib */; }; + 181A10AE1EDF123800996203 /* FOLTest1ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 181A10AC1EDF123800996203 /* FOLTest1ViewController.xib */; }; + 182225C91E77E5930081AA4B /* MyBaseLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B11E77E5930081AA4B /* MyBaseLayout.m */; }; + 182225CA1E77E5930081AA4B /* MyLinearLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B21E77E5930081AA4B /* MyLinearLayout.m */; }; + 182225CB1E77E5930081AA4B /* MyFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B41E77E5930081AA4B /* MyFlowLayout.m */; }; + 182225CC1E77E5930081AA4B /* MyRelativeLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B51E77E5930081AA4B /* MyRelativeLayout.m */; }; + 182225CD1E77E5930081AA4B /* MyPathLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B61E77E5930081AA4B /* MyPathLayout.m */; }; + 182225CE1E77E5930081AA4B /* MyFrameLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B71E77E5930081AA4B /* MyFrameLayout.m */; }; + 182225CF1E77E5930081AA4B /* MyFloatLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B91E77E5930081AA4B /* MyFloatLayout.m */; }; + 182225D01E77E5930081AA4B /* MyLayoutPos.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BB1E77E5930081AA4B /* MyLayoutPos.m */; }; + 182225D11E77E5930081AA4B /* MyLayoutSizeClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */; }; + 182225D21E77E5930081AA4B /* MyMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C11E77E5930081AA4B /* MyMaker.m */; }; + 182225D31E77E5930081AA4B /* MyTableLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C31E77E5930081AA4B /* MyTableLayout.m */; }; + 182225D41E77E5930081AA4B /* MyDimeScale.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C41E77E5930081AA4B /* MyDimeScale.m */; }; + 182225D51E77E5930081AA4B /* MyLayoutSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C51E77E5930081AA4B /* MyLayoutSize.m */; }; + 182DB6421EF7876200E2D65D /* MyGridLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182DB6401EF7876200E2D65D /* MyGridLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 182DB6431EF7876200E2D65D /* MyGridLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182DB6411EF7876200E2D65D /* MyGridLayout.m */; }; + 182DB6441EF7876200E2D65D /* MyGridLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182DB6411EF7876200E2D65D /* MyGridLayout.m */; }; + 1897384F1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 1897384E1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m */; }; + 189738511E16330B004F80D6 /* MyLayoutTestCaseBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 189738501E16330B004F80D6 /* MyLayoutTestCaseBase.m */; }; + 18B152341DEDDE5500AD7A1C /* MyLayoutUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */; }; + 18B2CCE81EAF5066001AE0E1 /* MyLinearLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */; }; + 18B2CCEA1EB046AC001AE0E1 /* MyFloatLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */; }; + 18C15AEC1EDF13D700AADEAC /* MyLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 18D684001C4F421400A48BB4 /* MyLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AED1EDF13DE00AADEAC /* MyFlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AB1E77E5930081AA4B /* MyFlowLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AEE1EDF13E500AADEAC /* MyLinearLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AC1E77E5930081AA4B /* MyLinearLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AEF1EDF13E900AADEAC /* MyFloatLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AD1E77E5930081AA4B /* MyFloatLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF01EDF13EF00AADEAC /* MyTableLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AE1E77E5930081AA4B /* MyTableLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF11EDF13F300AADEAC /* MyRelativeLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BE1E77E5930081AA4B /* MyRelativeLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF21EDF13F900AADEAC /* MyPathLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BD1E77E5930081AA4B /* MyPathLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF31EDF13FF00AADEAC /* MyFrameLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BA1E77E5930081AA4B /* MyFrameLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF41EDF140400AADEAC /* MyBaseLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AF1E77E5930081AA4B /* MyBaseLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF51EDF140D00AADEAC /* MyLayoutPos.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B01E77E5930081AA4B /* MyLayoutPos.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF61EDF141000AADEAC /* MyLayoutSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225BC1E77E5930081AA4B /* MyLayoutSize.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF71EDF141600AADEAC /* MyLayoutSizeClass.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */; }; + 18C15AF81EDF141A00AADEAC /* MyMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C21E77E5930081AA4B /* MyMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AF91EDF142000AADEAC /* MyDimeScale.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C71E77E5930081AA4B /* MyDimeScale.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AFA1EDF142300AADEAC /* MyLayoutDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B31E77E5930081AA4B /* MyLayoutDef.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18C15AFB1EDF144B00AADEAC /* MyFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B41E77E5930081AA4B /* MyFlowLayout.m */; }; + 18C15AFC1EDF144B00AADEAC /* MyLinearLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B21E77E5930081AA4B /* MyLinearLayout.m */; }; + 18C15AFD1EDF144B00AADEAC /* MyFloatLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B91E77E5930081AA4B /* MyFloatLayout.m */; }; + 18C15AFE1EDF144B00AADEAC /* MyTableLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C31E77E5930081AA4B /* MyTableLayout.m */; }; + 18C15AFF1EDF144B00AADEAC /* MyRelativeLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B51E77E5930081AA4B /* MyRelativeLayout.m */; }; + 18C15B001EDF144B00AADEAC /* MyPathLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B61E77E5930081AA4B /* MyPathLayout.m */; }; + 18C15B011EDF144B00AADEAC /* MyFrameLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B71E77E5930081AA4B /* MyFrameLayout.m */; }; + 18C15B021EDF144B00AADEAC /* MyBaseLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225B11E77E5930081AA4B /* MyBaseLayout.m */; }; + 18C15B031EDF144B00AADEAC /* MyLayoutPos.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BB1E77E5930081AA4B /* MyLayoutPos.m */; }; + 18C15B041EDF144B00AADEAC /* MyLayoutSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C51E77E5930081AA4B /* MyLayoutSize.m */; }; + 18C15B051EDF144B00AADEAC /* MyLayoutSizeClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */; }; + 18C15B061EDF144B00AADEAC /* MyMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C11E77E5930081AA4B /* MyMaker.m */; }; + 18C15B071EDF144B00AADEAC /* MyDimeScale.m in Sources */ = {isa = PBXBuildFile; fileRef = 182225C41E77E5930081AA4B /* MyDimeScale.m */; }; + 18D3C9111EDF074900D3DE43 /* LLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9041EDF074900D3DE43 /* LLTest1ViewController.m */; }; + 18D3C9121EDF074900D3DE43 /* LLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9061EDF074900D3DE43 /* LLTest2ViewController.m */; }; + 18D3C9131EDF074900D3DE43 /* LLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9081EDF074900D3DE43 /* LLTest3ViewController.m */; }; + 18D3C9141EDF074900D3DE43 /* LLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C90A1EDF074900D3DE43 /* LLTest4ViewController.m */; }; + 18D3C9151EDF074900D3DE43 /* LLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C90C1EDF074900D3DE43 /* LLTest5ViewController.m */; }; + 18D3C9161EDF074900D3DE43 /* LLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C90E1EDF074900D3DE43 /* LLTest6ViewController.m */; }; + 18D3C9171EDF074900D3DE43 /* LLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9101EDF074900D3DE43 /* LLTest7ViewController.m */; }; + 18D3C91C1EDF078200D3DE43 /* FLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9191EDF078200D3DE43 /* FLTest1ViewController.m */; }; + 18D3C91D1EDF078200D3DE43 /* FLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C91B1EDF078200D3DE43 /* FLTest2ViewController.m */; }; + 18D3C9281EDF07A700D3DE43 /* RLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C91F1EDF07A700D3DE43 /* RLTest1ViewController.m */; }; + 18D3C9291EDF07A700D3DE43 /* RLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9211EDF07A700D3DE43 /* RLTest2ViewController.m */; }; + 18D3C92A1EDF07A700D3DE43 /* RLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9231EDF07A700D3DE43 /* RLTest3ViewController.m */; }; + 18D3C92B1EDF07A700D3DE43 /* RLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9251EDF07A700D3DE43 /* RLTest4ViewController.m */; }; + 18D3C92C1EDF07A700D3DE43 /* RLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9271EDF07A700D3DE43 /* RLTest5ViewController.m */; }; + 18D3C9391EDF07C000D3DE43 /* FLLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C92E1EDF07C000D3DE43 /* FLLTest1ViewController.m */; }; + 18D3C93A1EDF07C000D3DE43 /* FLLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9301EDF07C000D3DE43 /* FLLTest2ViewController.m */; }; + 18D3C93B1EDF07C000D3DE43 /* FLLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9321EDF07C000D3DE43 /* FLLTest3ViewController.m */; }; + 18D3C93C1EDF07C000D3DE43 /* FLLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9341EDF07C000D3DE43 /* FLLTest4ViewController.m */; }; + 18D3C93D1EDF07C000D3DE43 /* FLLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9361EDF07C000D3DE43 /* FLLTest5ViewController.m */; }; + 18D3C93E1EDF07C000D3DE43 /* FLLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9381EDF07C000D3DE43 /* FLLTest6ViewController.m */; }; + 18D3C9491EDF07E700D3DE43 /* PLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9401EDF07E700D3DE43 /* PLTest1ViewController.m */; }; + 18D3C94A1EDF07E700D3DE43 /* PLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9421EDF07E700D3DE43 /* PLTest2ViewController.m */; }; + 18D3C94B1EDF07E700D3DE43 /* PLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9441EDF07E700D3DE43 /* PLTest3ViewController.m */; }; + 18D3C94C1EDF07E700D3DE43 /* PLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9461EDF07E700D3DE43 /* PLTest4ViewController.m */; }; + 18D3C94D1EDF07E700D3DE43 /* PLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9481EDF07E700D3DE43 /* PLTest5ViewController.m */; }; + 18D3C95A1EDF07F800D3DE43 /* FOLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C94F1EDF07F800D3DE43 /* FOLTest1ViewController.m */; }; + 18D3C95B1EDF07F800D3DE43 /* FOLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9511EDF07F800D3DE43 /* FOLTest2ViewController.m */; }; + 18D3C95C1EDF07F800D3DE43 /* FOLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9531EDF07F800D3DE43 /* FOLTest3ViewController.m */; }; + 18D3C95D1EDF07F800D3DE43 /* FOLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9551EDF07F800D3DE43 /* FOLTest4ViewController.m */; }; + 18D3C95E1EDF07F800D3DE43 /* FOLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9571EDF07F800D3DE43 /* FOLTest5ViewController.m */; }; + 18D3C95F1EDF07F800D3DE43 /* FOLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9591EDF07F800D3DE43 /* FOLTest6ViewController.m */; }; + 18D3C9661EDF080800D3DE43 /* TLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9611EDF080800D3DE43 /* TLTest1ViewController.m */; }; + 18D3C9671EDF080800D3DE43 /* TLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9631EDF080800D3DE43 /* TLTest2ViewController.m */; }; + 18D3C9681EDF080800D3DE43 /* TLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9651EDF080800D3DE43 /* TLTest3ViewController.m */; }; + 18D3C9711EDF082800D3DE43 /* AllTest1TableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C96A1EDF082800D3DE43 /* AllTest1TableViewCell.m */; }; + 18D3C9721EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C96C1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m */; }; + 18D3C9731EDF082800D3DE43 /* AllTest2TableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C96E1EDF082800D3DE43 /* AllTest2TableViewCell.m */; }; + 18D3C9741EDF082800D3DE43 /* AllTestDataModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9701EDF082800D3DE43 /* AllTestDataModel.m */; }; + 18D3C9851EDF084000D3DE43 /* AllTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9761EDF084000D3DE43 /* AllTest1ViewController.m */; }; + 18D3C9861EDF084000D3DE43 /* AllTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9781EDF084000D3DE43 /* AllTest2ViewController.m */; }; + 18D3C9871EDF084000D3DE43 /* AllTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C97A1EDF084000D3DE43 /* AllTest3ViewController.m */; }; + 18D3C9881EDF084000D3DE43 /* AllTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C97C1EDF084000D3DE43 /* AllTest4ViewController.m */; }; + 18D3C9891EDF084000D3DE43 /* AllTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C97E1EDF084000D3DE43 /* AllTest5ViewController.m */; }; + 18D3C98A1EDF084000D3DE43 /* AllTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9801EDF084000D3DE43 /* AllTest6ViewController.m */; }; + 18D3C98B1EDF084000D3DE43 /* AllTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9821EDF084000D3DE43 /* AllTest7ViewController.m */; }; + 18D3C98C1EDF084000D3DE43 /* AllTest8ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9841EDF084000D3DE43 /* AllTest8ViewController.m */; }; + 18D3C9931EDF08F800D3DE43 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C98E1EDF08F800D3DE43 /* ViewController.m */; }; + 18D3C9941EDF08F800D3DE43 /* YYFPSLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9901EDF08F800D3DE43 /* YYFPSLabel.m */; }; + 18D3C9951EDF08F800D3DE43 /* YYWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9921EDF08F800D3DE43 /* YYWeakProxy.m */; }; + 18D3C99B1EDF09BE00D3DE43 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9981EDF09BE00D3DE43 /* AppDelegate.m */; }; + 18D3C99C1EDF09BE00D3DE43 /* CFTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C99A1EDF09BE00D3DE43 /* CFTool.m */; }; + 18D3C9B41EDF0A5A00D3DE43 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9A21EDF0A5A00D3DE43 /* LaunchScreen.xib */; }; + 18D3C9B51EDF0A5A00D3DE43 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9A41EDF0A5A00D3DE43 /* Localizable.strings */; }; + 18D3C9B61EDF0A5A00D3DE43 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9A61EDF0A5A00D3DE43 /* Images.xcassets */; }; + 18D3C9B81EDF0A5A00D3DE43 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3C9A81EDF0A5A00D3DE43 /* main.m */; }; + 18D3C9BB1EDF0A5A00D3DE43 /* LaunchScreen.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9AE1EDF0A5A00D3DE43 /* LaunchScreen.strings */; }; + 18D3C9BC1EDF0A5A00D3DE43 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9B01EDF0A5A00D3DE43 /* Localizable.strings */; }; + 18D3C9CF1EDF0AB500D3DE43 /* fl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9BE1EDF0AB500D3DE43 /* fl.png */; }; + 18D3C9D01EDF0AB500D3DE43 /* fll.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9BF1EDF0AB500D3DE43 /* fll.png */; }; + 18D3C9D11EDF0AB500D3DE43 /* flo.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C01EDF0AB500D3DE43 /* flo.png */; }; + 18D3C9D21EDF0AB500D3DE43 /* layoutdemo1.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C11EDF0AB500D3DE43 /* layoutdemo1.gif */; }; + 18D3C9D31EDF0AB500D3DE43 /* layoutdemo2.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C21EDF0AB500D3DE43 /* layoutdemo2.gif */; }; + 18D3C9D41EDF0AB500D3DE43 /* layoutdemo3.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C31EDF0AB500D3DE43 /* layoutdemo3.gif */; }; + 18D3C9D51EDF0AB500D3DE43 /* layoutdemo4.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C41EDF0AB500D3DE43 /* layoutdemo4.gif */; }; + 18D3C9D61EDF0AB500D3DE43 /* layoutdemo5.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C51EDF0AB500D3DE43 /* layoutdemo5.gif */; }; + 18D3C9D71EDF0AB500D3DE43 /* layoutdemo6.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C61EDF0AB500D3DE43 /* layoutdemo6.gif */; }; + 18D3C9D81EDF0AB500D3DE43 /* layoutdemo7.gif in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C71EDF0AB500D3DE43 /* layoutdemo7.gif */; }; + 18D3C9D91EDF0AB500D3DE43 /* ll.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C81EDF0AB500D3DE43 /* ll.png */; }; + 18D3C9DA1EDF0AB500D3DE43 /* MyLayout.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9C91EDF0AB500D3DE43 /* MyLayout.png */; }; + 18D3C9DB1EDF0AB500D3DE43 /* MyLayoutClass.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CA1EDF0AB500D3DE43 /* MyLayoutClass.png */; }; + 18D3C9DC1EDF0AB500D3DE43 /* MyLayoutP.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CB1EDF0AB500D3DE43 /* MyLayoutP.png */; }; + 18D3C9DD1EDF0AB500D3DE43 /* pl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CC1EDF0AB500D3DE43 /* pl.png */; }; + 18D3C9DE1EDF0AB500D3DE43 /* rl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CD1EDF0AB500D3DE43 /* rl.png */; }; + 18D3C9DF1EDF0AB500D3DE43 /* tl.png in Resources */ = {isa = PBXBuildFile; fileRef = 18D3C9CE1EDF0AB500D3DE43 /* tl.png */; }; + 18D684591C4F423400A48BB4 /* MyLayoutTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D684551C4F423400A48BB4 /* MyLayoutTests.m */; }; + 200A26D91FA8A90300B06E7B /* AllTest9ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */; }; + 200A26DC1FA96B2400B06E7B /* AllTest9CollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */; }; + 204DC321209D5A8700F6CB57 /* TLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */; }; + 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */ = {isa = PBXBuildFile; fileRef = 205642841F4CFF9B00E8BDDE /* MyBorderline.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 205642871F4CFF9B00E8BDDE /* MyBorderline.m in Sources */ = {isa = PBXBuildFile; fileRef = 205642851F4CFF9B00E8BDDE /* MyBorderline.m */; }; + 205642881F4CFFB600E8BDDE /* MyBorderline.m in Sources */ = {isa = PBXBuildFile; fileRef = 205642851F4CFF9B00E8BDDE /* MyBorderline.m */; }; + 2056430A1F4E53CD00E8BDDE /* MyGridNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 205643081F4E53CD00E8BDDE /* MyGridNode.h */; }; + 2056430B1F4E53CD00E8BDDE /* MyGridNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643091F4E53CD00E8BDDE /* MyGridNode.m */; }; + 2056430C1F4E8B1E00E8BDDE /* MyGridNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643091F4E53CD00E8BDDE /* MyGridNode.m */; }; + 205643131F51C7EB00E8BDDE /* GLTest2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643121F51C7EB00E8BDDE /* GLTest2ViewController.m */; }; + 205643161F55A03000E8BDDE /* MyLayoutMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 205643141F55A03000E8BDDE /* MyLayoutMath.h */; }; + 205643171F55A03000E8BDDE /* MyLayoutMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643151F55A03000E8BDDE /* MyLayoutMath.m */; }; + 205643181F55A16400E8BDDE /* MyLayoutMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643151F55A03000E8BDDE /* MyLayoutMath.m */; }; + 205CFA8E1F49BD1C00355489 /* GLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */; }; + 205E0C5F20B90347001A8B99 /* MyGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = 205642891F4D013D00E8BDDE /* MyGrid.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 205E0C6020B907CC001A8B99 /* MyLayoutPosInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */; }; + 205E0C6120B907D1001A8B99 /* MyLayoutSizeInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C81E77E5930081AA4B /* MyLayoutSizeInner.h */; }; + 205E0C6220B907DB001A8B99 /* MyLayoutInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225B81E77E5930081AA4B /* MyLayoutInner.h */; }; + 205E0C6320B907EC001A8B99 /* MyLayoutDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */; }; + 205F9EBA1F7AA5710034732C /* gl.png in Resources */ = {isa = PBXBuildFile; fileRef = 205F9EB91F7AA5710034732C /* gl.png */; }; + 205F9EBC1F7AA6510034732C /* all.png in Resources */ = {isa = PBXBuildFile; fileRef = 205F9EBB1F7AA6510034732C /* all.png */; }; + 2075CC3220A0B2A400BA6F65 /* FLLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */; }; + 208157BD1F586AA700E945B6 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157BC1F586AA700E945B6 /* DetailViewController.m */; }; + 208157C31F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; + 208157C41F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; + 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */ = {isa = PBXBuildFile; fileRef = 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */; }; + 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */; }; + 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F783551F60399700BE5B31 /* GLTest3ViewController.m */; }; + 4411977B1F6AE78E00C22557 /* GridLayoutDemo5.json in Resources */ = {isa = PBXBuildFile; fileRef = 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */; }; + 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */; }; + 44EBDA8C1F619A6300B47CBD /* GLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */; }; + 44EBDA8E1F619C9000B47CBD /* GridLayoutDemo4.json in Resources */ = {isa = PBXBuildFile; fileRef = 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */; }; + 6740E1F820A52D9E00AFBC5A /* AllTest10ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */; }; + 6740E1FB20A52DA900AFBC5A /* AllTest10Model.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */; }; + 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */; }; + 6740E20120A52DC100AFBC5A /* AllTest10Cell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 184082A71B2C46E8003F378B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 184082851B2C46E8003F378B /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1840828C1B2C46E8003F378B; - remoteInfo = MyLinearLayoutDemo; - }; - 18B152361DEDDE5500AD7A1C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 184082851B2C46E8003F378B /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1840828C1B2C46E8003F378B; - remoteInfo = MyLayout; - }; + 184082A71B2C46E8003F378B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 184082851B2C46E8003F378B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1840828C1B2C46E8003F378B; + remoteInfo = MyLinearLayoutDemo; + }; + 18B152361DEDDE5500AD7A1C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 184082851B2C46E8003F378B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1840828C1B2C46E8003F378B; + remoteInfo = MyLayout; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 180BD8A01EA9EF9A00C6980B /* MyFrameLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyFrameLayoutTestCase.m; sourceTree = ""; }; - 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutPerformanceTestCase.m; sourceTree = ""; }; - 181836941EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyNoLayoutSuperviewTestCase.m; sourceTree = ""; }; - 181A10A91EDF11FF00996203 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/FLLTest2ViewController.xib; sourceTree = ""; }; - 181A10AB1EDF120E00996203 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "zh-Hans"; path = "zh-Hans.lproj/FLLTest2ViewController.xib"; sourceTree = ""; }; - 181A10AD1EDF123800996203 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/FOLTest1ViewController.xib; sourceTree = ""; }; - 181A10AF1EDF124400996203 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "zh-Hans"; path = "zh-Hans.lproj/FOLTest1ViewController.xib"; sourceTree = ""; }; - 181A10B51EDF12CF00996203 /* MyLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MyLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 182225AB1E77E5930081AA4B /* MyFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyFlowLayout.h; sourceTree = ""; }; - 182225AC1E77E5930081AA4B /* MyLinearLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLinearLayout.h; sourceTree = ""; }; - 182225AD1E77E5930081AA4B /* MyFloatLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyFloatLayout.h; sourceTree = ""; }; - 182225AE1E77E5930081AA4B /* MyTableLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MyTableLayout.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 182225AF1E77E5930081AA4B /* MyBaseLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MyBaseLayout.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 182225B01E77E5930081AA4B /* MyLayoutPos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutPos.h; sourceTree = ""; }; - 182225B11E77E5930081AA4B /* MyBaseLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyBaseLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 182225B21E77E5930081AA4B /* MyLinearLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyLinearLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 182225B31E77E5930081AA4B /* MyLayoutDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutDef.h; sourceTree = ""; }; - 182225B41E77E5930081AA4B /* MyFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFlowLayout.m; sourceTree = ""; }; - 182225B51E77E5930081AA4B /* MyRelativeLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyRelativeLayout.m; sourceTree = ""; }; - 182225B61E77E5930081AA4B /* MyPathLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyPathLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 182225B71E77E5930081AA4B /* MyFrameLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFrameLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 182225B81E77E5930081AA4B /* MyLayoutInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutInner.h; sourceTree = ""; }; - 182225B91E77E5930081AA4B /* MyFloatLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFloatLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 182225BA1E77E5930081AA4B /* MyFrameLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyFrameLayout.h; sourceTree = ""; }; - 182225BB1E77E5930081AA4B /* MyLayoutPos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutPos.m; sourceTree = ""; }; - 182225BC1E77E5930081AA4B /* MyLayoutSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutSize.h; sourceTree = ""; }; - 182225BD1E77E5930081AA4B /* MyPathLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyPathLayout.h; sourceTree = ""; }; - 182225BE1E77E5930081AA4B /* MyRelativeLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyRelativeLayout.h; sourceTree = ""; }; - 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyLayoutSizeClass.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutSizeClass.h; sourceTree = ""; }; - 182225C11E77E5930081AA4B /* MyMaker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyMaker.m; sourceTree = ""; }; - 182225C21E77E5930081AA4B /* MyMaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyMaker.h; sourceTree = ""; }; - 182225C31E77E5930081AA4B /* MyTableLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyTableLayout.m; sourceTree = ""; }; - 182225C41E77E5930081AA4B /* MyDimeScale.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyDimeScale.m; sourceTree = ""; }; - 182225C51E77E5930081AA4B /* MyLayoutSize.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutSize.m; sourceTree = ""; }; - 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutPosInner.h; sourceTree = ""; }; - 182225C71E77E5930081AA4B /* MyDimeScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyDimeScale.h; sourceTree = ""; }; - 182225C81E77E5930081AA4B /* MyLayoutSizeInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutSizeInner.h; sourceTree = ""; }; - 182DB6401EF7876200E2D65D /* MyGridLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyGridLayout.h; sourceTree = ""; }; - 182DB6411EF7876200E2D65D /* MyGridLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyGridLayout.m; sourceTree = ""; }; - 1840828D1B2C46E8003F378B /* MyLayoutDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MyLayoutDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 184082A61B2C46E8003F378B /* MyLayout.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MyLayout.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 1897384E1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyRelativeLayoutTestCase.m; sourceTree = ""; }; - 189738501E16330B004F80D6 /* MyLayoutTestCaseBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutTestCaseBase.m; sourceTree = ""; }; - 189738521E16340D004F80D6 /* MyLayoutTestCaseBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyLayoutTestCaseBase.h; sourceTree = ""; }; - 18B152311DEDDE5500AD7A1C /* MyLayoutUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MyLayoutUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyLayoutUITests.m; sourceTree = ""; }; - 18B152351DEDDE5500AD7A1C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLinearLayoutTestCase.m; sourceTree = ""; }; - 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyFloatLayoutTestCase.m; sourceTree = ""; }; - 18C15AEA1EDF133200AADEAC /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 18D3C9031EDF074900D3DE43 /* LLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest1ViewController.h; sourceTree = ""; }; - 18D3C9041EDF074900D3DE43 /* LLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest1ViewController.m; sourceTree = ""; }; - 18D3C9051EDF074900D3DE43 /* LLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest2ViewController.h; sourceTree = ""; }; - 18D3C9061EDF074900D3DE43 /* LLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest2ViewController.m; sourceTree = ""; }; - 18D3C9071EDF074900D3DE43 /* LLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest3ViewController.h; sourceTree = ""; }; - 18D3C9081EDF074900D3DE43 /* LLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest3ViewController.m; sourceTree = ""; }; - 18D3C9091EDF074900D3DE43 /* LLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest4ViewController.h; sourceTree = ""; }; - 18D3C90A1EDF074900D3DE43 /* LLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest4ViewController.m; sourceTree = ""; }; - 18D3C90B1EDF074900D3DE43 /* LLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest5ViewController.h; sourceTree = ""; }; - 18D3C90C1EDF074900D3DE43 /* LLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest5ViewController.m; sourceTree = ""; }; - 18D3C90D1EDF074900D3DE43 /* LLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest6ViewController.h; sourceTree = ""; }; - 18D3C90E1EDF074900D3DE43 /* LLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest6ViewController.m; sourceTree = ""; }; - 18D3C90F1EDF074900D3DE43 /* LLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest7ViewController.h; sourceTree = ""; }; - 18D3C9101EDF074900D3DE43 /* LLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = LLTest7ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C9181EDF078200D3DE43 /* FLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLTest1ViewController.h; sourceTree = ""; }; - 18D3C9191EDF078200D3DE43 /* FLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLTest1ViewController.m; sourceTree = ""; }; - 18D3C91A1EDF078200D3DE43 /* FLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLTest2ViewController.h; sourceTree = ""; }; - 18D3C91B1EDF078200D3DE43 /* FLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLTest2ViewController.m; sourceTree = ""; }; - 18D3C91E1EDF07A700D3DE43 /* RLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest1ViewController.h; sourceTree = ""; }; - 18D3C91F1EDF07A700D3DE43 /* RLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest1ViewController.m; sourceTree = ""; }; - 18D3C9201EDF07A700D3DE43 /* RLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest2ViewController.h; sourceTree = ""; }; - 18D3C9211EDF07A700D3DE43 /* RLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest2ViewController.m; sourceTree = ""; }; - 18D3C9221EDF07A700D3DE43 /* RLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest3ViewController.h; sourceTree = ""; }; - 18D3C9231EDF07A700D3DE43 /* RLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest3ViewController.m; sourceTree = ""; }; - 18D3C9241EDF07A700D3DE43 /* RLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest4ViewController.h; sourceTree = ""; }; - 18D3C9251EDF07A700D3DE43 /* RLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest4ViewController.m; sourceTree = ""; }; - 18D3C9261EDF07A700D3DE43 /* RLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest5ViewController.h; sourceTree = ""; }; - 18D3C9271EDF07A700D3DE43 /* RLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest5ViewController.m; sourceTree = ""; }; - 18D3C92D1EDF07C000D3DE43 /* FLLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest1ViewController.h; sourceTree = ""; }; - 18D3C92E1EDF07C000D3DE43 /* FLLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest1ViewController.m; sourceTree = ""; }; - 18D3C92F1EDF07C000D3DE43 /* FLLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest2ViewController.h; sourceTree = ""; }; - 18D3C9301EDF07C000D3DE43 /* FLLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest2ViewController.m; sourceTree = ""; }; - 18D3C9311EDF07C000D3DE43 /* FLLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest3ViewController.h; sourceTree = ""; }; - 18D3C9321EDF07C000D3DE43 /* FLLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest3ViewController.m; sourceTree = ""; }; - 18D3C9331EDF07C000D3DE43 /* FLLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest4ViewController.h; sourceTree = ""; }; - 18D3C9341EDF07C000D3DE43 /* FLLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest4ViewController.m; sourceTree = ""; }; - 18D3C9351EDF07C000D3DE43 /* FLLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest5ViewController.h; sourceTree = ""; }; - 18D3C9361EDF07C000D3DE43 /* FLLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest5ViewController.m; sourceTree = ""; }; - 18D3C9371EDF07C000D3DE43 /* FLLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest6ViewController.h; sourceTree = ""; }; - 18D3C9381EDF07C000D3DE43 /* FLLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest6ViewController.m; sourceTree = ""; }; - 18D3C93F1EDF07E700D3DE43 /* PLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest1ViewController.h; sourceTree = ""; }; - 18D3C9401EDF07E700D3DE43 /* PLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest1ViewController.m; sourceTree = ""; }; - 18D3C9411EDF07E700D3DE43 /* PLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest2ViewController.h; sourceTree = ""; }; - 18D3C9421EDF07E700D3DE43 /* PLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest2ViewController.m; sourceTree = ""; }; - 18D3C9431EDF07E700D3DE43 /* PLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest3ViewController.h; sourceTree = ""; }; - 18D3C9441EDF07E700D3DE43 /* PLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest3ViewController.m; sourceTree = ""; }; - 18D3C9451EDF07E700D3DE43 /* PLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest4ViewController.h; sourceTree = ""; }; - 18D3C9461EDF07E700D3DE43 /* PLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = PLTest4ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C9471EDF07E700D3DE43 /* PLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest5ViewController.h; sourceTree = ""; }; - 18D3C9481EDF07E700D3DE43 /* PLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest5ViewController.m; sourceTree = ""; }; - 18D3C94E1EDF07F800D3DE43 /* FOLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest1ViewController.h; sourceTree = ""; }; - 18D3C94F1EDF07F800D3DE43 /* FOLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest1ViewController.m; sourceTree = ""; }; - 18D3C9501EDF07F800D3DE43 /* FOLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest2ViewController.h; sourceTree = ""; }; - 18D3C9511EDF07F800D3DE43 /* FOLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest2ViewController.m; sourceTree = ""; }; - 18D3C9521EDF07F800D3DE43 /* FOLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest3ViewController.h; sourceTree = ""; }; - 18D3C9531EDF07F800D3DE43 /* FOLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest3ViewController.m; sourceTree = ""; }; - 18D3C9541EDF07F800D3DE43 /* FOLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest4ViewController.h; sourceTree = ""; }; - 18D3C9551EDF07F800D3DE43 /* FOLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest4ViewController.m; sourceTree = ""; }; - 18D3C9561EDF07F800D3DE43 /* FOLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest5ViewController.h; sourceTree = ""; }; - 18D3C9571EDF07F800D3DE43 /* FOLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest5ViewController.m; sourceTree = ""; }; - 18D3C9581EDF07F800D3DE43 /* FOLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest6ViewController.h; sourceTree = ""; }; - 18D3C9591EDF07F800D3DE43 /* FOLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest6ViewController.m; sourceTree = ""; }; - 18D3C9601EDF080800D3DE43 /* TLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest1ViewController.h; sourceTree = ""; }; - 18D3C9611EDF080800D3DE43 /* TLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = TLTest1ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C9621EDF080800D3DE43 /* TLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest2ViewController.h; sourceTree = ""; }; - 18D3C9631EDF080800D3DE43 /* TLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = TLTest2ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C9641EDF080800D3DE43 /* TLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest3ViewController.h; sourceTree = ""; }; - 18D3C9651EDF080800D3DE43 /* TLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLTest3ViewController.m; sourceTree = ""; }; - 18D3C9691EDF082800D3DE43 /* AllTest1TableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1TableViewCell.h; sourceTree = ""; }; - 18D3C96A1EDF082800D3DE43 /* AllTest1TableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1TableViewCell.m; sourceTree = ""; }; - 18D3C96B1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1TableViewHeaderFooterView.h; sourceTree = ""; }; - 18D3C96C1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1TableViewHeaderFooterView.m; sourceTree = ""; }; - 18D3C96D1EDF082800D3DE43 /* AllTest2TableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest2TableViewCell.h; sourceTree = ""; }; - 18D3C96E1EDF082800D3DE43 /* AllTest2TableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AllTest2TableViewCell.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C96F1EDF082800D3DE43 /* AllTestDataModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTestDataModel.h; sourceTree = ""; }; - 18D3C9701EDF082800D3DE43 /* AllTestDataModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTestDataModel.m; sourceTree = ""; }; - 18D3C9751EDF084000D3DE43 /* AllTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1ViewController.h; sourceTree = ""; }; - 18D3C9761EDF084000D3DE43 /* AllTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1ViewController.m; sourceTree = ""; }; - 18D3C9771EDF084000D3DE43 /* AllTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest2ViewController.h; sourceTree = ""; }; - 18D3C9781EDF084000D3DE43 /* AllTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest2ViewController.m; sourceTree = ""; }; - 18D3C9791EDF084000D3DE43 /* AllTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest3ViewController.h; sourceTree = ""; }; - 18D3C97A1EDF084000D3DE43 /* AllTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AllTest3ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C97B1EDF084000D3DE43 /* AllTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest4ViewController.h; sourceTree = ""; }; - 18D3C97C1EDF084000D3DE43 /* AllTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest4ViewController.m; sourceTree = ""; }; - 18D3C97D1EDF084000D3DE43 /* AllTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest5ViewController.h; sourceTree = ""; }; - 18D3C97E1EDF084000D3DE43 /* AllTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest5ViewController.m; sourceTree = ""; }; - 18D3C97F1EDF084000D3DE43 /* AllTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest6ViewController.h; sourceTree = ""; }; - 18D3C9801EDF084000D3DE43 /* AllTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest6ViewController.m; sourceTree = ""; }; - 18D3C9811EDF084000D3DE43 /* AllTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest7ViewController.h; sourceTree = ""; }; - 18D3C9821EDF084000D3DE43 /* AllTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AllTest7ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 18D3C9831EDF084000D3DE43 /* AllTest8ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest8ViewController.h; sourceTree = ""; }; - 18D3C9841EDF084000D3DE43 /* AllTest8ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest8ViewController.m; sourceTree = ""; }; - 18D3C98D1EDF08F800D3DE43 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; - 18D3C98E1EDF08F800D3DE43 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; - 18D3C98F1EDF08F800D3DE43 /* YYFPSLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYFPSLabel.h; sourceTree = ""; }; - 18D3C9901EDF08F800D3DE43 /* YYFPSLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYFPSLabel.m; sourceTree = ""; }; - 18D3C9911EDF08F800D3DE43 /* YYWeakProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWeakProxy.h; sourceTree = ""; }; - 18D3C9921EDF08F800D3DE43 /* YYWeakProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWeakProxy.m; sourceTree = ""; }; - 18D3C9971EDF09BE00D3DE43 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 18D3C9981EDF09BE00D3DE43 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 18D3C9991EDF09BE00D3DE43 /* CFTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFTool.h; sourceTree = ""; }; - 18D3C99A1EDF09BE00D3DE43 /* CFTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CFTool.m; sourceTree = ""; }; - 18D3C9A31EDF0A5A00D3DE43 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = LaunchScreen.xib; sourceTree = ""; }; - 18D3C9A51EDF0A5A00D3DE43 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Localizable.strings; sourceTree = ""; }; - 18D3C9A61EDF0A5A00D3DE43 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 18D3C9A71EDF0A5A00D3DE43 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 18D3C9A81EDF0A5A00D3DE43 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 18D3C9AF1EDF0A5A00D3DE43 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = LaunchScreen.strings; sourceTree = ""; }; - 18D3C9B11EDF0A5A00D3DE43 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = Localizable.strings; sourceTree = ""; }; - 18D3C9BE1EDF0AB500D3DE43 /* fl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = fl.png; sourceTree = ""; }; - 18D3C9BF1EDF0AB500D3DE43 /* fll.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = fll.png; sourceTree = ""; }; - 18D3C9C01EDF0AB500D3DE43 /* flo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flo.png; sourceTree = ""; }; - 18D3C9C11EDF0AB500D3DE43 /* layoutdemo1.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo1.gif; sourceTree = ""; }; - 18D3C9C21EDF0AB500D3DE43 /* layoutdemo2.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo2.gif; sourceTree = ""; }; - 18D3C9C31EDF0AB500D3DE43 /* layoutdemo3.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo3.gif; sourceTree = ""; }; - 18D3C9C41EDF0AB500D3DE43 /* layoutdemo4.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo4.gif; sourceTree = ""; }; - 18D3C9C51EDF0AB500D3DE43 /* layoutdemo5.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo5.gif; sourceTree = ""; }; - 18D3C9C61EDF0AB500D3DE43 /* layoutdemo6.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo6.gif; sourceTree = ""; }; - 18D3C9C71EDF0AB500D3DE43 /* layoutdemo7.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo7.gif; sourceTree = ""; }; - 18D3C9C81EDF0AB500D3DE43 /* ll.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ll.png; sourceTree = ""; }; - 18D3C9C91EDF0AB500D3DE43 /* MyLayout.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MyLayout.png; sourceTree = ""; }; - 18D3C9CA1EDF0AB500D3DE43 /* MyLayoutClass.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MyLayoutClass.png; sourceTree = ""; }; - 18D3C9CB1EDF0AB500D3DE43 /* MyLayoutP.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MyLayoutP.png; sourceTree = ""; }; - 18D3C9CC1EDF0AB500D3DE43 /* pl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = pl.png; sourceTree = ""; }; - 18D3C9CD1EDF0AB500D3DE43 /* rl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = rl.png; sourceTree = ""; }; - 18D3C9CE1EDF0AB500D3DE43 /* tl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tl.png; sourceTree = ""; }; - 18D684001C4F421400A48BB4 /* MyLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayout.h; sourceTree = ""; }; - 18D684541C4F423400A48BB4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 18D684551C4F423400A48BB4 /* MyLayoutTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutTests.m; sourceTree = ""; }; - 200A26D71FA8A90300B06E7B /* AllTest9ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AllTest9ViewController.h; sourceTree = ""; }; - 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest9ViewController.m; sourceTree = ""; }; - 200A26DA1FA96B2400B06E7B /* AllTest9CollectionViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AllTest9CollectionViewCell.h; sourceTree = ""; }; - 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest9CollectionViewCell.m; sourceTree = ""; }; - 2043D5DB20995DF800276C68 /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = System/Library/Frameworks/CoreBluetooth.framework; sourceTree = SDKROOT; }; - 204DC31F209D5A7C00F6CB57 /* TLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest4ViewController.h; sourceTree = ""; }; - 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLTest4ViewController.m; sourceTree = ""; }; - 205642841F4CFF9B00E8BDDE /* MyBorderline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyBorderline.h; sourceTree = ""; }; - 205642851F4CFF9B00E8BDDE /* MyBorderline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyBorderline.m; sourceTree = ""; }; - 205642891F4D013D00E8BDDE /* MyGrid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyGrid.h; sourceTree = ""; }; - 205643081F4E53CD00E8BDDE /* MyGridNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyGridNode.h; sourceTree = ""; }; - 205643091F4E53CD00E8BDDE /* MyGridNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyGridNode.m; sourceTree = ""; }; - 205643111F51C7DF00E8BDDE /* GLTest2ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GLTest2ViewController.h; sourceTree = ""; }; - 205643121F51C7EB00E8BDDE /* GLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GLTest2ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 205643141F55A03000E8BDDE /* MyLayoutMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutMath.h; sourceTree = ""; }; - 205643151F55A03000E8BDDE /* MyLayoutMath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutMath.m; sourceTree = ""; }; - 205CFA8C1F49BD1C00355489 /* GLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest1ViewController.h; sourceTree = ""; }; - 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GLTest1ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 205F9EB91F7AA5710034732C /* gl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = gl.png; sourceTree = ""; }; - 205F9EBB1F7AA6510034732C /* all.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = all.png; sourceTree = ""; }; - 2075CC3020A0B29700BA6F65 /* FLLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest7ViewController.h; sourceTree = ""; }; - 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest7ViewController.m; sourceTree = ""; }; - 208157BB1F586A9900E945B6 /* DetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = ""; }; - 208157BC1F586AA700E945B6 /* DetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; - 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutDelegate.h; sourceTree = ""; }; - 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutDelegate.m; sourceTree = ""; }; - 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo8.gif; sourceTree = ""; }; - 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest7ViewController.h; sourceTree = ""; }; - 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest7ViewController.m; sourceTree = ""; }; - 20F783541F60398C00BE5B31 /* GLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest3ViewController.h; sourceTree = ""; }; - 20F783551F60399700BE5B31 /* GLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest3ViewController.m; sourceTree = ""; }; - 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo5.json; sourceTree = ""; }; - 444B718F1F6A3E3F00331872 /* GLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest5ViewController.h; sourceTree = ""; }; - 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest5ViewController.m; sourceTree = ""; }; - 44EBDA8A1F619A6300B47CBD /* GLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest4ViewController.h; sourceTree = ""; }; - 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest4ViewController.m; sourceTree = ""; }; - 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo4.json; sourceTree = ""; }; - 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10ViewController.h; sourceTree = ""; }; - 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10ViewController.m; sourceTree = ""; }; - 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10Model.m; sourceTree = ""; }; - 6740E1FA20A52DA900AFBC5A /* AllTest10Model.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10Model.h; sourceTree = ""; }; - 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10HeaderView.m; sourceTree = ""; }; - 6740E1FD20A52DB000AFBC5A /* AllTest10HeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10HeaderView.h; sourceTree = ""; }; - 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10Cell.m; sourceTree = ""; }; - 6740E20020A52DC100AFBC5A /* AllTest10Cell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10Cell.h; sourceTree = ""; }; + 180BD8A01EA9EF9A00C6980B /* MyFrameLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyFrameLayoutTestCase.m; sourceTree = ""; }; + 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutPerformanceTestCase.m; sourceTree = ""; }; + 181836941EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyNoLayoutSuperviewTestCase.m; sourceTree = ""; }; + 181A10A91EDF11FF00996203 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/FLLTest2ViewController.xib; sourceTree = ""; }; + 181A10AB1EDF120E00996203 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "zh-Hans"; path = "zh-Hans.lproj/FLLTest2ViewController.xib"; sourceTree = ""; }; + 181A10AD1EDF123800996203 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/FOLTest1ViewController.xib; sourceTree = ""; }; + 181A10AF1EDF124400996203 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "zh-Hans"; path = "zh-Hans.lproj/FOLTest1ViewController.xib"; sourceTree = ""; }; + 181A10B51EDF12CF00996203 /* MyLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MyLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 182225AB1E77E5930081AA4B /* MyFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyFlowLayout.h; sourceTree = ""; }; + 182225AC1E77E5930081AA4B /* MyLinearLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLinearLayout.h; sourceTree = ""; }; + 182225AD1E77E5930081AA4B /* MyFloatLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyFloatLayout.h; sourceTree = ""; }; + 182225AE1E77E5930081AA4B /* MyTableLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MyTableLayout.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 182225AF1E77E5930081AA4B /* MyBaseLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MyBaseLayout.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 182225B01E77E5930081AA4B /* MyLayoutPos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutPos.h; sourceTree = ""; }; + 182225B11E77E5930081AA4B /* MyBaseLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyBaseLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225B21E77E5930081AA4B /* MyLinearLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyLinearLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225B31E77E5930081AA4B /* MyLayoutDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutDef.h; sourceTree = ""; }; + 182225B41E77E5930081AA4B /* MyFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFlowLayout.m; sourceTree = ""; }; + 182225B51E77E5930081AA4B /* MyRelativeLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyRelativeLayout.m; sourceTree = ""; }; + 182225B61E77E5930081AA4B /* MyPathLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyPathLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225B71E77E5930081AA4B /* MyFrameLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFrameLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225B81E77E5930081AA4B /* MyLayoutInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutInner.h; sourceTree = ""; }; + 182225B91E77E5930081AA4B /* MyFloatLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFloatLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225BA1E77E5930081AA4B /* MyFrameLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyFrameLayout.h; sourceTree = ""; }; + 182225BB1E77E5930081AA4B /* MyLayoutPos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutPos.m; sourceTree = ""; }; + 182225BC1E77E5930081AA4B /* MyLayoutSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutSize.h; sourceTree = ""; }; + 182225BD1E77E5930081AA4B /* MyPathLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyPathLayout.h; sourceTree = ""; }; + 182225BE1E77E5930081AA4B /* MyRelativeLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyRelativeLayout.h; sourceTree = ""; }; + 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyLayoutSizeClass.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutSizeClass.h; sourceTree = ""; }; + 182225C11E77E5930081AA4B /* MyMaker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyMaker.m; sourceTree = ""; }; + 182225C21E77E5930081AA4B /* MyMaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyMaker.h; sourceTree = ""; }; + 182225C31E77E5930081AA4B /* MyTableLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyTableLayout.m; sourceTree = ""; }; + 182225C41E77E5930081AA4B /* MyDimeScale.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyDimeScale.m; sourceTree = ""; }; + 182225C51E77E5930081AA4B /* MyLayoutSize.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutSize.m; sourceTree = ""; }; + 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutPosInner.h; sourceTree = ""; }; + 182225C71E77E5930081AA4B /* MyDimeScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyDimeScale.h; sourceTree = ""; }; + 182225C81E77E5930081AA4B /* MyLayoutSizeInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutSizeInner.h; sourceTree = ""; }; + 182DB6401EF7876200E2D65D /* MyGridLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyGridLayout.h; sourceTree = ""; }; + 182DB6411EF7876200E2D65D /* MyGridLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyGridLayout.m; sourceTree = ""; }; + 1840828D1B2C46E8003F378B /* MyLayoutDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MyLayoutDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 184082A61B2C46E8003F378B /* MyLayout.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MyLayout.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1897384E1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyRelativeLayoutTestCase.m; sourceTree = ""; }; + 189738501E16330B004F80D6 /* MyLayoutTestCaseBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutTestCaseBase.m; sourceTree = ""; }; + 189738521E16340D004F80D6 /* MyLayoutTestCaseBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyLayoutTestCaseBase.h; sourceTree = ""; }; + 18B152311DEDDE5500AD7A1C /* MyLayoutUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MyLayoutUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyLayoutUITests.m; sourceTree = ""; }; + 18B152351DEDDE5500AD7A1C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLinearLayoutTestCase.m; sourceTree = ""; }; + 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyFloatLayoutTestCase.m; sourceTree = ""; }; + 18C15AEA1EDF133200AADEAC /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 18D3C9031EDF074900D3DE43 /* LLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest1ViewController.h; sourceTree = ""; }; + 18D3C9041EDF074900D3DE43 /* LLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest1ViewController.m; sourceTree = ""; }; + 18D3C9051EDF074900D3DE43 /* LLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest2ViewController.h; sourceTree = ""; }; + 18D3C9061EDF074900D3DE43 /* LLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest2ViewController.m; sourceTree = ""; }; + 18D3C9071EDF074900D3DE43 /* LLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest3ViewController.h; sourceTree = ""; }; + 18D3C9081EDF074900D3DE43 /* LLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest3ViewController.m; sourceTree = ""; }; + 18D3C9091EDF074900D3DE43 /* LLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest4ViewController.h; sourceTree = ""; }; + 18D3C90A1EDF074900D3DE43 /* LLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest4ViewController.m; sourceTree = ""; }; + 18D3C90B1EDF074900D3DE43 /* LLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest5ViewController.h; sourceTree = ""; }; + 18D3C90C1EDF074900D3DE43 /* LLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest5ViewController.m; sourceTree = ""; }; + 18D3C90D1EDF074900D3DE43 /* LLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest6ViewController.h; sourceTree = ""; }; + 18D3C90E1EDF074900D3DE43 /* LLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest6ViewController.m; sourceTree = ""; }; + 18D3C90F1EDF074900D3DE43 /* LLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest7ViewController.h; sourceTree = ""; }; + 18D3C9101EDF074900D3DE43 /* LLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = LLTest7ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C9181EDF078200D3DE43 /* FLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLTest1ViewController.h; sourceTree = ""; }; + 18D3C9191EDF078200D3DE43 /* FLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLTest1ViewController.m; sourceTree = ""; }; + 18D3C91A1EDF078200D3DE43 /* FLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLTest2ViewController.h; sourceTree = ""; }; + 18D3C91B1EDF078200D3DE43 /* FLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLTest2ViewController.m; sourceTree = ""; }; + 18D3C91E1EDF07A700D3DE43 /* RLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest1ViewController.h; sourceTree = ""; }; + 18D3C91F1EDF07A700D3DE43 /* RLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest1ViewController.m; sourceTree = ""; }; + 18D3C9201EDF07A700D3DE43 /* RLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest2ViewController.h; sourceTree = ""; }; + 18D3C9211EDF07A700D3DE43 /* RLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest2ViewController.m; sourceTree = ""; }; + 18D3C9221EDF07A700D3DE43 /* RLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest3ViewController.h; sourceTree = ""; }; + 18D3C9231EDF07A700D3DE43 /* RLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest3ViewController.m; sourceTree = ""; }; + 18D3C9241EDF07A700D3DE43 /* RLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest4ViewController.h; sourceTree = ""; }; + 18D3C9251EDF07A700D3DE43 /* RLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest4ViewController.m; sourceTree = ""; }; + 18D3C9261EDF07A700D3DE43 /* RLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest5ViewController.h; sourceTree = ""; }; + 18D3C9271EDF07A700D3DE43 /* RLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest5ViewController.m; sourceTree = ""; }; + 18D3C92D1EDF07C000D3DE43 /* FLLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest1ViewController.h; sourceTree = ""; }; + 18D3C92E1EDF07C000D3DE43 /* FLLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest1ViewController.m; sourceTree = ""; }; + 18D3C92F1EDF07C000D3DE43 /* FLLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest2ViewController.h; sourceTree = ""; }; + 18D3C9301EDF07C000D3DE43 /* FLLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest2ViewController.m; sourceTree = ""; }; + 18D3C9311EDF07C000D3DE43 /* FLLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest3ViewController.h; sourceTree = ""; }; + 18D3C9321EDF07C000D3DE43 /* FLLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest3ViewController.m; sourceTree = ""; }; + 18D3C9331EDF07C000D3DE43 /* FLLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest4ViewController.h; sourceTree = ""; }; + 18D3C9341EDF07C000D3DE43 /* FLLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest4ViewController.m; sourceTree = ""; }; + 18D3C9351EDF07C000D3DE43 /* FLLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest5ViewController.h; sourceTree = ""; }; + 18D3C9361EDF07C000D3DE43 /* FLLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest5ViewController.m; sourceTree = ""; }; + 18D3C9371EDF07C000D3DE43 /* FLLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest6ViewController.h; sourceTree = ""; }; + 18D3C9381EDF07C000D3DE43 /* FLLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest6ViewController.m; sourceTree = ""; }; + 18D3C93F1EDF07E700D3DE43 /* PLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest1ViewController.h; sourceTree = ""; }; + 18D3C9401EDF07E700D3DE43 /* PLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest1ViewController.m; sourceTree = ""; }; + 18D3C9411EDF07E700D3DE43 /* PLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest2ViewController.h; sourceTree = ""; }; + 18D3C9421EDF07E700D3DE43 /* PLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest2ViewController.m; sourceTree = ""; }; + 18D3C9431EDF07E700D3DE43 /* PLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest3ViewController.h; sourceTree = ""; }; + 18D3C9441EDF07E700D3DE43 /* PLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest3ViewController.m; sourceTree = ""; }; + 18D3C9451EDF07E700D3DE43 /* PLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest4ViewController.h; sourceTree = ""; }; + 18D3C9461EDF07E700D3DE43 /* PLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = PLTest4ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C9471EDF07E700D3DE43 /* PLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLTest5ViewController.h; sourceTree = ""; }; + 18D3C9481EDF07E700D3DE43 /* PLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLTest5ViewController.m; sourceTree = ""; }; + 18D3C94E1EDF07F800D3DE43 /* FOLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest1ViewController.h; sourceTree = ""; }; + 18D3C94F1EDF07F800D3DE43 /* FOLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest1ViewController.m; sourceTree = ""; }; + 18D3C9501EDF07F800D3DE43 /* FOLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest2ViewController.h; sourceTree = ""; }; + 18D3C9511EDF07F800D3DE43 /* FOLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest2ViewController.m; sourceTree = ""; }; + 18D3C9521EDF07F800D3DE43 /* FOLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest3ViewController.h; sourceTree = ""; }; + 18D3C9531EDF07F800D3DE43 /* FOLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest3ViewController.m; sourceTree = ""; }; + 18D3C9541EDF07F800D3DE43 /* FOLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest4ViewController.h; sourceTree = ""; }; + 18D3C9551EDF07F800D3DE43 /* FOLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest4ViewController.m; sourceTree = ""; }; + 18D3C9561EDF07F800D3DE43 /* FOLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest5ViewController.h; sourceTree = ""; }; + 18D3C9571EDF07F800D3DE43 /* FOLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest5ViewController.m; sourceTree = ""; }; + 18D3C9581EDF07F800D3DE43 /* FOLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest6ViewController.h; sourceTree = ""; }; + 18D3C9591EDF07F800D3DE43 /* FOLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest6ViewController.m; sourceTree = ""; }; + 18D3C9601EDF080800D3DE43 /* TLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest1ViewController.h; sourceTree = ""; }; + 18D3C9611EDF080800D3DE43 /* TLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = TLTest1ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C9621EDF080800D3DE43 /* TLTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest2ViewController.h; sourceTree = ""; }; + 18D3C9631EDF080800D3DE43 /* TLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = TLTest2ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C9641EDF080800D3DE43 /* TLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest3ViewController.h; sourceTree = ""; }; + 18D3C9651EDF080800D3DE43 /* TLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLTest3ViewController.m; sourceTree = ""; }; + 18D3C9691EDF082800D3DE43 /* AllTest1TableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1TableViewCell.h; sourceTree = ""; }; + 18D3C96A1EDF082800D3DE43 /* AllTest1TableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1TableViewCell.m; sourceTree = ""; }; + 18D3C96B1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1TableViewHeaderFooterView.h; sourceTree = ""; }; + 18D3C96C1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1TableViewHeaderFooterView.m; sourceTree = ""; }; + 18D3C96D1EDF082800D3DE43 /* AllTest2TableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest2TableViewCell.h; sourceTree = ""; }; + 18D3C96E1EDF082800D3DE43 /* AllTest2TableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AllTest2TableViewCell.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C96F1EDF082800D3DE43 /* AllTestDataModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTestDataModel.h; sourceTree = ""; }; + 18D3C9701EDF082800D3DE43 /* AllTestDataModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTestDataModel.m; sourceTree = ""; }; + 18D3C9751EDF084000D3DE43 /* AllTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1ViewController.h; sourceTree = ""; }; + 18D3C9761EDF084000D3DE43 /* AllTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1ViewController.m; sourceTree = ""; }; + 18D3C9771EDF084000D3DE43 /* AllTest2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest2ViewController.h; sourceTree = ""; }; + 18D3C9781EDF084000D3DE43 /* AllTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest2ViewController.m; sourceTree = ""; }; + 18D3C9791EDF084000D3DE43 /* AllTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest3ViewController.h; sourceTree = ""; }; + 18D3C97A1EDF084000D3DE43 /* AllTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AllTest3ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C97B1EDF084000D3DE43 /* AllTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest4ViewController.h; sourceTree = ""; }; + 18D3C97C1EDF084000D3DE43 /* AllTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest4ViewController.m; sourceTree = ""; }; + 18D3C97D1EDF084000D3DE43 /* AllTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest5ViewController.h; sourceTree = ""; }; + 18D3C97E1EDF084000D3DE43 /* AllTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest5ViewController.m; sourceTree = ""; }; + 18D3C97F1EDF084000D3DE43 /* AllTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest6ViewController.h; sourceTree = ""; }; + 18D3C9801EDF084000D3DE43 /* AllTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest6ViewController.m; sourceTree = ""; }; + 18D3C9811EDF084000D3DE43 /* AllTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest7ViewController.h; sourceTree = ""; }; + 18D3C9821EDF084000D3DE43 /* AllTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AllTest7ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 18D3C9831EDF084000D3DE43 /* AllTest8ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest8ViewController.h; sourceTree = ""; }; + 18D3C9841EDF084000D3DE43 /* AllTest8ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest8ViewController.m; sourceTree = ""; }; + 18D3C98D1EDF08F800D3DE43 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 18D3C98E1EDF08F800D3DE43 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + 18D3C98F1EDF08F800D3DE43 /* YYFPSLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYFPSLabel.h; sourceTree = ""; }; + 18D3C9901EDF08F800D3DE43 /* YYFPSLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYFPSLabel.m; sourceTree = ""; }; + 18D3C9911EDF08F800D3DE43 /* YYWeakProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWeakProxy.h; sourceTree = ""; }; + 18D3C9921EDF08F800D3DE43 /* YYWeakProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWeakProxy.m; sourceTree = ""; }; + 18D3C9971EDF09BE00D3DE43 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 18D3C9981EDF09BE00D3DE43 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 18D3C9991EDF09BE00D3DE43 /* CFTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFTool.h; sourceTree = ""; }; + 18D3C99A1EDF09BE00D3DE43 /* CFTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CFTool.m; sourceTree = ""; }; + 18D3C9A31EDF0A5A00D3DE43 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = LaunchScreen.xib; sourceTree = ""; }; + 18D3C9A51EDF0A5A00D3DE43 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Localizable.strings; sourceTree = ""; }; + 18D3C9A61EDF0A5A00D3DE43 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 18D3C9A71EDF0A5A00D3DE43 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 18D3C9A81EDF0A5A00D3DE43 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 18D3C9AF1EDF0A5A00D3DE43 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = LaunchScreen.strings; sourceTree = ""; }; + 18D3C9B11EDF0A5A00D3DE43 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = Localizable.strings; sourceTree = ""; }; + 18D3C9BE1EDF0AB500D3DE43 /* fl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = fl.png; sourceTree = ""; }; + 18D3C9BF1EDF0AB500D3DE43 /* fll.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = fll.png; sourceTree = ""; }; + 18D3C9C01EDF0AB500D3DE43 /* flo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flo.png; sourceTree = ""; }; + 18D3C9C11EDF0AB500D3DE43 /* layoutdemo1.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo1.gif; sourceTree = ""; }; + 18D3C9C21EDF0AB500D3DE43 /* layoutdemo2.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo2.gif; sourceTree = ""; }; + 18D3C9C31EDF0AB500D3DE43 /* layoutdemo3.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo3.gif; sourceTree = ""; }; + 18D3C9C41EDF0AB500D3DE43 /* layoutdemo4.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo4.gif; sourceTree = ""; }; + 18D3C9C51EDF0AB500D3DE43 /* layoutdemo5.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo5.gif; sourceTree = ""; }; + 18D3C9C61EDF0AB500D3DE43 /* layoutdemo6.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo6.gif; sourceTree = ""; }; + 18D3C9C71EDF0AB500D3DE43 /* layoutdemo7.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo7.gif; sourceTree = ""; }; + 18D3C9C81EDF0AB500D3DE43 /* ll.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ll.png; sourceTree = ""; }; + 18D3C9C91EDF0AB500D3DE43 /* MyLayout.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MyLayout.png; sourceTree = ""; }; + 18D3C9CA1EDF0AB500D3DE43 /* MyLayoutClass.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MyLayoutClass.png; sourceTree = ""; }; + 18D3C9CB1EDF0AB500D3DE43 /* MyLayoutP.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MyLayoutP.png; sourceTree = ""; }; + 18D3C9CC1EDF0AB500D3DE43 /* pl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = pl.png; sourceTree = ""; }; + 18D3C9CD1EDF0AB500D3DE43 /* rl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = rl.png; sourceTree = ""; }; + 18D3C9CE1EDF0AB500D3DE43 /* tl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tl.png; sourceTree = ""; }; + 18D684001C4F421400A48BB4 /* MyLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayout.h; sourceTree = ""; }; + 18D684541C4F423400A48BB4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 18D684551C4F423400A48BB4 /* MyLayoutTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutTests.m; sourceTree = ""; }; + 200A26D71FA8A90300B06E7B /* AllTest9ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AllTest9ViewController.h; sourceTree = ""; }; + 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest9ViewController.m; sourceTree = ""; }; + 200A26DA1FA96B2400B06E7B /* AllTest9CollectionViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AllTest9CollectionViewCell.h; sourceTree = ""; }; + 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest9CollectionViewCell.m; sourceTree = ""; }; + 2043D5DB20995DF800276C68 /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = System/Library/Frameworks/CoreBluetooth.framework; sourceTree = SDKROOT; }; + 204DC31F209D5A7C00F6CB57 /* TLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTest4ViewController.h; sourceTree = ""; }; + 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLTest4ViewController.m; sourceTree = ""; }; + 205642841F4CFF9B00E8BDDE /* MyBorderline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyBorderline.h; sourceTree = ""; }; + 205642851F4CFF9B00E8BDDE /* MyBorderline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyBorderline.m; sourceTree = ""; }; + 205642891F4D013D00E8BDDE /* MyGrid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyGrid.h; sourceTree = ""; }; + 205643081F4E53CD00E8BDDE /* MyGridNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyGridNode.h; sourceTree = ""; }; + 205643091F4E53CD00E8BDDE /* MyGridNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyGridNode.m; sourceTree = ""; }; + 205643111F51C7DF00E8BDDE /* GLTest2ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GLTest2ViewController.h; sourceTree = ""; }; + 205643121F51C7EB00E8BDDE /* GLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GLTest2ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 205643141F55A03000E8BDDE /* MyLayoutMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutMath.h; sourceTree = ""; }; + 205643151F55A03000E8BDDE /* MyLayoutMath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutMath.m; sourceTree = ""; }; + 205CFA8C1F49BD1C00355489 /* GLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest1ViewController.h; sourceTree = ""; }; + 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GLTest1ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 205F9EB91F7AA5710034732C /* gl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = gl.png; sourceTree = ""; }; + 205F9EBB1F7AA6510034732C /* all.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = all.png; sourceTree = ""; }; + 2075CC3020A0B29700BA6F65 /* FLLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest7ViewController.h; sourceTree = ""; }; + 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest7ViewController.m; sourceTree = ""; }; + 208157BB1F586A9900E945B6 /* DetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = ""; }; + 208157BC1F586AA700E945B6 /* DetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; + 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutDelegate.h; sourceTree = ""; }; + 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutDelegate.m; sourceTree = ""; }; + 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo8.gif; sourceTree = ""; }; + 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest7ViewController.h; sourceTree = ""; }; + 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest7ViewController.m; sourceTree = ""; }; + 20F783541F60398C00BE5B31 /* GLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest3ViewController.h; sourceTree = ""; }; + 20F783551F60399700BE5B31 /* GLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest3ViewController.m; sourceTree = ""; }; + 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo5.json; sourceTree = ""; }; + 444B718F1F6A3E3F00331872 /* GLTest5ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest5ViewController.h; sourceTree = ""; }; + 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest5ViewController.m; sourceTree = ""; }; + 44EBDA8A1F619A6300B47CBD /* GLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest4ViewController.h; sourceTree = ""; }; + 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest4ViewController.m; sourceTree = ""; }; + 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo4.json; sourceTree = ""; }; + 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10ViewController.h; sourceTree = ""; }; + 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10ViewController.m; sourceTree = ""; }; + 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10Model.m; sourceTree = ""; }; + 6740E1FA20A52DA900AFBC5A /* AllTest10Model.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10Model.h; sourceTree = ""; }; + 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10HeaderView.m; sourceTree = ""; }; + 6740E1FD20A52DB000AFBC5A /* AllTest10HeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10HeaderView.h; sourceTree = ""; }; + 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10Cell.m; sourceTree = ""; }; + 6740E20020A52DC100AFBC5A /* AllTest10Cell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10Cell.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 181A10B11EDF12CF00996203 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1840828A1B2C46E8003F378B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 184082A31B2C46E8003F378B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18B1522E1DEDDE5500AD7A1C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; + 181A10B11EDF12CF00996203 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1840828A1B2C46E8003F378B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 184082A31B2C46E8003F378B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18B1522E1DEDDE5500AD7A1C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 184082841B2C46E8003F378B = { - isa = PBXGroup; - children = ( - 18D3C8F91EDF04E000D3DE43 /* MyLayoutDemo */, - 18D683E61C4F421400A48BB4 /* MyLayout */, - 18D684531C4F423400A48BB4 /* MyLayoutTests */, - 18B152321DEDDE5500AD7A1C /* MyLayoutUITests */, - 1840828E1B2C46E8003F378B /* Products */, - 2043D5DA20995DF800276C68 /* Frameworks */, - ); - sourceTree = ""; - }; - 1840828E1B2C46E8003F378B /* Products */ = { - isa = PBXGroup; - children = ( - 1840828D1B2C46E8003F378B /* MyLayoutDemo.app */, - 184082A61B2C46E8003F378B /* MyLayout.xctest */, - 18B152311DEDDE5500AD7A1C /* MyLayoutUITests.xctest */, - 181A10B51EDF12CF00996203 /* MyLayout.framework */, - ); - name = Products; - sourceTree = ""; - }; - 18B152321DEDDE5500AD7A1C /* MyLayoutUITests */ = { - isa = PBXGroup; - children = ( - 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */, - 18B152351DEDDE5500AD7A1C /* Info.plist */, - ); - path = MyLayoutUITests; - sourceTree = ""; - }; - 18D3C8F91EDF04E000D3DE43 /* MyLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C9971EDF09BE00D3DE43 /* AppDelegate.h */, - 18D3C9981EDF09BE00D3DE43 /* AppDelegate.m */, - 18D3C98D1EDF08F800D3DE43 /* ViewController.h */, - 18D3C98E1EDF08F800D3DE43 /* ViewController.m */, - 208157BB1F586A9900E945B6 /* DetailViewController.h */, - 208157BC1F586AA700E945B6 /* DetailViewController.m */, - 18D3C9991EDF09BE00D3DE43 /* CFTool.h */, - 18D3C99A1EDF09BE00D3DE43 /* CFTool.m */, - 18D3C98F1EDF08F800D3DE43 /* YYFPSLabel.h */, - 18D3C9901EDF08F800D3DE43 /* YYFPSLabel.m */, - 18D3C9911EDF08F800D3DE43 /* YYWeakProxy.h */, - 18D3C9921EDF08F800D3DE43 /* YYWeakProxy.m */, - 18D3C9961EDF091B00D3DE43 /* Supporting Files */, - 18D3C8FA1EDF051000D3DE43 /* LinearLayoutDemo */, - 18D3C8FB1EDF052300D3DE43 /* FrameLayoutDemo */, - 18D3C8FC1EDF053000D3DE43 /* RelativeLayoutDemo */, - 18D3C9001EDF056900D3DE43 /* TableLayoutDemo */, - 18D3C8FD1EDF053D00D3DE43 /* FlowLayoutDemo */, - 18D3C8FF1EDF055C00D3DE43 /* FloatLayoutDemo */, - 205CFA8B1F49BCAF00355489 /* GridLayoutDemo */, - 18D3C8FE1EDF055000D3DE43 /* PathLayoutDemo */, - 18D3C9011EDF059600D3DE43 /* IntegratedDemo */, - ); - path = MyLayoutDemo; - sourceTree = ""; - }; - 18D3C8FA1EDF051000D3DE43 /* LinearLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C9031EDF074900D3DE43 /* LLTest1ViewController.h */, - 18D3C9041EDF074900D3DE43 /* LLTest1ViewController.m */, - 18D3C9051EDF074900D3DE43 /* LLTest2ViewController.h */, - 18D3C9061EDF074900D3DE43 /* LLTest2ViewController.m */, - 18D3C9071EDF074900D3DE43 /* LLTest3ViewController.h */, - 18D3C9081EDF074900D3DE43 /* LLTest3ViewController.m */, - 18D3C9091EDF074900D3DE43 /* LLTest4ViewController.h */, - 18D3C90A1EDF074900D3DE43 /* LLTest4ViewController.m */, - 18D3C90B1EDF074900D3DE43 /* LLTest5ViewController.h */, - 18D3C90C1EDF074900D3DE43 /* LLTest5ViewController.m */, - 18D3C90D1EDF074900D3DE43 /* LLTest6ViewController.h */, - 18D3C90E1EDF074900D3DE43 /* LLTest6ViewController.m */, - 18D3C90F1EDF074900D3DE43 /* LLTest7ViewController.h */, - 18D3C9101EDF074900D3DE43 /* LLTest7ViewController.m */, - ); - name = LinearLayoutDemo; - sourceTree = ""; - }; - 18D3C8FB1EDF052300D3DE43 /* FrameLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C9181EDF078200D3DE43 /* FLTest1ViewController.h */, - 18D3C9191EDF078200D3DE43 /* FLTest1ViewController.m */, - 18D3C91A1EDF078200D3DE43 /* FLTest2ViewController.h */, - 18D3C91B1EDF078200D3DE43 /* FLTest2ViewController.m */, - ); - name = FrameLayoutDemo; - sourceTree = ""; - }; - 18D3C8FC1EDF053000D3DE43 /* RelativeLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C91E1EDF07A700D3DE43 /* RLTest1ViewController.h */, - 18D3C91F1EDF07A700D3DE43 /* RLTest1ViewController.m */, - 18D3C9201EDF07A700D3DE43 /* RLTest2ViewController.h */, - 18D3C9211EDF07A700D3DE43 /* RLTest2ViewController.m */, - 18D3C9221EDF07A700D3DE43 /* RLTest3ViewController.h */, - 18D3C9231EDF07A700D3DE43 /* RLTest3ViewController.m */, - 18D3C9241EDF07A700D3DE43 /* RLTest4ViewController.h */, - 18D3C9251EDF07A700D3DE43 /* RLTest4ViewController.m */, - 18D3C9261EDF07A700D3DE43 /* RLTest5ViewController.h */, - 18D3C9271EDF07A700D3DE43 /* RLTest5ViewController.m */, - ); - name = RelativeLayoutDemo; - sourceTree = ""; - }; - 18D3C8FD1EDF053D00D3DE43 /* FlowLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C92D1EDF07C000D3DE43 /* FLLTest1ViewController.h */, - 18D3C92E1EDF07C000D3DE43 /* FLLTest1ViewController.m */, - 18D3C92F1EDF07C000D3DE43 /* FLLTest2ViewController.h */, - 18D3C9301EDF07C000D3DE43 /* FLLTest2ViewController.m */, - 181A10A81EDF11FF00996203 /* FLLTest2ViewController.xib */, - 18D3C9311EDF07C000D3DE43 /* FLLTest3ViewController.h */, - 18D3C9321EDF07C000D3DE43 /* FLLTest3ViewController.m */, - 18D3C9331EDF07C000D3DE43 /* FLLTest4ViewController.h */, - 18D3C9341EDF07C000D3DE43 /* FLLTest4ViewController.m */, - 18D3C9351EDF07C000D3DE43 /* FLLTest5ViewController.h */, - 18D3C9361EDF07C000D3DE43 /* FLLTest5ViewController.m */, - 18D3C9371EDF07C000D3DE43 /* FLLTest6ViewController.h */, - 18D3C9381EDF07C000D3DE43 /* FLLTest6ViewController.m */, - 2075CC3020A0B29700BA6F65 /* FLLTest7ViewController.h */, - 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */, - ); - name = FlowLayoutDemo; - sourceTree = ""; - }; - 18D3C8FE1EDF055000D3DE43 /* PathLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C93F1EDF07E700D3DE43 /* PLTest1ViewController.h */, - 18D3C9401EDF07E700D3DE43 /* PLTest1ViewController.m */, - 18D3C9411EDF07E700D3DE43 /* PLTest2ViewController.h */, - 18D3C9421EDF07E700D3DE43 /* PLTest2ViewController.m */, - 18D3C9431EDF07E700D3DE43 /* PLTest3ViewController.h */, - 18D3C9441EDF07E700D3DE43 /* PLTest3ViewController.m */, - 18D3C9451EDF07E700D3DE43 /* PLTest4ViewController.h */, - 18D3C9461EDF07E700D3DE43 /* PLTest4ViewController.m */, - 18D3C9471EDF07E700D3DE43 /* PLTest5ViewController.h */, - 18D3C9481EDF07E700D3DE43 /* PLTest5ViewController.m */, - ); - name = PathLayoutDemo; - sourceTree = ""; - }; - 18D3C8FF1EDF055C00D3DE43 /* FloatLayoutDemo */ = { - isa = PBXGroup; - children = ( - 181A10AC1EDF123800996203 /* FOLTest1ViewController.xib */, - 18D3C94E1EDF07F800D3DE43 /* FOLTest1ViewController.h */, - 18D3C94F1EDF07F800D3DE43 /* FOLTest1ViewController.m */, - 18D3C9501EDF07F800D3DE43 /* FOLTest2ViewController.h */, - 18D3C9511EDF07F800D3DE43 /* FOLTest2ViewController.m */, - 18D3C9521EDF07F800D3DE43 /* FOLTest3ViewController.h */, - 18D3C9531EDF07F800D3DE43 /* FOLTest3ViewController.m */, - 18D3C9541EDF07F800D3DE43 /* FOLTest4ViewController.h */, - 18D3C9551EDF07F800D3DE43 /* FOLTest4ViewController.m */, - 18D3C9561EDF07F800D3DE43 /* FOLTest5ViewController.h */, - 18D3C9571EDF07F800D3DE43 /* FOLTest5ViewController.m */, - 18D3C9581EDF07F800D3DE43 /* FOLTest6ViewController.h */, - 18D3C9591EDF07F800D3DE43 /* FOLTest6ViewController.m */, - 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */, - 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */, - ); - name = FloatLayoutDemo; - sourceTree = ""; - }; - 18D3C9001EDF056900D3DE43 /* TableLayoutDemo */ = { - isa = PBXGroup; - children = ( - 18D3C9601EDF080800D3DE43 /* TLTest1ViewController.h */, - 18D3C9611EDF080800D3DE43 /* TLTest1ViewController.m */, - 18D3C9621EDF080800D3DE43 /* TLTest2ViewController.h */, - 18D3C9631EDF080800D3DE43 /* TLTest2ViewController.m */, - 18D3C9641EDF080800D3DE43 /* TLTest3ViewController.h */, - 18D3C9651EDF080800D3DE43 /* TLTest3ViewController.m */, - 204DC31F209D5A7C00F6CB57 /* TLTest4ViewController.h */, - 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */, - ); - name = TableLayoutDemo; - sourceTree = ""; - }; - 18D3C9011EDF059600D3DE43 /* IntegratedDemo */ = { - isa = PBXGroup; - children = ( - 18D3C9751EDF084000D3DE43 /* AllTest1ViewController.h */, - 18D3C9761EDF084000D3DE43 /* AllTest1ViewController.m */, - 18D3C9771EDF084000D3DE43 /* AllTest2ViewController.h */, - 18D3C9781EDF084000D3DE43 /* AllTest2ViewController.m */, - 18D3C9791EDF084000D3DE43 /* AllTest3ViewController.h */, - 18D3C97A1EDF084000D3DE43 /* AllTest3ViewController.m */, - 18D3C97B1EDF084000D3DE43 /* AllTest4ViewController.h */, - 18D3C97C1EDF084000D3DE43 /* AllTest4ViewController.m */, - 18D3C97D1EDF084000D3DE43 /* AllTest5ViewController.h */, - 18D3C97E1EDF084000D3DE43 /* AllTest5ViewController.m */, - 18D3C97F1EDF084000D3DE43 /* AllTest6ViewController.h */, - 18D3C9801EDF084000D3DE43 /* AllTest6ViewController.m */, - 18D3C9811EDF084000D3DE43 /* AllTest7ViewController.h */, - 18D3C9821EDF084000D3DE43 /* AllTest7ViewController.m */, - 18D3C9831EDF084000D3DE43 /* AllTest8ViewController.h */, - 18D3C9841EDF084000D3DE43 /* AllTest8ViewController.m */, - 200A26D71FA8A90300B06E7B /* AllTest9ViewController.h */, - 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */, - 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */, - 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */, - 18D3C9021EDF068200D3DE43 /* AllTestModel&View */, - ); - name = IntegratedDemo; - sourceTree = ""; - }; - 18D3C9021EDF068200D3DE43 /* AllTestModel&View */ = { - isa = PBXGroup; - children = ( - 18D3C9691EDF082800D3DE43 /* AllTest1TableViewCell.h */, - 18D3C96A1EDF082800D3DE43 /* AllTest1TableViewCell.m */, - 18D3C96B1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.h */, - 18D3C96C1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m */, - 18D3C96D1EDF082800D3DE43 /* AllTest2TableViewCell.h */, - 18D3C96E1EDF082800D3DE43 /* AllTest2TableViewCell.m */, - 18D3C96F1EDF082800D3DE43 /* AllTestDataModel.h */, - 18D3C9701EDF082800D3DE43 /* AllTestDataModel.m */, - 200A26DA1FA96B2400B06E7B /* AllTest9CollectionViewCell.h */, - 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */, - 6740E1FA20A52DA900AFBC5A /* AllTest10Model.h */, - 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */, - 6740E1FD20A52DB000AFBC5A /* AllTest10HeaderView.h */, - 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */, - 6740E20020A52DC100AFBC5A /* AllTest10Cell.h */, - 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */, - ); - name = "AllTestModel&View"; - sourceTree = ""; - }; - 18D3C9961EDF091B00D3DE43 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 18D3C9A91EDF0A5A00D3DE43 /* zh-Hans.lproj */, - 18D3C99D1EDF0A5A00D3DE43 /* Base.lproj */, - 18D3C9A61EDF0A5A00D3DE43 /* Images.xcassets */, - 18D3C9A71EDF0A5A00D3DE43 /* Info.plist */, - 18D3C9A81EDF0A5A00D3DE43 /* main.m */, - 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */, - 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 18D3C99D1EDF0A5A00D3DE43 /* Base.lproj */ = { - isa = PBXGroup; - children = ( - 18D3C9A21EDF0A5A00D3DE43 /* LaunchScreen.xib */, - 18D3C9A41EDF0A5A00D3DE43 /* Localizable.strings */, - ); - path = Base.lproj; - sourceTree = ""; - }; - 18D3C9A91EDF0A5A00D3DE43 /* zh-Hans.lproj */ = { - isa = PBXGroup; - children = ( - 18D3C9AE1EDF0A5A00D3DE43 /* LaunchScreen.strings */, - 18D3C9B01EDF0A5A00D3DE43 /* Localizable.strings */, - ); - path = "zh-Hans.lproj"; - sourceTree = ""; - }; - 18D3C9BD1EDF0A7900D3DE43 /* Images */ = { - isa = PBXGroup; - children = ( - 205F9EBB1F7AA6510034732C /* all.png */, - 205F9EB91F7AA5710034732C /* gl.png */, - 18D3C9BE1EDF0AB500D3DE43 /* fl.png */, - 18D3C9BF1EDF0AB500D3DE43 /* fll.png */, - 18D3C9C01EDF0AB500D3DE43 /* flo.png */, - 18D3C9C11EDF0AB500D3DE43 /* layoutdemo1.gif */, - 18D3C9C21EDF0AB500D3DE43 /* layoutdemo2.gif */, - 18D3C9C31EDF0AB500D3DE43 /* layoutdemo3.gif */, - 18D3C9C41EDF0AB500D3DE43 /* layoutdemo4.gif */, - 18D3C9C51EDF0AB500D3DE43 /* layoutdemo5.gif */, - 18D3C9C61EDF0AB500D3DE43 /* layoutdemo6.gif */, - 18D3C9C71EDF0AB500D3DE43 /* layoutdemo7.gif */, - 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */, - 18D3C9C81EDF0AB500D3DE43 /* ll.png */, - 18D3C9C91EDF0AB500D3DE43 /* MyLayout.png */, - 18D3C9CA1EDF0AB500D3DE43 /* MyLayoutClass.png */, - 18D3C9CB1EDF0AB500D3DE43 /* MyLayoutP.png */, - 18D3C9CC1EDF0AB500D3DE43 /* pl.png */, - 18D3C9CD1EDF0AB500D3DE43 /* rl.png */, - 18D3C9CE1EDF0AB500D3DE43 /* tl.png */, - ); - name = Images; - sourceTree = ""; - }; - 18D683E61C4F421400A48BB4 /* MyLayout */ = { - isa = PBXGroup; - children = ( - 18C15AEA1EDF133200AADEAC /* Info.plist */, - 18D3C9BD1EDF0A7900D3DE43 /* Images */, - 18D683FB1C4F421400A48BB4 /* Lib */, - ); - path = MyLayout; - sourceTree = ""; - }; - 18D683FB1C4F421400A48BB4 /* Lib */ = { - isa = PBXGroup; - children = ( - 18D684001C4F421400A48BB4 /* MyLayout.h */, - 182225AB1E77E5930081AA4B /* MyFlowLayout.h */, - 182225B41E77E5930081AA4B /* MyFlowLayout.m */, - 182225AC1E77E5930081AA4B /* MyLinearLayout.h */, - 182225B21E77E5930081AA4B /* MyLinearLayout.m */, - 182225AD1E77E5930081AA4B /* MyFloatLayout.h */, - 182225B91E77E5930081AA4B /* MyFloatLayout.m */, - 182225AE1E77E5930081AA4B /* MyTableLayout.h */, - 182225C31E77E5930081AA4B /* MyTableLayout.m */, - 182225BE1E77E5930081AA4B /* MyRelativeLayout.h */, - 182225B51E77E5930081AA4B /* MyRelativeLayout.m */, - 182225BD1E77E5930081AA4B /* MyPathLayout.h */, - 182225B61E77E5930081AA4B /* MyPathLayout.m */, - 182225BA1E77E5930081AA4B /* MyFrameLayout.h */, - 182225B71E77E5930081AA4B /* MyFrameLayout.m */, - 182225AF1E77E5930081AA4B /* MyBaseLayout.h */, - 182225B11E77E5930081AA4B /* MyBaseLayout.m */, - 182225B01E77E5930081AA4B /* MyLayoutPos.h */, - 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */, - 182225BB1E77E5930081AA4B /* MyLayoutPos.m */, - 182225BC1E77E5930081AA4B /* MyLayoutSize.h */, - 182225C81E77E5930081AA4B /* MyLayoutSizeInner.h */, - 182225C51E77E5930081AA4B /* MyLayoutSize.m */, - 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */, - 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */, - 182225C21E77E5930081AA4B /* MyMaker.h */, - 182225C11E77E5930081AA4B /* MyMaker.m */, - 182225C71E77E5930081AA4B /* MyDimeScale.h */, - 182225C41E77E5930081AA4B /* MyDimeScale.m */, - 182225B81E77E5930081AA4B /* MyLayoutInner.h */, - 182225B31E77E5930081AA4B /* MyLayoutDef.h */, - 205642891F4D013D00E8BDDE /* MyGrid.h */, - 182DB6401EF7876200E2D65D /* MyGridLayout.h */, - 182DB6411EF7876200E2D65D /* MyGridLayout.m */, - 205642841F4CFF9B00E8BDDE /* MyBorderline.h */, - 205642851F4CFF9B00E8BDDE /* MyBorderline.m */, - 205643081F4E53CD00E8BDDE /* MyGridNode.h */, - 205643091F4E53CD00E8BDDE /* MyGridNode.m */, - 205643141F55A03000E8BDDE /* MyLayoutMath.h */, - 205643151F55A03000E8BDDE /* MyLayoutMath.m */, - 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */, - 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */, - ); - path = Lib; - sourceTree = ""; - }; - 18D684531C4F423400A48BB4 /* MyLayoutTests */ = { - isa = PBXGroup; - children = ( - 18D684541C4F423400A48BB4 /* Info.plist */, - 18D684551C4F423400A48BB4 /* MyLayoutTests.m */, - 189738501E16330B004F80D6 /* MyLayoutTestCaseBase.m */, - 189738521E16340D004F80D6 /* MyLayoutTestCaseBase.h */, - 1897384E1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m */, - 180BD8A01EA9EF9A00C6980B /* MyFrameLayoutTestCase.m */, - 181836941EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m */, - 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */, - 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */, - 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */, - ); - path = MyLayoutTests; - sourceTree = ""; - }; - 2043D5DA20995DF800276C68 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 2043D5DB20995DF800276C68 /* CoreBluetooth.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 205CFA8B1F49BCAF00355489 /* GridLayoutDemo */ = { - isa = PBXGroup; - children = ( - 205CFA8C1F49BD1C00355489 /* GLTest1ViewController.h */, - 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */, - 205643111F51C7DF00E8BDDE /* GLTest2ViewController.h */, - 205643121F51C7EB00E8BDDE /* GLTest2ViewController.m */, - 20F783541F60398C00BE5B31 /* GLTest3ViewController.h */, - 20F783551F60399700BE5B31 /* GLTest3ViewController.m */, - 44EBDA8A1F619A6300B47CBD /* GLTest4ViewController.h */, - 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */, - 444B718F1F6A3E3F00331872 /* GLTest5ViewController.h */, - 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */, - ); - name = GridLayoutDemo; - sourceTree = ""; - }; + 184082841B2C46E8003F378B = { + isa = PBXGroup; + children = ( + 18D3C8F91EDF04E000D3DE43 /* MyLayoutDemo */, + 18D683E61C4F421400A48BB4 /* MyLayout */, + 18D684531C4F423400A48BB4 /* MyLayoutTests */, + 18B152321DEDDE5500AD7A1C /* MyLayoutUITests */, + 1840828E1B2C46E8003F378B /* Products */, + 2043D5DA20995DF800276C68 /* Frameworks */, + ); + sourceTree = ""; + }; + 1840828E1B2C46E8003F378B /* Products */ = { + isa = PBXGroup; + children = ( + 1840828D1B2C46E8003F378B /* MyLayoutDemo.app */, + 184082A61B2C46E8003F378B /* MyLayout.xctest */, + 18B152311DEDDE5500AD7A1C /* MyLayoutUITests.xctest */, + 181A10B51EDF12CF00996203 /* MyLayout.framework */, + ); + name = Products; + sourceTree = ""; + }; + 18B152321DEDDE5500AD7A1C /* MyLayoutUITests */ = { + isa = PBXGroup; + children = ( + 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */, + 18B152351DEDDE5500AD7A1C /* Info.plist */, + ); + path = MyLayoutUITests; + sourceTree = ""; + }; + 18D3C8F91EDF04E000D3DE43 /* MyLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C9971EDF09BE00D3DE43 /* AppDelegate.h */, + 18D3C9981EDF09BE00D3DE43 /* AppDelegate.m */, + 18D3C98D1EDF08F800D3DE43 /* ViewController.h */, + 18D3C98E1EDF08F800D3DE43 /* ViewController.m */, + 208157BB1F586A9900E945B6 /* DetailViewController.h */, + 208157BC1F586AA700E945B6 /* DetailViewController.m */, + 18D3C9991EDF09BE00D3DE43 /* CFTool.h */, + 18D3C99A1EDF09BE00D3DE43 /* CFTool.m */, + 18D3C98F1EDF08F800D3DE43 /* YYFPSLabel.h */, + 18D3C9901EDF08F800D3DE43 /* YYFPSLabel.m */, + 18D3C9911EDF08F800D3DE43 /* YYWeakProxy.h */, + 18D3C9921EDF08F800D3DE43 /* YYWeakProxy.m */, + 18D3C9961EDF091B00D3DE43 /* Supporting Files */, + 18D3C8FA1EDF051000D3DE43 /* LinearLayoutDemo */, + 18D3C8FB1EDF052300D3DE43 /* FrameLayoutDemo */, + 18D3C8FC1EDF053000D3DE43 /* RelativeLayoutDemo */, + 18D3C9001EDF056900D3DE43 /* TableLayoutDemo */, + 18D3C8FD1EDF053D00D3DE43 /* FlowLayoutDemo */, + 18D3C8FF1EDF055C00D3DE43 /* FloatLayoutDemo */, + 205CFA8B1F49BCAF00355489 /* GridLayoutDemo */, + 18D3C8FE1EDF055000D3DE43 /* PathLayoutDemo */, + 18D3C9011EDF059600D3DE43 /* IntegratedDemo */, + ); + path = MyLayoutDemo; + sourceTree = ""; + }; + 18D3C8FA1EDF051000D3DE43 /* LinearLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C9031EDF074900D3DE43 /* LLTest1ViewController.h */, + 18D3C9041EDF074900D3DE43 /* LLTest1ViewController.m */, + 18D3C9051EDF074900D3DE43 /* LLTest2ViewController.h */, + 18D3C9061EDF074900D3DE43 /* LLTest2ViewController.m */, + 18D3C9071EDF074900D3DE43 /* LLTest3ViewController.h */, + 18D3C9081EDF074900D3DE43 /* LLTest3ViewController.m */, + 18D3C9091EDF074900D3DE43 /* LLTest4ViewController.h */, + 18D3C90A1EDF074900D3DE43 /* LLTest4ViewController.m */, + 18D3C90B1EDF074900D3DE43 /* LLTest5ViewController.h */, + 18D3C90C1EDF074900D3DE43 /* LLTest5ViewController.m */, + 18D3C90D1EDF074900D3DE43 /* LLTest6ViewController.h */, + 18D3C90E1EDF074900D3DE43 /* LLTest6ViewController.m */, + 18D3C90F1EDF074900D3DE43 /* LLTest7ViewController.h */, + 18D3C9101EDF074900D3DE43 /* LLTest7ViewController.m */, + ); + name = LinearLayoutDemo; + sourceTree = ""; + }; + 18D3C8FB1EDF052300D3DE43 /* FrameLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C9181EDF078200D3DE43 /* FLTest1ViewController.h */, + 18D3C9191EDF078200D3DE43 /* FLTest1ViewController.m */, + 18D3C91A1EDF078200D3DE43 /* FLTest2ViewController.h */, + 18D3C91B1EDF078200D3DE43 /* FLTest2ViewController.m */, + ); + name = FrameLayoutDemo; + sourceTree = ""; + }; + 18D3C8FC1EDF053000D3DE43 /* RelativeLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C91E1EDF07A700D3DE43 /* RLTest1ViewController.h */, + 18D3C91F1EDF07A700D3DE43 /* RLTest1ViewController.m */, + 18D3C9201EDF07A700D3DE43 /* RLTest2ViewController.h */, + 18D3C9211EDF07A700D3DE43 /* RLTest2ViewController.m */, + 18D3C9221EDF07A700D3DE43 /* RLTest3ViewController.h */, + 18D3C9231EDF07A700D3DE43 /* RLTest3ViewController.m */, + 18D3C9241EDF07A700D3DE43 /* RLTest4ViewController.h */, + 18D3C9251EDF07A700D3DE43 /* RLTest4ViewController.m */, + 18D3C9261EDF07A700D3DE43 /* RLTest5ViewController.h */, + 18D3C9271EDF07A700D3DE43 /* RLTest5ViewController.m */, + ); + name = RelativeLayoutDemo; + sourceTree = ""; + }; + 18D3C8FD1EDF053D00D3DE43 /* FlowLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C92D1EDF07C000D3DE43 /* FLLTest1ViewController.h */, + 18D3C92E1EDF07C000D3DE43 /* FLLTest1ViewController.m */, + 18D3C92F1EDF07C000D3DE43 /* FLLTest2ViewController.h */, + 18D3C9301EDF07C000D3DE43 /* FLLTest2ViewController.m */, + 181A10A81EDF11FF00996203 /* FLLTest2ViewController.xib */, + 18D3C9311EDF07C000D3DE43 /* FLLTest3ViewController.h */, + 18D3C9321EDF07C000D3DE43 /* FLLTest3ViewController.m */, + 18D3C9331EDF07C000D3DE43 /* FLLTest4ViewController.h */, + 18D3C9341EDF07C000D3DE43 /* FLLTest4ViewController.m */, + 18D3C9351EDF07C000D3DE43 /* FLLTest5ViewController.h */, + 18D3C9361EDF07C000D3DE43 /* FLLTest5ViewController.m */, + 18D3C9371EDF07C000D3DE43 /* FLLTest6ViewController.h */, + 18D3C9381EDF07C000D3DE43 /* FLLTest6ViewController.m */, + 2075CC3020A0B29700BA6F65 /* FLLTest7ViewController.h */, + 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */, + ); + name = FlowLayoutDemo; + sourceTree = ""; + }; + 18D3C8FE1EDF055000D3DE43 /* PathLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C93F1EDF07E700D3DE43 /* PLTest1ViewController.h */, + 18D3C9401EDF07E700D3DE43 /* PLTest1ViewController.m */, + 18D3C9411EDF07E700D3DE43 /* PLTest2ViewController.h */, + 18D3C9421EDF07E700D3DE43 /* PLTest2ViewController.m */, + 18D3C9431EDF07E700D3DE43 /* PLTest3ViewController.h */, + 18D3C9441EDF07E700D3DE43 /* PLTest3ViewController.m */, + 18D3C9451EDF07E700D3DE43 /* PLTest4ViewController.h */, + 18D3C9461EDF07E700D3DE43 /* PLTest4ViewController.m */, + 18D3C9471EDF07E700D3DE43 /* PLTest5ViewController.h */, + 18D3C9481EDF07E700D3DE43 /* PLTest5ViewController.m */, + ); + name = PathLayoutDemo; + sourceTree = ""; + }; + 18D3C8FF1EDF055C00D3DE43 /* FloatLayoutDemo */ = { + isa = PBXGroup; + children = ( + 181A10AC1EDF123800996203 /* FOLTest1ViewController.xib */, + 18D3C94E1EDF07F800D3DE43 /* FOLTest1ViewController.h */, + 18D3C94F1EDF07F800D3DE43 /* FOLTest1ViewController.m */, + 18D3C9501EDF07F800D3DE43 /* FOLTest2ViewController.h */, + 18D3C9511EDF07F800D3DE43 /* FOLTest2ViewController.m */, + 18D3C9521EDF07F800D3DE43 /* FOLTest3ViewController.h */, + 18D3C9531EDF07F800D3DE43 /* FOLTest3ViewController.m */, + 18D3C9541EDF07F800D3DE43 /* FOLTest4ViewController.h */, + 18D3C9551EDF07F800D3DE43 /* FOLTest4ViewController.m */, + 18D3C9561EDF07F800D3DE43 /* FOLTest5ViewController.h */, + 18D3C9571EDF07F800D3DE43 /* FOLTest5ViewController.m */, + 18D3C9581EDF07F800D3DE43 /* FOLTest6ViewController.h */, + 18D3C9591EDF07F800D3DE43 /* FOLTest6ViewController.m */, + 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */, + 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */, + ); + name = FloatLayoutDemo; + sourceTree = ""; + }; + 18D3C9001EDF056900D3DE43 /* TableLayoutDemo */ = { + isa = PBXGroup; + children = ( + 18D3C9601EDF080800D3DE43 /* TLTest1ViewController.h */, + 18D3C9611EDF080800D3DE43 /* TLTest1ViewController.m */, + 18D3C9621EDF080800D3DE43 /* TLTest2ViewController.h */, + 18D3C9631EDF080800D3DE43 /* TLTest2ViewController.m */, + 18D3C9641EDF080800D3DE43 /* TLTest3ViewController.h */, + 18D3C9651EDF080800D3DE43 /* TLTest3ViewController.m */, + 204DC31F209D5A7C00F6CB57 /* TLTest4ViewController.h */, + 204DC320209D5A8600F6CB57 /* TLTest4ViewController.m */, + ); + name = TableLayoutDemo; + sourceTree = ""; + }; + 18D3C9011EDF059600D3DE43 /* IntegratedDemo */ = { + isa = PBXGroup; + children = ( + 18D3C9751EDF084000D3DE43 /* AllTest1ViewController.h */, + 18D3C9761EDF084000D3DE43 /* AllTest1ViewController.m */, + 18D3C9771EDF084000D3DE43 /* AllTest2ViewController.h */, + 18D3C9781EDF084000D3DE43 /* AllTest2ViewController.m */, + 18D3C9791EDF084000D3DE43 /* AllTest3ViewController.h */, + 18D3C97A1EDF084000D3DE43 /* AllTest3ViewController.m */, + 18D3C97B1EDF084000D3DE43 /* AllTest4ViewController.h */, + 18D3C97C1EDF084000D3DE43 /* AllTest4ViewController.m */, + 18D3C97D1EDF084000D3DE43 /* AllTest5ViewController.h */, + 18D3C97E1EDF084000D3DE43 /* AllTest5ViewController.m */, + 18D3C97F1EDF084000D3DE43 /* AllTest6ViewController.h */, + 18D3C9801EDF084000D3DE43 /* AllTest6ViewController.m */, + 18D3C9811EDF084000D3DE43 /* AllTest7ViewController.h */, + 18D3C9821EDF084000D3DE43 /* AllTest7ViewController.m */, + 18D3C9831EDF084000D3DE43 /* AllTest8ViewController.h */, + 18D3C9841EDF084000D3DE43 /* AllTest8ViewController.m */, + 200A26D71FA8A90300B06E7B /* AllTest9ViewController.h */, + 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */, + 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */, + 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */, + 18D3C9021EDF068200D3DE43 /* AllTestModel&View */, + ); + name = IntegratedDemo; + sourceTree = ""; + }; + 18D3C9021EDF068200D3DE43 /* AllTestModel&View */ = { + isa = PBXGroup; + children = ( + 18D3C9691EDF082800D3DE43 /* AllTest1TableViewCell.h */, + 18D3C96A1EDF082800D3DE43 /* AllTest1TableViewCell.m */, + 18D3C96B1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.h */, + 18D3C96C1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m */, + 18D3C96D1EDF082800D3DE43 /* AllTest2TableViewCell.h */, + 18D3C96E1EDF082800D3DE43 /* AllTest2TableViewCell.m */, + 18D3C96F1EDF082800D3DE43 /* AllTestDataModel.h */, + 18D3C9701EDF082800D3DE43 /* AllTestDataModel.m */, + 200A26DA1FA96B2400B06E7B /* AllTest9CollectionViewCell.h */, + 200A26DB1FA96B2400B06E7B /* AllTest9CollectionViewCell.m */, + 6740E1FA20A52DA900AFBC5A /* AllTest10Model.h */, + 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */, + 6740E1FD20A52DB000AFBC5A /* AllTest10HeaderView.h */, + 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */, + 6740E20020A52DC100AFBC5A /* AllTest10Cell.h */, + 6740E1FF20A52DC100AFBC5A /* AllTest10Cell.m */, + ); + name = "AllTestModel&View"; + sourceTree = ""; + }; + 18D3C9961EDF091B00D3DE43 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 18D3C9A91EDF0A5A00D3DE43 /* zh-Hans.lproj */, + 18D3C99D1EDF0A5A00D3DE43 /* Base.lproj */, + 18D3C9A61EDF0A5A00D3DE43 /* Images.xcassets */, + 18D3C9A71EDF0A5A00D3DE43 /* Info.plist */, + 18D3C9A81EDF0A5A00D3DE43 /* main.m */, + 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */, + 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 18D3C99D1EDF0A5A00D3DE43 /* Base.lproj */ = { + isa = PBXGroup; + children = ( + 18D3C9A21EDF0A5A00D3DE43 /* LaunchScreen.xib */, + 18D3C9A41EDF0A5A00D3DE43 /* Localizable.strings */, + ); + path = Base.lproj; + sourceTree = ""; + }; + 18D3C9A91EDF0A5A00D3DE43 /* zh-Hans.lproj */ = { + isa = PBXGroup; + children = ( + 18D3C9AE1EDF0A5A00D3DE43 /* LaunchScreen.strings */, + 18D3C9B01EDF0A5A00D3DE43 /* Localizable.strings */, + ); + path = "zh-Hans.lproj"; + sourceTree = ""; + }; + 18D3C9BD1EDF0A7900D3DE43 /* Images */ = { + isa = PBXGroup; + children = ( + 205F9EBB1F7AA6510034732C /* all.png */, + 205F9EB91F7AA5710034732C /* gl.png */, + 18D3C9BE1EDF0AB500D3DE43 /* fl.png */, + 18D3C9BF1EDF0AB500D3DE43 /* fll.png */, + 18D3C9C01EDF0AB500D3DE43 /* flo.png */, + 18D3C9C11EDF0AB500D3DE43 /* layoutdemo1.gif */, + 18D3C9C21EDF0AB500D3DE43 /* layoutdemo2.gif */, + 18D3C9C31EDF0AB500D3DE43 /* layoutdemo3.gif */, + 18D3C9C41EDF0AB500D3DE43 /* layoutdemo4.gif */, + 18D3C9C51EDF0AB500D3DE43 /* layoutdemo5.gif */, + 18D3C9C61EDF0AB500D3DE43 /* layoutdemo6.gif */, + 18D3C9C71EDF0AB500D3DE43 /* layoutdemo7.gif */, + 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */, + 18D3C9C81EDF0AB500D3DE43 /* ll.png */, + 18D3C9C91EDF0AB500D3DE43 /* MyLayout.png */, + 18D3C9CA1EDF0AB500D3DE43 /* MyLayoutClass.png */, + 18D3C9CB1EDF0AB500D3DE43 /* MyLayoutP.png */, + 18D3C9CC1EDF0AB500D3DE43 /* pl.png */, + 18D3C9CD1EDF0AB500D3DE43 /* rl.png */, + 18D3C9CE1EDF0AB500D3DE43 /* tl.png */, + ); + name = Images; + sourceTree = ""; + }; + 18D683E61C4F421400A48BB4 /* MyLayout */ = { + isa = PBXGroup; + children = ( + 18C15AEA1EDF133200AADEAC /* Info.plist */, + 18D3C9BD1EDF0A7900D3DE43 /* Images */, + 18D683FB1C4F421400A48BB4 /* Lib */, + ); + path = MyLayout; + sourceTree = ""; + }; + 18D683FB1C4F421400A48BB4 /* Lib */ = { + isa = PBXGroup; + children = ( + 18D684001C4F421400A48BB4 /* MyLayout.h */, + 182225AB1E77E5930081AA4B /* MyFlowLayout.h */, + 182225B41E77E5930081AA4B /* MyFlowLayout.m */, + 182225AC1E77E5930081AA4B /* MyLinearLayout.h */, + 182225B21E77E5930081AA4B /* MyLinearLayout.m */, + 182225AD1E77E5930081AA4B /* MyFloatLayout.h */, + 182225B91E77E5930081AA4B /* MyFloatLayout.m */, + 182225AE1E77E5930081AA4B /* MyTableLayout.h */, + 182225C31E77E5930081AA4B /* MyTableLayout.m */, + 182225BE1E77E5930081AA4B /* MyRelativeLayout.h */, + 182225B51E77E5930081AA4B /* MyRelativeLayout.m */, + 182225BD1E77E5930081AA4B /* MyPathLayout.h */, + 182225B61E77E5930081AA4B /* MyPathLayout.m */, + 182225BA1E77E5930081AA4B /* MyFrameLayout.h */, + 182225B71E77E5930081AA4B /* MyFrameLayout.m */, + 182225AF1E77E5930081AA4B /* MyBaseLayout.h */, + 182225B11E77E5930081AA4B /* MyBaseLayout.m */, + 182225B01E77E5930081AA4B /* MyLayoutPos.h */, + 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */, + 182225BB1E77E5930081AA4B /* MyLayoutPos.m */, + 182225BC1E77E5930081AA4B /* MyLayoutSize.h */, + 182225C81E77E5930081AA4B /* MyLayoutSizeInner.h */, + 182225C51E77E5930081AA4B /* MyLayoutSize.m */, + 182225C01E77E5930081AA4B /* MyLayoutSizeClass.h */, + 182225BF1E77E5930081AA4B /* MyLayoutSizeClass.m */, + 182225C21E77E5930081AA4B /* MyMaker.h */, + 182225C11E77E5930081AA4B /* MyMaker.m */, + 182225C71E77E5930081AA4B /* MyDimeScale.h */, + 182225C41E77E5930081AA4B /* MyDimeScale.m */, + 182225B81E77E5930081AA4B /* MyLayoutInner.h */, + 182225B31E77E5930081AA4B /* MyLayoutDef.h */, + 205642891F4D013D00E8BDDE /* MyGrid.h */, + 182DB6401EF7876200E2D65D /* MyGridLayout.h */, + 182DB6411EF7876200E2D65D /* MyGridLayout.m */, + 205642841F4CFF9B00E8BDDE /* MyBorderline.h */, + 205642851F4CFF9B00E8BDDE /* MyBorderline.m */, + 205643081F4E53CD00E8BDDE /* MyGridNode.h */, + 205643091F4E53CD00E8BDDE /* MyGridNode.m */, + 205643141F55A03000E8BDDE /* MyLayoutMath.h */, + 205643151F55A03000E8BDDE /* MyLayoutMath.m */, + 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */, + 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */, + ); + path = Lib; + sourceTree = ""; + }; + 18D684531C4F423400A48BB4 /* MyLayoutTests */ = { + isa = PBXGroup; + children = ( + 18D684541C4F423400A48BB4 /* Info.plist */, + 18D684551C4F423400A48BB4 /* MyLayoutTests.m */, + 189738501E16330B004F80D6 /* MyLayoutTestCaseBase.m */, + 189738521E16340D004F80D6 /* MyLayoutTestCaseBase.h */, + 1897384E1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m */, + 180BD8A01EA9EF9A00C6980B /* MyFrameLayoutTestCase.m */, + 181836941EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m */, + 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */, + 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */, + 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */, + ); + path = MyLayoutTests; + sourceTree = ""; + }; + 2043D5DA20995DF800276C68 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2043D5DB20995DF800276C68 /* CoreBluetooth.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 205CFA8B1F49BCAF00355489 /* GridLayoutDemo */ = { + isa = PBXGroup; + children = ( + 205CFA8C1F49BD1C00355489 /* GLTest1ViewController.h */, + 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */, + 205643111F51C7DF00E8BDDE /* GLTest2ViewController.h */, + 205643121F51C7EB00E8BDDE /* GLTest2ViewController.m */, + 20F783541F60398C00BE5B31 /* GLTest3ViewController.h */, + 20F783551F60399700BE5B31 /* GLTest3ViewController.m */, + 44EBDA8A1F619A6300B47CBD /* GLTest4ViewController.h */, + 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */, + 444B718F1F6A3E3F00331872 /* GLTest5ViewController.h */, + 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */, + ); + name = GridLayoutDemo; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 181A10B21EDF12CF00996203 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 2056430A1F4E53CD00E8BDDE /* MyGridNode.h in Headers */, - 18C15AEC1EDF13D700AADEAC /* MyLayout.h in Headers */, - 18C15AED1EDF13DE00AADEAC /* MyFlowLayout.h in Headers */, - 18C15AEE1EDF13E500AADEAC /* MyLinearLayout.h in Headers */, - 18C15AEF1EDF13E900AADEAC /* MyFloatLayout.h in Headers */, - 18C15AF01EDF13EF00AADEAC /* MyTableLayout.h in Headers */, - 18C15AF11EDF13F300AADEAC /* MyRelativeLayout.h in Headers */, - 18C15AF21EDF13F900AADEAC /* MyPathLayout.h in Headers */, - 205643161F55A03000E8BDDE /* MyLayoutMath.h in Headers */, - 18C15AF31EDF13FF00AADEAC /* MyFrameLayout.h in Headers */, - 18C15AF41EDF140400AADEAC /* MyBaseLayout.h in Headers */, - 18C15AF51EDF140D00AADEAC /* MyLayoutPos.h in Headers */, - 18C15AF61EDF141000AADEAC /* MyLayoutSize.h in Headers */, - 205E0C5F20B90347001A8B99 /* MyGrid.h in Headers */, - 182DB6421EF7876200E2D65D /* MyGridLayout.h in Headers */, - 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */, - 18C15AF81EDF141A00AADEAC /* MyMaker.h in Headers */, - 18C15AF71EDF141600AADEAC /* MyLayoutSizeClass.h in Headers */, - 18C15AF91EDF142000AADEAC /* MyDimeScale.h in Headers */, - 18C15AFA1EDF142300AADEAC /* MyLayoutDef.h in Headers */, - 205E0C6020B907CC001A8B99 /* MyLayoutPosInner.h in Headers */, - 205E0C6120B907D1001A8B99 /* MyLayoutSizeInner.h in Headers */, - 205E0C6220B907DB001A8B99 /* MyLayoutInner.h in Headers */, - 205E0C6320B907EC001A8B99 /* MyLayoutDelegate.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; + 181A10B21EDF12CF00996203 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2056430A1F4E53CD00E8BDDE /* MyGridNode.h in Headers */, + 18C15AEC1EDF13D700AADEAC /* MyLayout.h in Headers */, + 18C15AED1EDF13DE00AADEAC /* MyFlowLayout.h in Headers */, + 18C15AEE1EDF13E500AADEAC /* MyLinearLayout.h in Headers */, + 18C15AEF1EDF13E900AADEAC /* MyFloatLayout.h in Headers */, + 18C15AF01EDF13EF00AADEAC /* MyTableLayout.h in Headers */, + 18C15AF11EDF13F300AADEAC /* MyRelativeLayout.h in Headers */, + 18C15AF21EDF13F900AADEAC /* MyPathLayout.h in Headers */, + 205643161F55A03000E8BDDE /* MyLayoutMath.h in Headers */, + 18C15AF31EDF13FF00AADEAC /* MyFrameLayout.h in Headers */, + 18C15AF41EDF140400AADEAC /* MyBaseLayout.h in Headers */, + 18C15AF51EDF140D00AADEAC /* MyLayoutPos.h in Headers */, + 18C15AF61EDF141000AADEAC /* MyLayoutSize.h in Headers */, + 205E0C5F20B90347001A8B99 /* MyGrid.h in Headers */, + 182DB6421EF7876200E2D65D /* MyGridLayout.h in Headers */, + 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */, + 18C15AF81EDF141A00AADEAC /* MyMaker.h in Headers */, + 18C15AF71EDF141600AADEAC /* MyLayoutSizeClass.h in Headers */, + 18C15AF91EDF142000AADEAC /* MyDimeScale.h in Headers */, + 18C15AFA1EDF142300AADEAC /* MyLayoutDef.h in Headers */, + 205E0C6020B907CC001A8B99 /* MyLayoutPosInner.h in Headers */, + 205E0C6120B907D1001A8B99 /* MyLayoutSizeInner.h in Headers */, + 205E0C6220B907DB001A8B99 /* MyLayoutInner.h in Headers */, + 205E0C6320B907EC001A8B99 /* MyLayoutDelegate.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 181A10B41EDF12CF00996203 /* MyLayout */ = { - isa = PBXNativeTarget; - buildConfigurationList = 181A10BA1EDF12CF00996203 /* Build configuration list for PBXNativeTarget "MyLayout" */; - buildPhases = ( - 181A10B01EDF12CF00996203 /* Sources */, - 181A10B11EDF12CF00996203 /* Frameworks */, - 181A10B21EDF12CF00996203 /* Headers */, - 181A10B31EDF12CF00996203 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = MyLayout; - productName = MyLayout; - productReference = 181A10B51EDF12CF00996203 /* MyLayout.framework */; - productType = "com.apple.product-type.framework"; - }; - 1840828C1B2C46E8003F378B /* MyLayoutDemo */ = { - isa = PBXNativeTarget; - buildConfigurationList = 184082B01B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutDemo" */; - buildPhases = ( - 184082891B2C46E8003F378B /* Sources */, - 1840828A1B2C46E8003F378B /* Frameworks */, - 1840828B1B2C46E8003F378B /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = MyLayoutDemo; - productName = MyLayout; - productReference = 1840828D1B2C46E8003F378B /* MyLayoutDemo.app */; - productType = "com.apple.product-type.application"; - }; - 184082A51B2C46E8003F378B /* MyLayoutTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 184082B31B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutTests" */; - buildPhases = ( - 184082A21B2C46E8003F378B /* Sources */, - 184082A31B2C46E8003F378B /* Frameworks */, - 184082A41B2C46E8003F378B /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 184082A81B2C46E8003F378B /* PBXTargetDependency */, - ); - name = MyLayoutTests; - productName = MyLayoutTests; - productReference = 184082A61B2C46E8003F378B /* MyLayout.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 18B152301DEDDE5500AD7A1C /* MyLayoutUITests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 18B1523A1DEDDE5500AD7A1C /* Build configuration list for PBXNativeTarget "MyLayoutUITests" */; - buildPhases = ( - 18B1522D1DEDDE5500AD7A1C /* Sources */, - 18B1522E1DEDDE5500AD7A1C /* Frameworks */, - 18B1522F1DEDDE5500AD7A1C /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 18B152371DEDDE5500AD7A1C /* PBXTargetDependency */, - ); - name = MyLayoutUITests; - productName = MyLayoutUITests; - productReference = 18B152311DEDDE5500AD7A1C /* MyLayoutUITests.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; + 181A10B41EDF12CF00996203 /* MyLayout */ = { + isa = PBXNativeTarget; + buildConfigurationList = 181A10BA1EDF12CF00996203 /* Build configuration list for PBXNativeTarget "MyLayout" */; + buildPhases = ( + 181A10B01EDF12CF00996203 /* Sources */, + 181A10B11EDF12CF00996203 /* Frameworks */, + 181A10B21EDF12CF00996203 /* Headers */, + 181A10B31EDF12CF00996203 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MyLayout; + productName = MyLayout; + productReference = 181A10B51EDF12CF00996203 /* MyLayout.framework */; + productType = "com.apple.product-type.framework"; + }; + 1840828C1B2C46E8003F378B /* MyLayoutDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 184082B01B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutDemo" */; + buildPhases = ( + 184082891B2C46E8003F378B /* Sources */, + 1840828A1B2C46E8003F378B /* Frameworks */, + 1840828B1B2C46E8003F378B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MyLayoutDemo; + productName = MyLayout; + productReference = 1840828D1B2C46E8003F378B /* MyLayoutDemo.app */; + productType = "com.apple.product-type.application"; + }; + 184082A51B2C46E8003F378B /* MyLayoutTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 184082B31B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutTests" */; + buildPhases = ( + 184082A21B2C46E8003F378B /* Sources */, + 184082A31B2C46E8003F378B /* Frameworks */, + 184082A41B2C46E8003F378B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 184082A81B2C46E8003F378B /* PBXTargetDependency */, + ); + name = MyLayoutTests; + productName = MyLayoutTests; + productReference = 184082A61B2C46E8003F378B /* MyLayout.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 18B152301DEDDE5500AD7A1C /* MyLayoutUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18B1523A1DEDDE5500AD7A1C /* Build configuration list for PBXNativeTarget "MyLayoutUITests" */; + buildPhases = ( + 18B1522D1DEDDE5500AD7A1C /* Sources */, + 18B1522E1DEDDE5500AD7A1C /* Frameworks */, + 18B1522F1DEDDE5500AD7A1C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 18B152371DEDDE5500AD7A1C /* PBXTargetDependency */, + ); + name = MyLayoutUITests; + productName = MyLayoutUITests; + productReference = 18B152311DEDDE5500AD7A1C /* MyLayoutUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 184082851B2C46E8003F378B /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0920; - ORGANIZATIONNAME = YoungSoft; - TargetAttributes = { - 181A10B41EDF12CF00996203 = { - CreatedOnToolsVersion = 8.3.2; - DevelopmentTeam = BGQ8WB468K; - ProvisioningStyle = Automatic; - }; - 1840828C1B2C46E8003F378B = { - CreatedOnToolsVersion = 6.3.2; - DevelopmentTeam = BGQ8WB468K; - ProvisioningStyle = Automatic; - }; - 184082A51B2C46E8003F378B = { - CreatedOnToolsVersion = 6.3.2; - DevelopmentTeam = Q5MFLFRY64; - TestTargetID = 1840828C1B2C46E8003F378B; - }; - 18B152301DEDDE5500AD7A1C = { - CreatedOnToolsVersion = 8.1; - ProvisioningStyle = Automatic; - TestTargetID = 1840828C1B2C46E8003F378B; - }; - }; - }; - buildConfigurationList = 184082881B2C46E8003F378B /* Build configuration list for PBXProject "MyLayout" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - Base, - "zh-Hans", - ); - mainGroup = 184082841B2C46E8003F378B; - productRefGroup = 1840828E1B2C46E8003F378B /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 1840828C1B2C46E8003F378B /* MyLayoutDemo */, - 184082A51B2C46E8003F378B /* MyLayoutTests */, - 18B152301DEDDE5500AD7A1C /* MyLayoutUITests */, - 181A10B41EDF12CF00996203 /* MyLayout */, - ); - }; + 184082851B2C46E8003F378B /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0920; + ORGANIZATIONNAME = YoungSoft; + TargetAttributes = { + 181A10B41EDF12CF00996203 = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = BGQ8WB468K; + ProvisioningStyle = Automatic; + }; + 1840828C1B2C46E8003F378B = { + CreatedOnToolsVersion = 6.3.2; + DevelopmentTeam = BGQ8WB468K; + ProvisioningStyle = Automatic; + }; + 184082A51B2C46E8003F378B = { + CreatedOnToolsVersion = 6.3.2; + DevelopmentTeam = Q5MFLFRY64; + TestTargetID = 1840828C1B2C46E8003F378B; + }; + 18B152301DEDDE5500AD7A1C = { + CreatedOnToolsVersion = 8.1; + ProvisioningStyle = Automatic; + TestTargetID = 1840828C1B2C46E8003F378B; + }; + }; + }; + buildConfigurationList = 184082881B2C46E8003F378B /* Build configuration list for PBXProject "MyLayout" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + "zh-Hans", + ); + mainGroup = 184082841B2C46E8003F378B; + productRefGroup = 1840828E1B2C46E8003F378B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1840828C1B2C46E8003F378B /* MyLayoutDemo */, + 184082A51B2C46E8003F378B /* MyLayoutTests */, + 18B152301DEDDE5500AD7A1C /* MyLayoutUITests */, + 181A10B41EDF12CF00996203 /* MyLayout */, + ); + }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 181A10B31EDF12CF00996203 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1840828B1B2C46E8003F378B /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 181A10AA1EDF11FF00996203 /* FLLTest2ViewController.xib in Resources */, - 18D3C9D01EDF0AB500D3DE43 /* fll.png in Resources */, - 18D3C9DB1EDF0AB500D3DE43 /* MyLayoutClass.png in Resources */, - 18D3C9CF1EDF0AB500D3DE43 /* fl.png in Resources */, - 18D3C9DC1EDF0AB500D3DE43 /* MyLayoutP.png in Resources */, - 18D3C9D31EDF0AB500D3DE43 /* layoutdemo2.gif in Resources */, - 18D3C9DF1EDF0AB500D3DE43 /* tl.png in Resources */, - 18D3C9B61EDF0A5A00D3DE43 /* Images.xcassets in Resources */, - 4411977B1F6AE78E00C22557 /* GridLayoutDemo5.json in Resources */, - 18D3C9D91EDF0AB500D3DE43 /* ll.png in Resources */, - 18D3C9D11EDF0AB500D3DE43 /* flo.png in Resources */, - 18D3C9D41EDF0AB500D3DE43 /* layoutdemo3.gif in Resources */, - 18D3C9DE1EDF0AB500D3DE43 /* rl.png in Resources */, - 181A10AE1EDF123800996203 /* FOLTest1ViewController.xib in Resources */, - 18D3C9BB1EDF0A5A00D3DE43 /* LaunchScreen.strings in Resources */, - 205F9EBC1F7AA6510034732C /* all.png in Resources */, - 18D3C9B51EDF0A5A00D3DE43 /* Localizable.strings in Resources */, - 18D3C9DD1EDF0AB500D3DE43 /* pl.png in Resources */, - 44EBDA8E1F619C9000B47CBD /* GridLayoutDemo4.json in Resources */, - 18D3C9D71EDF0AB500D3DE43 /* layoutdemo6.gif in Resources */, - 18D3C9D81EDF0AB500D3DE43 /* layoutdemo7.gif in Resources */, - 18D3C9BC1EDF0A5A00D3DE43 /* Localizable.strings in Resources */, - 18D3C9D21EDF0AB500D3DE43 /* layoutdemo1.gif in Resources */, - 18D3C9D61EDF0AB500D3DE43 /* layoutdemo5.gif in Resources */, - 18D3C9DA1EDF0AB500D3DE43 /* MyLayout.png in Resources */, - 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */, - 18D3C9B41EDF0A5A00D3DE43 /* LaunchScreen.xib in Resources */, - 18D3C9D51EDF0AB500D3DE43 /* layoutdemo4.gif in Resources */, - 205F9EBA1F7AA5710034732C /* gl.png in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 184082A41B2C46E8003F378B /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18B1522F1DEDDE5500AD7A1C /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; + 181A10B31EDF12CF00996203 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1840828B1B2C46E8003F378B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 181A10AA1EDF11FF00996203 /* FLLTest2ViewController.xib in Resources */, + 18D3C9D01EDF0AB500D3DE43 /* fll.png in Resources */, + 18D3C9DB1EDF0AB500D3DE43 /* MyLayoutClass.png in Resources */, + 18D3C9CF1EDF0AB500D3DE43 /* fl.png in Resources */, + 18D3C9DC1EDF0AB500D3DE43 /* MyLayoutP.png in Resources */, + 18D3C9D31EDF0AB500D3DE43 /* layoutdemo2.gif in Resources */, + 18D3C9DF1EDF0AB500D3DE43 /* tl.png in Resources */, + 18D3C9B61EDF0A5A00D3DE43 /* Images.xcassets in Resources */, + 4411977B1F6AE78E00C22557 /* GridLayoutDemo5.json in Resources */, + 18D3C9D91EDF0AB500D3DE43 /* ll.png in Resources */, + 18D3C9D11EDF0AB500D3DE43 /* flo.png in Resources */, + 18D3C9D41EDF0AB500D3DE43 /* layoutdemo3.gif in Resources */, + 18D3C9DE1EDF0AB500D3DE43 /* rl.png in Resources */, + 181A10AE1EDF123800996203 /* FOLTest1ViewController.xib in Resources */, + 18D3C9BB1EDF0A5A00D3DE43 /* LaunchScreen.strings in Resources */, + 205F9EBC1F7AA6510034732C /* all.png in Resources */, + 18D3C9B51EDF0A5A00D3DE43 /* Localizable.strings in Resources */, + 18D3C9DD1EDF0AB500D3DE43 /* pl.png in Resources */, + 44EBDA8E1F619C9000B47CBD /* GridLayoutDemo4.json in Resources */, + 18D3C9D71EDF0AB500D3DE43 /* layoutdemo6.gif in Resources */, + 18D3C9D81EDF0AB500D3DE43 /* layoutdemo7.gif in Resources */, + 18D3C9BC1EDF0A5A00D3DE43 /* Localizable.strings in Resources */, + 18D3C9D21EDF0AB500D3DE43 /* layoutdemo1.gif in Resources */, + 18D3C9D61EDF0AB500D3DE43 /* layoutdemo5.gif in Resources */, + 18D3C9DA1EDF0AB500D3DE43 /* MyLayout.png in Resources */, + 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */, + 18D3C9B41EDF0A5A00D3DE43 /* LaunchScreen.xib in Resources */, + 18D3C9D51EDF0AB500D3DE43 /* layoutdemo4.gif in Resources */, + 205F9EBA1F7AA5710034732C /* gl.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 184082A41B2C46E8003F378B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18B1522F1DEDDE5500AD7A1C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 181A10B01EDF12CF00996203 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 18C15AFB1EDF144B00AADEAC /* MyFlowLayout.m in Sources */, - 205642871F4CFF9B00E8BDDE /* MyBorderline.m in Sources */, - 18C15AFC1EDF144B00AADEAC /* MyLinearLayout.m in Sources */, - 18C15AFD1EDF144B00AADEAC /* MyFloatLayout.m in Sources */, - 18C15AFE1EDF144B00AADEAC /* MyTableLayout.m in Sources */, - 2056430B1F4E53CD00E8BDDE /* MyGridNode.m in Sources */, - 205643171F55A03000E8BDDE /* MyLayoutMath.m in Sources */, - 18C15AFF1EDF144B00AADEAC /* MyRelativeLayout.m in Sources */, - 182DB6441EF7876200E2D65D /* MyGridLayout.m in Sources */, - 18C15B001EDF144B00AADEAC /* MyPathLayout.m in Sources */, - 18C15B011EDF144B00AADEAC /* MyFrameLayout.m in Sources */, - 18C15B021EDF144B00AADEAC /* MyBaseLayout.m in Sources */, - 18C15B031EDF144B00AADEAC /* MyLayoutPos.m in Sources */, - 18C15B041EDF144B00AADEAC /* MyLayoutSize.m in Sources */, - 208157C41F5A886400E945B6 /* MyLayoutDelegate.m in Sources */, - 18C15B051EDF144B00AADEAC /* MyLayoutSizeClass.m in Sources */, - 18C15B061EDF144B00AADEAC /* MyMaker.m in Sources */, - 18C15B071EDF144B00AADEAC /* MyDimeScale.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 184082891B2C46E8003F378B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 205643131F51C7EB00E8BDDE /* GLTest2ViewController.m in Sources */, - 18D3C9B81EDF0A5A00D3DE43 /* main.m in Sources */, - 18D3C94B1EDF07E700D3DE43 /* PLTest3ViewController.m in Sources */, - 18D3C9391EDF07C000D3DE43 /* FLLTest1ViewController.m in Sources */, - 18D3C9681EDF080800D3DE43 /* TLTest3ViewController.m in Sources */, - 182225CB1E77E5930081AA4B /* MyFlowLayout.m in Sources */, - 182225D31E77E5930081AA4B /* MyTableLayout.m in Sources */, - 18D3C95B1EDF07F800D3DE43 /* FOLTest2ViewController.m in Sources */, - 18D3C9121EDF074900D3DE43 /* LLTest2ViewController.m in Sources */, - 182225D41E77E5930081AA4B /* MyDimeScale.m in Sources */, - 18D3C92A1EDF07A700D3DE43 /* RLTest3ViewController.m in Sources */, - 208157BD1F586AA700E945B6 /* DetailViewController.m in Sources */, - 18D3C9861EDF084000D3DE43 /* AllTest2ViewController.m in Sources */, - 18D3C9731EDF082800D3DE43 /* AllTest2TableViewCell.m in Sources */, - 18D3C95F1EDF07F800D3DE43 /* FOLTest6ViewController.m in Sources */, - 182225D51E77E5930081AA4B /* MyLayoutSize.m in Sources */, - 6740E20120A52DC100AFBC5A /* AllTest10Cell.m in Sources */, - 18D3C93A1EDF07C000D3DE43 /* FLLTest2ViewController.m in Sources */, - 18D3C95A1EDF07F800D3DE43 /* FOLTest1ViewController.m in Sources */, - 182225D01E77E5930081AA4B /* MyLayoutPos.m in Sources */, - 18D3C98B1EDF084000D3DE43 /* AllTest7ViewController.m in Sources */, - 200A26DC1FA96B2400B06E7B /* AllTest9CollectionViewCell.m in Sources */, - 18D3C9881EDF084000D3DE43 /* AllTest4ViewController.m in Sources */, - 18D3C9131EDF074900D3DE43 /* LLTest3ViewController.m in Sources */, - 18D3C95E1EDF07F800D3DE43 /* FOLTest5ViewController.m in Sources */, - 18D3C99C1EDF09BE00D3DE43 /* CFTool.m in Sources */, - 18D3C9141EDF074900D3DE43 /* LLTest4ViewController.m in Sources */, - 18D3C9931EDF08F800D3DE43 /* ViewController.m in Sources */, - 18D3C93B1EDF07C000D3DE43 /* FLLTest3ViewController.m in Sources */, - 205643181F55A16400E8BDDE /* MyLayoutMath.m in Sources */, - 18D3C95C1EDF07F800D3DE43 /* FOLTest3ViewController.m in Sources */, - 18D3C9491EDF07E700D3DE43 /* PLTest1ViewController.m in Sources */, - 18D3C95D1EDF07F800D3DE43 /* FOLTest4ViewController.m in Sources */, - 2075CC3220A0B2A400BA6F65 /* FLLTest7ViewController.m in Sources */, - 182225CE1E77E5930081AA4B /* MyFrameLayout.m in Sources */, - 18D3C9941EDF08F800D3DE43 /* YYFPSLabel.m in Sources */, - 18D3C91D1EDF078200D3DE43 /* FLTest2ViewController.m in Sources */, - 18D3C9661EDF080800D3DE43 /* TLTest1ViewController.m in Sources */, - 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */, - 18D3C94A1EDF07E700D3DE43 /* PLTest2ViewController.m in Sources */, - 205642881F4CFFB600E8BDDE /* MyBorderline.m in Sources */, - 18D3C93C1EDF07C000D3DE43 /* FLLTest4ViewController.m in Sources */, - 18D3C98C1EDF084000D3DE43 /* AllTest8ViewController.m in Sources */, - 18D3C93D1EDF07C000D3DE43 /* FLLTest5ViewController.m in Sources */, - 18D3C9671EDF080800D3DE43 /* TLTest2ViewController.m in Sources */, - 18D3C99B1EDF09BE00D3DE43 /* AppDelegate.m in Sources */, - 18D3C9291EDF07A700D3DE43 /* RLTest2ViewController.m in Sources */, - 18D3C9151EDF074900D3DE43 /* LLTest5ViewController.m in Sources */, - 18D3C9891EDF084000D3DE43 /* AllTest5ViewController.m in Sources */, - 182225CC1E77E5930081AA4B /* MyRelativeLayout.m in Sources */, - 18D3C94C1EDF07E700D3DE43 /* PLTest4ViewController.m in Sources */, - 2056430C1F4E8B1E00E8BDDE /* MyGridNode.m in Sources */, - 182225D11E77E5930081AA4B /* MyLayoutSizeClass.m in Sources */, - 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */, - 18D3C9741EDF082800D3DE43 /* AllTestDataModel.m in Sources */, - 205CFA8E1F49BD1C00355489 /* GLTest1ViewController.m in Sources */, - 18D3C9171EDF074900D3DE43 /* LLTest7ViewController.m in Sources */, - 18D3C98A1EDF084000D3DE43 /* AllTest6ViewController.m in Sources */, - 18D3C9111EDF074900D3DE43 /* LLTest1ViewController.m in Sources */, - 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */, - 18D3C93E1EDF07C000D3DE43 /* FLLTest6ViewController.m in Sources */, - 200A26D91FA8A90300B06E7B /* AllTest9ViewController.m in Sources */, - 18D3C9281EDF07A700D3DE43 /* RLTest1ViewController.m in Sources */, - 182225CA1E77E5930081AA4B /* MyLinearLayout.m in Sources */, - 18D3C91C1EDF078200D3DE43 /* FLTest1ViewController.m in Sources */, - 18D3C9951EDF08F800D3DE43 /* YYWeakProxy.m in Sources */, - 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */, - 44EBDA8C1F619A6300B47CBD /* GLTest4ViewController.m in Sources */, - 18D3C9711EDF082800D3DE43 /* AllTest1TableViewCell.m in Sources */, - 182225CF1E77E5930081AA4B /* MyFloatLayout.m in Sources */, - 18D3C92B1EDF07A700D3DE43 /* RLTest4ViewController.m in Sources */, - 6740E1FB20A52DA900AFBC5A /* AllTest10Model.m in Sources */, - 18D3C92C1EDF07A700D3DE43 /* RLTest5ViewController.m in Sources */, - 204DC321209D5A8700F6CB57 /* TLTest4ViewController.m in Sources */, - 182DB6431EF7876200E2D65D /* MyGridLayout.m in Sources */, - 18D3C9871EDF084000D3DE43 /* AllTest3ViewController.m in Sources */, - 18D3C9161EDF074900D3DE43 /* LLTest6ViewController.m in Sources */, - 18D3C9721EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m in Sources */, - 208157C31F5A886400E945B6 /* MyLayoutDelegate.m in Sources */, - 18D3C94D1EDF07E700D3DE43 /* PLTest5ViewController.m in Sources */, - 6740E1F820A52D9E00AFBC5A /* AllTest10ViewController.m in Sources */, - 18D3C9851EDF084000D3DE43 /* AllTest1ViewController.m in Sources */, - 182225D21E77E5930081AA4B /* MyMaker.m in Sources */, - 182225C91E77E5930081AA4B /* MyBaseLayout.m in Sources */, - 182225CD1E77E5930081AA4B /* MyPathLayout.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 184082A21B2C46E8003F378B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 18B2CCE81EAF5066001AE0E1 /* MyLinearLayoutTestCase.m in Sources */, - 18D684591C4F423400A48BB4 /* MyLayoutTests.m in Sources */, - 1810AC221EB966D30022CBFF /* MyLayoutPerformanceTestCase.m in Sources */, - 181836951EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m in Sources */, - 180BD8A11EA9EF9A00C6980B /* MyFrameLayoutTestCase.m in Sources */, - 1897384F1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m in Sources */, - 189738511E16330B004F80D6 /* MyLayoutTestCaseBase.m in Sources */, - 18B2CCEA1EB046AC001AE0E1 /* MyFloatLayoutTestCase.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18B1522D1DEDDE5500AD7A1C /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 18B152341DEDDE5500AD7A1C /* MyLayoutUITests.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; + 181A10B01EDF12CF00996203 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18C15AFB1EDF144B00AADEAC /* MyFlowLayout.m in Sources */, + 205642871F4CFF9B00E8BDDE /* MyBorderline.m in Sources */, + 18C15AFC1EDF144B00AADEAC /* MyLinearLayout.m in Sources */, + 18C15AFD1EDF144B00AADEAC /* MyFloatLayout.m in Sources */, + 18C15AFE1EDF144B00AADEAC /* MyTableLayout.m in Sources */, + 2056430B1F4E53CD00E8BDDE /* MyGridNode.m in Sources */, + 205643171F55A03000E8BDDE /* MyLayoutMath.m in Sources */, + 18C15AFF1EDF144B00AADEAC /* MyRelativeLayout.m in Sources */, + 182DB6441EF7876200E2D65D /* MyGridLayout.m in Sources */, + 18C15B001EDF144B00AADEAC /* MyPathLayout.m in Sources */, + 18C15B011EDF144B00AADEAC /* MyFrameLayout.m in Sources */, + 18C15B021EDF144B00AADEAC /* MyBaseLayout.m in Sources */, + 18C15B031EDF144B00AADEAC /* MyLayoutPos.m in Sources */, + 18C15B041EDF144B00AADEAC /* MyLayoutSize.m in Sources */, + 208157C41F5A886400E945B6 /* MyLayoutDelegate.m in Sources */, + 18C15B051EDF144B00AADEAC /* MyLayoutSizeClass.m in Sources */, + 18C15B061EDF144B00AADEAC /* MyMaker.m in Sources */, + 18C15B071EDF144B00AADEAC /* MyDimeScale.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 184082891B2C46E8003F378B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 205643131F51C7EB00E8BDDE /* GLTest2ViewController.m in Sources */, + 18D3C9B81EDF0A5A00D3DE43 /* main.m in Sources */, + 18D3C94B1EDF07E700D3DE43 /* PLTest3ViewController.m in Sources */, + 18D3C9391EDF07C000D3DE43 /* FLLTest1ViewController.m in Sources */, + 18D3C9681EDF080800D3DE43 /* TLTest3ViewController.m in Sources */, + 182225CB1E77E5930081AA4B /* MyFlowLayout.m in Sources */, + 182225D31E77E5930081AA4B /* MyTableLayout.m in Sources */, + 18D3C95B1EDF07F800D3DE43 /* FOLTest2ViewController.m in Sources */, + 18D3C9121EDF074900D3DE43 /* LLTest2ViewController.m in Sources */, + 182225D41E77E5930081AA4B /* MyDimeScale.m in Sources */, + 18D3C92A1EDF07A700D3DE43 /* RLTest3ViewController.m in Sources */, + 208157BD1F586AA700E945B6 /* DetailViewController.m in Sources */, + 18D3C9861EDF084000D3DE43 /* AllTest2ViewController.m in Sources */, + 18D3C9731EDF082800D3DE43 /* AllTest2TableViewCell.m in Sources */, + 18D3C95F1EDF07F800D3DE43 /* FOLTest6ViewController.m in Sources */, + 182225D51E77E5930081AA4B /* MyLayoutSize.m in Sources */, + 6740E20120A52DC100AFBC5A /* AllTest10Cell.m in Sources */, + 18D3C93A1EDF07C000D3DE43 /* FLLTest2ViewController.m in Sources */, + 18D3C95A1EDF07F800D3DE43 /* FOLTest1ViewController.m in Sources */, + 182225D01E77E5930081AA4B /* MyLayoutPos.m in Sources */, + 18D3C98B1EDF084000D3DE43 /* AllTest7ViewController.m in Sources */, + 200A26DC1FA96B2400B06E7B /* AllTest9CollectionViewCell.m in Sources */, + 18D3C9881EDF084000D3DE43 /* AllTest4ViewController.m in Sources */, + 18D3C9131EDF074900D3DE43 /* LLTest3ViewController.m in Sources */, + 18D3C95E1EDF07F800D3DE43 /* FOLTest5ViewController.m in Sources */, + 18D3C99C1EDF09BE00D3DE43 /* CFTool.m in Sources */, + 18D3C9141EDF074900D3DE43 /* LLTest4ViewController.m in Sources */, + 18D3C9931EDF08F800D3DE43 /* ViewController.m in Sources */, + 18D3C93B1EDF07C000D3DE43 /* FLLTest3ViewController.m in Sources */, + 205643181F55A16400E8BDDE /* MyLayoutMath.m in Sources */, + 18D3C95C1EDF07F800D3DE43 /* FOLTest3ViewController.m in Sources */, + 18D3C9491EDF07E700D3DE43 /* PLTest1ViewController.m in Sources */, + 18D3C95D1EDF07F800D3DE43 /* FOLTest4ViewController.m in Sources */, + 2075CC3220A0B2A400BA6F65 /* FLLTest7ViewController.m in Sources */, + 182225CE1E77E5930081AA4B /* MyFrameLayout.m in Sources */, + 18D3C9941EDF08F800D3DE43 /* YYFPSLabel.m in Sources */, + 18D3C91D1EDF078200D3DE43 /* FLTest2ViewController.m in Sources */, + 18D3C9661EDF080800D3DE43 /* TLTest1ViewController.m in Sources */, + 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */, + 18D3C94A1EDF07E700D3DE43 /* PLTest2ViewController.m in Sources */, + 205642881F4CFFB600E8BDDE /* MyBorderline.m in Sources */, + 18D3C93C1EDF07C000D3DE43 /* FLLTest4ViewController.m in Sources */, + 18D3C98C1EDF084000D3DE43 /* AllTest8ViewController.m in Sources */, + 18D3C93D1EDF07C000D3DE43 /* FLLTest5ViewController.m in Sources */, + 18D3C9671EDF080800D3DE43 /* TLTest2ViewController.m in Sources */, + 18D3C99B1EDF09BE00D3DE43 /* AppDelegate.m in Sources */, + 18D3C9291EDF07A700D3DE43 /* RLTest2ViewController.m in Sources */, + 18D3C9151EDF074900D3DE43 /* LLTest5ViewController.m in Sources */, + 18D3C9891EDF084000D3DE43 /* AllTest5ViewController.m in Sources */, + 182225CC1E77E5930081AA4B /* MyRelativeLayout.m in Sources */, + 18D3C94C1EDF07E700D3DE43 /* PLTest4ViewController.m in Sources */, + 2056430C1F4E8B1E00E8BDDE /* MyGridNode.m in Sources */, + 182225D11E77E5930081AA4B /* MyLayoutSizeClass.m in Sources */, + 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */, + 18D3C9741EDF082800D3DE43 /* AllTestDataModel.m in Sources */, + 205CFA8E1F49BD1C00355489 /* GLTest1ViewController.m in Sources */, + 18D3C9171EDF074900D3DE43 /* LLTest7ViewController.m in Sources */, + 18D3C98A1EDF084000D3DE43 /* AllTest6ViewController.m in Sources */, + 18D3C9111EDF074900D3DE43 /* LLTest1ViewController.m in Sources */, + 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */, + 18D3C93E1EDF07C000D3DE43 /* FLLTest6ViewController.m in Sources */, + 200A26D91FA8A90300B06E7B /* AllTest9ViewController.m in Sources */, + 18D3C9281EDF07A700D3DE43 /* RLTest1ViewController.m in Sources */, + 182225CA1E77E5930081AA4B /* MyLinearLayout.m in Sources */, + 18D3C91C1EDF078200D3DE43 /* FLTest1ViewController.m in Sources */, + 18D3C9951EDF08F800D3DE43 /* YYWeakProxy.m in Sources */, + 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */, + 44EBDA8C1F619A6300B47CBD /* GLTest4ViewController.m in Sources */, + 18D3C9711EDF082800D3DE43 /* AllTest1TableViewCell.m in Sources */, + 182225CF1E77E5930081AA4B /* MyFloatLayout.m in Sources */, + 18D3C92B1EDF07A700D3DE43 /* RLTest4ViewController.m in Sources */, + 6740E1FB20A52DA900AFBC5A /* AllTest10Model.m in Sources */, + 18D3C92C1EDF07A700D3DE43 /* RLTest5ViewController.m in Sources */, + 204DC321209D5A8700F6CB57 /* TLTest4ViewController.m in Sources */, + 182DB6431EF7876200E2D65D /* MyGridLayout.m in Sources */, + 18D3C9871EDF084000D3DE43 /* AllTest3ViewController.m in Sources */, + 18D3C9161EDF074900D3DE43 /* LLTest6ViewController.m in Sources */, + 18D3C9721EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m in Sources */, + 208157C31F5A886400E945B6 /* MyLayoutDelegate.m in Sources */, + 18D3C94D1EDF07E700D3DE43 /* PLTest5ViewController.m in Sources */, + 6740E1F820A52D9E00AFBC5A /* AllTest10ViewController.m in Sources */, + 18D3C9851EDF084000D3DE43 /* AllTest1ViewController.m in Sources */, + 182225D21E77E5930081AA4B /* MyMaker.m in Sources */, + 182225C91E77E5930081AA4B /* MyBaseLayout.m in Sources */, + 182225CD1E77E5930081AA4B /* MyPathLayout.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 184082A21B2C46E8003F378B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18B2CCE81EAF5066001AE0E1 /* MyLinearLayoutTestCase.m in Sources */, + 18D684591C4F423400A48BB4 /* MyLayoutTests.m in Sources */, + 1810AC221EB966D30022CBFF /* MyLayoutPerformanceTestCase.m in Sources */, + 181836951EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m in Sources */, + 180BD8A11EA9EF9A00C6980B /* MyFrameLayoutTestCase.m in Sources */, + 1897384F1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m in Sources */, + 189738511E16330B004F80D6 /* MyLayoutTestCaseBase.m in Sources */, + 18B2CCEA1EB046AC001AE0E1 /* MyFloatLayoutTestCase.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18B1522D1DEDDE5500AD7A1C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18B152341DEDDE5500AD7A1C /* MyLayoutUITests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 184082A81B2C46E8003F378B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1840828C1B2C46E8003F378B /* MyLayoutDemo */; - targetProxy = 184082A71B2C46E8003F378B /* PBXContainerItemProxy */; - }; - 18B152371DEDDE5500AD7A1C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1840828C1B2C46E8003F378B /* MyLayoutDemo */; - targetProxy = 18B152361DEDDE5500AD7A1C /* PBXContainerItemProxy */; - }; + 184082A81B2C46E8003F378B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1840828C1B2C46E8003F378B /* MyLayoutDemo */; + targetProxy = 184082A71B2C46E8003F378B /* PBXContainerItemProxy */; + }; + 18B152371DEDDE5500AD7A1C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1840828C1B2C46E8003F378B /* MyLayoutDemo */; + targetProxy = 18B152361DEDDE5500AD7A1C /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - 181A10A81EDF11FF00996203 /* FLLTest2ViewController.xib */ = { - isa = PBXVariantGroup; - children = ( - 181A10A91EDF11FF00996203 /* Base */, - 181A10AB1EDF120E00996203 /* zh-Hans */, - ); - name = FLLTest2ViewController.xib; - sourceTree = ""; - }; - 181A10AC1EDF123800996203 /* FOLTest1ViewController.xib */ = { - isa = PBXVariantGroup; - children = ( - 181A10AD1EDF123800996203 /* Base */, - 181A10AF1EDF124400996203 /* zh-Hans */, - ); - name = FOLTest1ViewController.xib; - sourceTree = ""; - }; - 18D3C9A21EDF0A5A00D3DE43 /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 18D3C9A31EDF0A5A00D3DE43 /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; - 18D3C9A41EDF0A5A00D3DE43 /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - 18D3C9A51EDF0A5A00D3DE43 /* Base */, - ); - name = Localizable.strings; - sourceTree = ""; - }; - 18D3C9AE1EDF0A5A00D3DE43 /* LaunchScreen.strings */ = { - isa = PBXVariantGroup; - children = ( - 18D3C9AF1EDF0A5A00D3DE43 /* zh-Hans */, - ); - name = LaunchScreen.strings; - sourceTree = ""; - }; - 18D3C9B01EDF0A5A00D3DE43 /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - 18D3C9B11EDF0A5A00D3DE43 /* zh-Hans */, - ); - name = Localizable.strings; - sourceTree = ""; - }; + 181A10A81EDF11FF00996203 /* FLLTest2ViewController.xib */ = { + isa = PBXVariantGroup; + children = ( + 181A10A91EDF11FF00996203 /* Base */, + 181A10AB1EDF120E00996203 /* zh-Hans */, + ); + name = FLLTest2ViewController.xib; + sourceTree = ""; + }; + 181A10AC1EDF123800996203 /* FOLTest1ViewController.xib */ = { + isa = PBXVariantGroup; + children = ( + 181A10AD1EDF123800996203 /* Base */, + 181A10AF1EDF124400996203 /* zh-Hans */, + ); + name = FOLTest1ViewController.xib; + sourceTree = ""; + }; + 18D3C9A21EDF0A5A00D3DE43 /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 18D3C9A31EDF0A5A00D3DE43 /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; + 18D3C9A41EDF0A5A00D3DE43 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 18D3C9A51EDF0A5A00D3DE43 /* Base */, + ); + name = Localizable.strings; + sourceTree = ""; + }; + 18D3C9AE1EDF0A5A00D3DE43 /* LaunchScreen.strings */ = { + isa = PBXVariantGroup; + children = ( + 18D3C9AF1EDF0A5A00D3DE43 /* zh-Hans */, + ); + name = LaunchScreen.strings; + sourceTree = ""; + }; + 18D3C9B01EDF0A5A00D3DE43 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 18D3C9B11EDF0A5A00D3DE43 /* zh-Hans */, + ); + name = Localizable.strings; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - 181A10BB1EDF12CF00996203 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = BGQ8WB468K; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = MyLayout/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayout; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 181A10BC1EDF12CF00996203 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CODE_SIGN_IDENTITY = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = BGQ8WB468K; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = MyLayout/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayout; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 184082AE1B2C46E8003F378B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = ""; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 184082AF1B2C46E8003F378B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 184082B11B2C46E8003F378B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_CODE_COVERAGE = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = BGQ8WB468K; - GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; - INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutDemo; - PRODUCT_NAME = MyLayoutDemo; - PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = ""; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 184082B21B2C46E8003F378B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_CODE_COVERAGE = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = BGQ8WB468K; - GCC_PREPROCESSOR_DEFINITIONS = ""; - INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutDemo; - PRODUCT_NAME = MyLayoutDemo; - PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = ""; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 184082B41B2C46E8003F378B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - DEVELOPMENT_TEAM = Q5MFLFRY64; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = MyLayoutTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.youngsoft.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = MyLayout; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MyLayoutDemo.app/MyLayoutDemo"; - }; - name = Debug; - }; - 184082B51B2C46E8003F378B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - DEVELOPMENT_TEAM = Q5MFLFRY64; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - INFOPLIST_FILE = MyLayoutTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.youngsoft.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = MyLayout; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MyLayoutDemo.app/MyLayoutDemo"; - }; - name = Release; - }; - 18B152381DEDDE5500AD7A1C /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_SUSPICIOUS_MOVES = YES; - DEBUG_INFORMATION_FORMAT = dwarf; - INFOPLIST_FILE = MyLayoutUITests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "4bac08b2-6788-4e38-8e3e-241ebd7fba1e"; - TEST_TARGET_NAME = MyLayout; - }; - name = Debug; - }; - 18B152391DEDDE5500AD7A1C /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_SUSPICIOUS_MOVES = YES; - INFOPLIST_FILE = MyLayoutUITests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "4bac08b2-6788-4e38-8e3e-241ebd7fba1e"; - TEST_TARGET_NAME = MyLayout; - }; - name = Release; - }; + 181A10BB1EDF12CF00996203 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = BGQ8WB468K; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = MyLayout/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + OTHER_LDFLAGS = ""; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayout; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 181A10BC1EDF12CF00996203 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CODE_SIGN_IDENTITY = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = BGQ8WB468K; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = MyLayout/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + OTHER_LDFLAGS = ""; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayout; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 184082AE1B2C46E8003F378B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ""; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 184082AF1B2C46E8003F378B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 184082B11B2C46E8003F378B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_CODE_COVERAGE = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = BGQ8WB468K; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; + INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutDemo; + PRODUCT_NAME = MyLayoutDemo; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 184082B21B2C46E8003F378B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_CODE_COVERAGE = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = BGQ8WB468K; + GCC_PREPROCESSOR_DEFINITIONS = ""; + INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutDemo; + PRODUCT_NAME = MyLayoutDemo; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 184082B41B2C46E8003F378B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + DEVELOPMENT_TEAM = Q5MFLFRY64; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = MyLayoutTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.youngsoft.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = MyLayout; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MyLayoutDemo.app/MyLayoutDemo"; + }; + name = Debug; + }; + 184082B51B2C46E8003F378B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + DEVELOPMENT_TEAM = Q5MFLFRY64; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = MyLayoutTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.youngsoft.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = MyLayout; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MyLayoutDemo.app/MyLayoutDemo"; + }; + name = Release; + }; + 18B152381DEDDE5500AD7A1C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + INFOPLIST_FILE = MyLayoutUITests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "4bac08b2-6788-4e38-8e3e-241ebd7fba1e"; + TEST_TARGET_NAME = MyLayout; + }; + name = Debug; + }; + 18B152391DEDDE5500AD7A1C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + INFOPLIST_FILE = MyLayoutUITests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "4bac08b2-6788-4e38-8e3e-241ebd7fba1e"; + TEST_TARGET_NAME = MyLayout; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 181A10BA1EDF12CF00996203 /* Build configuration list for PBXNativeTarget "MyLayout" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 181A10BB1EDF12CF00996203 /* Debug */, - 181A10BC1EDF12CF00996203 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 184082881B2C46E8003F378B /* Build configuration list for PBXProject "MyLayout" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 184082AE1B2C46E8003F378B /* Debug */, - 184082AF1B2C46E8003F378B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 184082B01B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 184082B11B2C46E8003F378B /* Debug */, - 184082B21B2C46E8003F378B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 184082B31B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 184082B41B2C46E8003F378B /* Debug */, - 184082B51B2C46E8003F378B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 18B1523A1DEDDE5500AD7A1C /* Build configuration list for PBXNativeTarget "MyLayoutUITests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 18B152381DEDDE5500AD7A1C /* Debug */, - 18B152391DEDDE5500AD7A1C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; + 181A10BA1EDF12CF00996203 /* Build configuration list for PBXNativeTarget "MyLayout" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 181A10BB1EDF12CF00996203 /* Debug */, + 181A10BC1EDF12CF00996203 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 184082881B2C46E8003F378B /* Build configuration list for PBXProject "MyLayout" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 184082AE1B2C46E8003F378B /* Debug */, + 184082AF1B2C46E8003F378B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 184082B01B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 184082B11B2C46E8003F378B /* Debug */, + 184082B21B2C46E8003F378B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 184082B31B2C46E8003F378B /* Build configuration list for PBXNativeTarget "MyLayoutTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 184082B41B2C46E8003F378B /* Debug */, + 184082B51B2C46E8003F378B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18B1523A1DEDDE5500AD7A1C /* Build configuration list for PBXNativeTarget "MyLayoutUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18B152381DEDDE5500AD7A1C /* Debug */, + 18B152391DEDDE5500AD7A1C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ - }; - rootObject = 184082851B2C46E8003F378B /* Project object */; + }; + rootObject = 184082851B2C46E8003F378B /* Project object */; } diff --git a/MyLayout/Info.plist b/MyLayout/Info.plist index f705e65..5133e74 100644 --- a/MyLayout/Info.plist +++ b/MyLayout/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.5.3 + 1.5.4 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index 55d914c..2343077 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -37,7 +37,7 @@ */ -//Current version is 1.5.3, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.5.4, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. #ifndef MyLayout_MyLayout_h diff --git a/MyLayoutDemo/Info.plist b/MyLayoutDemo/Info.plist index e0e2348..881c44f 100644 --- a/MyLayoutDemo/Info.plist +++ b/MyLayoutDemo/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.5.3 + 1.5.4 CFBundleSignature ???? CFBundleVersion From a376373640a0a63db9210802d4bd9f857dc972cc Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Fri, 3 Aug 2018 18:43:32 +0800 Subject: [PATCH 020/115] =?UTF-8?q?1.=E6=B7=BB=E5=8A=A0=E5=B8=83=E5=B1=80?= =?UTF-8?q?=E8=A7=86=E5=9B=BElayoutTransform=E5=AE=9E=E7=8E=B0=E5=B8=83?= =?UTF-8?q?=E5=B1=80=E8=A7=86=E5=9B=BE=E5=86=85=E5=AD=90=E8=A7=86=E5=9B=BE?= =?UTF-8?q?=E7=9A=84=E6=95=B4=E4=BD=93=E5=9D=90=E6=A0=87=E5=8F=98=E6=8D=A2?= =?UTF-8?q?=E3=80=82=202.=E5=AF=B9=E6=B5=81=E5=BC=8F=E5=B8=83=E5=B1=80MyFl?= =?UTF-8?q?owLayout=E7=9A=84=E6=95=B0=E9=87=8F=E7=BA=A6=E6=9D=9F=E5=B8=83?= =?UTF-8?q?=E5=B1=80=E5=AE=9E=E7=8E=B0=E5=AD=90=E8=A7=86=E5=9B=BE=E5=9B=BA?= =?UTF-8?q?=E5=AE=9A=E4=BD=86=E9=97=B4=E8=B7=9D=E6=8B=89=E4=BC=B8=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E3=80=82=203.=E4=BF=AE=E5=A4=8Dlabel?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E4=B8=BAwrap=E5=8F=88=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E6=9C=80=E5=A4=A7=E5=B0=BA=E5=AF=B8=E7=9A=84?= =?UTF-8?q?BUG=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout.xcodeproj/project.pbxproj | 12 ++ MyLayout/Lib/MyBaseLayout.h | 18 +++ MyLayout/Lib/MyBaseLayout.m | 56 ++++++- MyLayout/Lib/MyFloatLayout.m | 3 + MyLayout/Lib/MyFlowLayout.h | 6 +- MyLayout/Lib/MyFlowLayout.m | 62 +++++++- MyLayout/Lib/MyFrameLayout.m | 4 +- MyLayout/Lib/MyGridLayout.m | 3 + MyLayout/Lib/MyLayoutDef.h | 5 +- MyLayout/Lib/MyLayoutInner.h | 2 + MyLayout/Lib/MyLayoutSizeClass.h | 19 ++- MyLayout/Lib/MyLayoutSizeClass.m | 5 +- MyLayout/Lib/MyLinearLayout.m | 5 +- MyLayout/Lib/MyPathLayout.m | 5 +- MyLayout/Lib/MyRelativeLayout.m | 3 + MyLayoutDemo/AllTest11ViewController.h | 16 ++ MyLayoutDemo/AllTest11ViewController.m | 188 +++++++++++++++++++++++ MyLayoutDemo/AllTest4ViewController.m | 3 + MyLayoutDemo/AppDelegate.m | 3 +- MyLayoutDemo/FLLTest8ViewController.h | 13 ++ MyLayoutDemo/FLLTest8ViewController.m | 58 +++++++ MyLayoutDemo/LLTest1ViewController.m | 26 ++++ MyLayoutDemo/ViewController.m | 8 + MyLayoutTests/MyRelativeLayoutTestCase.m | 34 ++++ 24 files changed, 534 insertions(+), 23 deletions(-) create mode 100644 MyLayoutDemo/AllTest11ViewController.h create mode 100644 MyLayoutDemo/AllTest11ViewController.m create mode 100644 MyLayoutDemo/FLLTest8ViewController.h create mode 100644 MyLayoutDemo/FLLTest8ViewController.m diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index 2205015..bfc4b06 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -163,6 +163,8 @@ 208157C41F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */ = {isa = PBXBuildFile; fileRef = 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */; }; 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */; }; + 20F0DFFD2111749A00CFCE8C /* AllTest11ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F0DFFC2111749A00CFCE8C /* AllTest11ViewController.m */; }; + 20F0E00021120A8D00CFCE8C /* FLLTest8ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F0DFFF21120A8D00CFCE8C /* FLLTest8ViewController.m */; }; 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F783551F60399700BE5B31 /* GLTest3ViewController.m */; }; 4411977B1F6AE78E00C22557 /* GridLayoutDemo5.json in Resources */ = {isa = PBXBuildFile; fileRef = 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */; }; 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */; }; @@ -401,6 +403,10 @@ 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo8.gif; sourceTree = ""; }; 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest7ViewController.h; sourceTree = ""; }; 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest7ViewController.m; sourceTree = ""; }; + 20F0DFFB2111749A00CFCE8C /* AllTest11ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AllTest11ViewController.h; sourceTree = ""; }; + 20F0DFFC2111749A00CFCE8C /* AllTest11ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest11ViewController.m; sourceTree = ""; }; + 20F0DFFE21120A8D00CFCE8C /* FLLTest8ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLLTest8ViewController.h; sourceTree = ""; }; + 20F0DFFF21120A8D00CFCE8C /* FLLTest8ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLLTest8ViewController.m; sourceTree = ""; }; 20F783541F60398C00BE5B31 /* GLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest3ViewController.h; sourceTree = ""; }; 20F783551F60399700BE5B31 /* GLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest3ViewController.m; sourceTree = ""; }; 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo5.json; sourceTree = ""; }; @@ -579,6 +585,8 @@ 18D3C9381EDF07C000D3DE43 /* FLLTest6ViewController.m */, 2075CC3020A0B29700BA6F65 /* FLLTest7ViewController.h */, 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */, + 20F0DFFE21120A8D00CFCE8C /* FLLTest8ViewController.h */, + 20F0DFFF21120A8D00CFCE8C /* FLLTest8ViewController.m */, ); name = FlowLayoutDemo; sourceTree = ""; @@ -660,6 +668,8 @@ 200A26D81FA8A90300B06E7B /* AllTest9ViewController.m */, 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */, 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */, + 20F0DFFB2111749A00CFCE8C /* AllTest11ViewController.h */, + 20F0DFFC2111749A00CFCE8C /* AllTest11ViewController.m */, 18D3C9021EDF068200D3DE43 /* AllTestModel&View */, ); name = IntegratedDemo; @@ -1119,6 +1129,7 @@ 18D3C95A1EDF07F800D3DE43 /* FOLTest1ViewController.m in Sources */, 182225D01E77E5930081AA4B /* MyLayoutPos.m in Sources */, 18D3C98B1EDF084000D3DE43 /* AllTest7ViewController.m in Sources */, + 20F0E00021120A8D00CFCE8C /* FLLTest8ViewController.m in Sources */, 200A26DC1FA96B2400B06E7B /* AllTest9CollectionViewCell.m in Sources */, 18D3C9881EDF084000D3DE43 /* AllTest4ViewController.m in Sources */, 18D3C9131EDF074900D3DE43 /* LLTest3ViewController.m in Sources */, @@ -1164,6 +1175,7 @@ 182225CA1E77E5930081AA4B /* MyLinearLayout.m in Sources */, 18D3C91C1EDF078200D3DE43 /* FLTest1ViewController.m in Sources */, 18D3C9951EDF08F800D3DE43 /* YYWeakProxy.m in Sources */, + 20F0DFFD2111749A00CFCE8C /* AllTest11ViewController.m in Sources */, 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */, 44EBDA8C1F619A6300B47CBD /* GLTest4ViewController.m in Sources */, 18D3C9711EDF082800D3DE43 /* AllTest1TableViewCell.m in Sources */, diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index dd59bc9..3a1e6f8 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -757,6 +757,24 @@ @property(nonatomic, assign) BOOL reverseLayout; +/** + 设置布局内所有子视图的位置的坐标变换,这个坐标变换不会影响到子视图的尺寸。默认值为CGAffineTransformIdentity,表示对子视图不进行任何位置变换。 + 这个属性会对布局视图内所有的子视图进行单独的位置变换,而不是进行整体的变换。在对子视图进行变换时的坐标原点是布局视图的中心点,并且是以子视图自身的中心点作为坐标变换计算的依据。 + + @note + 我们可以设置如下的值进行一些常见的位置变化: + 1.CGAffineTransformIdentity 表示恢复正常,不进行任何位置变换。 + 2.CGAffineTransformMakeTranslation(tx, ty) 表示布局视图内所有子视图的水平位置都将偏移tx, 垂直位置都将偏移ty。 + 3.CGAffineTransformMakeScale(sx,sy) 表示布局视图内所有子视图的水平位置都将缩放sx倍,所有子视图的垂直位置都将缩放sy倍。 + 4.CGAffineTransformMake(-1,0,0,1,0,0) 表示布局视图内所有子视图的位置都将水平翻转,形成水平镜像效果。 + 5.CGAffineTransformMake(1,0,0,-1,0,0) 表示布局视图内所有子视图的位置都将垂直翻转,形成垂直镜像效果。 + 6.CGAffineTransformMake(-1,0,0,-1,0,0) 表示布局视图内所有子视图的位置都将旋转180度。 + 7. 当然我们还可以进行任意的坐标变换,只要您熟悉CGAffineTransform的使用和设置方法。 + */ +@property(nonatomic, assign) CGAffineTransform layoutTransform; + + + /** *把一个布局视图放入到UIScrollView(UITableView和UICollectionView除外)内时是否自动调整UIScrollView的contentSize值。默认是MyAdjustScrollViewContentSizeModeAuto表示布局视图会自动接管UIScrollView的contentSize的值。 你可以将这个属性设置MyAdjustScrollViewContentSizeModeNo而不调整和控制contentSize的值,设置为MyAdjustScrollViewContentSizeModeYes则一定会调整contentSize. */ diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 1d7460c..d98fca5 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -997,6 +997,23 @@ -(BOOL)reverseLayout return self.myCurrentSizeClass.reverseLayout; } + + +-(CGAffineTransform)layoutTransform +{ + return self.myCurrentSizeClass.layoutTransform; +} + +-(void)setLayoutTransform:(CGAffineTransform)layoutTransform +{ + MyBaseLayout *lsc = self.myCurrentSizeClass; + if (!CGAffineTransformEqualToTransform(lsc.layoutTransform, layoutTransform)) + { + lsc.layoutTransform = layoutTransform; + [self setNeedsLayout]; + } +} + -(void)removeAllSubviews { [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; @@ -2365,7 +2382,13 @@ -(void)myCalcSizeOfWrapContentSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc sbvmyFra if (isWrapWidth || isWrapHeight) { - CGSize fitSize = [sbv sizeThatFits:CGSizeZero]; + + CGSize thatFits = CGSizeZero; + //在一些场景中,计算包裹时有可能设置了最大的尺寸约束,所以这里要进行特殊处理。 + thatFits.width = sbvsc.widthSizeInner.uBoundValInner.dimeNumVal.doubleValue; + thatFits.height = sbvsc.heightSizeInner.uBoundValInner.dimeNumVal.doubleValue; + + CGSize fitSize = [sbv sizeThatFits:thatFits]; if (isWrapWidth) { if (sbvsc.wrapContentWidth) @@ -3000,6 +3023,37 @@ -(void)myAdjustSubviewsRTLPos:(NSArray*)sbs selfWidth:(CGFloat)selfWidth myFrame.leading = selfWidth - myFrame.leading - myFrame.width; myFrame.trailing = myFrame.leading + myFrame.width; + + } + } +} + + +-(void)myAdjustSubviewsLayoutTransform:(NSArray*)sbs lsc:(MyBaseLayout*)lsc selfWidth:(CGFloat)selfWidth selfHeight:(CGFloat)selfHeight +{ + CGAffineTransform layoutTransform = lsc.layoutTransform; + if (!CGAffineTransformIsIdentity(layoutTransform)) + { + for (UIView *sbv in sbs) + { + MyFrame *myFrame = sbv.myFrame; + + //取子视图中心点坐标。因为这个坐标系的原点是布局视图的左上角,所以要转化为数学坐标系的原点坐标, 才能应用坐标变换。 + CGPoint centerPoint = CGPointMake(myFrame.leading + myFrame.width / 2 - selfWidth / 2, + myFrame.top + myFrame.height / 2 - selfHeight / 2); + + //应用坐标变换 + centerPoint = CGPointApplyAffineTransform(centerPoint, layoutTransform); + + //还原为左上角坐标系。 + centerPoint.x += selfWidth / 2; + centerPoint.y += selfHeight / 2; + + //根据中心点的变化调整开始和结束位置。 + myFrame.leading = centerPoint.x - myFrame.width / 2; + myFrame.trailing = myFrame.leading + myFrame.width; + myFrame.top = centerPoint.y - myFrame.height / 2; + myFrame.bottom = myFrame.top + myFrame.height; } } } diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 651ce38..01b714a 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -192,6 +192,9 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; + //对所有子视图进行布局变换 + [self myAdjustSubviewsLayoutTransform:sbs lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; + //对所有子视图进行RTL设置 [self myAdjustSubviewsRTLPos:sbs selfWidth:selfSize.width]; return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs lsc:lsc]; diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index bd7cb06..c0397c7 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -216,13 +216,15 @@ /** - 在内容约束流式布局的一些应用场景中我们希望子视图的宽度是固定的但间距是浮动的,这样就尽可能在一排中容纳更多的子视图。比如设置每个子视图的宽度固定为80,那么在小屏幕下每排只能放3个,而大屏幕则每排能放4个或者5个子视图。 因此您可以通过如下方法来设置子视图的固定尺寸和最小最大浮动间距。这个方法会根据您当前布局的方向不同而具有不同的意义: + 在流式布局的一些应用场景中我们希望子视图的宽度或者高度是固定的但间距是浮动的,这样就尽可能在一排中容纳更多的子视图。比如设置每个子视图的宽度固定为80,那么在小屏幕下每排只能放3个,而大屏幕则每排能放4个或者5个子视图。 因此您可以通过如下方法来设置子视图的固定尺寸和最小最大浮动间距。这个方法会根据您当前布局的方向不同而具有不同的意义: 1.如果您的布局方向是垂直的则设置的是每排内子视图的水平浮动间距,其中的subviewSize指定的是子视图的固定宽度;minSpace指定的是最小的水平间距;maxSpace指定的是最大的水平间距,如果指定的subviewSize计算出的间距大于最大间距maxSpace则会缩小subviewSize的宽度值。 2.如果您的布局方向是水平的则设置的是每排内子视图的垂直浮动间距,其中的subviewSize指定的是子视图的固定高度;minSpace指定的是最小的垂直间距;maxSpace指定的是最大的垂直间距,如果指定的subviewSize计算出的间距大于最大间距maxSpace则会调整subviewSize的高度值。 - @note 如果您不想使用浮动间距则请将subviewSize设置为0就可以了。这个方法只在内容约束流式布局里面设置才有意义。 + @note 如果您不想使用浮动间距则请将subviewSize设置为0就可以了。 + + @note 对于数量约束流式布局来说,因为每行和每列的数量的固定的,因此不存在根据屏幕的大小自动换行的能力以及进行最佳数量的排列,但是可以使用这个方法来实现所有子视图尺寸固定但是间距是浮动的功能需求。 @param subviewSize 指定子视图的尺寸。 @param minSpace 指定子视图之间的最小间距 diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 134c24d..751e8a0 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -221,7 +221,9 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //调整布局视图自己的尺寸。 [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; - //如果是反向则调整所有子视图的左右位置。 + //对所有子视图进行布局变换 + [self myAdjustSubviewsLayoutTransform:sbs lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; + //对所有子视图进行RTL设置 [self myAdjustSubviewsRTLPos:sbs selfWidth:selfSize.width]; return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs lsc:lsc]; @@ -1003,6 +1005,27 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; + CGFloat subviewSize = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).subviewSize; + if (subviewSize != 0) + { + CGFloat maxSpace = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).maxSpace; + CGFloat minSpace = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).minSpace; + if (arrangedCount > 1) + { + horzSpace = (selfSize.width - paddingHorz - subviewSize * arrangedCount)/(arrangedCount - 1); + if (_myCGFloatGreat(horzSpace, maxSpace) || _myCGFloatLess(horzSpace, minSpace)) + { + if (_myCGFloatGreat(horzSpace, maxSpace)) + horzSpace = maxSpace; + if (_myCGFloatLess(horzSpace, minSpace)) + horzSpace = minSpace; + + subviewSize = (selfSize.width - paddingHorz - horzSpace * (arrangedCount - 1)) / arrangedCount; + + } + } + } + #if TARGET_OS_IOS //判断父滚动视图是否分页滚动 BOOL isPagingScroll = (self.superview != nil && @@ -1084,6 +1107,9 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst } else { + if (subviewSize != 0) + rect.size.width = subviewSize; + if (pagingItemWidth != 0) rect.size.width = pagingItemWidth; @@ -1459,6 +1485,9 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb if (sbvsc.widthSizeInner.dimeNumVal != nil) rect.size.width = sbvsc.widthSizeInner.measure; + if (subviewSize != 0) + rect.size.height = subviewSize; + if (sbvsc.heightSizeInner.dimeNumVal != nil) rect.size.height = sbvsc.heightSizeInner.measure; @@ -1512,15 +1541,14 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb if (sbvsc.widthSizeInner.dimeNumVal != nil) rect.size.width = sbvsc.widthSizeInner.measure; + if (subviewSize != 0) + rect.size.height = subviewSize; + if (sbvsc.heightSizeInner.dimeNumVal != nil) rect.size.height = sbvsc.heightSizeInner.measure; [self mySetSubviewRelativeDimeSize:sbvsc.heightSizeInner selfSize:selfSize lsc:lsc pRect:&rect]; - if (subviewSize != 0) - rect.size.height = subviewSize; - - [self mySetSubviewRelativeDimeSize:sbvsc.widthSizeInner selfSize:selfSize lsc:lsc pRect:&rect]; @@ -1706,6 +1734,27 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; + CGFloat subviewSize = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).subviewSize; + if (subviewSize != 0) + { + + CGFloat maxSpace = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).maxSpace; + CGFloat minSpace = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).minSpace; + if (arrangedCount > 1) + { + vertSpace = (selfSize.height - paddingVert - subviewSize * arrangedCount)/(arrangedCount - 1); + if (_myCGFloatGreat(vertSpace, maxSpace) || _myCGFloatLess(vertSpace, minSpace)) + { + if (_myCGFloatGreat(vertSpace, maxSpace)) + vertSpace = maxSpace; + if (_myCGFloatLess(vertSpace, minSpace)) + vertSpace = minSpace; + + subviewSize = (selfSize.height - paddingVert - vertSpace * (arrangedCount - 1)) / arrangedCount; + + } + } + } //父滚动视图是否分页滚动。 #if TARGET_OS_IOS @@ -1803,6 +1852,9 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst BOOL isFlexedHeight = sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]] && sbvsc.heightSizeInner.dimeRelaVal.view != self; + if (subviewSize != 0) + rect.size.height = subviewSize; + if (pagingItemHeight != 0) rect.size.height = pagingItemHeight; diff --git a/MyLayout/Lib/MyFrameLayout.m b/MyLayout/Lib/MyFrameLayout.m index 6d70d10..e918c03 100644 --- a/MyLayout/Lib/MyFrameLayout.m +++ b/MyLayout/Lib/MyFrameLayout.m @@ -98,7 +98,9 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( } - //如果是反向则调整左右位置。 + //对所有子视图进行布局变换 + [self myAdjustSubviewsLayoutTransform:sbs lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; + //对所有子视图进行RTL设置 [self myAdjustSubviewsRTLPos:sbs selfWidth:selfSize.width]; return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs lsc:lsc]; diff --git a/MyLayout/Lib/MyGridLayout.m b/MyLayout/Lib/MyGridLayout.m index 16ad83a..c0db472 100644 --- a/MyLayout/Lib/MyGridLayout.m +++ b/MyLayout/Lib/MyGridLayout.m @@ -919,6 +919,9 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; + //对所有子视图进行布局变换 + [self myAdjustSubviewsLayoutTransform:sbs lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; + //对所有子视图进行RTL设置 [self myAdjustSubviewsRTLPos:sbs selfWidth:selfSize.width]; return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs lsc:lsc]; diff --git a/MyLayout/Lib/MyLayoutDef.h b/MyLayout/Lib/MyLayoutDef.h index 23c6a78..493ad4b 100644 --- a/MyLayout/Lib/MyLayoutDef.h +++ b/MyLayout/Lib/MyLayoutDef.h @@ -123,8 +123,7 @@ typedef enum : unsigned short { *设置当将布局视图嵌入到UIScrollView以及其派生类时对UIScrollView的contentSize的调整设置模式的枚举类型定义。 *当将一个布局视图作为子视图添加到UIScrollView或者其派生类时(UITableView,UICollectionView除外)系统会自动调整和计算并设置其中的contentSize值。您可以使用布局视图的属性adjustScrollViewContentSizeMode来进行设置定义的枚举值。 */ -typedef enum :unsigned char -{ +typedef enum :unsigned char { /**自动调整,在添加到UIScrollView之前(UITableView, UICollectionView除外)。如果值被设置Auto则在添加到父视图后自动会变为YES。*/ MyAdjustScrollViewContentSizeModeAuto = 0, /**不调整,任何加入到UIScrollView中的布局视图在尺寸变化时都不会调整和设置contentSize的值。*/ @@ -138,7 +137,7 @@ typedef enum :unsigned char /** *用来设置当线性布局中的子视图的尺寸大于线性布局的尺寸时的子视图的压缩策略和压缩内容枚举类型定义。请参考线性布局的shrinkType属性的定义。 */ -typedef enum : NSUInteger { +typedef enum : unsigned char { /**不压缩。*/ MySubviewsShrink_None = 0, /**平均压缩。*/ diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index 2656da2..0ecc9ad 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -96,6 +96,8 @@ -(void)myAdjustSubviewsRTLPos:(NSArray*)sbs selfWidth:(CGFloat)selfWidth; +-(void)myAdjustSubviewsLayoutTransform:(NSArray*)sbs lsc:(MyBaseLayout*)lsc selfWidth:(CGFloat)selfWidth selfHeight:(CGFloat)selfHeight; + -(MyGravity)myConvertLeftRightGravityToLeadingTrailing:(MyGravity)horzGravity; //为支持iOS11的safeArea而进行的padding的转化 diff --git a/MyLayout/Lib/MyLayoutSizeClass.h b/MyLayout/Lib/MyLayoutSizeClass.h index 6fbca6a..42167e6 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.h +++ b/MyLayout/Lib/MyLayoutSizeClass.h @@ -96,6 +96,15 @@ @interface MyLayoutViewSizeClass : MyViewSizeClass +@property(nonatomic, assign) BOOL zeroPadding; + +@property(nonatomic, assign) BOOL reverseLayout; +@property(nonatomic, assign) CGAffineTransform layoutTransform; //布局变换。 + +@property(nonatomic, assign) MyGravity gravity; + +@property(nonatomic, assign) BOOL insetLandscapeFringePadding; + @property(nonatomic, assign) CGFloat topPadding; @property(nonatomic, assign) CGFloat leadingPadding; @property(nonatomic, assign) CGFloat bottomPadding; @@ -107,10 +116,8 @@ @property(nonatomic, assign) CGFloat rightPadding; -@property(nonatomic, assign) BOOL zeroPadding; @property(nonatomic, assign) UIRectEdge insetsPaddingFromSafeArea; -@property(nonatomic, assign) BOOL insetLandscapeFringePadding; @@ -118,9 +125,8 @@ @property(nonatomic, assign) CGFloat subviewHSpace; @property(nonatomic, assign) CGFloat subviewSpace; -@property(nonatomic, assign) MyGravity gravity; -@property(nonatomic, assign) BOOL reverseLayout; //逆序布局,子视图从后往前。 + @@ -153,10 +159,11 @@ @interface MyFlowLayoutViewSizeClass : MySequentLayoutViewSizeClass +@property(nonatomic,assign) MyGravity arrangedGravity; +@property(nonatomic,assign) BOOL autoArrange; + @property(nonatomic,assign) NSInteger arrangedCount; @property(nonatomic, assign) NSInteger pagedCount; -@property(nonatomic,assign) BOOL autoArrange; -@property(nonatomic,assign) MyGravity arrangedGravity; @property(nonatomic, assign) CGFloat subviewSize; @property(nonatomic, assign) CGFloat minSpace; diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index 6a8f720..e9385fd 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -558,7 +558,7 @@ -(id)init _zeroPadding = YES; _insetsPaddingFromSafeArea = UIRectEdgeLeft | UIRectEdgeRight; _insetLandscapeFringePadding = NO; - + _layoutTransform = CGAffineTransformIdentity; } return self; @@ -818,6 +818,7 @@ - (id)copyWithZone:(NSZone *)zone lsc.insetLandscapeFringePadding = self.insetLandscapeFringePadding; lsc.gravity = self.gravity; lsc.reverseLayout = self.reverseLayout; + lsc.layoutTransform = self.layoutTransform; lsc.subviewVSpace = self.subviewVSpace; lsc.subviewHSpace = self.subviewHSpace; @@ -833,7 +834,7 @@ -(NSString*)debugDescription NSStringFromUIEdgeInsets(self.padding), self.zeroPadding?@"YES":@"NO", self.gravity, - self.reverseLayout ? @"YES":@"NO", + self.reverseLayout?@"YES":@"NO", self.subviewVSpace, self.subviewHSpace ]; diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index c01bc58..e3ab689 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -247,7 +247,10 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //调整布局视图自己的尺寸。 [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; - //如果是反向则调整所有子视图的左右位置。 + + //对所有子视图进行布局变换 + [self myAdjustSubviewsLayoutTransform:sbs lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; + //对所有子视图进行RTL设置 [self myAdjustSubviewsRTLPos:sbs selfWidth:selfSize.width]; return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs lsc:lsc]; diff --git a/MyLayout/Lib/MyPathLayout.m b/MyLayout/Lib/MyPathLayout.m index 6a6714a..b8ae21f 100644 --- a/MyLayout/Lib/MyPathLayout.m +++ b/MyLayout/Lib/MyPathLayout.m @@ -821,8 +821,11 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; + //对所有子视图进行布局变换 + [self myAdjustSubviewsLayoutTransform:sbs lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; + //路径布局不支持RTL。 - // [self myAdjustSubviewsRTLPos:sbs2 selfWidth:selfSize.width]; + return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs2 lsc:lsc]; } diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 2264900..9838590 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -114,6 +114,9 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //如果是反向则调整所有子视图的左右位置。 NSArray *sbs2 = [self myGetLayoutSubviews]; + //对所有子视图进行布局变换 + [self myAdjustSubviewsLayoutTransform:sbs2 lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; + //对所有子视图进行RTL设置 [self myAdjustSubviewsRTLPos:sbs2 selfWidth:selfSize.width]; return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs2 lsc:lsc]; diff --git a/MyLayoutDemo/AllTest11ViewController.h b/MyLayoutDemo/AllTest11ViewController.h new file mode 100644 index 0000000..fe88ad8 --- /dev/null +++ b/MyLayoutDemo/AllTest11ViewController.h @@ -0,0 +1,16 @@ +// +// AllTest11ViewController.h +// MyLayoutDemo +// +// Created by oubaiquan on 2018/8/1. +// Copyright © 2018年 YoungSoft. All rights reserved. +// + +#import + +/** + *❁5.Subviews layout transform + */ +@interface AllTest11ViewController : UIViewController + +@end diff --git a/MyLayoutDemo/AllTest11ViewController.m b/MyLayoutDemo/AllTest11ViewController.m new file mode 100644 index 0000000..ea15526 --- /dev/null +++ b/MyLayoutDemo/AllTest11ViewController.m @@ -0,0 +1,188 @@ +// +// AllTest11ViewController.m +// MyLayoutDemo +// +// Created by oubaiquan on 2018/8/1. +// Copyright © 2018年 YoungSoft. All rights reserved. +// + +#import "AllTest11ViewController.h" +#import "MyLayout.h" +#import "CFTool.h" + +@interface AllTest11ViewController () + +@property(nonatomic, strong) MyBaseLayout *contentLayout; //对于布局视图来说,所有种类布局的布局视图都支持layoutTransform属性。 + +@end + +@implementation AllTest11ViewController + +-(void)loadView +{ + /* + + 这个DEMO主要用来演示布局视图的layoutTransform属性的使用和设置方法,这个属性用来对布局视图内所有子视图的位置进行坐标变换。只要你了解CGAffineTransform的设置和使用 + 方法,就可以用他来进行各种布局视图内子视图的整体的坐标变换,比如:平移、缩放、水平反转、垂直反转、旋转等以及一些复合的坐标变换。在下面的例子里面我分别列举了一些常见的布局位置 + 坐标变换的设置方法以及参数。 + + */ + + self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + + + MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + rootLayout.gravity = MyGravity_Horz_Fill; //里面所有子视图的宽度都填充为和父视图一样宽。 + rootLayout.backgroundColor = [UIColor whiteColor]; + self.view = rootLayout; + + //添加操作按钮。 + MyFlowLayout *actionLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; + actionLayout.wrapContentHeight = YES; + actionLayout.gravity = MyGravity_Horz_Fill; //所有子视图水平填充,也就是所有子视图的宽度相等。 + actionLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); + actionLayout.subviewHSpace = 5; + actionLayout.subviewVSpace = 5; + [rootLayout addSubview:actionLayout]; + + [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"Identity", @"") + action:@selector(handleIdentityTransform:)]]; + [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"Translation", @"") + action:@selector(handleTranslationTransform:)]]; + [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"Scale", @"") + action:@selector(handleScaleTransform:)]]; + [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"Horz Reflection", @"") + action:@selector(handleHorzReflectionTransform:)]]; + [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"Vert Reflection", @"") + action:@selector(handleVertReflectionTransform:)]]; + [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"Reverse", @"") + action:@selector(handleReverseTransform:)]]; + + MyFlowLayout *contentLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:4]; + contentLayout.backgroundColor = [CFTool color:5]; + contentLayout.weight = 1.0; //占用线性布局中的剩余高度。 + contentLayout.subviewSpace = 10; + [rootLayout addSubview:contentLayout]; + self.contentLayout = contentLayout; + + for (int i = 0; i < 14; i++) + { + UILabel *label = [UILabel new]; + label.text = [NSString stringWithFormat:@"%d", i]; + label.backgroundColor = [UIColor redColor]; + label.mySize = CGSizeMake(40, 40); + label.textAlignment = NSTextAlignmentCenter; + [contentLayout addSubview:label]; + } + + + +} + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +#pragma mark -- Layout Construction + +//创建动作操作按钮。 +-(UIButton*)createActionButton:(NSString*)title action:(SEL)action +{ + UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; + [button setTitle:title forState:UIControlStateNormal]; + button.titleLabel.font = [CFTool font:14]; + [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside]; + button.myHeight = 30; + button.layer.borderColor = [UIColor lightGrayColor].CGColor; + button.layer.borderWidth = 0.5; + + return button; + +} + +#pragma mark -- Handle Method + +-(void)handleIdentityTransform:(id)sender +{ + //还原位置的坐标变换,这也是默认值。 + self.contentLayout.layoutTransform = CGAffineTransformIdentity; + [self.contentLayout layoutAnimationWithDuration:0.3]; +} + +-(void)handleTranslationTransform:(id)sender +{ + //子视图的整体水平和垂直的平移变换。 + static BOOL flag = YES; + if (flag) + self.contentLayout.layoutTransform = CGAffineTransformMakeTranslation(100, 0); + else + self.contentLayout.layoutTransform = CGAffineTransformMakeTranslation(100, 100); + + flag = !flag; + + [self.contentLayout layoutAnimationWithDuration:0.3]; +} + +-(void)handleScaleTransform:(id)sender +{ + //布局内子视图位置的放大和缩小的位置变换。因为缩放是以布局视图的中心点为中心进行缩放的,所以如果是想要以某个点为中心进行缩放。所以在缩放的同时还需要进行位移的调整。 + //下面的例子里面,因为缩放默认是以布局视图的中心点为中心进行缩放,但这里是想以第一个子视图保持不变而进行缩放,所以除了要进行缩放外,还需要调整所有子视图的偏移,因为第一个 + //子视图的中心点的位置按照布局视图中心点原点坐标的话位置是: (20 - 布局视图的宽度/2, 20 - 布局视图的高度/2), 这里的20是因为视图的高度都是40。 + //所以只要保证第一个子视图的中心点在放大后的位置还是一样,就会实现以第一个子视图为中心进行放大的效果。 + + + CGSize size = self.contentLayout.frame.size; + + //缩放因子。 + static CGFloat factor = 2; + self.contentLayout.layoutTransform = CGAffineTransformMake(factor, 0, 0, factor, (1 - factor) * (20 - size.width / 2.0), (1 - factor) * (20 - size.height / 2)); //这里因为要让第一个子视图的位置保持不变,所以tx,ty参数需要进行特殊设置。 + + if (factor == 2) + factor = 0.9; + else + factor = 2; + + [self.contentLayout layoutAnimationWithDuration:0.3]; +} + +-(void)handleHorzReflectionTransform:(id)sender +{ + //布局内所有子视图都进行水平翻转排列,也就是水平镜像的效果。 + self.contentLayout.layoutTransform = CGAffineTransformMake(-1,0,0,1,0,0); + [self.contentLayout layoutAnimationWithDuration:0.3]; +} + +-(void)handleVertReflectionTransform:(id)sender +{ + //布局内所有子视图都进行垂直翻转排列,也就是垂直镜像的效果。 + self.contentLayout.layoutTransform = CGAffineTransformMake(1,0,0,-1,0,0); + [self.contentLayout layoutAnimationWithDuration:0.3]; + +} + + +-(void)handleReverseTransform:(id)sender +{ + //布局内所有子视图整体翻转180度的效果。 + self.contentLayout.layoutTransform = CGAffineTransformMake(-1,0,0,-1,0,0); + [self.contentLayout layoutAnimationWithDuration:0.3]; +} + +@end diff --git a/MyLayoutDemo/AllTest4ViewController.m b/MyLayoutDemo/AllTest4ViewController.m index 1c12c1c..9fd41c1 100644 --- a/MyLayoutDemo/AllTest4ViewController.m +++ b/MyLayoutDemo/AllTest4ViewController.m @@ -265,9 +265,12 @@ -(void)handleReverse:(id)sender { //MyBaseLayout的属性reverseLayout可以将子视图按照添加的顺序逆序布局。 + for (MyBaseLayout *layout in self.containerLayouts) { + layout.reverseLayout = !layout.reverseLayout; + [layout layoutAnimationWithDuration:0.3]; } } diff --git a/MyLayoutDemo/AppDelegate.m b/MyLayoutDemo/AppDelegate.m index 503cf71..262a7c6 100644 --- a/MyLayoutDemo/AppDelegate.m +++ b/MyLayoutDemo/AppDelegate.m @@ -33,7 +33,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( ViewController *vc = [[ViewController alloc] init]; - UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; + UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; + nav.navigationBar.translucent = NO; self.window.rootViewController = nav; [self.window makeKeyAndVisible]; diff --git a/MyLayoutDemo/FLLTest8ViewController.h b/MyLayoutDemo/FLLTest8ViewController.h new file mode 100644 index 0000000..630431a --- /dev/null +++ b/MyLayoutDemo/FLLTest8ViewController.h @@ -0,0 +1,13 @@ +// +// FLLTest8ViewController.h +// MyLayoutDemo +// +// Created by oubaiquan on 2018/8/1. +// Copyright © 2018年 YoungSoft. All rights reserved. +// + +#import + +@interface FLLTest8ViewController : UIViewController + +@end diff --git a/MyLayoutDemo/FLLTest8ViewController.m b/MyLayoutDemo/FLLTest8ViewController.m new file mode 100644 index 0000000..42be025 --- /dev/null +++ b/MyLayoutDemo/FLLTest8ViewController.m @@ -0,0 +1,58 @@ +// +// FLLTest8ViewController.m +// MyLayoutDemo +// +// Created by oubaiquan on 2018/8/1. +// Copyright © 2018年 YoungSoft. All rights reserved. +// + +#import "FLLTest8ViewController.h" +#import "MyFlowLayout.h" + +@interface FLLTest8ViewController () + +@end + +@implementation FLLTest8ViewController + +-(void)loadView +{ + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:4]; + rootLayout.gravity = MyGravity_Vert_Between; + + for (int i = 0; i < 14; i++) + { + UILabel *label = [UILabel new]; + label.myHeight = 60; + label.backgroundColor = [UIColor redColor]; + [rootLayout addSubview:label]; + } + + [rootLayout setSubviewsSize:60 minSpace:0 maxSpace:CGFLOAT_MAX]; + + self.view = rootLayout; + + +} + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/MyLayoutDemo/LLTest1ViewController.m b/MyLayoutDemo/LLTest1ViewController.m index 6ed3764..a211948 100644 --- a/MyLayoutDemo/LLTest1ViewController.m +++ b/MyLayoutDemo/LLTest1ViewController.m @@ -20,6 +20,32 @@ @implementation LLTest1ViewController -(void)loadView { + MyFloatLayout *roo1 = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Horz]; + roo1.subviewHSpace = 10; + roo1.subviewVSpace = 10; + roo1.layoutTransform = CGAffineTransformMake(0, 1, 1, 0, 0, 0); + self.view = roo1; + + for (int i = 0; i < 10; i++) + { + UILabel *v1 = [UILabel new]; + v1.backgroundColor = [UIColor redColor]; + v1.text = [NSString stringWithFormat:@"%d",i]; + v1.mySize = CGSizeMake(100, 100); + + if (i % 4 == 0) + { + v1.clearFloat = YES; + } + + [roo1 addSubview:v1]; + } + + + + return; + + /* 使用MyLayout时必读的知识点: diff --git a/MyLayoutDemo/ViewController.m b/MyLayoutDemo/ViewController.m index 1f757ea..4b7bb8e 100644 --- a/MyLayoutDemo/ViewController.m +++ b/MyLayoutDemo/ViewController.m @@ -42,6 +42,7 @@ #import "FLLTest5ViewController.h" #import "FLLTest6ViewController.h" #import "FLLTest7ViewController.h" +#import "FLLTest8ViewController.h" #import "AllTest1ViewController.h" @@ -54,6 +55,7 @@ #import "AllTest8ViewController.h" #import "AllTest9ViewController.h" #import "AllTest10ViewController.h" +#import "AllTest11ViewController.h" #import "FOLTest1ViewController.h" @@ -187,6 +189,9 @@ -(NSArray*)demoTypeList }, @{@"title":NSLocalizedString(@"7.FlowLayout - Auto Arrange", @""), @"class":[FLLTest7ViewController class] + }, + @{@"title":NSLocalizedString(@"8.FlowLayout - Flex space", @""), + @"class":[FLLTest8ViewController class] } ] }, @@ -288,6 +293,9 @@ -(NSArray*)demoTypeList }, @{@"title":NSLocalizedString(@"❁4.Circle of friends height self-adaption", @""), @"class":[AllTest10ViewController class] + }, + @{@"title":NSLocalizedString(@"❁5.Subviews layout transform", @""), + @"class":[AllTest11ViewController class] } ] } diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index fba316d..84c9230 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -877,6 +877,40 @@ -(void)testBaseline } +-(void)testMaxHeightAndWidth +{ + MyRelativeLayout *rellayout = [MyRelativeLayout new]; + + UIView *vv = [UIView new]; + [rellayout addSubview:vv]; + + UILabel *label = [UILabel new]; + [rellayout addSubview:label]; + + label.myLeft = 10; + label.wrapContentWidth = YES; + label.widthSize.max(100); + label.wrapContentHeight = YES; + + + vv.topPos.equalTo(label.topPos); + vv.bottomPos.equalTo(label.bottomPos); + vv.leftPos.equalTo(label.leftPos); + vv.rightPos.equalTo(label.rightPos); + + + label.text = @"测试12345660392034323"; + vv.backgroundColor = [UIColor redColor]; + + [rellayout sizeThatFits:CGSizeZero]; + + XCTAssertTrue(CGSizeEqualToSize(label.estimatedRect.size, CGSizeMake(90, 61))); + XCTAssertTrue(CGSizeEqualToSize(vv.estimatedRect.size, CGSizeMake(90, 61))); + XCTAssertTrue(CGSizeEqualToSize(vv.estimatedRect.size, label.estimatedRect.size)); + + +} + - (void)testPerformanceExample { // This is an example of a performance test case. [self measureBlock:^{ From a4760ffdef74fd7cf55034a805a65aaa00a27eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E9=98=B3=E5=A4=A7=E5=93=A52013?= Date: Fri, 3 Aug 2018 21:54:30 +0800 Subject: [PATCH 021/115] Delete .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index ad8409f0e75e1096920fdc495e4f97c6d13adaa3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK!Ab)`41K9R6ucBq-kdKG`v*g*H$CkSD6Leac9&ws-saPN$waichaQSZNnrA_ znIyCGU}rV}WV&5UfH8m(hoY#_BkJy*8hG#-QLM%eEw*^WH9mR@{YRI+`vvZ?!yO)} zzu$jOdx0l(*wA`eEho*qeeG-$gR7fE^SbAsd6s_Adhg9u0w7^f`MQl7zhS} zfuk|t_sZz}XcePSFc1u!3IlpRBo4*wSSs4lL1irfaY(lbZS5sACpl)vQjs$hsj0-8 zD&As9O{YJ3Ty`uKYdXZ65Al`1nisLvSwC4gBv%X_3 Date: Sat, 4 Aug 2018 12:13:49 +0800 Subject: [PATCH 022/115] Release V1.6.0 --- CHANGELOG.md | 10 +++ MyLayout.podspec | 2 +- MyLayout/Lib/MyLayout.h | 2 +- MyLayoutDemo/AllTest11ViewController.m | 5 ++ MyLayoutDemo/FLLTest8ViewController.h | 1 + MyLayoutDemo/FLLTest8ViewController.m | 68 ++++++++++++++++--- MyLayoutDemo/LLTest1ViewController.m | 27 -------- .../zh-Hans.lproj/Localizable.strings | 16 ++++- 8 files changed, 92 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8454c38..7e50f52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ **MyLayout**的所有版本的变更日志都将会在这里记录. --- +## [V1.6.0](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.6.0)(2018/08/04) + +#### Added +1. 添加布局属性`layoutTransform`,用来实现对布局内子视图的整体位置变换,可以通过这个属性来实现一般常见的平移,缩放,水平翻转,垂直翻转等功能。具体的DEMO在新增加的[AllTest11ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/AllTest11ViewController.m)中可以查看。 +2. 为流式布局`MyFlowLayout`支持子视图固定尺寸并且间距动态拉伸调整的能力,你可以通过设置流式布局的方法:`setSubviewsSize:minSpace:maxSpace:`来实现,这个方法原先只支持内容约束流式布局,现在新版本对数量约束流式布局也同样支持了。具体的DEMO在新增加的[FLLTest8ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/FLLTest8ViewController.m)中可以查看。 + +#### Fixed +1. 修复了UILabel等控件的尺寸设置了wrapContentHeight或者wrapContentWidth为YES并且同时又设置了最大最小尺寸时,在相对布局内进行尺寸计算内可能会出现的问题。 +2. 修复了通过Carthage引入库时出现符合以及文件无法找到的问题。 + ## [V1.5.3](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.5.3)(2018/05/11) diff --git a/MyLayout.podspec b/MyLayout.podspec index 0f89412..b19b31c 100644 --- a/MyLayout.podspec +++ b/MyLayout.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "MyLayout" - s.version = "1.5.3" + s.version = "1.6.0" s.summary = "MyLayout is an iOS UI framework integrates the functions with Android,AutoLayout,SizeClass,HTML CSS float and flexbox,UIView UITableView." s.description = <<-DESC diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index 2343077..bbae89c 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -37,7 +37,7 @@ */ -//Current version is 1.5.4, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.6.0, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. #ifndef MyLayout_MyLayout_h diff --git a/MyLayoutDemo/AllTest11ViewController.m b/MyLayoutDemo/AllTest11ViewController.m index ea15526..4c2a77b 100644 --- a/MyLayoutDemo/AllTest11ViewController.m +++ b/MyLayoutDemo/AllTest11ViewController.m @@ -26,6 +26,9 @@ -(void)loadView 方法,就可以用他来进行各种布局视图内子视图的整体的坐标变换,比如:平移、缩放、水平反转、垂直反转、旋转等以及一些复合的坐标变换。在下面的例子里面我分别列举了一些常见的布局位置 坐标变换的设置方法以及参数。 + + 当你的布局内所有视图都需要有统一的变换的动画时,你可以借助layoutTransform属性并且配合layoutAnimationWithDuration方法来实现动画效果。 + */ self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 @@ -58,6 +61,8 @@ -(void)loadView [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"Reverse", @"") action:@selector(handleReverseTransform:)]]; + + //下面是用于测试的layoutTransform属性的布局视图,本系统中的所有布局视图都支持layoutTransform属性。 MyFlowLayout *contentLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:4]; contentLayout.backgroundColor = [CFTool color:5]; contentLayout.weight = 1.0; //占用线性布局中的剩余高度。 diff --git a/MyLayoutDemo/FLLTest8ViewController.h b/MyLayoutDemo/FLLTest8ViewController.h index 630431a..c689109 100644 --- a/MyLayoutDemo/FLLTest8ViewController.h +++ b/MyLayoutDemo/FLLTest8ViewController.h @@ -8,6 +8,7 @@ #import +/*8.FlowLayout - Flex space*/ @interface FLLTest8ViewController : UIViewController @end diff --git a/MyLayoutDemo/FLLTest8ViewController.m b/MyLayoutDemo/FLLTest8ViewController.m index 42be025..f31c6b4 100644 --- a/MyLayoutDemo/FLLTest8ViewController.m +++ b/MyLayoutDemo/FLLTest8ViewController.m @@ -7,7 +7,8 @@ // #import "FLLTest8ViewController.h" -#import "MyFlowLayout.h" +#import "MyLayout.h" +#import "CFTool.h" @interface FLLTest8ViewController () @@ -17,21 +18,72 @@ @implementation FLLTest8ViewController -(void)loadView { - MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:4]; - rootLayout.gravity = MyGravity_Vert_Between; + /* + 这个例子主要用于展示流式布局的间距的可伸缩性。当我们布局视图中的子视图的宽度或者高度为固定值,但是其中的间距又希望是可以伸缩的,那么就可以借助流式布局提供的方法 + + -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace; + + 来设置子视图的尺寸,以及最小和最大的间距值。并且当布局视图中子视图的间距小于最小值时会自动调整子视图的尺寸来满足这个最小的间距。 + + 对于垂直流式布局来说,这个方法只用于设置子视图的宽度和水平间距。 + 对于水平流式布局来说,这个方法只用于设置子视图的高度和垂直间距。 + + + 你可以在这个界面中尝试一下屏幕的旋转,看看布局为了支持横屏和竖屏而进行的布局调整,以便达到最完美的布局效果。 + + */ + + self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + + //这里的根视图是一个每列只有一个子视图的垂直流式布局,效果就相当于垂直线性布局了。 + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:1]; + rootLayout.gravity = MyGravity_Fill; //这里将gravity设置为MyGravity_Fill表明子视图的宽度和高度都将平分这个流式布局,可见一个简单的属性设置就可以很容易的实现子视图的尺寸的设置,而不需要编写太复杂的约束。 + rootLayout.subviewSpace = 10; + rootLayout.backgroundColor = [UIColor whiteColor]; + self.view = rootLayout; + + + MyFlowLayout *vertLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:4]; + //这个垂直流式布局中,每个子视图之间的水平间距是浮动的,并且子视图的宽度是固定为60。间距最小为10,最大不限制。 + [vertLayout setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX]; + + vertLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); + vertLayout.backgroundColor = [CFTool color:5]; + vertLayout.subviewVSpace = 20; + vertLayout.gravity = MyGravity_Vert_Fill; //因为上面setSubviewsSize设置了固定宽度,这个属性设置子视图的高度是填充满子布局视图,因此系统内部会自动设置每个子视图的高度,如果你不设置这个属性,那么你就需要在下面分别为每个子视图设置高度。 + [rootLayout addSubview:vertLayout]; for (int i = 0; i < 14; i++) { UILabel *label = [UILabel new]; - label.myHeight = 60; - label.backgroundColor = [UIColor redColor]; - [rootLayout addSubview:label]; + //label.myHeight = 60; 因为子视图的宽度在布局视图的setSubviewsSize:minSpace:maxSpace:中设置了,你也可以在这里单独为每个子视图设置高度,当然如果你的父布局视图使用了gravity来设置填充属性的话,那么子视图是不需要单独设置高度尺寸的。 + label.text = [NSString stringWithFormat:@"%d", i]; + label.textAlignment = NSTextAlignmentCenter; + label.backgroundColor = [CFTool color:2]; + [vertLayout addSubview:label]; } - [rootLayout setSubviewsSize:60 minSpace:0 maxSpace:CGFLOAT_MAX]; + - self.view = rootLayout; + MyFlowLayout *horzLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:4]; + //这个水平流式布局中,每个子视图之间的垂直间距是浮动的,并且子视图的高度是固定为60。间距最小为10,最大不限制。 + [horzLayout setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX]; + + horzLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); + horzLayout.backgroundColor = [CFTool color:6]; + horzLayout.subviewHSpace = 20; + horzLayout.gravity = MyGravity_Horz_Fill; //因为上面setSubviewsSize设置了固定高度,这个属性设置子视图的宽度是填充满子布局视图,因此系统内部会自动设置每个子视图的宽度,如果你不设置这个属性,那么你就需要在下面分别为每个子视图设置宽度。 + [rootLayout addSubview:horzLayout]; + for (int i = 0; i < 14; i++) + { + UILabel *label = [UILabel new]; + //label.myWidth = 60; 因为子视图的高度在布局视图的setSubviewsSize:minSpace:maxSpace:中设置了,你也可以在这里单独为每个子视图设置宽度,当然如果你的父布局视图使用了gravity来设置填充属性的话,那么子视图是不需要单独设置宽度尺寸的。 + label.text = [NSString stringWithFormat:@"%d", i]; + label.textAlignment = NSTextAlignmentCenter; + label.backgroundColor = [CFTool color:3];; + [horzLayout addSubview:label]; + } } diff --git a/MyLayoutDemo/LLTest1ViewController.m b/MyLayoutDemo/LLTest1ViewController.m index a211948..294a98b 100644 --- a/MyLayoutDemo/LLTest1ViewController.m +++ b/MyLayoutDemo/LLTest1ViewController.m @@ -19,33 +19,6 @@ @implementation LLTest1ViewController -(void)loadView { - - MyFloatLayout *roo1 = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Horz]; - roo1.subviewHSpace = 10; - roo1.subviewVSpace = 10; - roo1.layoutTransform = CGAffineTransformMake(0, 1, 1, 0, 0, 0); - self.view = roo1; - - for (int i = 0; i < 10; i++) - { - UILabel *v1 = [UILabel new]; - v1.backgroundColor = [UIColor redColor]; - v1.text = [NSString stringWithFormat:@"%d",i]; - v1.mySize = CGSizeMake(100, 100); - - if (i % 4 == 0) - { - v1.clearFloat = YES; - } - - [roo1 addSubview:v1]; - } - - - - return; - - /* 使用MyLayout时必读的知识点: diff --git a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings index 13242ba..e05f919 100644 --- a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings +++ b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings @@ -34,6 +34,7 @@ "5.FlowLayout - Paging" = "5.流式布局-对分页滚动的支持"; "6.FlowLayout - Scroll" = "6.流式布局-不同方向的滚动"; "7.FlowLayout - Auto Arrange" = "7.流式布局-自动布局和对瀑布流的支持"; +"8.FlowLayout - Flex space" = "8.流式布局-浮动间距"; "1.FloatLayout - Float" = "1.浮动布局-浮动效果的演示"; "2.FloatLayout - Jagged" = "2.浮动布局-仿天猫淘宝首页实现" ; "3.FloatLayout - Card news" = "3.浮动布局-仿ZAKER今日头条实现"; @@ -60,8 +61,8 @@ "❁1.Screen perfect fit - Demo1" = "❁1.界面的完美适配DEMO"; "❁2.Screen perfect fit - Demo2" = "❁2.界面的完美适配DEMO2"; "❁3.UICollectionView height self-adaption" = "❁3.UICollectionView 高度自适应"; -"❁4.Circle of friends height self-adaption" = "❁3.朋友圈 高度自适应"; - +"❁4.Circle of friends height self-adaption" = "❁4.朋友圈 高度自适应"; +"❁5.Subviews layout transform" = "❁5.布局内子视图的整体变换"; //LLTest1ViewController "vertical(from top to bottom)" = "垂直布局(从上到下)"; "left margin" = "左边边距"; @@ -272,3 +273,14 @@ //AllTest8ViewController "Pop layoutview at center"="居中弹出布局视图"; "Title"="标题"; + +//AllTest11ViewController +"Identity"="正常"; +"Translation" = "平移"; +"Scale" = "缩放"; +"Horz Reflection" = "水平翻转"; +"Vert Reflection" = "垂直翻转"; +"Reverse" = "对角翻转"; + + + From 5c4d6db9e559e97ff5ddba503be99b8ad03468d0 Mon Sep 17 00:00:00 2001 From: fzy Date: Sat, 4 Aug 2018 12:21:12 +0800 Subject: [PATCH 023/115] Release V1.6.0 --- MyLayoutDemo/AppDelegate.m | 1 - 1 file changed, 1 deletion(-) diff --git a/MyLayoutDemo/AppDelegate.m b/MyLayoutDemo/AppDelegate.m index 262a7c6..daa53d7 100644 --- a/MyLayoutDemo/AppDelegate.m +++ b/MyLayoutDemo/AppDelegate.m @@ -34,7 +34,6 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( ViewController *vc = [[ViewController alloc] init]; UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; - nav.navigationBar.translucent = NO; self.window.rootViewController = nav; [self.window makeKeyAndVisible]; From 0b788523bafc42a12040ff5bb8112b0e515a2aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E9=98=B3=E5=A4=A7=E5=93=A52013?= Date: Sun, 5 Aug 2018 08:55:12 +0800 Subject: [PATCH 024/115] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e50f52..f0926aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,7 +56,7 @@ 2. 添加了对 **基线对齐baseline**的支持[issue:#43](https://github.com/youngsoft/MyLinearLayout/issues/43),目前只有**水平线性布局(MyLinearLayout)**和**相对布局(MyRelativeLayout)**支持基线对齐。 1. 在**MyGravity**中添加了`MyGravity_Vert_Baseline`的枚举定义来支持线性布局的基线对齐,并且在线性布局中添加了一个属性:`baselineBaseView`来指定某个基线基准视图。同时在布局视图的gravity属性中支持对`MyGravity_Vert_Baseline`的设置。具体例子参考:[LLTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/LLTest1ViewController.m) - 2. 在UIView的扩展属性中增加了一个扩展属性:`baselinePos`。你可以在相对布局中的子视图使用这个属性来进行基线对齐的设置。具体例子请参考:[RLTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/RLTest1ViewController.m) + 2. 在UIView的扩展属性中增加了一个扩展属性:`baselinePos`。你可以在相对布局中的子视图使用这个属性来进行基线对齐的设置。具体例子请参考:[RLTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/RelativeLayoutDemo/RLTest1ViewController.m) 3. 添加对Apple TV_OS 的支持,您可以用MyLayout来开发apple TV方面的应用。 4. **MyLayoutPos**中增加了一个特殊的值`safeAreaMargin`用来支持对iOS11应用的适配。 From eac51d7e04fdfa169082d69f4eb0c8329b082e45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E9=98=B3=E5=A4=A7=E5=93=A52013?= Date: Sun, 5 Aug 2018 09:51:08 +0800 Subject: [PATCH 025/115] Update CHANGELOG.md --- CHANGELOG.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0926aa..bb63daf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,8 @@ ## [V1.6.0](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.6.0)(2018/08/04) #### Added -1. 添加布局属性`layoutTransform`,用来实现对布局内子视图的整体位置变换,可以通过这个属性来实现一般常见的平移,缩放,水平翻转,垂直翻转等功能。具体的DEMO在新增加的[AllTest11ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/AllTest11ViewController.m)中可以查看。 -2. 为流式布局`MyFlowLayout`支持子视图固定尺寸并且间距动态拉伸调整的能力,你可以通过设置流式布局的方法:`setSubviewsSize:minSpace:maxSpace:`来实现,这个方法原先只支持内容约束流式布局,现在新版本对数量约束流式布局也同样支持了。具体的DEMO在新增加的[FLLTest8ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/FLLTest8ViewController.m)中可以查看。 +1. 添加布局属性`layoutTransform`,用来实现对布局内子视图的整体位置变换,可以通过这个属性来实现一般常见的平移,缩放,水平翻转,垂直翻转等功能。具体的DEMO在新增加的[AllTest11ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/AllTest11ViewController.m)中可以查看。 +2. 为流式布局`MyFlowLayout`支持子视图固定尺寸并且间距动态拉伸调整的能力,你可以通过设置流式布局的方法:`setSubviewsSize:minSpace:maxSpace:`来实现,这个方法原先只支持内容约束流式布局,现在新版本对数量约束流式布局也同样支持了。具体的DEMO在新增加的[FLLTest8ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/FLLTest8ViewController.m)中可以查看。 #### Fixed 1. 修复了UILabel等控件的尺寸设置了wrapContentHeight或者wrapContentWidth为YES并且同时又设置了最大最小尺寸时,在相对布局内进行尺寸计算内可能会出现的问题。 @@ -16,11 +16,11 @@ ## [V1.5.3](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.5.3)(2018/05/11) #### Added -1.添加了流式布局`MyFlowLayout`对瀑布流的支持,主要是数量约束流式布局来实现,通过设置`autoArrange`为YES或者设置`arrangedGravity`属性为`MyGravity_Horz_Between或者MyGravity_Vert_Between`来实现两种不同策略的瀑布流模式,瀑布流模式其实就是一种紧凑的流式布局排列方式。具体的DEMO在新增加的[FLLTest7ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/FLLTest7ViewController.m)中可以查看。 +1.添加了流式布局`MyFlowLayout`对瀑布流的支持,主要是数量约束流式布局来实现,通过设置`autoArrange`为YES或者设置`arrangedGravity`属性为`MyGravity_Horz_Between或者MyGravity_Vert_Between`来实现两种不同策略的瀑布流模式,瀑布流模式其实就是一种紧凑的流式布局排列方式。具体的DEMO在新增加的[FLLTest7ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/FLLTest7ViewController.m)中可以查看。 #### Fixed 1. 修复了流式布局`MyFlowLayout`中的arrangedGravity属性设置和子视图的myAlignment属性同时设置时有可能对齐方式不正确的问题,以及gravity属性设置后停靠有可能不正确的问题。 -2. 优化和修复了对UIScrollView+布局视图时,设置UIScrollView的高度或者宽度由布局视图的尺寸进行自适应的问题。新版本中UIScrollView的尺寸可以依赖于布局视图的尺寸,同时布局视图的最大最小尺寸可以设置为UIScrollView的尺寸。具体例子参考:[FLLTest7ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/FLLTest7ViewController.m) +2. 优化和修复了对UIScrollView+布局视图时,设置UIScrollView的高度或者宽度由布局视图的尺寸进行自适应的问题。新版本中UIScrollView的尺寸可以依赖于布局视图的尺寸,同时布局视图的最大最小尺寸可以设置为UIScrollView的尺寸。具体例子参考:[FLLTest7ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/FLLTest7ViewController.m) 3. 添加了对`myTop,myBottom,myLeft,myRight,myLeading,myTrailing,mySize,myWidth,myHeight,myMargin, myHorzMargin, myVertMargin`的读取使用的告警处理!一般情况下这些属性只能用于设置具体的数值,而不能用来获取某个尺寸,get方法也并不代表着视图的约束尺寸,这个点切记,切记。 4. 添加了对布局视图的`cacheEstimatedRect`属性的使用限制说明,这个属性只能用于那些需要高度自适应的UITableViewCell的根布局视图中使用,其他地方如果使用则有可能会出现计算不正确的问题。 5. 恢复了对XCODE8.0以前的编译器版本使用MyLayout的支持。 @@ -34,13 +34,13 @@ 2. 修复路径布局中的`MyPathSpace`的初始化方法和蓝牙框架一起使用时可能会出现编译时错误的问题。[BUG#70](https://github.com/youngsoft/MyLinearLayout/issues/70) 3. 修复表格布局`MyTableLayout`的行高是MyLayoutSize.wrap时,并且又设置了智能边界线时,列子视图的边界线显示不完整的问题。[BUG#71](https://github.com/youngsoft/MyLinearLayout/issues/71) 4. 修复了一些编译和分析有可能会产生报警的代码。 -5. 提供了新的关于表格布局的DEMO:[TLTest4ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/TLTest4ViewController.m) +5. 提供了新的关于表格布局的DEMO:[TLTest4ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/TLTest4ViewController.m) ## [V1.5.1](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.5.1)(2018/04/23) #### Added -1. 添加了对浮动布局MyFloatLayout中的子视图的行或者列内对齐方式的设置,您可以借助子视图的myAlignment属性来设置行或者列内的对齐方式,具体的DEMO请参考:[FOLTest7ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/FOLTest7ViewController.m) 中的介绍。 +1. 添加了对浮动布局MyFloatLayout中的子视图的行或者列内对齐方式的设置,您可以借助子视图的myAlignment属性来设置行或者列内的对齐方式,具体的DEMO请参考:[FOLTest7ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/FOLTest7ViewController.m) 中的介绍。 2. 将所有设置为过期的方法删除。 3. 修正一些编译上的告警以及一些和Masonry公用时的一些问题。 4. 修复方向旋转时有可能不调用`rotationToDeviceOrientationBlock`的问题。 @@ -54,9 +54,9 @@ #### Added 1. 添加新的布局种类:**栅格布局(MyGridLayout)**。栅格布局是一种将矩形区域划分为多个子矩形区域,并将这个划分一直持续下去的机制,然后再将子视图填充到对应的栅格区域里面的一种布局视图。栅格布局特别适合于动态布局,布局样式可以从服务器动态下发,并且可以用JSON格式的语言来描述这种布局结构,具体请参考新增加的栅格布局和对应的DEMO。以及对应的说明文档:[栅格布局介绍](http://bicyclering.com/2017/09/01/IOS-UIViewLayout-%E5%B8%83%E5%B1%80-MyLinearLayout/#more) 2. 添加了对 **基线对齐baseline**的支持[issue:#43](https://github.com/youngsoft/MyLinearLayout/issues/43),目前只有**水平线性布局(MyLinearLayout)**和**相对布局(MyRelativeLayout)**支持基线对齐。 - 1. 在**MyGravity**中添加了`MyGravity_Vert_Baseline`的枚举定义来支持线性布局的基线对齐,并且在线性布局中添加了一个属性:`baselineBaseView`来指定某个基线基准视图。同时在布局视图的gravity属性中支持对`MyGravity_Vert_Baseline`的设置。具体例子参考:[LLTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/LLTest1ViewController.m) + 1. 在**MyGravity**中添加了`MyGravity_Vert_Baseline`的枚举定义来支持线性布局的基线对齐,并且在线性布局中添加了一个属性:`baselineBaseView`来指定某个基线基准视图。同时在布局视图的gravity属性中支持对`MyGravity_Vert_Baseline`的设置。具体例子参考:[LLTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/LLTest1ViewController.m) - 2. 在UIView的扩展属性中增加了一个扩展属性:`baselinePos`。你可以在相对布局中的子视图使用这个属性来进行基线对齐的设置。具体例子请参考:[RLTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/RelativeLayoutDemo/RLTest1ViewController.m) + 2. 在UIView的扩展属性中增加了一个扩展属性:`baselinePos`。你可以在相对布局中的子视图使用这个属性来进行基线对齐的设置。具体例子请参考:[RLTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/RLTest1ViewController.m) 3. 添加对Apple TV_OS 的支持,您可以用MyLayout来开发apple TV方面的应用。 4. **MyLayoutPos**中增加了一个特殊的值`safeAreaMargin`用来支持对iOS11应用的适配。 @@ -80,7 +80,7 @@ #### Added 1. 添加适配iOS11的能力以及**iPhoneX**的方法。基本不需要改动当前代码。如果需要改动只需要设置根布局视图的一些属性即可。 1. 新增布局视图属性:`insetsPaddingFromSafeArea`用来设置在哪个方向缩进对应方向的安全区域。 - 2. 新增布局视图属性:`insetLandscapeFringePadding`用来设置当支持横屏时,并且insetsPaddingFromSafeArea设置为左右缩进时,是否只缩进有刘海的那一边。这个属性默认设置为NO,表示两边都缩进。您可以在特殊需要时将这个属性设置为YES表示只缩进刘海那一边,非刘海那一边则不缩进。具体参考使用DEMO:[LLTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/LLTest1ViewController.m) + 2. 新增布局视图属性:`insetLandscapeFringePadding`用来设置当支持横屏时,并且insetsPaddingFromSafeArea设置为左右缩进时,是否只缩进有刘海的那一边。这个属性默认设置为NO,表示两边都缩进。您可以在特殊需要时将这个属性设置为YES表示只缩进刘海那一边,非刘海那一边则不缩进。具体参考使用DEMO:[LLTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/LLTest1ViewController.m) #### Changed 1. 布局方法:`estimateLayoutRect`设置为过期,请用`sizeThatFits`方法来代替,方法换名字的原因是iOS的默认sizeThatFits本来就是用来进行尺寸评估的,所以没有必要用新方法。 @@ -91,7 +91,7 @@ ## [V1.4.2](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.4.2)(2017/8/31) #### Added -1. 表格布局MyTableLayout添加了`addRow:colCount:`方法,目的是为了支持那些列数固定并且宽度固定的需求,具体例子见DEMO:[TLTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/TLTest1ViewController.m)中的第五行的代码。 +1. 表格布局MyTableLayout添加了`addRow:colCount:`方法,目的是为了支持那些列数固定并且宽度固定的需求,具体例子见DEMO:[TLTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/TLTest1ViewController.m)中的第五行的代码。 2. 添加了布局视图的高度等于非布局父视图宽度以及布局视图宽度等于非布局父视图高度的支持,目的是为了支持对布局视图进行旋转`transform`的支持。 3. 添加了框架布局MyFrameLayout中子视图的高度等于另外视图宽度以及宽度等于另外视图高度的支持。 4. 下一个版本将会有重大功能的添加:栅格布局的支持、基线对齐的支持、均分的再次优化等等功能,敬请期待吧。。 @@ -150,7 +150,7 @@ 3. 将原先线性布局、流式布局、浮动布局中的`gravity`属性提升到了布局基类中,目前线性布局、流式布局、浮动布局、和框架布局都支持`gravity`的设置。 4. 进一步优化了布局视图的性能,表现为对KVO监听的延迟处理和优化。 5. 进一步优化了布局视图的内存占用尺寸,将布局视图中对触摸事件处理的变量变为按需要才创建,以及布局视图的边界线对象也改为了按需要才建立,这两部分按需处理机制将有效的减少了布局视图的内存占用。 -6. 为了更进一步的优化和简化MyLayout对UITableviewCell高度自适应的处理,新版本中对实现的解决方案进行优化处理,具体详情请参考:[AllTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayout/AllTest1ViewController.m)中的介绍 +6. 为了更进一步的优化和简化MyLayout对UITableviewCell高度自适应的处理,新版本中对实现的解决方案进行优化处理,具体详情请参考:[AllTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/AllTest1ViewController.m)中的介绍 7. 优化工程目录结构。 From baeaab21f8f7f22ad42703ccd8796c282f8fa5fb Mon Sep 17 00:00:00 2001 From: bq oy Date: Fri, 21 Sep 2018 00:47:38 +0800 Subject: [PATCH 026/115] =?UTF-8?q?=E5=8F=91=E5=B8=831.6.1=E7=89=88?= =?UTF-8?q?=E6=9C=AC=EF=BC=8C=E4=BF=AE=E5=A4=8D=E5=AF=B9iPhoneX=E7=B3=BB?= =?UTF-8?q?=E5=88=97=E8=AE=BE=E5=A4=87=E7=9A=84=E6=94=AF=E6=8C=81=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AF=B9Application=20Extentsion=E4=B8=8A?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E5=B8=83=E5=B1=80=E5=BA=93=E7=9A=84=E6=94=AF?= =?UTF-8?q?=E6=8C=81:=20#issue81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 ++++ MyLayout.podspec | 2 +- MyLayout/Lib/MyLayout.h | 2 +- MyLayout/Lib/MyLayoutSizeClass.m | 48 +++++++++++++++----------------- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb63daf..59854a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ **MyLayout**的所有版本的变更日志都将会在这里记录. --- +## [V1.6.1](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.6.1)(2018/09/29) +#### Fixed +1. 修复对所有iPhoneX系列的设备的布局视图在设置padding的值为safeAreaMargin时的BUG。 +2. 添加对Application Extension上使用布局库视图的支持。[BUG#81](https://github.com/youngsoft/MyLinearLayout/issues/81) + + ## [V1.6.0](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.6.0)(2018/08/04) #### Added diff --git a/MyLayout.podspec b/MyLayout.podspec index b19b31c..553a21c 100644 --- a/MyLayout.podspec +++ b/MyLayout.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "MyLayout" - s.version = "1.6.0" + s.version = "1.6.1" s.summary = "MyLayout is an iOS UI framework integrates the functions with Android,AutoLayout,SizeClass,HTML CSS float and flexbox,UIView UITableView." s.description = <<-DESC diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index bbae89c..4251f4a 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -37,7 +37,7 @@ */ -//Current version is 1.6.0, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.6.1, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. #ifndef MyLayout_MyLayout_h diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index e9385fd..2ee5b38 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -637,7 +637,15 @@ -(CGFloat)myLayoutTopPadding //如果padding值是特殊的值。 if (self.topPadding >= MyLayoutPos.safeAreaMargin - 2000 && self.topPadding <= MyLayoutPos.safeAreaMargin + 2000) { - return self.topPadding - MyLayoutPos.safeAreaMargin + CGRectGetHeight([UIApplication sharedApplication].statusBarFrame); + + CGFloat topPaddingAdd = 20.0; //默认高度是状态栏的高度。 +#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) + + if (@available(iOS 11.0, *)) { + topPaddingAdd = self.view.safeAreaInsets.top; + } +#endif + return self.topPadding - MyLayoutPos.safeAreaMargin + topPaddingAdd; } if ((self.insetsPaddingFromSafeArea & UIRectEdgeTop) == UIRectEdgeTop) @@ -659,15 +667,11 @@ -(CGFloat)myLayoutBottomPadding if (self.bottomPadding >= MyLayoutPos.safeAreaMargin - 2000 && self.bottomPadding <= MyLayoutPos.safeAreaMargin + 2000) { CGFloat bottomPaddingAdd = 0; -#if TARGET_OS_IOS - //如果设备是iPhoneX就特殊处理。竖屏是34,横屏是21 - if ([UIScreen mainScreen].bounds.size.height == 812 || [UIScreen mainScreen].bounds.size.width == 812) - { - if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) - bottomPaddingAdd = 21; - else - bottomPaddingAdd = 34; - } +#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) + + if (@available(iOS 11.0, *)) { + bottomPaddingAdd = self.view.safeAreaInsets.bottom; + } #endif return self.bottomPadding - MyLayoutPos.safeAreaMargin + bottomPaddingAdd; } @@ -691,14 +695,10 @@ -(CGFloat)myLayoutLeadingPadding if (self.leadingPadding >= MyLayoutPos.safeAreaMargin - 2000 && self.leadingPadding <= MyLayoutPos.safeAreaMargin + 2000) { CGFloat leadingPaddingAdd = 0; -#if TARGET_OS_IOS - //如果设备是iPhoneX就特殊处理。竖屏是34,横屏是21 - if ([UIScreen mainScreen].bounds.size.height == 812 || [UIScreen mainScreen].bounds.size.width == 812) - { - if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) - leadingPaddingAdd = 44; - else - leadingPaddingAdd = 0; +#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) + + if (@available(iOS 11.0, *)) { + leadingPaddingAdd = self.view.safeAreaInsets.left; //因为这里左右的缩进都是一样的,因此不需要考虑RTL的情况。 } #endif return self.leadingPadding - MyLayoutPos.safeAreaMargin + leadingPaddingAdd; @@ -741,14 +741,10 @@ -(CGFloat)myLayoutTrailingPadding if (self.trailingPadding >= MyLayoutPos.safeAreaMargin - 2000 && self.trailingPadding <= MyLayoutPos.safeAreaMargin + 2000) { CGFloat trailingPaddingAdd = 0; -#if TARGET_OS_IOS - //如果设备是iPhoneX就特殊处理。竖屏是34,横屏是21 - if ([UIScreen mainScreen].bounds.size.height == 812 || [UIScreen mainScreen].bounds.size.width == 812) - { - if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) - trailingPaddingAdd = 44; - else - trailingPaddingAdd = 0; +#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) + + if (@available(iOS 11.0, *)) { + trailingPaddingAdd = self.view.safeAreaInsets.right; } #endif return self.trailingPadding - MyLayoutPos.safeAreaMargin + trailingPaddingAdd; From 83f1536fece7850b290ce6bba11d7b9f3b46f151 Mon Sep 17 00:00:00 2001 From: 383160955 <383160955@qq.com> Date: Mon, 13 May 2019 16:14:38 +0800 Subject: [PATCH 027/115] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=B0=8F=E9=9C=80?= =?UTF-8?q?=E6=B1=82=E2=80=94=E2=80=94=E9=98=BF=E6=8B=89=E4=BC=AF=E8=AF=AD?= =?UTF-8?q?=E2=80=94=E2=80=94UI=E2=80=94=E2=80=94=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout.xcodeproj/project.pbxproj | 7 ++--- MyLayout/Lib/MyBaseLayout.h | 13 ++++++++++ MyLayout/Lib/MyBaseLayout.m | 26 +++++++++++++++++++ .../friend_zan.imageset/Contents.json | 4 +++ .../interactive_fill.imageset/Contents.json | 4 +++ .../zan_select.imageset/Contents.json | 4 +++ MyLayoutDemo/LLTest1ViewController.m | 16 ++++++++++++ 7 files changed, 71 insertions(+), 3 deletions(-) diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index bfc4b06..8372303 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -982,7 +982,7 @@ }; 1840828C1B2C46E8003F378B = { CreatedOnToolsVersion = 6.3.2; - DevelopmentTeam = BGQ8WB468K; + DevelopmentTeam = 8EDMCH2Z7A; ProvisioningStyle = Automatic; }; 184082A51B2C46E8003F378B = { @@ -1002,6 +1002,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, Base, "zh-Hans", ); @@ -1455,7 +1456,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = BGQ8WB468K; + DEVELOPMENT_TEAM = 8EDMCH2Z7A; GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1477,7 +1478,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = BGQ8WB468K; + DEVELOPMENT_TEAM = 8EDMCH2Z7A; GCC_PREPROCESSOR_DEFINITIONS = ""; INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index 3a1e6f8..aead304 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -631,6 +631,11 @@ +(void)setIsRTL:(BOOL)isRTL; #endif +/** + 只是适配UI-RTL ,不是显示字RTL + */ ++ (void)myUpArabicUI:(BOOL)isArabicUI inWindow:(UIWindow *)window; + /* 布局视图里面的padding属性用来设置布局视图的内边距。内边距是指布局视图里面的子视图离自己距离。外边距则是视图与父视图之间的距离。 内边距是在自己的尺寸内离子视图的距离,而外边距则不是自己尺寸内离其他视图的距离。下面是内边距和外边距的效果图: @@ -1008,5 +1013,13 @@ @end +/** + 只是适配UI-RTL ,不是显示字RTL + */ + +@interface UIWindow (MyBaseUpUIRTL) +-(void)myUpBasisUIViewMyLayout:(BOOL)isRTL; + +@end diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index d98fca5..8f67bf6 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -759,6 +759,10 @@ +(void)setIsRTL:(BOOL)isRTL [MyViewSizeClass setIsRTL:isRTL]; } ++ (void)myUpArabicUI:(BOOL)isArabicUI inWindow:(UIWindow *)window +{ + [window myUpBasisUIViewMyLayout:isArabicUI]; +} -(CGFloat)topPadding @@ -3510,7 +3514,29 @@ -(NSString*)description { return [NSString stringWithFormat:@"leading:%g, top:%g, width:%g, height:%g, trailing:%g, bottom:%g",_leading,_top,_width,_height,_trailing,_bottom]; } +@end +@implementation UIWindow (MyBaseUpUIRTL) + + +-(void)myUpBasisUIViewMyLayout:(BOOL)isRTL + +{ + [MyBaseLayout setIsRTL:isRTL]; + [self mySetBasisUISubviewsNeedLayoutRTL:self]; +} +-(void)mySetBasisUISubviewsNeedLayoutRTL:(UIView *)v +{ + NSArray *sbs = v.subviews; + for (UIView *sv in sbs) + { + if ([sv isKindOfClass:[MyBaseLayout class]]) + { + [sv setNeedsLayout]; + } + [self mySetBasisUISubviewsNeedLayoutRTL:sv]; + } +} @end diff --git a/MyLayoutDemo/Images.xcassets/friend_zan.imageset/Contents.json b/MyLayoutDemo/Images.xcassets/friend_zan.imageset/Contents.json index 27282fb..5cca9cd 100644 --- a/MyLayoutDemo/Images.xcassets/friend_zan.imageset/Contents.json +++ b/MyLayoutDemo/Images.xcassets/friend_zan.imageset/Contents.json @@ -1,5 +1,9 @@ { "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, { "idiom" : "universal", "filename" : "friend_zan@2x.png", diff --git a/MyLayoutDemo/Images.xcassets/interactive_fill.imageset/Contents.json b/MyLayoutDemo/Images.xcassets/interactive_fill.imageset/Contents.json index c3016d8..e2f135a 100644 --- a/MyLayoutDemo/Images.xcassets/interactive_fill.imageset/Contents.json +++ b/MyLayoutDemo/Images.xcassets/interactive_fill.imageset/Contents.json @@ -1,5 +1,9 @@ { "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, { "idiom" : "universal", "filename" : "interactive_fill@2x.png", diff --git a/MyLayoutDemo/Images.xcassets/zan_select.imageset/Contents.json b/MyLayoutDemo/Images.xcassets/zan_select.imageset/Contents.json index cbdc3c5..32604f4 100644 --- a/MyLayoutDemo/Images.xcassets/zan_select.imageset/Contents.json +++ b/MyLayoutDemo/Images.xcassets/zan_select.imageset/Contents.json @@ -1,5 +1,9 @@ { "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, { "idiom" : "universal", "filename" : "zan_select@2x.png", diff --git a/MyLayoutDemo/LLTest1ViewController.m b/MyLayoutDemo/LLTest1ViewController.m index 294a98b..17091af 100644 --- a/MyLayoutDemo/LLTest1ViewController.m +++ b/MyLayoutDemo/LLTest1ViewController.m @@ -122,9 +122,25 @@ -(void)loadView - (void)viewDidLoad { [super viewDidLoad]; + + UIBarButtonItem *RTLBar = [[UIBarButtonItem alloc]initWithTitle:@"RTL" style:UIBarButtonItemStylePlain target:self action:@selector(RTLAction)]; + UIBarButtonItem *LTRBar = [[UIBarButtonItem alloc]initWithTitle:@"LTR" style:UIBarButtonItemStylePlain target:self action:@selector(LTRAction)]; + self.navigationItem.rightBarButtonItems = @[RTLBar,LTRBar]; // Do any additional setup after loading the view. } +// RTL- UI - 更新 +- (void)RTLAction +{ + // 当前view的window + [MyBaseLayout myUpArabicUI:YES inWindow:self.view.window]; +} +- (void)LTRAction +{ + // 这个适合APP 使用appdelegate 中的window + [MyBaseLayout myUpArabicUI:NO inWindow:[UIApplication sharedApplication].delegate.window]; +} + - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. From ea9ce1b1f40e4d6dd37fe1bb2dc6cb22c6633836 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Thu, 16 May 2019 09:34:21 +0800 Subject: [PATCH 028/115] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E5=88=B01.7.0?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8DBUG#90=EF=BC=8C=E8=A7=A3=E5=86=B3iss?= =?UTF-8?q?ue#79?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 12 + MyLayout.podspec | 2 +- MyLayout.xcodeproj/project.pbxproj | 27 +- MyLayout/Info.plist | 2 +- MyLayout/Lib/MyBaseLayout.m | 142 ++++++++++- MyLayout/Lib/MyFloatLayout.m | 18 +- MyLayout/Lib/MyFlowLayout.m | 36 +-- MyLayout/Lib/MyFrameLayout.m | 4 +- MyLayout/Lib/MyGridLayout.m | 4 +- MyLayout/Lib/MyLayout.h | 2 +- MyLayout/Lib/MyLinearLayout.m | 22 +- MyLayout/Lib/MyPathLayout.m | 6 +- MyLayout/Lib/MyRelativeLayout.m | 17 +- MyLayoutDemo/AllTest12ViewController.h | 16 ++ MyLayoutDemo/AllTest12ViewController.m | 218 ++++++++++++++++ MyLayoutDemo/AllTest1TableViewCell.h | 1 + .../AllTest1TableViewCellForAutoLayout.h | 25 ++ .../AllTest1TableViewCellForAutoLayout.m | 238 ++++++++++++++++++ MyLayoutDemo/AllTest1ViewController.m | 17 +- MyLayoutDemo/Info.plist | 2 +- MyLayoutDemo/ViewController.m | 4 + .../zh-Hans.lproj/Localizable.strings | 1 + 22 files changed, 750 insertions(+), 66 deletions(-) create mode 100644 MyLayoutDemo/AllTest12ViewController.h create mode 100644 MyLayoutDemo/AllTest12ViewController.m create mode 100644 MyLayoutDemo/AllTest1TableViewCellForAutoLayout.h create mode 100644 MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m diff --git a/CHANGELOG.md b/CHANGELOG.md index 59854a3..5ed7a4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ **MyLayout**的所有版本的变更日志都将会在这里记录. --- + +## [V1.7.0](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.7.0)(2019/05/16) +#### Added +1. 添加了对MyLayout的尺寸自适应和AutoLayout结合的能力。AutoLayout能使用和UILabel一样的MyLayout布局视图中的高度和宽度自适应的设置。具体需求见[issue#79](https://github.com/youngsoft/MyLinearLayout/issues/79)。这个问题的解决得到简化处理。新版本的能力让UITableViewCell的高度自适应的能力得到简化。具体的代码演示见[AllTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/AllTest1ViewController.m),以及[AllTest12ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/AllTest12ViewController.m)中的详细介绍。 + + 2. 添加了对RTL设置的即时生效的能力,您可通过方法`+[MyBaseLayout myUpArabicUI:(BOOL)isArabicUI inWindow:(UIWindow *)window +`来设置,具体的功能实现要感谢[LAnqxpp](https://github.com/LAnqxpp)的贡献。 +#### Fixed +1. 修复了在完成布局后再对子视图设置约束时子视图约束不起作用的[BUG#90](https://github.com/youngsoft/MyLinearLayout/issues/90)。当代码中不对布局视图中的子视图设置任何约束时就会出现这个问题,这个问题涉及到所有布局。 +2. 修复了相对布局可能会产生尺寸无限大的问题,尤其是当相对布局的高度为自适应,并且相对布局中同样存在着具有高度自适应的子布局视图的情况。 + + ## [V1.6.1](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.6.1)(2018/09/29) #### Fixed 1. 修复对所有iPhoneX系列的设备的布局视图在设置padding的值为safeAreaMargin时的BUG。 diff --git a/MyLayout.podspec b/MyLayout.podspec index 553a21c..eb673a1 100644 --- a/MyLayout.podspec +++ b/MyLayout.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "MyLayout" - s.version = "1.6.1" + s.version = "1.7.0" s.summary = "MyLayout is an iOS UI framework integrates the functions with Android,AutoLayout,SizeClass,HTML CSS float and flexbox,UIView UITableView." s.description = <<-DESC diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index 8372303..198e3d3 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -170,6 +170,8 @@ 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */; }; 44EBDA8C1F619A6300B47CBD /* GLTest4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */; }; 44EBDA8E1F619C9000B47CBD /* GridLayoutDemo4.json in Resources */ = {isa = PBXBuildFile; fileRef = 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */; }; + 467E63CC228C4D6F0065D080 /* AllTest12ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 467E63CB228C4D6F0065D080 /* AllTest12ViewController.m */; }; + 467E63CF228CDA660065D080 /* AllTest1TableViewCellForAutoLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 467E63CE228CDA660065D080 /* AllTest1TableViewCellForAutoLayout.m */; }; 6740E1F820A52D9E00AFBC5A /* AllTest10ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */; }; 6740E1FB20A52DA900AFBC5A /* AllTest10Model.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */; }; 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */; }; @@ -415,6 +417,10 @@ 44EBDA8A1F619A6300B47CBD /* GLTest4ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest4ViewController.h; sourceTree = ""; }; 44EBDA8B1F619A6300B47CBD /* GLTest4ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest4ViewController.m; sourceTree = ""; }; 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo4.json; sourceTree = ""; }; + 467E63CA228C4D630065D080 /* AllTest12ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest12ViewController.h; sourceTree = ""; }; + 467E63CB228C4D6F0065D080 /* AllTest12ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest12ViewController.m; sourceTree = ""; }; + 467E63CD228CDA550065D080 /* AllTest1TableViewCellForAutoLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1TableViewCellForAutoLayout.h; sourceTree = ""; }; + 467E63CE228CDA660065D080 /* AllTest1TableViewCellForAutoLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1TableViewCellForAutoLayout.m; sourceTree = ""; }; 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10ViewController.h; sourceTree = ""; }; 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10ViewController.m; sourceTree = ""; }; 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10Model.m; sourceTree = ""; }; @@ -670,6 +676,8 @@ 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */, 20F0DFFB2111749A00CFCE8C /* AllTest11ViewController.h */, 20F0DFFC2111749A00CFCE8C /* AllTest11ViewController.m */, + 467E63CA228C4D630065D080 /* AllTest12ViewController.h */, + 467E63CB228C4D6F0065D080 /* AllTest12ViewController.m */, 18D3C9021EDF068200D3DE43 /* AllTestModel&View */, ); name = IntegratedDemo; @@ -680,6 +688,8 @@ children = ( 18D3C9691EDF082800D3DE43 /* AllTest1TableViewCell.h */, 18D3C96A1EDF082800D3DE43 /* AllTest1TableViewCell.m */, + 467E63CD228CDA550065D080 /* AllTest1TableViewCellForAutoLayout.h */, + 467E63CE228CDA660065D080 /* AllTest1TableViewCellForAutoLayout.m */, 18D3C96B1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.h */, 18D3C96C1EDF082800D3DE43 /* AllTest1TableViewHeaderFooterView.m */, 18D3C96D1EDF082800D3DE43 /* AllTest2TableViewCell.h */, @@ -982,16 +992,17 @@ }; 1840828C1B2C46E8003F378B = { CreatedOnToolsVersion = 6.3.2; - DevelopmentTeam = 8EDMCH2Z7A; + DevelopmentTeam = BGQ8WB468K; ProvisioningStyle = Automatic; }; 184082A51B2C46E8003F378B = { CreatedOnToolsVersion = 6.3.2; - DevelopmentTeam = Q5MFLFRY64; + DevelopmentTeam = BGQ8WB468K; TestTargetID = 1840828C1B2C46E8003F378B; }; 18B152301DEDDE5500AD7A1C = { CreatedOnToolsVersion = 8.1; + DevelopmentTeam = BGQ8WB468K; ProvisioningStyle = Automatic; TestTargetID = 1840828C1B2C46E8003F378B; }; @@ -1127,6 +1138,7 @@ 182225D51E77E5930081AA4B /* MyLayoutSize.m in Sources */, 6740E20120A52DC100AFBC5A /* AllTest10Cell.m in Sources */, 18D3C93A1EDF07C000D3DE43 /* FLLTest2ViewController.m in Sources */, + 467E63CF228CDA660065D080 /* AllTest1TableViewCellForAutoLayout.m in Sources */, 18D3C95A1EDF07F800D3DE43 /* FOLTest1ViewController.m in Sources */, 182225D01E77E5930081AA4B /* MyLayoutPos.m in Sources */, 18D3C98B1EDF084000D3DE43 /* AllTest7ViewController.m in Sources */, @@ -1148,6 +1160,7 @@ 18D3C9941EDF08F800D3DE43 /* YYFPSLabel.m in Sources */, 18D3C91D1EDF078200D3DE43 /* FLTest2ViewController.m in Sources */, 18D3C9661EDF080800D3DE43 /* TLTest1ViewController.m in Sources */, + 467E63CC228C4D6F0065D080 /* AllTest12ViewController.m in Sources */, 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */, 18D3C94A1EDF07E700D3DE43 /* PLTest2ViewController.m in Sources */, 205642881F4CFFB600E8BDDE /* MyBorderline.m in Sources */, @@ -1456,7 +1469,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 8EDMCH2Z7A; + DEVELOPMENT_TEAM = BGQ8WB468K; GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1478,7 +1491,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 8EDMCH2Z7A; + DEVELOPMENT_TEAM = BGQ8WB468K; GCC_PREPROCESSOR_DEFINITIONS = ""; INFOPLIST_FILE = "$(SRCROOT)/MyLayoutDemo/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1496,7 +1509,7 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; - DEVELOPMENT_TEAM = Q5MFLFRY64; + DEVELOPMENT_TEAM = BGQ8WB468K; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", @@ -1517,7 +1530,7 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; - DEVELOPMENT_TEAM = Q5MFLFRY64; + DEVELOPMENT_TEAM = BGQ8WB468K; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", @@ -1538,6 +1551,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = BGQ8WB468K; INFOPLIST_FILE = MyLayoutUITests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -1555,6 +1569,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; + DEVELOPMENT_TEAM = BGQ8WB468K; INFOPLIST_FILE = MyLayoutUITests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; diff --git a/MyLayout/Info.plist b/MyLayout/Info.plist index 5133e74..6718324 100644 --- a/MyLayout/Info.plist +++ b/MyLayout/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.5.4 + 1.7.0 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 8f67bf6..5386695 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -1770,6 +1770,146 @@ -(void)safeAreaInsetsDidChange } } + +-(void)setNeedsLayout +{ + [super setNeedsLayout]; + if (!self.translatesAutoresizingMaskIntoConstraints) + { + if (self.wrapContentWidth || self.wrapContentHeight) + [self invalidateIntrinsicContentSize]; + } +} + +-(CGSize)intrinsicContentSize +{ + + CGSize sz = [super intrinsicContentSize]; + if (self.translatesAutoresizingMaskIntoConstraints == NO && (self.wrapContentWidth || self.wrapContentHeight)) + { + if (self.wrapContentWidth && self.wrapContentHeight) + { + sz = [self sizeThatFits:CGSizeZero]; + } + else if (self.wrapContentWidth) + { + //动态宽度 + NSLayoutConstraint *heightConstraint = nil; + for (NSLayoutConstraint *constraint in self.constraints) + { + if (constraint.firstItem == self && constraint.firstAttribute == NSLayoutAttributeHeight) + { + heightConstraint = constraint; + break; + } + } + + if (heightConstraint == nil) + { + for (NSLayoutConstraint *constraint in self.superview.constraints) + { + if (constraint.firstItem == self && constraint.firstAttribute == NSLayoutAttributeHeight) + { + heightConstraint = constraint; + break; + } + } + } + + if (heightConstraint != nil) + { + CGFloat dependHeight = UIViewNoIntrinsicMetric; + if ([heightConstraint.secondItem isKindOfClass:[UIView class]]) + { + UIView *dependView = (UIView*)heightConstraint.secondItem; + CGRect dependViewRect = dependView.bounds; + if (heightConstraint.secondAttribute == NSLayoutAttributeHeight) + dependHeight = CGRectGetHeight(dependViewRect); + else if (heightConstraint.secondAttribute == NSLayoutAttributeWidth) + dependHeight = CGRectGetWidth(dependViewRect); + else + dependHeight = UIViewNoIntrinsicMetric; + } + else if (heightConstraint.secondItem == nil) + { + dependHeight = 0; + } + else + { + //do nothing... + } + + if (dependHeight != UIViewNoIntrinsicMetric) + { + dependHeight *= heightConstraint.multiplier; + dependHeight += heightConstraint.constant; + + sz.width = [self sizeThatFits:CGSizeMake(0, dependHeight)].width; + } + } + } + else + { + //动态高度 + NSLayoutConstraint *widthConstraint = nil; + for (NSLayoutConstraint *constraint in self.constraints) + { + if (constraint.firstItem == self && constraint.firstAttribute == NSLayoutAttributeWidth) + { + widthConstraint = constraint; + break; + } + } + + if (widthConstraint == nil) + { + for (NSLayoutConstraint *constraint in self.superview.constraints) + { + if (constraint.firstItem == self && constraint.firstAttribute == NSLayoutAttributeWidth) + { + widthConstraint = constraint; + break; + } + } + } + + CGFloat dependWidth = UIViewNoIntrinsicMetric; + if (widthConstraint != nil) + { + if ([widthConstraint.secondItem isKindOfClass:[UIView class]]) + { + UIView *dependView = (UIView*)widthConstraint.secondItem; + CGRect dependViewRect = dependView.bounds; + if (widthConstraint.secondAttribute == NSLayoutAttributeWidth) + dependWidth = CGRectGetWidth(dependViewRect); + else if (widthConstraint.secondAttribute == NSLayoutAttributeHeight) + dependWidth = CGRectGetHeight(dependViewRect); + else + dependWidth = UIViewNoIntrinsicMetric; + } + else if (widthConstraint.secondItem == nil) + { + dependWidth = 0; + } + else + { + //do nothing... + } + + if (dependWidth != UIViewNoIntrinsicMetric) + { + dependWidth *= widthConstraint.multiplier; + dependWidth += widthConstraint.constant; + sz.height = [self sizeThatFits:CGSizeMake(dependWidth, 0)].height; + } + } + } + } + + return sz; + +} + -(void)layoutSubviews { @@ -1841,7 +1981,7 @@ -(void)layoutSubviews CGPoint sbvOldCenter = sbv.center; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvmyFrame.leading != CGFLOAT_MAX && sbvmyFrame.top != CGFLOAT_MAX && !sbvsc.noLayout && !sbvsc.useFrame) { diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 01b714a..b902b25 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -140,7 +140,7 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (!isEstimate) { @@ -420,7 +420,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; @@ -521,7 +521,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( { UIView *sbv = sbs[idx]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; @@ -932,7 +932,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvmyFrame.height > lineMaxHeight) lineMaxHeight = sbvmyFrame.height; @@ -946,7 +946,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; switch (sbvsc.myAlignment & MyGravity_Horz_Mask) { case MyGravity_Vert_Center: sbvmyFrame.top += (lineMaxHeight - sbvmyFrame.height) / 2.0; @@ -997,7 +997,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; @@ -1100,7 +1100,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( { UIView *sbv = sbs[idx]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; @@ -1499,7 +1499,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvmyFrame.width > lineMaxWidth) lineMaxWidth = sbvmyFrame.width; @@ -1513,7 +1513,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; switch ([self myConvertLeftRightGravityToLeadingTrailing:sbvsc.myAlignment & MyGravity_Vert_Mask]) { case MyGravity_Horz_Center: sbvmyFrame.leading += (lineMaxWidth - sbvmyFrame.width) / 2.0; diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 751e8a0..b05dd93 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -154,7 +154,7 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (!isEstimate) { @@ -243,7 +243,7 @@ - (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFlo { UIView *sbv = sbs[j]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.weight != 0) { @@ -266,7 +266,7 @@ - (void)myCalcHorzLayoutSinglelineWeight:(CGSize)selfSize totalFloatHeight:(CGFl { UIView *sbv = sbs[j]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.weight != 0) { @@ -345,7 +345,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo UIView *sbv = sbs[j]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (!isEstimate && self.intelligentBorderline != nil) { @@ -506,7 +506,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa { UIView *sbv = sbs[j]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (!isEstimate && self.intelligentBorderline != nil) @@ -757,7 +757,7 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb for (UIView* sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; #ifdef DEBUG //约束异常:垂直流式布局设置autoArrange为YES时,子视图不能将weight设置为非0. @@ -794,7 +794,7 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; @@ -1079,7 +1079,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (arrangedIndex >= arrangedCount) { @@ -1165,7 +1165,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; //新的一行 if (arrangedIndex >= arrangedCount) @@ -1293,8 +1293,9 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst else { //取前一行的对应的列的子视图。 - MyFrame *myPrevColSbvFrame = ((UIView*)sbs[i - arrangedCount]).myFrame; - UIView *myPrevColSbvsc = [self myCurrentSizeClassFrom:myPrevColSbvFrame]; + UIView *myPrevColSbv = (UIView*)sbs[i - arrangedCount]; + MyFrame *myPrevColSbvFrame = myPrevColSbv.myFrame; + UIView *myPrevColSbvsc = [myPrevColSbv myCurrentSizeClassFrom:myPrevColSbvFrame]; //当前子视图的位置等于前一行对应列的最大y的值 + 前面对应列的底部间距 + 子视图之间的行间距。 yPos = CGRectGetMaxY(myPrevColSbvFrame.frame)+ myPrevColSbvsc.bottomPosInner.absVal + vertSpace; } @@ -1470,7 +1471,7 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb for (UIView* sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; #ifdef DEBUG //约束异常:水平流式布局设置autoArrange为YES时,子视图不能将weight设置为非0. @@ -1529,7 +1530,7 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.absVal; @@ -1808,7 +1809,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (arrangedIndex >= arrangedCount) { @@ -1918,7 +1919,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (arrangedIndex >= arrangedCount) { @@ -2030,8 +2031,9 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst else { //取前一列的对应的行的子视图。 - MyFrame *myPrevColSbvFrame = ((UIView*)sbs[i - arrangedCount]).myFrame; - UIView *myPrevColSbvsc = [self myCurrentSizeClassFrom:myPrevColSbvFrame]; + UIView *myPrevColSbv = (UIView*)sbs[i - arrangedCount]; + MyFrame *myPrevColSbvFrame = myPrevColSbv.myFrame; + UIView *myPrevColSbvsc = [myPrevColSbv myCurrentSizeClassFrom:myPrevColSbvFrame]; //当前子视图的位置等于前一列对应行的最大x的值 + 前面对应行的尾部间距 + 子视图之间的列间距。 xPos = CGRectGetMaxX(myPrevColSbvFrame.frame)+ myPrevColSbvsc.trailingPosInner.absVal + horzSpace; } diff --git a/MyLayout/Lib/MyFrameLayout.m b/MyLayout/Lib/MyFrameLayout.m index e918c03..0c4a673 100644 --- a/MyLayout/Lib/MyFrameLayout.m +++ b/MyLayout/Lib/MyFrameLayout.m @@ -50,7 +50,7 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; [self myAdjustSubviewWrapContentSet:sbv isEstimate:isEstimate sbvmyFrame:sbvmyFrame sbvsc:sbvsc selfSize:selfSize sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; @@ -79,7 +79,7 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; //只有子视图的尺寸或者位置依赖父视图的情况下才需要重新计算位置和尺寸。 diff --git a/MyLayout/Lib/MyGridLayout.m b/MyLayout/Lib/MyGridLayout.m index c0db472..a7a13ce 100644 --- a/MyLayout/Lib/MyGridLayout.m +++ b/MyLayout/Lib/MyGridLayout.m @@ -1016,7 +1016,7 @@ -(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigi //调整位置和尺寸。。。 MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; //取垂直和水平对齐 MyGravity vertGravity = grid.gravity & MyGravity_Horz_Mask; @@ -1295,7 +1295,7 @@ -(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc if (!grid.anchor || (grid.measure == 0 && grid.anchor)) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; sbvmyFrame.frame = sbv.bounds; //如果子视图不设置任何约束但是又是包裹的则这里特殊处理。 diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index 4251f4a..c4579e5 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -37,7 +37,7 @@ */ -//Current version is 1.6.1, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.7.0, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. #ifndef MyLayout_MyLayout_h diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index e3ab689..b6c057d 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -196,7 +196,7 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (!isEstimate) { @@ -399,7 +399,7 @@ - (CGSize)myCalcMaxWrapWidth:(NSArray *)sbs selfSize:(CGSize)selfSize paddingHor for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; //只有宽度不依赖于父视图并且没有设置左右边距则参与最大包裹宽度计算。 MyLayoutSize *relaSize = sbvsc.widthSizeInner.dimeRelaVal; @@ -456,7 +456,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGRect rect = sbvmyFrame.frame; @@ -648,7 +648,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.posNumVal.doubleValue; @@ -785,7 +785,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.leadingPosInner.isRelativePos) { @@ -983,7 +983,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat leadingSpace = sbvsc.leadingPosInner.posNumVal.doubleValue; CGFloat trailingSpace = sbvsc.trailingPosInner.posNumVal.doubleValue; @@ -1152,7 +1152,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGRect rect = sbvmyFrame.frame; @@ -1217,7 +1217,7 @@ -(CGSize)myLayoutSubviewsForVertGravity:(CGSize)selfSize sbs:(NSArray*)sbs lsc:( for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; BOOL canAddToNoWrapSbs = YES; CGRect rect = sbvmyFrame.frame; @@ -1339,7 +1339,7 @@ -(CGSize)myLayoutSubviewsForVertGravity:(CGSize)selfSize sbs:(NSArray*)sbs lsc:( { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; pos += [self myValidMargin:sbvsc.topPosInner sbv:sbv calcPos:[sbvsc.topPosInner realPosIn:floatingHeight] selfLayoutSize:selfSize]; @@ -1396,7 +1396,7 @@ -(CGSize)myLayoutSubviewsForHorzGravity:(CGSize)selfSize sbs:(NSArray*)sbs lsc:( for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; BOOL canAddToNoWrapSbs = YES; CGRect rect = sbvmyFrame.frame; @@ -1533,7 +1533,7 @@ -(CGSize)myLayoutSubviewsForHorzGravity:(CGSize)selfSize sbs:(NSArray*)sbs lsc:( for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; pos += [self myValidMargin:sbvsc.leadingPosInner sbv:sbv calcPos:[sbvsc.leadingPosInner realPosIn:floatingWidth] selfLayoutSize:selfSize]; diff --git a/MyLayout/Lib/MyPathLayout.m b/MyLayout/Lib/MyPathLayout.m index b8ae21f..c01affc 100644 --- a/MyLayout/Lib/MyPathLayout.m +++ b/MyLayout/Lib/MyPathLayout.m @@ -561,7 +561,7 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (!isEstimate) { @@ -617,7 +617,7 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGPoint pt = CGPointZero; if (pts.count > i) @@ -704,7 +704,7 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbv != nil) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGRect rect = sbvmyFrame.frame; diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 9838590..04f8412 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -25,7 +25,7 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( for (UIView *sbv in self.subviews) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.useFrame) continue; @@ -55,7 +55,12 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (isEstimate && (sbvsc.wrapContentWidth || sbvsc.wrapContentHeight)) { - [(MyBaseLayout*)sbv sizeThatFits:sbvmyFrame.frame.size inSizeClass:sizeClass]; + CGSize sbvSize = sbvmyFrame.frame.size; + if (sbvSize.width == CGFLOAT_MAX) + sbvSize.width = 0; + if (sbvSize.height == CGFLOAT_MAX) + sbvSize.height = 0; + [(MyBaseLayout*)sbv sizeThatFits:sbvSize inSizeClass:sizeClass]; sbvmyFrame.leading = sbvmyFrame.trailing = sbvmyFrame.top = sbvmyFrame.bottom = CGFLOAT_MAX; @@ -488,7 +493,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL -(CGFloat)myCalcSubView:(UIView*)sbv lsc:(MyRelativeLayout*)lsc gravity:(MyGravity)gravity selfSize:(CGSize)selfSize { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; switch (gravity) { case MyGravity_Horz_Leading: @@ -806,7 +811,7 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize for (UIView *sbv in self.subviews) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; @@ -863,7 +868,7 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize for (UIView *sbv in self.subviews) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.widthSizeInner.dimeArrVal != nil) { @@ -1149,7 +1154,7 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [self myCurrentSizeClassFrom:sbvmyFrame]; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; BOOL sbvWrapContentHeight = sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]; [self myCalcSubViewLeadingTrailing:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; diff --git a/MyLayoutDemo/AllTest12ViewController.h b/MyLayoutDemo/AllTest12ViewController.h new file mode 100644 index 0000000..c9a0735 --- /dev/null +++ b/MyLayoutDemo/AllTest12ViewController.h @@ -0,0 +1,16 @@ +// +// AllTest11ViewController.h +// MyLayoutDemo +// +// Created by oubaiquan on 2018/8/1. +// Copyright © 2018年 YoungSoft. All rights reserved. +// + +#import + +/** +*❁6.MyLayout & AutoLayout +*/ +@interface AllTest12ViewController : UIViewController + +@end diff --git a/MyLayoutDemo/AllTest12ViewController.m b/MyLayoutDemo/AllTest12ViewController.m new file mode 100644 index 0000000..8a6c019 --- /dev/null +++ b/MyLayoutDemo/AllTest12ViewController.m @@ -0,0 +1,218 @@ +// +// AllTest11ViewController.m +// MyLayoutDemo +// +// Created by oubaiquan on 2018/8/1. +// Copyright © 2018年 YoungSoft. All rights reserved. +// + +#import "AllTest12ViewController.h" +#import "MyLayout.h" +#import "CFTool.h" + +@interface AllTest12ViewController () + + +@end + +@implementation AllTest12ViewController + +- (void)viewDidLoad { + self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + + // Do any additional setup after loading the view. + /* + 这个DEMO演示MyLayout和AutoLayout的代码结合的例子。因为布局视图也是一个普通的视图,因此可以把一个布局视图添加到现有的其他非布局父视图中并且对布局视图设置 + 约束。 因为布局视图具有wrapContent的特性,就如UILabel一样因为具有intrinsicContentSize的能力,因此不需要在约束中明确设置宽度或者高度约束。当一个布局视图 + 的高度或者宽度都是由子视图决定的,也就是wrapContent为YES时,布局视图也不需要明确的设置宽度或者高度的约束。而且其他视图还可以依赖这种布局视图尺寸的自包含的能力。 + + 本例子由3个子示例组成。 + + */ + + //容器视图包含一个垂直线性布局视图,垂直线性布局视图的尺寸由2个子视图决定,容器视图的尺寸由线性布局视图决定 + [self demo1]; + //一个线性布局视图的宽度为某个具体的约束值,高度由子视图决定。另外一个兄弟视图在线性布局视图的下面,一个兄弟视图在线性布局的右边。 + [self demo2]; + //一个水平线性布局的高度固定,宽度自适应,另外一个兄弟视图在水平线性布局视图的右边。 + [self demo3]; + + +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +-(void)demo1 +{ + //容器视图包含一个垂直线性布局视图,垂直线性布局视图的尺寸由2个子视图决定,容器视图的尺寸由线性布局视图决定 + + UIView *containerView = [UIView new]; + containerView.backgroundColor = [UIColor greenColor]; + containerView.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:containerView]; + + + MyLinearLayout *linelayout = [MyLinearLayout new]; + linelayout.translatesAutoresizingMaskIntoConstraints = NO; + linelayout.backgroundColor = [UIColor redColor]; + [containerView addSubview:linelayout]; + + + UIView *sbv1 = [UIView new]; + sbv1.backgroundColor = [UIColor blueColor]; + [linelayout addSubview:sbv1]; + UIView *sbv2 = [UIView new]; + sbv2.backgroundColor = [UIColor blueColor]; + [linelayout addSubview:sbv2]; + + + + //MyLayout中的约束设置方法 + linelayout.orientation = MyOrientation_Vert; + linelayout.wrapContentSize = YES; + linelayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); + linelayout.subviewSpace = 10; + + sbv1.mySize = CGSizeMake(100, 40); + sbv2.mySize = CGSizeMake(150, 50); + + + + //AutoLayout中的约束设置方法,采用iOS9提供的约束设置方法。 + [containerView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES; + [containerView.topAnchor constraintEqualToAnchor:self.view.topAnchor].active = YES; + //父视图约束依赖子视图约束会产生父视图的尺寸由子视图进行自适应的效果。 + [containerView.bottomAnchor constraintEqualToAnchor:linelayout.bottomAnchor constant:10].active = YES; + [containerView.rightAnchor constraintEqualToAnchor:linelayout.rightAnchor constant:10].active = YES; + + //线性布局视图的宽度和高度自适应,所以不需要设置任何高度和宽度的约束。 + [linelayout.leftAnchor constraintEqualToAnchor:containerView.leftAnchor constant:10].active = YES; + [linelayout.topAnchor constraintEqualToAnchor:containerView.topAnchor constant:10].active = YES; + +} + +-(void)demo2 +{ + //一个线性布局视图的宽度为某个具体的约束值,高度由子视图决定。另外一个兄弟视图在线性布局视图的下面,一个兄弟视图在线性布局的右边。 + + MyLinearLayout *linelayout = [MyLinearLayout new]; + linelayout.translatesAutoresizingMaskIntoConstraints = NO; + linelayout.backgroundColor = [UIColor redColor]; + [self.view addSubview:linelayout]; + + + UIView *sbv1 = [UIView new]; + sbv1.backgroundColor = [UIColor blueColor]; + [linelayout addSubview:sbv1]; + UIView *sbv2 = [UIView new]; + sbv2.backgroundColor = [UIColor blueColor]; + [linelayout addSubview:sbv2]; + + + UIView *brotherView1 = [UIView new]; + brotherView1.translatesAutoresizingMaskIntoConstraints = NO; + brotherView1.backgroundColor = [UIColor greenColor]; + [self.view addSubview:brotherView1]; + + UIView *brotherView2 = [UIView new]; + brotherView2.translatesAutoresizingMaskIntoConstraints = NO; + brotherView2.backgroundColor = [UIColor orangeColor]; + [self.view addSubview:brotherView2]; + + + //MyLayout中的约束设置 + linelayout.orientation = MyOrientation_Vert; + linelayout.wrapContentHeight = YES; + linelayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); + linelayout.subviewSpace = 10; + + sbv1.mySize = CGSizeMake(100, 40); + sbv2.mySize = CGSizeMake(150, 50); + + + //AutoLayout中的约束设置 + //线性布局因为高度是自适应的所以不需要设置高度约束。 + [linelayout.leftAnchor constraintEqualToAnchor:self.view.leftAnchor constant:10].active = YES; + [linelayout.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:180].active = YES; + //当布局视图的高度由子视图自适应且宽度为autolayout约束时,目前只支持对布局视图设置明确宽度约束才有效。 + //同时设置左右边界约束来推导布局视图宽度,并且高度又自适应目前不支持。 + [linelayout.widthAnchor constraintEqualToAnchor:self.view.widthAnchor constant:-150].active = YES; + + [brotherView1.leftAnchor constraintEqualToAnchor:linelayout.leftAnchor].active = YES; + [brotherView1.topAnchor constraintEqualToAnchor:linelayout.bottomAnchor constant:10].active = YES; + [brotherView1.widthAnchor constraintEqualToAnchor:linelayout.widthAnchor].active = YES; + [brotherView1.heightAnchor constraintEqualToAnchor:linelayout.heightAnchor].active = YES; + + + [brotherView2.leftAnchor constraintEqualToAnchor:linelayout.rightAnchor constant:10].active = YES; + [brotherView2.topAnchor constraintEqualToAnchor:linelayout.topAnchor].active = YES; + [brotherView2.widthAnchor constraintEqualToConstant:50].active = YES; + [brotherView2.heightAnchor constraintEqualToAnchor:linelayout.heightAnchor].active = YES; + +} + +-(void)demo3 +{ + MyLinearLayout *linelayout = [MyLinearLayout new]; + linelayout.translatesAutoresizingMaskIntoConstraints = NO; + linelayout.backgroundColor = [UIColor redColor]; + [self.view addSubview:linelayout]; + + + UIView *sbv1 = [UIView new]; + sbv1.backgroundColor = [UIColor blueColor]; + [linelayout addSubview:sbv1]; + UIView *sbv2 = [UIView new]; + sbv2.backgroundColor = [UIColor blueColor]; + [linelayout addSubview:sbv2]; + + + UIView *brotherView1 = [UIView new]; + brotherView1.translatesAutoresizingMaskIntoConstraints = NO; + brotherView1.backgroundColor = [UIColor greenColor]; + [self.view addSubview:brotherView1]; + + + //MyLayout中的约束设置 + linelayout.orientation = MyOrientation_Horz; + linelayout.wrapContentWidth = YES; + linelayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); + linelayout.subviewSpace = 10; + linelayout.gravity = MyGravity_Vert_Fill; + + + sbv1.myWidth = 50; + sbv2.myWidth = 60; + + + //AutoLayout中的约束设置 + [linelayout.leftAnchor constraintEqualToAnchor:self.view.leftAnchor constant:10].active = YES; + [linelayout.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:500].active = YES; + [linelayout.heightAnchor constraintEqualToConstant:60].active = YES; + + [brotherView1.leftAnchor constraintEqualToAnchor:linelayout.rightAnchor constant:10].active = YES; + [brotherView1.topAnchor constraintEqualToAnchor:linelayout.topAnchor].active = YES; + [brotherView1.widthAnchor constraintEqualToAnchor:linelayout.widthAnchor].active = YES; + [brotherView1.heightAnchor constraintEqualToAnchor:linelayout.heightAnchor].active = YES; + + +} + + +@end diff --git a/MyLayoutDemo/AllTest1TableViewCell.h b/MyLayoutDemo/AllTest1TableViewCell.h index eb036a7..852fbe7 100644 --- a/MyLayoutDemo/AllTest1TableViewCell.h +++ b/MyLayoutDemo/AllTest1TableViewCell.h @@ -12,6 +12,7 @@ /** * 动态高度UITableViewCell + * 本例子是将布局视图的高度自适应能力和在不使用AutoLayout的情况下实现UITableViewCell高度自适应的能力 */ @interface AllTest1TableViewCell : UITableViewCell diff --git a/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.h b/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.h new file mode 100644 index 0000000..4906966 --- /dev/null +++ b/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.h @@ -0,0 +1,25 @@ +// +// AllTest1TableViewCellForAutoLayout.h +// MyLayout +// +// Created by apple on 19/5/16. +// Copyright © 2016年 YoungSoft. All rights reserved. +// + +#import +#import "MyLayout.h" +#import "AllTestDataModel.h" + +/** + * 动态高度UITableViewCellForAutoLayout + * 本例子是将布局视图的高度自适应能力和使用Autolayout的情况下实现UITableViewCell高度自适应的能力 + */ +@interface AllTest1TableViewCellForAutoLayout : UITableViewCell + +//对于需要动态评估高度的UITableViewCell来说可以把布局视图暴露出来。用于高度评估和边界线处理。以及事件处理的设置。 +@property(nonatomic, strong, readonly) MyBaseLayout *rootLayout; + + +-(void)setModel:(AllTest1DataModel*)model isImageMessageHidden:(BOOL)isImageMessageHidden; + +@end diff --git a/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m b/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m new file mode 100644 index 0000000..250e50c --- /dev/null +++ b/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m @@ -0,0 +1,238 @@ +// +// AllTest1TableViewCellForAutoLayout.m +// MyLayout +// +// Created by apple on 19/5/16. +// Copyright © 2016年 YoungSoft. All rights reserved. +// + +#import "AllTest1TableViewCellForAutoLayout.h" +#import "CFTool.h" + + +@interface AllTest1TableViewCellForAutoLayout() + +@property(nonatomic, strong) UIImageView *headImageView; +@property(nonatomic, strong) UILabel *nickNameLabel; +@property(nonatomic, strong) UILabel *textMessageLabel; +@property(nonatomic, strong) UIImageView *imageMessageImageView; + +@end + + +@implementation AllTest1TableViewCellForAutoLayout + +-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier +{ + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self != nil) + { + /** + * 您可以尝试用不同的布局来实现相同的功能。 + */ + [self createLinearRootLayout]; + // [self createRelativeRootLayout]; + // [self createFloatRootLayout]; + + //设置布局视图的autolayout约束,这里是用iOS9提供的约束设置方法,您也可以用低级版本设置,以及用masonry来进行设置。 + [_rootLayout.leftAnchor constraintEqualToAnchor:self.contentView.leftAnchor].active = YES; + [_rootLayout.topAnchor constraintEqualToAnchor:self.contentView.topAnchor].active = YES; + //目前MyLayout和AutoLayout相结合并且高度根据宽度自适应时只能通过明确设置宽度约束,暂时不支持同时设置左右约束来确定宽度的能力。 + [_rootLayout.widthAnchor constraintEqualToAnchor:self.contentView.widthAnchor].active = YES; + + //这句代码很关键,表明self.contentView的高度随着子视图_rootLayout的高度自适应。 + [self.contentView.bottomAnchor constraintEqualToAnchor:_rootLayout.bottomAnchor constant:0].active = YES; + + + } + + return self; +} + +-(void)setModel:(AllTest1DataModel*)model isImageMessageHidden:(BOOL)isImageMessageHidden +{ + self.headImageView.image = [UIImage imageNamed:model.headImage]; + [self.headImageView sizeToFit]; + + + self.nickNameLabel.text = model.nickName; + [self.nickNameLabel sizeToFit]; + + self.textMessageLabel.text = model.textMessage; + + if (model.imageMessage.length == 0) + { + self.imageMessageImageView.myVisibility = MyVisibility_Gone; + } + else + { + self.imageMessageImageView.image = [UIImage imageNamed:model.imageMessage]; + [self.imageMessageImageView sizeToFit]; + if (isImageMessageHidden) + { + self.imageMessageImageView.myVisibility = MyVisibility_Gone; + } + else + { + self.imageMessageImageView.myVisibility = MyVisibility_Visible; + } + } + +} + + +- (void)awakeFromNib { + // Initialization code + [super awakeFromNib]; + +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + + +#pragma mark -- Layout Construction + +//用线性布局来实现UI界面 +-(void)createLinearRootLayout +{ + _rootLayout= [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + _rootLayout.translatesAutoresizingMaskIntoConstraints = NO; //通过代码形式来设置autolayout约束时必须要将这个属性设置为NO + _rootLayout.topPadding = 5; + _rootLayout.bottomPadding = 5; + //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! + _rootLayout.cacheEstimatedRect = YES; + _rootLayout.wrapContentHeight = YES; + _rootLayout.wrapContentWidth = NO; + [self.contentView addSubview:_rootLayout]; + + + + /* + 用线性布局实现时,整体用一个水平线性布局:左边是头像,右边是一个垂直的线性布局。垂直线性布局依次加入昵称、文本消息、图片消息。 + */ + + + _headImageView = [UIImageView new]; + [_rootLayout addSubview:_headImageView]; + + + MyLinearLayout *messageLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + messageLayout.weight = 1; + messageLayout.myLeading = 5; //前面2行代码描述的是垂直布局占用除头像外的所有宽度,并和头像保持5个点的间距。 + messageLayout.subviewVSpace = 5; //垂直布局里面所有子视图都保持5个点的间距。 + [_rootLayout addSubview:messageLayout]; + + + _nickNameLabel = [UILabel new]; + _nickNameLabel.textColor = [CFTool color:3]; + _nickNameLabel.font = [CFTool font:17]; + [messageLayout addSubview:_nickNameLabel]; + + + _textMessageLabel = [UILabel new]; + _textMessageLabel.font = [CFTool font:15]; + _textMessageLabel.textColor = [CFTool color:4]; + _textMessageLabel.myLeading = 0; + _textMessageLabel.myTrailing = 0; //垂直线性布局里面如果同时设置了左右边距则能确定子视图的宽度,这里表示宽度和父视图相等。 + _textMessageLabel.wrapContentHeight = YES; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + [messageLayout addSubview:_textMessageLabel]; + + + _imageMessageImageView = [UIImageView new]; + _imageMessageImageView.myCenterX = 0; //图片视图在父布局视图中水平居中。 + [messageLayout addSubview:_imageMessageImageView]; +} + +//用相对布局来实现UI界面 +-(void)createRelativeRootLayout +{ + _rootLayout = [MyRelativeLayout new]; + _rootLayout.translatesAutoresizingMaskIntoConstraints = NO; + _rootLayout.topPadding = 5; + _rootLayout.bottomPadding = 5; + //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! + _rootLayout.cacheEstimatedRect = YES; + _rootLayout.wrapContentHeight = YES; + [self.contentView addSubview:_rootLayout]; + + + /* + 用相对布局实现时,左边是头像视图,昵称文本在头像视图的右边,文本消息在昵称文本的下面,图片消息在文本消息的下面。 + */ + + _headImageView = [UIImageView new]; + [_rootLayout addSubview:_headImageView]; + + + _nickNameLabel = [UILabel new]; + _nickNameLabel.textColor = [CFTool color:3]; + _nickNameLabel.font = [CFTool font:17]; + _nickNameLabel.leadingPos.equalTo(_headImageView.trailingPos).offset(5); //昵称文本的左边在头像视图的右边并偏移5个点。 + [_rootLayout addSubview:_nickNameLabel]; + + + _textMessageLabel = [UILabel new]; + _textMessageLabel.font = [CFTool font:15]; + _textMessageLabel.textColor = [CFTool color:4]; + _textMessageLabel.leadingPos.equalTo(_headImageView.trailingPos).offset(5); //文本消息的左边在头像视图的右边并偏移5个点。 + _textMessageLabel.trailingPos.equalTo(_rootLayout.trailingPos); //文本消息的右边和父布局的右边对齐。上面2行代码也同时确定了文本消息的宽度。 + _textMessageLabel.topPos.equalTo(_nickNameLabel.bottomPos).offset(5); //文本消息的顶部在昵称文本的底部并偏移5个点。 + _textMessageLabel.wrapContentHeight = YES; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + [_rootLayout addSubview:_textMessageLabel]; + + + _imageMessageImageView = [UIImageView new]; + _imageMessageImageView.centerXPos.equalTo(@5); //图片消息的水平中心点等于父布局的水平中心点并偏移5个点的位置,这里要偏移5的原因是头像和消息之间需要5个点的间距。 + _imageMessageImageView.topPos.equalTo(_textMessageLabel.bottomPos).offset(5); //图片消息的顶部在文本消息的底部并偏移5个点。 + [_rootLayout addSubview:_imageMessageImageView]; + +} + +//用浮动布局来实现UI界面 +-(void)createFloatRootLayout +{ + _rootLayout= [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; + _rootLayout.topPadding = 5; + _rootLayout.bottomPadding = 5; + //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! + _rootLayout.cacheEstimatedRect = YES; + _rootLayout.wrapContentHeight = YES; + [self.contentView addSubview:_rootLayout]; + + /* + 用浮动布局实现时,头像视图浮动到最左边,昵称文本跟在头像视图后面并占用剩余宽度,文本消息也跟在头像视图后面并占用剩余宽度,图片消息不浮动占据所有宽度。 + 要想了解浮动布局的原理,请参考文章:http://www.jianshu.com/p/0c075f2fdab2 中的介绍。 + */ + + + _headImageView = [UIImageView new]; + _headImageView.myTrailing = 5; //右边保留出5个点的视图间距。 + [_rootLayout addSubview:_headImageView]; + + _nickNameLabel = [UILabel new]; + _nickNameLabel.textColor = [CFTool color:3]; + _nickNameLabel.font = [CFTool font:17]; + _nickNameLabel.myBottom = 5; //下边保留出5个点的视图间距。 + _nickNameLabel.weight = 1; //占用剩余宽度。 + [_rootLayout addSubview:_nickNameLabel]; + + _textMessageLabel = [UILabel new]; + _textMessageLabel.font = [CFTool font:15]; + _textMessageLabel.textColor = [CFTool color:4]; + _textMessageLabel.weight = 1; //占用剩余宽度 + _textMessageLabel.wrapContentHeight = YES; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + [_rootLayout addSubview:_textMessageLabel]; + + _imageMessageImageView = [UIImageView new]; + _imageMessageImageView.myTop = 5; + _imageMessageImageView.reverseFloat = YES; //反向浮动 + _imageMessageImageView.weight = 1; //占用剩余空间。 + _imageMessageImageView.contentMode = UIViewContentModeCenter; + [_rootLayout addSubview:_imageMessageImageView]; +} + +@end diff --git a/MyLayoutDemo/AllTest1ViewController.m b/MyLayoutDemo/AllTest1ViewController.m index 445c6ba..381fe7d 100644 --- a/MyLayoutDemo/AllTest1ViewController.m +++ b/MyLayoutDemo/AllTest1ViewController.m @@ -9,6 +9,7 @@ #import "AllTest1ViewController.h" #import "AllTestDataModel.h" #import "AllTest1TableViewCell.h" +#import "AllTest1TableViewCellForAutoLayout.h" #import "AllTest1TableViewHeaderFooterView.h" #import "MyLayout.h" @@ -98,10 +99,11 @@ - (void)viewDidLoad { //设置所有cell的高度为高度自适应,如果cell高度是动态的请这么设置。 如果不同的cell有差异那么可以通过实现协议方法-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath //如果您最低要支持到iOS7那么请您实现-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath方法来代替这个属性的设置。 self.tableView.rowHeight = UITableViewAutomaticDimension; - - + + //MyLayout中的布局视图可以支持UITableViewCell的高度自适应的能力。这里注册两个cell,一个是不和AutoLayout结合的实现,一个是和AutoLayout结合的实现。至于使用哪种方式您可以二选一。 [self.tableView registerClass:[AllTest1TableViewCell class] forCellReuseIdentifier:@"alltest1_cell"]; - + [self.tableView registerClass:[AllTest1TableViewCellForAutoLayout class] forCellReuseIdentifier:@"alltest1_cell_forautolayout"]; + /** @@ -233,15 +235,20 @@ -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSI AllTest1TableViewCell *cell; + //MyLayout中的布局视图可以支持UITableViewCell的高度自适应的能力。这里注册两个cell,一个是不和AutoLayout结合的实现,一个是和AutoLayout结合的实现。至于使用哪种方式您可以二选一。 + NSString *identifiers[2] = {@"alltest1_cell", @"alltest1_cell_forautolayout"}; + + //这里因为AllTest1TableViewCell和AllTest1TableViewCellForAutoLayout的方法名相同,所以这里虽然是两个不同的类,但是我们还是可以使用 + //AllTest1TableViewCell 这种类型来操作这些方法。 if ([UIDevice currentDevice].systemVersion.floatValue < 8) { //如果您的系统要求最低支持到iOS7那么需要通过-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 来评估高度,因此请不要使用- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath 这个方法来初始化UITableviewCell,否则可能造成系统崩溃!!! - cell = (AllTest1TableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"alltest1_cell"]; + cell = (AllTest1TableViewCell*)[tableView dequeueReusableCellWithIdentifier:identifiers[rand()%2]]; } else { //如果你最低支持到iOS8那么请用这个方法来初始化一个UITableviewCell,用这个方法要记得调用registerClass来注册UITableviewCell,否则可能会返回nil - cell = (AllTest1TableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"alltest1_cell" forIndexPath:indexPath]; + cell = (AllTest1TableViewCell*)[tableView dequeueReusableCellWithIdentifier:identifiers[rand()%2] forIndexPath:indexPath]; } diff --git a/MyLayoutDemo/Info.plist b/MyLayoutDemo/Info.plist index 881c44f..325e420 100644 --- a/MyLayoutDemo/Info.plist +++ b/MyLayoutDemo/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.5.4 + 1.7.0 CFBundleSignature ???? CFBundleVersion diff --git a/MyLayoutDemo/ViewController.m b/MyLayoutDemo/ViewController.m index 4b7bb8e..439d467 100644 --- a/MyLayoutDemo/ViewController.m +++ b/MyLayoutDemo/ViewController.m @@ -56,6 +56,7 @@ #import "AllTest9ViewController.h" #import "AllTest10ViewController.h" #import "AllTest11ViewController.h" +#import "AllTest12ViewController.h" #import "FOLTest1ViewController.h" @@ -296,6 +297,9 @@ -(NSArray*)demoTypeList }, @{@"title":NSLocalizedString(@"❁5.Subviews layout transform", @""), @"class":[AllTest11ViewController class] + }, + @{@"title":NSLocalizedString(@"❁6.MyLayout & AutoLayout", @""), + @"class":[AllTest12ViewController class] } ] } diff --git a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings index e05f919..56fe993 100644 --- a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings +++ b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings @@ -63,6 +63,7 @@ "❁3.UICollectionView height self-adaption" = "❁3.UICollectionView 高度自适应"; "❁4.Circle of friends height self-adaption" = "❁4.朋友圈 高度自适应"; "❁5.Subviews layout transform" = "❁5.布局内子视图的整体变换"; +"❁6.MyLayout & AutoLayout" = "❁6.MyLayout和AutoLayout结合"; //LLTest1ViewController "vertical(from top to bottom)" = "垂直布局(从上到下)"; "left margin" = "左边边距"; From 046b85a281220c7832088fdb19a1a88123125de0 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Fri, 21 Jun 2019 16:03:13 +0800 Subject: [PATCH 029/115] =?UTF-8?q?1.=E9=87=8D=E6=9E=84=E7=BA=BF=E6=80=A7?= =?UTF-8?q?=E5=B8=83=E5=B1=80=EF=BC=8C2.=E4=BF=AE=E5=A4=8D=E7=BA=BF?= =?UTF-8?q?=E4=B8=8ABUG=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout.xcodeproj/project.pbxproj | 12 +- ...0B2E8D10-2561-4DF8-8F44-0650622D8DB9.plist | 5 + MyLayout/Lib/MyBaseLayout.m | 280 ++-- MyLayout/Lib/MyFloatLayout.m | 391 ++---- MyLayout/Lib/MyFlowLayout.m | 446 +++--- MyLayout/Lib/MyFrameLayout.m | 138 -- MyLayout/Lib/MyLayout.h | 2 +- MyLayout/Lib/MyLayoutInner.h | 39 +- MyLayout/Lib/MyLinearLayout.m | 1224 ++++++----------- MyLayout/Lib/MyPathLayout.m | 131 +- MyLayout/Lib/MyRelativeLayout.m | 88 +- .../AllTest1TableViewCellForAutoLayout.m | 5 +- MyLayoutDemo/LLTest3ViewController.m | 2 +- MyLayoutDemo/RLTest4ViewController.m | 1 + MyLayoutTests/MyFloatLayoutTestCase.m | 126 ++ MyLayoutTests/MyFlowLayoutTestCase.m | 278 ++++ MyLayoutTests/MyLinearLayoutTestCase.m | 124 ++ 17 files changed, 1629 insertions(+), 1663 deletions(-) create mode 100644 MyLayout.xcodeproj/xcshareddata/xcbaselines/184082A51B2C46E8003F378B.xcbaseline/0B2E8D10-2561-4DF8-8F44-0650622D8DB9.plist create mode 100644 MyLayoutTests/MyFlowLayoutTestCase.m diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index 198e3d3..625c3d3 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -32,7 +32,7 @@ 189738511E16330B004F80D6 /* MyLayoutTestCaseBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 189738501E16330B004F80D6 /* MyLayoutTestCaseBase.m */; }; 18B152341DEDDE5500AD7A1C /* MyLayoutUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */; }; 18B2CCE81EAF5066001AE0E1 /* MyLinearLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */; }; - 18B2CCEA1EB046AC001AE0E1 /* MyFloatLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */; }; + 18B2CCEA1EB046AC001AE0E1 /* MyFlowLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B2CCE91EB046AB001AE0E1 /* MyFlowLayoutTestCase.m */; }; 18C15AEC1EDF13D700AADEAC /* MyLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 18D684001C4F421400A48BB4 /* MyLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18C15AED1EDF13DE00AADEAC /* MyFlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AB1E77E5930081AA4B /* MyFlowLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18C15AEE1EDF13E500AADEAC /* MyLinearLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225AC1E77E5930081AA4B /* MyLinearLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -149,6 +149,7 @@ 205643161F55A03000E8BDDE /* MyLayoutMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 205643141F55A03000E8BDDE /* MyLayoutMath.h */; }; 205643171F55A03000E8BDDE /* MyLayoutMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643151F55A03000E8BDDE /* MyLayoutMath.m */; }; 205643181F55A16400E8BDDE /* MyLayoutMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 205643151F55A03000E8BDDE /* MyLayoutMath.m */; }; + 205AE95E22BC4C2900BE8E76 /* MyFloatLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 205AE95D22BC4C2900BE8E76 /* MyFloatLayoutTestCase.m */; }; 205CFA8E1F49BD1C00355489 /* GLTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */; }; 205E0C5F20B90347001A8B99 /* MyGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = 205642891F4D013D00E8BDDE /* MyGrid.h */; settings = {ATTRIBUTES = (Public, ); }; }; 205E0C6020B907CC001A8B99 /* MyLayoutPosInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 182225C61E77E5930081AA4B /* MyLayoutPosInner.h */; }; @@ -245,7 +246,7 @@ 18B152331DEDDE5500AD7A1C /* MyLayoutUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyLayoutUITests.m; sourceTree = ""; }; 18B152351DEDDE5500AD7A1C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLinearLayoutTestCase.m; sourceTree = ""; }; - 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyFloatLayoutTestCase.m; sourceTree = ""; }; + 18B2CCE91EB046AB001AE0E1 /* MyFlowLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyFlowLayoutTestCase.m; sourceTree = ""; }; 18C15AEA1EDF133200AADEAC /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 18D3C9031EDF074900D3DE43 /* LLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLTest1ViewController.h; sourceTree = ""; }; 18D3C9041EDF074900D3DE43 /* LLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLTest1ViewController.m; sourceTree = ""; }; @@ -392,6 +393,7 @@ 205643121F51C7EB00E8BDDE /* GLTest2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GLTest2ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 205643141F55A03000E8BDDE /* MyLayoutMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutMath.h; sourceTree = ""; }; 205643151F55A03000E8BDDE /* MyLayoutMath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutMath.m; sourceTree = ""; }; + 205AE95D22BC4C2900BE8E76 /* MyFloatLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyFloatLayoutTestCase.m; sourceTree = ""; }; 205CFA8C1F49BD1C00355489 /* GLTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest1ViewController.h; sourceTree = ""; }; 205CFA8D1F49BD1C00355489 /* GLTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GLTest1ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 205F9EB91F7AA5710034732C /* gl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = gl.png; sourceTree = ""; }; @@ -837,7 +839,8 @@ 180BD8A01EA9EF9A00C6980B /* MyFrameLayoutTestCase.m */, 181836941EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m */, 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */, - 18B2CCE91EB046AB001AE0E1 /* MyFloatLayoutTestCase.m */, + 18B2CCE91EB046AB001AE0E1 /* MyFlowLayoutTestCase.m */, + 205AE95D22BC4C2900BE8E76 /* MyFloatLayoutTestCase.m */, 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */, ); path = MyLayoutTests; @@ -1217,13 +1220,14 @@ buildActionMask = 2147483647; files = ( 18B2CCE81EAF5066001AE0E1 /* MyLinearLayoutTestCase.m in Sources */, + 205AE95E22BC4C2900BE8E76 /* MyFloatLayoutTestCase.m in Sources */, 18D684591C4F423400A48BB4 /* MyLayoutTests.m in Sources */, 1810AC221EB966D30022CBFF /* MyLayoutPerformanceTestCase.m in Sources */, 181836951EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m in Sources */, 180BD8A11EA9EF9A00C6980B /* MyFrameLayoutTestCase.m in Sources */, 1897384F1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m in Sources */, 189738511E16330B004F80D6 /* MyLayoutTestCaseBase.m in Sources */, - 18B2CCEA1EB046AC001AE0E1 /* MyFloatLayoutTestCase.m in Sources */, + 18B2CCEA1EB046AC001AE0E1 /* MyFlowLayoutTestCase.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MyLayout.xcodeproj/xcshareddata/xcbaselines/184082A51B2C46E8003F378B.xcbaseline/0B2E8D10-2561-4DF8-8F44-0650622D8DB9.plist b/MyLayout.xcodeproj/xcshareddata/xcbaselines/184082A51B2C46E8003F378B.xcbaseline/0B2E8D10-2561-4DF8-8F44-0650622D8DB9.plist new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/MyLayout.xcodeproj/xcshareddata/xcbaselines/184082A51B2C46E8003F378B.xcbaseline/0B2E8D10-2561-4DF8-8F44-0650622D8DB9.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 5386695..bd772f7 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -720,6 +720,24 @@ -(MyLayoutSize*)heightSizeInner return self.myCurrentSizeClass.heightSizeInner; } + +-(CGFloat)myEstimatedWidth +{ + MyFrame *myFrame = self.myFrame; + if (myFrame.width == CGFLOAT_MAX) + return CGRectGetWidth(self.bounds); + return myFrame.width; +} + +-(CGFloat)myEstimatedHeight +{ + MyFrame *myFrame = self.myFrame; + if (myFrame.height == CGFLOAT_MAX) + return CGRectGetHeight(self.bounds); + return myFrame.height; +} + + @end @@ -1503,6 +1521,8 @@ - (void)didAddSubview:(UIView *)subview ((MyBaseLayout*)subview).cacheEstimatedRect = self.cacheEstimatedRect; } + [self myInvalidateIntrinsicContentSize]; + } - (void)willRemoveSubview:(UIView *)subview @@ -1510,6 +1530,8 @@ - (void)willRemoveSubview:(UIView *)subview [super willRemoveSubview:subview]; //删除后恢复其原来的实现。 [self myRemoveSubviewObserver:subview]; + + [self myInvalidateIntrinsicContentSize]; } -(void)willMoveToWindow:(UIWindow *)newWindow @@ -1774,11 +1796,7 @@ -(void)safeAreaInsetsDidChange -(void)setNeedsLayout { [super setNeedsLayout]; - if (!self.translatesAutoresizingMaskIntoConstraints) - { - if (self.wrapContentWidth || self.wrapContentHeight) - [self invalidateIntrinsicContentSize]; - } + [self myInvalidateIntrinsicContentSize]; } -(CGSize)intrinsicContentSize @@ -1926,7 +1944,7 @@ -(void)layoutSubviews if (!self.isMyLayouting) { - _isMyLayouting = YES; + self.isMyLayouting = YES; if (self.priorAutoresizingMask) [super layoutSubviews]; @@ -2112,16 +2130,21 @@ -(void)layoutSubviews CGRect currentBounds = self.bounds; CGPoint currentCenter = self.center; + //针对滚动父视图做特殊处理,如果父视图是滚动视图,而且当前的缩放比例不为1时系统会调整中心点的位置,因此这里需要特殊处理。 + CGFloat superViewZoomScale = 1.0; + if ([self.superview isKindOfClass:[UIScrollView class]]) + superViewZoomScale = ((UIScrollView*)self.superview).zoomScale; + if (isWidthAlter && lsc.wrapContentWidth) { currentBounds.size.width = newSelfSize.width; - currentCenter.x += (newSelfSize.width - oldSelfSize.width) * self.layer.anchorPoint.x; + currentCenter.x += (newSelfSize.width - oldSelfSize.width) * self.layer.anchorPoint.x * superViewZoomScale; } if (isHeightAlter && lsc.wrapContentHeight) { currentBounds.size.height = newSelfSize.height; - currentCenter.y += (newSelfSize.height - oldSelfSize.height) * self.layer.anchorPoint.y; + currentCenter.y += (newSelfSize.height - oldSelfSize.height) * self.layer.anchorPoint.y * superViewZoomScale; } self.bounds = currentBounds; @@ -2260,7 +2283,7 @@ -(void)layoutSubviews if (selfMyFrame.multiple) selfMyFrame.sizeClass = [self myDefaultSizeClass]; - _isMyLayouting = NO; + self.isMyLayouting = NO; } @@ -2345,7 +2368,7 @@ -(MyGravity)myGetSubviewVertGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc vertGravit } --(void)myCalcVertGravity:(MyGravity)vertGravity +-(CGFloat)myCalcVertGravity:(MyGravity)vertGravity sbv:(UIView *)sbv sbvsc:(UIView*)sbvsc paddingTop:(CGFloat)paddingTop @@ -2412,6 +2435,7 @@ -(void)myCalcVertGravity:(MyGravity)vertGravity ; } + return topMargin + centerMargin + bottomMargin + pRect->size.height; } @@ -2459,7 +2483,7 @@ -(MyGravity)myGetSubviewHorzGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc horzGravit } --(void)myCalcHorzGravity:(MyGravity)horzGravity +-(CGFloat)myCalcHorzGravity:(MyGravity)horzGravity sbv:(UIView *)sbv sbvsc:(UIView*)sbvsc paddingLeading:(CGFloat)paddingLeading @@ -2514,11 +2538,20 @@ -(void)myCalcHorzGravity:(MyGravity)horzGravity { ; } + + return leadingMargin + centerMargin + trailingMargin + pRect->size.width; } -(void)myCalcSizeOfWrapContentSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc sbvmyFrame:(MyFrame*)sbvmyFrame { + if (sbvsc.myVisibility == MyVisibility_Gone) + { + sbvmyFrame.width = 0; + sbvmyFrame.height = 0; + return; + } + BOOL isLayoutView = [sbv isKindOfClass:[MyBaseLayout class]]; BOOL isWrapWidth = (sbvsc.widthSizeInner.dimeSelfVal != nil) || (!isLayoutView && sbvsc.wrapContentWidth); //宽度包裹特殊处理 BOOL isWrapHeight = (sbvsc.heightSizeInner.dimeSelfVal != nil) || (!isLayoutView && sbvsc.wrapContentSize);//高度包裹也特殊处理 @@ -2636,9 +2669,14 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview CGFloat bottomMargin = [lsc.bottomPosInner realPosIn:rectSuper.size.height]; CGRect rectSelf = self.bounds; + //针对滚动父视图做特殊处理,如果父视图是滚动视图,而且当前的缩放比例不为1时系统会调整中心点的位置,因此这里需要特殊处理。 + CGFloat superViewZoomScale = 1.0; + if ([newSuperview isKindOfClass:[UIScrollView class]]) + superViewZoomScale = ((UIScrollView*)newSuperview).zoomScale; + //得到在设置center后的原始值。 - rectSelf.origin.y = self.center.y - rectSelf.size.height * self.layer.anchorPoint.y; - rectSelf.origin.x = self.center.x - rectSelf.size.width * self.layer.anchorPoint.x; + rectSelf.origin.x = self.center.x - rectSelf.size.width * self.layer.anchorPoint.x * superViewZoomScale; + rectSelf.origin.y = self.center.y - rectSelf.size.height * self.layer.anchorPoint.y * superViewZoomScale; CGRect oldRectSelf = rectSelf; //确定左右边距和宽度。 @@ -2845,7 +2883,7 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview else { self.bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y,rectSelf.size.width, rectSelf.size.height); - self.center = CGPointMake(rectSelf.origin.x + self.layer.anchorPoint.x * rectSelf.size.width, rectSelf.origin.y + self.layer.anchorPoint.y * rectSelf.size.height); + self.center = CGPointMake(rectSelf.origin.x + self.layer.anchorPoint.x * rectSelf.size.width * superViewZoomScale, rectSelf.origin.y + self.layer.anchorPoint.y * rectSelf.size.height * superViewZoomScale); } } else if (lsc.wrapContentWidth || lsc.wrapContentHeight) @@ -2865,10 +2903,13 @@ -(CGFloat)myHeightFromFlexedHeightView:(UIView*)sbv sbvsc:(UIView*)sbvsc inWidth if ([sbv isKindOfClass:[UIImageView class]]) { //根据图片的尺寸进行等比缩放得到合适的高度。 - UIImage *img = ((UIImageView*)sbv).image; - if (img != nil && img.size.width != 0) + if (!sbvsc.wrapContentWidth) { - h = img.size.height * (width / img.size.width); + UIImage *img = ((UIImageView*)sbv).image; + if (img != nil && img.size.width != 0) + { + h = img.size.height * (width / img.size.width); + } } } else if ([sbv isKindOfClass:[UIButton class]]) @@ -3101,40 +3142,6 @@ -(NSMutableArray*)myGetLayoutSubviewsFrom:(NSArray*)sbsFrom } --(void)mySetSubviewRelativeDimeSize:(MyLayoutSize*)dime selfSize:(CGSize)selfSize lsc:(MyBaseLayout*)lsc pRect:(CGRect*)pRect -{ - if (dime.dimeRelaVal == nil) - return; - - if (dime.dime == MyGravity_Horz_Fill) - { - - if (dime.dimeRelaVal == lsc.widthSizeInner && !lsc.wrapContentWidth) - pRect->size.width = [dime measureWith:(selfSize.width - lsc.myLayoutLeadingPadding - lsc.myLayoutTrailingPadding)]; - else if (dime.dimeRelaVal == lsc.heightSizeInner) - pRect->size.width = [dime measureWith:(selfSize.height - lsc.myLayoutTopPadding - lsc.myLayoutBottomPadding)]; - else if (dime.dimeRelaVal == dime.view.heightSizeInner) - pRect->size.width = [dime measureWith:pRect->size.height]; - else if (dime.dimeRelaVal.dime == MyGravity_Horz_Fill) - pRect->size.width = [dime measureWith:dime.dimeRelaVal.view.estimatedRect.size.width]; - else - pRect->size.width = [dime measureWith:dime.dimeRelaVal.view.estimatedRect.size.height]; - } - else - { - if (dime.dimeRelaVal == lsc.heightSizeInner && !lsc.wrapContentHeight) - pRect->size.height = [dime measureWith:(selfSize.height - lsc.myLayoutTopPadding - lsc.myLayoutBottomPadding)]; - else if (dime.dimeRelaVal == lsc.widthSizeInner) - pRect->size.height = [dime measureWith:(selfSize.width - lsc.myLayoutLeadingPadding - lsc.myLayoutTrailingPadding)]; - else if (dime.dimeRelaVal == dime.view.widthSizeInner) - pRect->size.height = [dime measureWith:pRect->size.width]; - else if (dime.dimeRelaVal.dime == MyGravity_Horz_Fill) - pRect->size.height = [dime measureWith:dime.dimeRelaVal.view.estimatedRect.size.width]; - else - pRect->size.height = [dime measureWith:dime.dimeRelaVal.view.estimatedRect.size.height]; - } -} - -(CGSize)myAdjustSizeWhenNoSubviews:(CGSize)size sbs:(NSArray *)sbs lsc:(MyBaseLayout*)lsc { //如果没有子视图,并且padding不参与空子视图尺寸计算则尺寸应该扣除padding的值。 @@ -3305,6 +3312,11 @@ - (void)myAlterScrollViewContentSize:(CGSize)newSize lsc:(MyBaseLayout*)lsc //因为调整contentsize可能会调整contentOffset,所以为了保持一致性这里要还原掉原来的contentOffset CGPoint oldOffset = scrolv.contentOffset; + + contsize.width *= scrolv.zoomScale; + contsize.height *= scrolv.zoomScale; + + if (!CGSizeEqualToSize(scrolv.contentSize, contsize)) scrolv.contentSize = contsize; @@ -3450,6 +3462,86 @@ -(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sb } +-(CGFloat)myGetSubviewWidthSizeValue:(UIView *)sbv + sbvsc:(UIView *)sbvsc + lsc:(MyBaseLayout *)lsc + selfSize:(CGSize)selfSize + paddingTop:(CGFloat)paddingTop + paddingLeading:(CGFloat)paddingLeading + paddingBottom:(CGFloat)paddingBottom + paddingTrailing:(CGFloat)paddingTrailing + sbvSize:(CGSize)sbvSize +{ + CGFloat retVal = sbvSize.width; + + MyLayoutSize *sbvWidthSizeInner = sbvsc.widthSizeInner; + + if (sbvWidthSizeInner.dimeNumVal != nil) + {//宽度等于固定的值。 + + retVal = sbvWidthSizeInner.measure; + } + else if (sbvWidthSizeInner.dimeRelaVal != nil && sbvWidthSizeInner.dimeRelaVal.view != sbv) + {//宽度等于其他的依赖的视图。 + + if (sbvWidthSizeInner.dimeRelaVal == lsc.widthSizeInner) + retVal = [sbvWidthSizeInner measureWith:selfSize.width - paddingLeading - paddingTrailing]; + else if (sbvWidthSizeInner.dimeRelaVal == lsc.heightSizeInner) + retVal = [sbvWidthSizeInner measureWith:selfSize.height - paddingTop - paddingBottom]; + else + { + if (sbvWidthSizeInner.dimeRelaVal.dime == MyGravity_Horz_Fill) + retVal = [sbvWidthSizeInner measureWith:sbvWidthSizeInner.dimeRelaVal.view.myEstimatedWidth]; + else + retVal = [sbvWidthSizeInner measureWith:sbvWidthSizeInner.dimeRelaVal.view.myEstimatedHeight]; + } + } + + return retVal; +} + +-(CGFloat)myGetSubviewHeightSizeValue:(UIView *)sbv + sbvsc:(UIView *)sbvsc + lsc:(MyBaseLayout *)lsc + selfSize:(CGSize)selfSize + paddingTop:(CGFloat)paddingTop + paddingLeading:(CGFloat)paddingLeading + paddingBottom:(CGFloat)paddingBottom + paddingTrailing:(CGFloat)paddingTrailing + sbvSize:(CGSize)sbvSize +{ + CGFloat retVal = sbvSize.height; + + + MyLayoutSize *sbvHeightSizeInner = sbvsc.heightSizeInner; + + + if (sbvHeightSizeInner.dimeNumVal != nil) + {//高度等于固定的值。 + retVal = sbvHeightSizeInner.measure; + } + else if (sbvHeightSizeInner.dimeRelaVal != nil && sbvHeightSizeInner.dimeRelaVal.view != sbv) + {//高度等于其他依赖的视图 + if (sbvHeightSizeInner.dimeRelaVal == lsc.heightSizeInner) + retVal = [sbvHeightSizeInner measureWith:selfSize.height - paddingTop - paddingBottom]; + else if (sbvHeightSizeInner.dimeRelaVal == lsc.widthSizeInner) + retVal = [sbvHeightSizeInner measureWith:selfSize.width - paddingLeading - paddingTrailing]; + else + { + if (sbvHeightSizeInner.dimeRelaVal.dime == MyGravity_Horz_Fill) + retVal = [sbvHeightSizeInner measureWith:sbvHeightSizeInner.dimeRelaVal.view.myEstimatedWidth]; + else + retVal = [sbvHeightSizeInner measureWith:sbvHeightSizeInner.dimeRelaVal.view.myEstimatedHeight]; + } + } + + //高度等于内容的高度,特殊处理。 + if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) + retVal = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:sbvSize.width]; + + return retVal; +} + -(void)myCalcSubViewRect:(UIView*)sbv @@ -3469,47 +3561,12 @@ -(void)myCalcSubViewRect:(UIView*)sbv CGRect rect = sbvmyFrame.frame; - if (sbvsc.widthSizeInner.dimeNumVal != nil) - {//宽度等于固定的值。 - - rect.size.width = sbvsc.widthSizeInner.measure; - } - else if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal.view != sbv) - {//宽度等于其他的依赖的视图。 - - if (sbvsc.widthSizeInner.dimeRelaVal == self.widthSizeInner) - rect.size.width = [sbvsc.widthSizeInner measureWith:selfSize.width - paddingLeading - paddingTrailing]; - else if (sbvsc.widthSizeInner.dimeRelaVal == self.heightSizeInner) - { - rect.size.width = [sbvsc.widthSizeInner measureWith:selfSize.height - paddingTop - paddingBottom]; - } - else - rect.size.width = [sbvsc.widthSizeInner measureWith:sbvsc.widthSizeInner.dimeRelaVal.view.estimatedRect.size.width]; - } + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; [self myCalcHorzGravity:[self myGetSubviewHorzGravity:sbv sbvsc:sbvsc horzGravity:horzGravity] sbv:sbv sbvsc:sbvsc paddingLeading:paddingLeading paddingTrailing:paddingTrailing selfSize:selfSize pRect:&rect]; - - - if (sbvsc.heightSizeInner.dimeNumVal != nil) - {//高度等于固定的值。 - rect.size.height = sbvsc.heightSizeInner.measure; - } - else if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal.view != sbv) - {//高度等于其他依赖的视图 - if (sbvsc.heightSizeInner.dimeRelaVal == self.heightSizeInner) - rect.size.height = [sbvsc.heightSizeInner measureWith:selfSize.height - paddingTop - paddingBottom]; - else if (sbvsc.heightSizeInner.dimeRelaVal == self.widthSizeInner) - rect.size.height = [sbvsc.heightSizeInner measureWith:selfSize.width - paddingLeading - paddingTrailing]; - else - rect.size.height = [sbvsc.heightSizeInner measureWith:sbvsc.heightSizeInner.dimeRelaVal.view.estimatedRect.size.height]; - } - - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) - {//高度等于内容的高度 - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - } + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; [self myCalcVertGravity:[self myGetSubviewVertGravity:sbv sbvsc:sbvsc vertGravity:vertGravity] sbv:sbv sbvsc:sbvsc paddingTop:paddingTop paddingBottom:paddingBottom baselinePos:CGFLOAT_MAX selfSize:selfSize pRect:&rect]; @@ -3530,9 +3587,7 @@ -(void)myCalcSubViewRect:(UIView*)sbv rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) - { rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - } rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; @@ -3597,6 +3652,51 @@ -(void)myHookSublayout:(MyBaseLayout *)sublayout borderlineRect:(CGRect *)pRect //do nothing... } +-(void)myInvalidateIntrinsicContentSize +{ + if (!self.translatesAutoresizingMaskIntoConstraints) + { + if (self.wrapContentWidth || self.wrapContentHeight) + [self invalidateIntrinsicContentSize]; + } +} + +-(void)myCalcSubviewsWrapContentSize:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSArray*)sbs withCustomSetting:(void (^)(UIView *sbv, UIView *sbvsc))customSetting +{ + for (UIView *sbv in sbs) + { + MyFrame *sbvmyFrame = sbv.myFrame; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + + if (!isEstimate) + { + sbvmyFrame.frame = sbv.bounds; + [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; + } + + if ([sbv isKindOfClass:[MyBaseLayout class]]) + { + + if (customSetting != nil) + customSetting(sbv, sbvsc); + + BOOL isSbvWrap = sbvsc.wrapContentHeight || sbvsc.wrapContentWidth; + + if (pHasSubLayout != nil && isSbvWrap) + *pHasSubLayout = YES; + + if (isEstimate && isSbvWrap) + { + [(MyBaseLayout*)sbv sizeThatFits:sbvmyFrame.frame.size inSizeClass:sizeClass]; + if (sbvmyFrame.multiple) + { + sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为sizeThatFits执行后会还原,所以这里要重新设置 + } + } + } + } +} + @end diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index b902b25..1f109e7 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -134,55 +134,27 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( sbs = [self myGetLayoutSubviews]; MyFloatLayout *lsc = self.myCurrentSizeClass; - MyOrientation orientation = lsc.orientation; - for (UIView *sbv in sbs) - { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + [self myCalcSubviewsWrapContentSize:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs withCustomSetting:^(UIView *sbv, UIView *sbvsc) { - if (!isEstimate) + if (sbvsc.wrapContentWidth) { - sbvmyFrame.frame = sbv.bounds; - [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; + if (sbvsc.widthSizeInner.dimeVal != nil || (orientation == MyOrientation_Vert && sbvsc.weight != 0)) + { + sbvsc.wrapContentWidth = NO; + } } - if ([sbv isKindOfClass:[MyBaseLayout class]]) + if (sbvsc.wrapContentHeight) { - - if (sbvsc.wrapContentWidth) - { - if (sbvsc.widthSizeInner.dimeVal != nil || (orientation == MyOrientation_Vert && sbvsc.weight != 0)) - { - sbvsc.wrapContentWidth = NO; - } - } - - if (sbvsc.wrapContentHeight) - { - if (sbvsc.heightSizeInner.dimeVal != nil || (orientation == MyOrientation_Horz && sbvsc.weight != 0)) - { - sbvsc.wrapContentHeight = NO; - } - } - - BOOL isSbvWrap = sbvsc.wrapContentHeight || sbvsc.wrapContentWidth; - - if (pHasSubLayout != nil && isSbvWrap) - *pHasSubLayout = YES; - - if (isEstimate && isSbvWrap) + if (sbvsc.heightSizeInner.dimeVal != nil || (orientation == MyOrientation_Horz && sbvsc.weight != 0)) { - [(MyBaseLayout*)sbv sizeThatFits:sbvmyFrame.frame.size inSizeClass:sizeClass]; - if (sbvmyFrame.multiple) - { - sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为sizeThatFits执行后会还原,所以这里要重新设置 - } + sbvsc.wrapContentHeight = NO; } } - } - + + }]; if (orientation == MyOrientation_Vert) selfSize = [self myLayoutSubviewsForVert:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; @@ -393,8 +365,89 @@ -(CGPoint)myFindTopCandidatePoint:(CGRect)bottomCandidateRect height:(CGFloat)h } +-(CGFloat)myCalcMaxMinSubviewSize:(CGFloat)selfSize lsc:(MyFloatLayoutViewSizeClass*)lsc space:(CGFloat*)pSpace +{ + CGFloat subviewSize = lsc.subviewSize; + if (subviewSize != 0) + { + + CGFloat minSpace = lsc.minSpace; + CGFloat maxSpace = lsc.maxSpace; + + NSInteger rowCount = floor((selfSize + minSpace) / (subviewSize + minSpace)); + if (rowCount > 1) + { + *pSpace = (selfSize - subviewSize * rowCount)/(rowCount - 1); + + //如果超过最大间距或者小于最小间距则调整子视图的宽度。 + if (_myCGFloatGreat(*pSpace, maxSpace) || _myCGFloatLess(*pSpace, minSpace)) + { + if (_myCGFloatGreat(*pSpace, maxSpace)) + *pSpace = maxSpace; + if (_myCGFloatLess(*pSpace, minSpace)) + *pSpace = minSpace; + + subviewSize = (selfSize - (*pSpace) * (rowCount - 1)) / rowCount; + } + } + } + + return subviewSize; +} + + +-(void)myCalcFloatLayoutSubviewsSize:(NSArray*)sbs + lsc:(MyFloatLayout*)lsc + selfSize:(CGSize)selfSize + paddingTop:(CGFloat)paddingTop + paddingLeading:(CGFloat)paddingLeading + paddingBottom:(CGFloat)paddingBottom + paddingTrailing:(CGFloat)paddingTrailing + subviewSize:(CGFloat)subviewSize + isWidth:(BOOL)isWidth +{ + //设置子视图的宽度和高度。 + for (UIView *sbv in sbs) + { + MyFrame *sbvmyFrame = sbv.myFrame; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + CGRect rect = sbvmyFrame.frame; + + if (subviewSize != 0) + { + if (isWidth) + rect.size.width = subviewSize; + else + rect.size.height = subviewSize; + } + + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + {//特殊处理高度等于宽度的情况 + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } + + + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + } + + sbvmyFrame.width = rect.size.width; + sbvmyFrame.height = rect.size.height; + } + +} + --(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFloatLayout*)lsc +-(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFloatLayout*)lsc { //对于垂直浮动布局来说,默认是左浮动,当设置为RTL时则默认是右浮动,因此我们只需要改变一下sbv.reverseFloat的定义就好了。 @@ -403,7 +456,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; CGFloat paddingHorz = paddingLeading + paddingTrailing; - CGFloat paddingVert = paddingTop + paddingBottom; + // CGFloat paddingVert = paddingTop + paddingBottom; BOOL hasBoundaryLimit = YES; if (lsc.wrapContentWidth && lsc.noBoundaryLimit) @@ -413,6 +466,15 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( if (!hasBoundaryLimit) selfSize.width = CGFLOAT_MAX; + + //支持浮动水平间距。 + CGFloat vertSpace = lsc.subviewVSpace; + CGFloat horzSpace = lsc.subviewHSpace; + CGFloat subviewSize = [self myCalcMaxMinSubviewSize:selfSize.width - paddingHorz lsc:(MyFloatLayoutViewSizeClass *)lsc space:&horzSpace]; + + //设置子视图的宽度和高度。 + [self myCalcFloatLayoutSubviewsSize:sbs lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing subviewSize:subviewSize isWidth:YES]; + //遍历所有的子视图,查看是否有子视图的宽度会比视图自身要宽,如果有且有包裹属性则扩充自身的宽度 if (lsc.wrapContentWidth && hasBoundaryLimit) { @@ -424,74 +486,19 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; - CGRect rect = sbvmyFrame.frame; + CGFloat sbvWidth = sbvmyFrame.width; - //因为这里是计算包裹宽度属性,所以只会计算那些设置了固定宽度的子视图 - - //这里有可能设置了固定的宽度 - if (sbvsc.widthSizeInner.dimeNumVal != nil) - rect.size.width = sbvsc.widthSizeInner.measure; - - //有可能宽度是和他的高度相等。 - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - { - if (sbvsc.heightSizeInner.dimeNumVal != nil) - rect.size.height = sbvsc.heightSizeInner.measure; - - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) - rect.size.height = [sbvsc.heightSizeInner measureWith:(selfSize.height - paddingVert) ]; - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - - rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; - } - - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - - if (_myCGFloatGreat(leadingSpace + rect.size.width + trailingSpace, maxContentWidth) && + if (_myCGFloatGreat(leadingSpace + sbvWidth + trailingSpace, maxContentWidth) && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) && sbvsc.weight == 0) { - maxContentWidth = leadingSpace + rect.size.width + trailingSpace; + maxContentWidth = leadingSpace + sbvWidth + trailingSpace; } } selfSize.width = paddingHorz + maxContentWidth; } - //支持浮动水平间距。 - CGFloat vertSpace = lsc.subviewVSpace; - CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = ((MyFloatLayoutViewSizeClass*)self.myCurrentSizeClass).subviewSize; - if (subviewSize != 0) - { - -#ifdef DEBUG - //异常崩溃:当布局视图设置了noBoundaryLimit为YES时,不能设置最小垂直间距。 - NSCAssert(hasBoundaryLimit, @"Constraint exception!!, vertical float layout:%@ can not set noBoundaryLimit to YES when call setSubviewsSize:minSpace:maxSpace method",self); -#endif - - - CGFloat minSpace = ((MyFloatLayoutViewSizeClass*)self.myCurrentSizeClass).minSpace; - CGFloat maxSpace = ((MyFloatLayoutViewSizeClass*)self.myCurrentSizeClass).maxSpace; - - NSInteger rowCount = floor((selfSize.width - paddingHorz + minSpace) / (subviewSize + minSpace)); - if (rowCount > 1) - { - horzSpace = (selfSize.width - paddingHorz - subviewSize * rowCount)/(rowCount - 1); - - //如果超过最大间距则调整子视图的宽度。 - if (_myCGFloatGreat(horzSpace,maxSpace)) - { - horzSpace = maxSpace; - - subviewSize = (selfSize.width - paddingHorz - horzSpace * (rowCount - 1)) / rowCount; - - } - - } - } - //左边候选区域数组,保存的是CGRect值。 NSMutableArray *leadingCandidateRects = [NSMutableArray new]; @@ -532,50 +539,6 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( //只要有一个子视图设置了对齐,就会做对齐处理,否则不会,这里这样做是为了对后面的对齐计算做优化。 sbvHasAlignment |= ((sbvsc.myAlignment & MyGravity_Horz_Mask) > MyGravity_Vert_Top); - - if (subviewSize != 0) - rect.size.width = subviewSize; - - if (sbvsc.widthSizeInner.dimeNumVal != nil) - rect.size.width = sbvsc.widthSizeInner.measure; - - if (sbvsc.heightSizeInner.dimeNumVal != nil) - rect.size.height = sbvsc.heightSizeInner.measure; - - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner && !lsc.wrapContentHeight) - rect.size.height = [sbvsc.heightSizeInner measureWith:(selfSize.height - paddingVert) ]; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner) - rect.size.width = [sbvsc.widthSizeInner measureWith:(selfSize.width - paddingHorz) ]; - - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) - rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height ]; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal.view != nil && sbvsc.widthSizeInner.dimeRelaVal.view != self && sbvsc.widthSizeInner.dimeRelaVal.view != sbv) - { - rect.size.width = [sbvsc.widthSizeInner measureWith:sbvsc.widthSizeInner.dimeRelaVal.view.estimatedRect.size.width]; - } - - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal.view != nil && sbvsc.heightSizeInner.dimeRelaVal.view != self && sbvsc.heightSizeInner.dimeRelaVal.view != sbv) - { - rect.size.height = [sbvsc.heightSizeInner measureWith:sbvsc.heightSizeInner.dimeRelaVal.view.estimatedRect.size.height]; - } - - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - - //如果高度是浮动的则需要调整高度。 - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - //如果是RTL的场景则默认是右对齐的。 if (sbvsc.isReverseFloat) { @@ -621,14 +584,20 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:(nextPoint.x - leadingCandidateXBoundary + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace sbvSize:rect.size selfLayoutSize:selfSize]; - + //特殊处理高度等于宽度,并且高度依赖宽度的情况。 if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + { rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } + //特殊处理高度包裹的场景 if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) + { rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } @@ -770,13 +739,19 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:(trailingCandidateXBoundary - nextPoint.x + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace sbvSize:rect.size selfLayoutSize:selfSize]; + //特殊处理高度等于宽度,并且高度依赖宽度的情况。 if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + { rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } + //特殊处理高度包裹的场景 if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) + { rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } } @@ -979,7 +954,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - CGFloat paddingHorz = paddingLeading + paddingTrailing; + // CGFloat paddingHorz = paddingLeading + paddingTrailing; CGFloat paddingVert = paddingTop + paddingBottom; BOOL hasBoundaryLimit = YES; @@ -990,6 +965,14 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( if (!hasBoundaryLimit) selfSize.height = CGFLOAT_MAX; + //支持浮动垂直间距。 + CGFloat horzSpace = lsc.subviewHSpace; + CGFloat vertSpace = lsc.subviewVSpace; + CGFloat subviewSize = [self myCalcMaxMinSubviewSize:selfSize.height - paddingVert lsc:(MyFloatLayoutViewSizeClass*)lsc space:&vertSpace]; + + //设置子视图的宽度和高度。 + [self myCalcFloatLayoutSubviewsSize:sbs lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing subviewSize:subviewSize isWidth:NO]; + //遍历所有的子视图,查看是否有子视图的宽度会比视图自身要宽,如果有且有包裹属性则扩充自身的宽度 if (lsc.wrapContentHeight && hasBoundaryLimit) { @@ -1001,76 +984,20 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; - CGRect rect = sbvmyFrame.frame; - - - //这里有可能设置了固定的高度 - if (sbvsc.heightSizeInner.dimeNumVal != nil) - rect.size.height = sbvsc.heightSizeInner.measure; - - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - - //有可能高度是和他的宽度相等。 - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) - { - if (sbvsc.widthSizeInner.dimeNumVal != nil) - rect.size.width = sbvsc.widthSizeInner.measure; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner) - rect.size.width = [sbvsc.widthSizeInner measureWith:(selfSize.width - paddingHorz) ]; - - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - - - rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; - } - - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + CGFloat sbvHeight = sbvmyFrame.height; - if (_myCGFloatGreat(topSpace + rect.size.height + bottomSpace, maxContentHeight) && + if (_myCGFloatGreat(topSpace + sbvHeight + bottomSpace, maxContentHeight) && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) && sbvsc.weight == 0) { - maxContentHeight = topSpace + rect.size.height + bottomSpace; + maxContentHeight = topSpace + sbvHeight + bottomSpace; } } selfSize.height = paddingVert + maxContentHeight; } - //支持浮动垂直间距。 - CGFloat horzSpace = lsc.subviewHSpace; - CGFloat vertSpace = lsc.subviewVSpace; - CGFloat subviewSize = ((MyFloatLayoutViewSizeClass*)self.myCurrentSizeClass).subviewSize; - if (subviewSize != 0) - { -#ifdef DEBUG - //异常崩溃:当布局视图设置了noBoundaryLimit为YES时,不能设置最小垂直间距。 - NSCAssert(hasBoundaryLimit, @"Constraint exception!!, horizontal float layout:%@ can not set noBoundaryLimit to YES when call setSubviewsSize:minSpace:maxSpace method",self); -#endif - - CGFloat minSpace = ((MyFloatLayoutViewSizeClass*)self.myCurrentSizeClass).minSpace; - CGFloat maxSpace = ((MyFloatLayoutViewSizeClass*)self.myCurrentSizeClass).maxSpace; - - NSInteger rowCount = floor((selfSize.height - paddingVert + minSpace) / (subviewSize + minSpace)); - if (rowCount > 1) - { - vertSpace = (selfSize.height - paddingVert - subviewSize * rowCount)/(rowCount - 1); - - if (_myCGFloatGreat(vertSpace,maxSpace)) - { - vertSpace = maxSpace; - - subviewSize = (selfSize.height - paddingVert - vertSpace * (rowCount - 1)) / rowCount; - - } - - } - } - + //上边候选区域数组,保存的是CGRect值。 NSMutableArray *topCandidateRects = [NSMutableArray new]; @@ -1111,53 +1038,6 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( //只要有一个子视图设置了对齐,就会做对齐处理,否则不会,这里这样做是为了对后面的对齐计算做优化。 sbvHasAlignment |= ((sbvsc.myAlignment & MyGravity_Vert_Mask) > MyGravity_Horz_Left); - if (sbvsc.widthSizeInner.dimeNumVal != nil) - rect.size.width = sbvsc.widthSizeInner.measure; - - if (subviewSize != 0) - rect.size.height = subviewSize; - - if (sbvsc.heightSizeInner.dimeNumVal != nil) - rect.size.height = sbvsc.heightSizeInner.measure; - - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) - rect.size.height = [sbvsc.heightSizeInner measureWith:(selfSize.height - paddingVert) ]; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner && !lsc.wrapContentWidth) - rect.size.width = [sbvsc.widthSizeInner measureWith:(selfSize.width - paddingHorz) ]; - - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) - rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; - - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal.view != nil && sbvsc.widthSizeInner.dimeRelaVal.view != self && sbvsc.widthSizeInner.dimeRelaVal.view != sbv) - { - rect.size.width = [sbvsc.widthSizeInner measureWith:sbvsc.widthSizeInner.dimeRelaVal.view.estimatedRect.size.width]; - } - - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal.view != nil && sbvsc.heightSizeInner.dimeRelaVal.view != self && sbvsc.heightSizeInner.dimeRelaVal.view != sbv) - { - rect.size.height = [sbvsc.heightSizeInner measureWith:sbvsc.heightSizeInner.dimeRelaVal.view.estimatedRect.size.height]; - } - - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - - - //如果高度是浮动的则需要调整高度。 - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - - - if (sbvsc.reverseFloat) { #ifdef DEBUG @@ -1201,6 +1081,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( { rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:(nextPoint.y - topCandidateYBoundary + sbvsc.heightSizeInner.addVal) * sbvsc.weight - topSpace - bottomSpace sbvSize:rect.size selfLayoutSize:selfSize]; + //特殊处理宽度等于高度的问题。 if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:[sbvsc.widthSizeInner measureWith: rect.size.height] sbvSize:rect.size selfLayoutSize:selfSize]; diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index b05dd93..68dccb5 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -151,57 +151,29 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyGravity gravity = lsc.gravity; MyGravity arrangedGravity = lsc.arrangedGravity; - for (UIView *sbv in sbs) - { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + [self myCalcSubviewsWrapContentSize:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs withCustomSetting:^(UIView *sbv, UIView *sbvsc) { - if (!isEstimate) + if (sbvsc.wrapContentWidth) { - sbvmyFrame.frame = sbv.bounds; - [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; + if (lsc.pagedCount > 0 || sbvsc.widthSizeInner.dimeVal != nil || + (orientation == MyOrientation_Horz && (arrangedGravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill) || + (orientation == MyOrientation_Vert && ((gravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill || sbvsc.weight != 0))) + { + sbvsc.wrapContentWidth = NO; + } } - if ([sbv isKindOfClass:[MyBaseLayout class]]) + if (sbvsc.wrapContentHeight) { - - if (sbvsc.wrapContentWidth) - { - if (lsc.pagedCount > 0 || sbvsc.widthSizeInner.dimeVal != nil || - (orientation == MyOrientation_Horz && (arrangedGravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill) || - (orientation == MyOrientation_Vert && ((gravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill || sbvsc.weight != 0))) - { - sbvsc.wrapContentWidth = NO; - } - } - - if (sbvsc.wrapContentHeight) - { - if (lsc.pagedCount > 0 || sbvsc.heightSizeInner.dimeVal != nil || - (orientation == MyOrientation_Vert && (arrangedGravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill) || - (orientation == MyOrientation_Horz && ((gravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill || sbvsc.weight != 0))) - { - sbvsc.wrapContentHeight = NO; - } - } - - - BOOL isSbvWrap = sbvsc.wrapContentHeight || sbvsc.wrapContentWidth; - - if (pHasSubLayout != nil && isSbvWrap) - *pHasSubLayout = YES; - - if (isEstimate && isSbvWrap) + if (lsc.pagedCount > 0 || sbvsc.heightSizeInner.dimeVal != nil || + (orientation == MyOrientation_Vert && (arrangedGravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill) || + (orientation == MyOrientation_Horz && ((gravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill || sbvsc.weight != 0))) { - [(MyBaseLayout*)sbv sizeThatFits:sbvmyFrame.frame.size inSizeClass:sizeClass]; - if (sbvmyFrame.multiple) - { - sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为sizeThatFits执行后会还原,所以这里要重新设置 - } + sbvsc.wrapContentHeight = NO; } } - } - + + }]; if (orientation == MyOrientation_Vert) @@ -707,6 +679,61 @@ -(void)myCalcAutoArrangeSinglelineSubviews:(NSMutableArray*)sbs } +-(CGFloat)myCalcMaxMinSubviewSizeForContent:(CGFloat)selfSize lsc:(MyFlowLayoutViewSizeClass*)lsc space:(CGFloat*)pSpace +{ + CGFloat subviewSize = lsc.subviewSize; + if (subviewSize != 0) + { + + CGFloat minSpace = lsc.minSpace; + CGFloat maxSpace = lsc.maxSpace; + + NSInteger rowCount = floor((selfSize + minSpace) / (subviewSize + minSpace)); + if (rowCount > 1) + { + *pSpace = (selfSize - subviewSize * rowCount)/(rowCount - 1); + if (_myCGFloatGreat(*pSpace, maxSpace) || _myCGFloatLess(*pSpace, minSpace)) + { + if (_myCGFloatGreat(*pSpace, maxSpace)) + *pSpace = maxSpace; + if (_myCGFloatLess(*pSpace, minSpace)) + *pSpace = minSpace; + + subviewSize = (selfSize - (*pSpace) * (rowCount - 1)) / rowCount; + } + } + } + + return subviewSize; +} + + +-(CGFloat)myCalcMaxMinSubviewSize:(CGFloat)selfSize lsc:(MyFlowLayoutViewSizeClass*)lsc arrangedCount:(NSInteger)arrangedCount space:(CGFloat*)pSpace +{ + CGFloat subviewSize = lsc.subviewSize; + if (subviewSize != 0) + { + CGFloat maxSpace = lsc.maxSpace; + CGFloat minSpace = lsc.minSpace; + if (arrangedCount > 1) + { + *pSpace = (selfSize - subviewSize * arrangedCount)/(arrangedCount - 1); + if (_myCGFloatGreat(*pSpace, maxSpace) || _myCGFloatLess(*pSpace, minSpace)) + { + if (_myCGFloatGreat(*pSpace, maxSpace)) + *pSpace = maxSpace; + if (_myCGFloatLess(*pSpace, minSpace)) + *pSpace = minSpace; + + subviewSize = (selfSize - (*pSpace) * (arrangedCount - 1)) / arrangedCount; + + } + } + } + + return subviewSize; +} + -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc { @@ -729,27 +756,7 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb //支持浮动水平间距。 CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).subviewSize; - if (subviewSize != 0) - { - - CGFloat minSpace = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).minSpace; - CGFloat maxSpace = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).maxSpace; - - NSInteger rowCount = floor((selfSize.width - paddingHorz + minSpace) / (subviewSize + minSpace)); - if (rowCount > 1) - { - horzSpace = (selfSize.width - paddingHorz - subviewSize * rowCount)/(rowCount - 1); - if (_myCGFloatGreat(horzSpace, maxSpace)) - { - horzSpace = maxSpace; - - subviewSize = (selfSize.width - paddingHorz - horzSpace * (rowCount - 1)) / rowCount; - - } - } - } - + CGFloat subviewSize = [self myCalcMaxMinSubviewSizeForContent:selfSize.width - paddingHorz lsc:(MyFlowLayoutViewSizeClass*)lsc space:&horzSpace]; if (lsc.autoArrange) { @@ -766,13 +773,8 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; - - if (sbvsc.widthSizeInner.dimeNumVal != nil) - rect.size.width = sbvsc.widthSizeInner.measure; - - - [self mySetSubviewRelativeDimeSize:sbvsc.widthSizeInner selfSize:selfSize lsc:lsc pRect:&rect]; - + + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; //暂时把宽度存放sbv.myFrame.trailing上。因为浮动布局来说这个属性无用。 @@ -802,23 +804,12 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; - + //计算子视图的宽度。 if (subviewSize != 0) + { rect.size.width = subviewSize; - - if (sbvsc.widthSizeInner.dimeNumVal != nil) - rect.size.width = sbvsc.widthSizeInner.measure; - - if (sbvsc.heightSizeInner.dimeNumVal != nil) - rect.size.height = sbvsc.heightSizeInner.measure; - - - [self mySetSubviewRelativeDimeSize:sbvsc.widthSizeInner selfSize:selfSize lsc:lsc pRect:&rect]; - - [self mySetSubviewRelativeDimeSize:sbvsc.heightSizeInner selfSize:selfSize lsc:lsc pRect:&rect]; - - - if (sbvsc.weight != 0) + } + else if (sbvsc.weight != 0) { //如果过了,则表示当前的剩余空间为0了,所以就按新的一行来算。。 CGFloat floatWidth = selfSize.width - paddingHorz - rowMaxWidth; @@ -834,19 +825,34 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb rect.size.width = (floatWidth + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace; } - + else + { + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + + } rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + + //计算子视图的高度。 + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) - rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width ]; + {//特殊处理高度等于宽度的情况 + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } - //如果高度是浮动的则需要调整高度。 - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + } + - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; //计算xPos的值加上leadingSpace + rect.size.width + trailingSpace 的值要小于整体的宽度。 CGFloat place = xPos + leadingSpace + rect.size.width + trailingSpace; @@ -863,7 +869,7 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb [arrangeIndexSet addIndex:i - arrangedIndex]; - //计算每行的gravity情况。 + //计算前面每行的gravity情况。 [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; //计算单独的sbv的宽度是否大于整体的宽度。如果大于则缩小宽度。 @@ -872,12 +878,19 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:selfSize.width - paddingHorz - leadingSpace - trailingSpace sbvSize:rect.size selfLayoutSize:selfSize]; + //特殊处理高度包裹。 if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) { rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + {//特殊处理高度等于宽度的情况 + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } + } rowMaxHeight = 0; @@ -1004,27 +1017,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - - CGFloat subviewSize = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).subviewSize; - if (subviewSize != 0) - { - CGFloat maxSpace = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).maxSpace; - CGFloat minSpace = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).minSpace; - if (arrangedCount > 1) - { - horzSpace = (selfSize.width - paddingHorz - subviewSize * arrangedCount)/(arrangedCount - 1); - if (_myCGFloatGreat(horzSpace, maxSpace) || _myCGFloatLess(horzSpace, minSpace)) - { - if (_myCGFloatGreat(horzSpace, maxSpace)) - horzSpace = maxSpace; - if (_myCGFloatLess(horzSpace, minSpace)) - horzSpace = minSpace; - - subviewSize = (selfSize.width - paddingHorz - horzSpace * (arrangedCount - 1)) / arrangedCount; - - } - } - } + CGFloat subviewSize = [self myCalcMaxMinSubviewSize:selfSize.width - paddingHorz lsc:(MyFlowLayoutViewSizeClass*)lsc arrangedCount:arrangedCount space:&horzSpace]; #if TARGET_OS_IOS //判断父滚动视图是否分页滚动 @@ -1109,17 +1102,29 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst { if (subviewSize != 0) rect.size.width = subviewSize; - - if (pagingItemWidth != 0) + else if (pagingItemWidth != 0) rect.size.width = pagingItemWidth; - - if (sbvsc.widthSizeInner.dimeNumVal != nil && !averageArrange) - rect.size.width = sbvsc.widthSizeInner.measure; - - - [self mySetSubviewRelativeDimeSize:sbvsc.widthSizeInner selfSize:selfSize lsc:lsc pRect:&rect]; - - + else + { + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + + if (pagingItemHeight != 0) + rect.size.height = pagingItemHeight; + else + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + + + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + } + else + { + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + } + } + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; rowTotalFixedWidth += rect.size.width; @@ -1221,14 +1226,6 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; - BOOL isFlexedHeight = sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]] && sbvsc.heightSizeInner.dimeRelaVal.view != self; - - if (pagingItemHeight != 0) - rect.size.height = pagingItemHeight; - - - if (sbvsc.heightSizeInner.dimeNumVal != nil) - rect.size.height = sbvsc.heightSizeInner.measure; if (averageArrange) { @@ -1236,14 +1233,32 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst } - [self mySetSubviewRelativeDimeSize:sbvsc.heightSizeInner selfSize:selfSize lsc:lsc pRect:&rect]; + if (pagingItemHeight != 0) + rect.size.height = pagingItemHeight; + else + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - //如果高度是浮动的则需要调整高度。 - if (isFlexedHeight) - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; + //再算一次宽度。 + if (!averageArrange) + { + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + } - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + //特殊处理宽度和高度相互依赖的情况。。 + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + {//特殊处理高度等于宽度的情况 + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } + + + if (!averageArrange && sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + } //得到最大的行高 if (_myCGFloatLess(rowMaxHeight, topSpace + bottomSpace + rect.size.height)) @@ -1444,25 +1459,8 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb //支持浮动垂直间距。 CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).subviewSize; - if (subviewSize != 0) - { - - CGFloat minSpace = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).minSpace; - CGFloat maxSpace = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).maxSpace; - NSInteger rowCount = floor((selfSize.height - paddingVert + minSpace) / (subviewSize + minSpace)); - if (rowCount > 1) - { - vertSpace = (selfSize.height - paddingVert - subviewSize * rowCount)/(rowCount - 1); - if (_myCGFloatGreat(vertSpace, maxSpace)) - { - vertSpace = maxSpace; - - subviewSize = (selfSize.height - paddingVert - vertSpace * (rowCount - 1)) / rowCount; - - } - } - } + CGFloat subviewSize = [self myCalcMaxMinSubviewSizeForContent:selfSize.height - paddingVert lsc:(MyFlowLayoutViewSizeClass*)lsc space:&vertSpace]; + if (lsc.autoArrange) @@ -1483,33 +1481,13 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; CGRect rect = sbvmyFrame.frame; - if (sbvsc.widthSizeInner.dimeNumVal != nil) - rect.size.width = sbvsc.widthSizeInner.measure; - - if (subviewSize != 0) - rect.size.height = subviewSize; - - if (sbvsc.heightSizeInner.dimeNumVal != nil) - rect.size.height = sbvsc.heightSizeInner.measure; - - [self mySetSubviewRelativeDimeSize:sbvsc.heightSizeInner selfSize:selfSize lsc:lsc pRect:&rect]; - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - - [self mySetSubviewRelativeDimeSize:sbvsc.widthSizeInner selfSize:selfSize lsc:lsc pRect:&rect]; + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - - //如果高度是浮动的则需要调整高度。 - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) - { - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - } - - + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + //暂时把宽度存放sbv.myFrame.trailing上。因为浮动布局来说这个属性无用。 sbvmyFrame.trailing = topSpace + rect.size.height + bottomSpace; if (_myCGFloatGreat(sbvmyFrame.trailing, selfSize.height - paddingVert)) @@ -1539,21 +1517,14 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; - if (sbvsc.widthSizeInner.dimeNumVal != nil) - rect.size.width = sbvsc.widthSizeInner.measure; + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; if (subviewSize != 0) + { rect.size.height = subviewSize; - - if (sbvsc.heightSizeInner.dimeNumVal != nil) - rect.size.height = sbvsc.heightSizeInner.measure; - - [self mySetSubviewRelativeDimeSize:sbvsc.heightSizeInner selfSize:selfSize lsc:lsc pRect:&rect]; - - [self mySetSubviewRelativeDimeSize:sbvsc.widthSizeInner selfSize:selfSize lsc:lsc pRect:&rect]; - - - if (sbvsc.weight != 0) + } + else if (sbvsc.weight != 0) { //如果过了,则表示当前的剩余空间为0了,所以就按新的一行来算。。 CGFloat floatHeight = selfSize.height - paddingVert - colMaxHeight; @@ -1569,24 +1540,27 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb rect.size.height = (floatHeight + sbvsc.heightSizeInner.addVal) * sbvsc.weight - topSpace - bottomSpace; } - + else + { + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + } rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height ]; + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + {//特殊处理高度等于宽度的情况 + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + } - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - //如果高度是浮动的则需要调整高度。 - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) - { - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - } //计算yPos的值加上topSpace + rect.size.height + bottomSpace的值要小于整体的高度。 CGFloat place = yPos + topSpace + rect.size.height + bottomSpace; @@ -1610,6 +1584,12 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb if (_myCGFloatGreat(topSpace + bottomSpace + rect.size.height, selfSize.height - paddingVert)) { rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:selfSize.height - paddingVert - topSpace - bottomSpace sbvSize:rect.size selfLayoutSize:selfSize]; + + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + } } colMaxWidth = 0; @@ -1735,27 +1715,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).subviewSize; - if (subviewSize != 0) - { - - CGFloat maxSpace = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).maxSpace; - CGFloat minSpace = ((MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass).minSpace; - if (arrangedCount > 1) - { - vertSpace = (selfSize.height - paddingVert - subviewSize * arrangedCount)/(arrangedCount - 1); - if (_myCGFloatGreat(vertSpace, maxSpace) || _myCGFloatLess(vertSpace, minSpace)) - { - if (_myCGFloatGreat(vertSpace, maxSpace)) - vertSpace = maxSpace; - if (_myCGFloatLess(vertSpace, minSpace)) - vertSpace = minSpace; - - subviewSize = (selfSize.height - paddingVert - vertSpace * (arrangedCount - 1)) / arrangedCount; - - } - } - } + CGFloat subviewSize = [self myCalcMaxMinSubviewSize:selfSize.height - paddingVert lsc:(MyFlowLayoutViewSizeClass*)lsc arrangedCount:arrangedCount space:&vertSpace]; //父滚动视图是否分页滚动。 #if TARGET_OS_IOS @@ -1832,13 +1792,8 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst if (pagingItemWidth != 0) rect.size.width = pagingItemWidth; - - if (sbvsc.widthSizeInner.dimeNumVal != nil) - rect.size.width = sbvsc.widthSizeInner.measure; - - //当子视图的尺寸是相对依赖于其他尺寸的值。 - [self mySetSubviewRelativeDimeSize:sbvsc.widthSizeInner selfSize:selfSize lsc:lsc pRect:&rect]; - + else + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; @@ -1851,29 +1806,28 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst else { - BOOL isFlexedHeight = sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]] && sbvsc.heightSizeInner.dimeRelaVal.view != self; - if (subviewSize != 0) rect.size.height = subviewSize; - - if (pagingItemHeight != 0) + else if (pagingItemHeight != 0) rect.size.height = pagingItemHeight; + else + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; - if (sbvsc.heightSizeInner.dimeNumVal != nil && !averageArrange) - rect.size.height = sbvsc.heightSizeInner.measure; - - //当子视图的尺寸是相对依赖于其他尺寸的值。 - [self mySetSubviewRelativeDimeSize:sbvsc.heightSizeInner selfSize:selfSize lsc:lsc pRect:&rect]; - + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - //如果高度是浮动的则需要调整高度。 - if (isFlexedHeight) - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + {//特殊处理高度等于宽度的情况 + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:[sbvsc.widthSizeInner measureWith: rect.size.height ] sbvSize:rect.size selfLayoutSize:selfSize]; + {//特殊处理宽度等于高度的情况 + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + } + rowTotalFixedHeight += rect.size.height; } diff --git a/MyLayout/Lib/MyFrameLayout.m b/MyLayout/Lib/MyFrameLayout.m index 0c4a673..a55d5e5 100644 --- a/MyLayout/Lib/MyFrameLayout.m +++ b/MyLayout/Lib/MyFrameLayout.m @@ -116,143 +116,5 @@ -(id)createSizeClassInstance #pragma mark -- Private Methods --(void)myCalcSubViewRect:(UIView*)sbv - sbvsc:(UIView*)sbvsc - sbvmyFrame:(MyFrame*)sbvmyFrame - lsc:(MyFrameLayout*)lsc - vertGravity:(MyGravity)vertGravity - horzGravity:(MyGravity)horzGravity - inSelfSize:(CGSize)selfSize - paddingTop:(CGFloat)paddingTop - paddingLeading:(CGFloat)paddingLeading - paddingBottom:(CGFloat)paddingBottom - paddingTrailing:(CGFloat)paddingTrailing - pMaxWrapSize:(CGSize*)pMaxWrapSize -{ - - - CGRect rect = sbvmyFrame.frame; - - if (sbvsc.widthSizeInner.dimeNumVal != nil) - {//宽度等于固定的值。 - - rect.size.width = sbvsc.widthSizeInner.measure; - } - else if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal.view != sbv) - {//宽度等于其他的依赖的视图。 - - if (sbvsc.widthSizeInner.dimeRelaVal == self.widthSizeInner) - rect.size.width = [sbvsc.widthSizeInner measureWith:selfSize.width - paddingLeading - paddingTrailing]; - else if (sbvsc.widthSizeInner.dimeRelaVal == self.heightSizeInner) - rect.size.width = [sbvsc.widthSizeInner measureWith:selfSize.height - paddingTop - paddingBottom]; - else - rect.size.width = [sbvsc.widthSizeInner measureWith:sbvsc.widthSizeInner.dimeRelaVal.view.estimatedRect.size.width]; - } - - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - [self myCalcHorzGravity:[self myGetSubviewHorzGravity:sbv sbvsc:sbvsc horzGravity:horzGravity] sbv:sbv sbvsc:sbvsc paddingLeading:paddingLeading paddingTrailing:paddingTrailing selfSize:selfSize pRect:&rect]; - - - - if (sbvsc.heightSizeInner.dimeNumVal != nil) - {//高度等于固定的值。 - rect.size.height = sbvsc.heightSizeInner.measure; - } - else if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal.view != sbv) - {//高度等于其他依赖的视图 - if (sbvsc.heightSizeInner.dimeRelaVal == self.heightSizeInner) - rect.size.height = [sbvsc.heightSizeInner measureWith:selfSize.height - paddingTop - paddingBottom]; - else if (sbvsc.heightSizeInner.dimeRelaVal == self.widthSizeInner) - rect.size.height = [sbvsc.heightSizeInner measureWith:selfSize.width - paddingLeading - paddingTrailing]; - else - rect.size.height = [sbvsc.heightSizeInner measureWith:sbvsc.heightSizeInner.dimeRelaVal.view.estimatedRect.size.height]; - } - - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) - {//高度等于内容的高度 - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - } - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - [self myCalcVertGravity:[self myGetSubviewVertGravity:sbv sbvsc:sbvsc vertGravity:vertGravity] sbv:sbv sbvsc:sbvsc paddingTop:paddingTop paddingBottom:paddingBottom baselinePos:CGFLOAT_MAX selfSize:selfSize pRect:&rect]; - - - //特殊处理宽度等于高度 - if (sbvsc.widthSizeInner.dimeRelaVal.view == sbv && sbvsc.widthSizeInner.dimeRelaVal.dime == MyGravity_Vert_Fill) - { - rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - - [self myCalcHorzGravity:[self myGetSubviewHorzGravity:sbv sbvsc:sbvsc horzGravity:horzGravity] sbv:sbv sbvsc:sbvsc paddingLeading:paddingLeading paddingTrailing:paddingTrailing selfSize:selfSize pRect:&rect]; - } - - //特殊处理高度等于宽度。 - if (sbvsc.heightSizeInner.dimeRelaVal.view == sbv && sbvsc.heightSizeInner.dimeRelaVal.dime == MyGravity_Horz_Fill) - { - rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; - - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) - { - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - } - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - - [self myCalcVertGravity:[self myGetSubviewVertGravity:sbv sbvsc:sbvsc vertGravity:vertGravity] sbv:sbv sbvsc:sbvsc paddingTop:paddingTop paddingBottom:paddingBottom baselinePos:CGFLOAT_MAX selfSize:selfSize pRect:&rect]; - - } - - sbvmyFrame.frame = rect; - - if (pMaxWrapSize != NULL) - { - if (lsc.wrapContentWidth) - { - //如果同时设置左右边界则左右边界为最小的宽度 - if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) - { - if (_myCGFloatLess(pMaxWrapSize->width, sbvsc.leadingPosInner.absVal + sbvsc.trailingPosInner.absVal + paddingLeading + paddingTrailing)) - pMaxWrapSize->width = sbvsc.leadingPosInner.absVal + sbvsc.trailingPosInner.absVal + paddingLeading + paddingTrailing; - } - - //宽度不依赖布局并且没有同时设置左右边距则参与最大宽度计算。 - if ((sbvsc.widthSizeInner.dimeRelaVal.view != self) && - (sbvsc.leadingPosInner.posVal == nil || sbvsc.trailingPosInner.posVal == nil)) - { - - if (_myCGFloatLess(pMaxWrapSize->width, sbvmyFrame.width + sbvsc.leadingPosInner.absVal + sbvsc.centerXPosInner.absVal + sbvsc.trailingPosInner.absVal + paddingLeading + paddingTrailing)) - pMaxWrapSize->width = sbvmyFrame.width + sbvsc.leadingPosInner.absVal + sbvsc.centerXPosInner.absVal + sbvsc.trailingPosInner.absVal + paddingLeading + paddingTrailing; - - if (_myCGFloatLess(pMaxWrapSize->width,sbvmyFrame.trailing + sbvsc.trailingPosInner.absVal + paddingTrailing)) - pMaxWrapSize->width = sbvmyFrame.trailing + sbvsc.trailingPosInner.absVal + paddingTrailing; - - } - } - - if (lsc.wrapContentHeight) - { - //如果同时设置上下边界则上下边界为最小的高度 - if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) - { - if (_myCGFloatLess(pMaxWrapSize->height, sbvsc.topPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom)) - pMaxWrapSize->height = sbvsc.topPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom; - } - - //高度不依赖布局并且没有同时设置上下边距则参与最大高度计算。 - if ((sbvsc.heightSizeInner.dimeRelaVal.view != self) && - (sbvsc.topPosInner.posVal == nil || sbvsc.bottomPosInner.posVal == nil)) - { - if (_myCGFloatLess(pMaxWrapSize->height, sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.centerYPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom)) - pMaxWrapSize->height = sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.centerYPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom; - - if (_myCGFloatLess(pMaxWrapSize->height, sbvmyFrame.bottom + sbvsc.bottomPosInner.absVal + paddingBottom)) - pMaxWrapSize->height = sbvmyFrame.bottom + sbvsc.bottomPosInner.absVal + paddingBottom; - } - } - } - - -} - @end diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index c4579e5..b6a16cd 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -37,7 +37,7 @@ */ -//Current version is 1.7.0, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.8.0beta, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. #ifndef MyLayout_MyLayout_h diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index 0ecc9ad..4586a4f 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -42,6 +42,9 @@ @interface MyBaseLayout() +@property(nonatomic,assign) BOOL isMyLayouting; + + //派生类重载这个函数进行布局 -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs; @@ -54,7 +57,7 @@ -(MyGravity)myGetSubviewVertGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc vertGravity:(MyGravity)vertGravity; --(void)myCalcVertGravity:(MyGravity)vert +-(CGFloat)myCalcVertGravity:(MyGravity)vert sbv:(UIView *)sbv sbvsc:(UIView*)sbvsc paddingTop:(CGFloat)paddingTop @@ -66,7 +69,7 @@ -(MyGravity)myGetSubviewHorzGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc horzGravity:(MyGravity)horzGravity; --(void)myCalcHorzGravity:(MyGravity)horz +-(CGFloat)myCalcHorzGravity:(MyGravity)horz sbv:(UIView *)sbv sbvsc:(UIView*)sbvsc paddingLeading:(CGFloat)paddingLeading @@ -87,9 +90,6 @@ -(NSMutableArray*)myGetLayoutSubviews; -(NSMutableArray*)myGetLayoutSubviewsFrom:(NSArray*)sbsFrom; -//设置子视图的相对依赖的尺寸 --(void)mySetSubviewRelativeDimeSize:(MyLayoutSize*)dime selfSize:(CGSize)selfSize lsc:(MyBaseLayout*)lsc pRect:(CGRect*)pRect; - -(CGSize)myAdjustSizeWhenNoSubviews:(CGSize)size sbs:(NSArray*)sbs lsc:(MyBaseLayout*)lsc; - (void)myAdjustLayoutSelfSize:(CGSize *)pSelfSize lsc:(MyBaseLayout*)lsc; @@ -111,6 +111,29 @@ -(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame sbvsc:(UIView*)sbvsc selfSize:(CGSize)selfSize sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout; +//根据子视图的宽度约束得到宽度值 +-(CGFloat)myGetSubviewWidthSizeValue:(UIView *)sbv + sbvsc:(UIView *)sbvsc + lsc:(MyBaseLayout *)lsc + selfSize:(CGSize)selfSize + paddingTop:(CGFloat)paddingTop + paddingLeading:(CGFloat)paddingLeading + paddingBottom:(CGFloat)paddingBottom + paddingTrailing:(CGFloat)paddingTrailing + sbvSize:(CGSize)sbvSize; + +//根据子视图的高度约束得到高度值 +-(CGFloat)myGetSubviewHeightSizeValue:(UIView *)sbv + sbvsc:(UIView *)sbvsc + lsc:(MyBaseLayout *)lsc + selfSize:(CGSize)selfSize + paddingTop:(CGFloat)paddingTop + paddingLeading:(CGFloat)paddingLeading + paddingBottom:(CGFloat)paddingBottom + paddingTrailing:(CGFloat)paddingTrailing + sbvSize:(CGSize)sbvSize; + + -(void)myCalcSubViewRect:(UIView*)sbv sbvsc:(UIView*)sbvsc sbvmyFrame:(MyFrame*)sbvmyFrame @@ -131,6 +154,8 @@ //给父布局视图机会来更改子布局视图的边界线的显示的rect -(void)myHookSublayout:(MyBaseLayout*)sublayout borderlineRect:(CGRect*)pRect; +-(void)myCalcSubviewsWrapContentSize:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSArray*)sbs withCustomSetting:(void (^)(UIView *sbv, UIView *sbvsc))customSetting; + @end @@ -195,5 +220,9 @@ @property(nonatomic, readonly) MyLayoutPos *baselinePosInner; +@property(nonatomic, readonly) CGFloat myEstimatedWidth; +@property(nonatomic, readonly) CGFloat myEstimatedHeight; + + @end diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index b6c057d..29fd451 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -193,50 +193,16 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyGravity horzGravity = lsc.gravity & MyGravity_Vert_Mask; MyOrientation oreintation = lsc.orientation; - for (UIView *sbv in sbs) - { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + [self myCalcSubviewsWrapContentSize:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs withCustomSetting:^(UIView *sbv, UIView *sbvsc) { - if (!isEstimate) - { - sbvmyFrame.frame = sbv.bounds; - [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; - } - - if ([sbv isKindOfClass:[MyBaseLayout class]]) - { - [self myAdjustSubviewWrapContent:sbv sbvsc:sbvsc orientation:oreintation gravity:(oreintation == MyOrientation_Vert)? horzGravity : vertGravity]; - - BOOL isSbvWrap = sbvsc.wrapContentHeight || sbvsc.wrapContentWidth; - if (pHasSubLayout != nil && isSbvWrap) - *pHasSubLayout = YES; - - if (isEstimate && isSbvWrap) - { - [(MyBaseLayout*)sbv sizeThatFits:sbvmyFrame.frame.size inSizeClass:sizeClass]; - if (sbvmyFrame.multiple) - { - sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为sizeThatFits执行后会还原,所以这里要重新设置 - } - } - } - } + [self myAdjustSubviewWrapContent:sbv sbvsc:sbvsc orientation:oreintation gravity:(oreintation == MyOrientation_Vert)? horzGravity : vertGravity]; + }]; + if (oreintation == MyOrientation_Vert) - { - if (vertGravity != MyGravity_None) - selfSize = [self myLayoutSubviewsForVertGravity:selfSize sbs:sbs lsc:lsc]; - else - selfSize = [self myLayoutSubviewsForVert:selfSize sbs:sbs lsc:lsc]; - } + selfSize = [self myLayoutSubviewsForVert:selfSize sbs:sbs lsc:lsc]; else - { - if (horzGravity != MyGravity_None) - selfSize = [self myLayoutSubviewsForHorzGravity:selfSize sbs:sbs lsc:lsc]; - else - selfSize = [self myLayoutSubviewsForHorz:selfSize sbs:sbs lsc:lsc]; - } + selfSize = [self myLayoutSubviewsForHorz:selfSize sbs:sbs lsc:lsc]; //绘制智能线。 if (!isEstimate) @@ -390,46 +356,6 @@ -(void)mySetLayoutIntelligentBorderline:(NSArray*)sbs lsc:(MyLinearLayout*)lsc } } -//计算得到最大的包裹宽度 -- (CGSize)myCalcMaxWrapWidth:(NSArray *)sbs selfSize:(CGSize)selfSize paddingHorz:(CGFloat)paddingHorz lsc:(MyLinearLayout*)lsc -{ - CGFloat maxWrapWidth = 0; - if (lsc.wrapContentWidth) - { - for (UIView *sbv in sbs) - { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - - //只有宽度不依赖于父视图并且没有设置左右边距则参与最大包裹宽度计算。 - MyLayoutSize *relaSize = sbvsc.widthSizeInner.dimeRelaVal; - if (relaSize.view != self && (sbvsc.leadingPosInner.posVal == nil || sbvsc.trailingPosInner.posVal == nil)) - { - - CGFloat subviewWidth = sbvmyFrame.width; - if (sbvsc.widthSizeInner.dimeNumVal != nil) - { - subviewWidth = sbvsc.widthSizeInner.measure; - } - sbvmyFrame.width = subviewWidth; - - //头部 + 中间偏移 + 宽度 + 尾部。 这里要进行计算的原因是有可能左边距或者右边距设置的是相对边距,因此这里要推导出布局视图的宽度。 - maxWrapWidth = [self myCalcSelfSize:maxWrapWidth - subviewSize:subviewWidth - headPos:sbvsc.leadingPosInner - centerPos:sbvsc.centerXPosInner - tailPos:sbvsc.trailingPosInner]; - - - } - } - - selfSize.width = maxWrapWidth + paddingHorz; - } - - return selfSize; -} - -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinearLayout*)lsc { CGFloat subviewSpace = lsc.subviewVSpace; @@ -437,62 +363,75 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - CGFloat paddingHorz = paddingLeading + paddingTrailing; CGFloat paddingVert = paddingTop + paddingBottom; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; - + MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; + CGFloat fixedHeight = 0; //计算固定部分的高度 CGFloat totalWeight = 0; //剩余部分的总比重 CGFloat addSpace = 0; //用于压缩时的间距压缩增量。 - - selfSize = [self myCalcMaxWrapWidth:sbs selfSize:selfSize paddingHorz:paddingHorz lsc:lsc]; //调整自身的宽度 - + CGFloat maxSelfWidth = 0; + + //高度不是包裹的子视图集合 + NSMutableSet *noWrapsbsSet = [NSMutableSet new]; + //固定高度尺寸的子视图集合 NSMutableArray *fixedSizeSbs = [NSMutableArray new]; CGFloat fixedSizeHeight = 0; NSInteger fixedSpaceCount = 0; //固定间距的子视图数量。 - CGFloat fixedSpaceHeight = 0; //固定间距的子视图的宽度。 + CGFloat fixedSpaceHeight = 0; //固定间距的子视图的高度。 CGFloat pos = paddingTop; for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - CGRect rect = sbvmyFrame.frame; - - [self myCalcLeadingTrailingRect:horzGravity - selfSize:selfSize - rect_p:&rect - sbv:sbv - paddingTrailing:paddingTrailing - paddingLeading:paddingLeading - sbvsc:sbvsc - lsc:lsc]; - - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]] && sbvsc.weight == 0) - {//特殊处理高度等于wrap的情况。 + + //计算子视图的高度 + rect.size.height = [self myGetSubviewHeightSizeValue:sbv + sbvsc:sbvsc + lsc:lsc + selfSize:selfSize + paddingTop:paddingTop + paddingLeading:paddingLeading + paddingBottom:paddingBottom + paddingTrailing:paddingTrailing + sbvSize:rect.size]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; } - else if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + + //计算子视图宽度以及对齐, 先计算宽度的原因是处理那些高度依赖宽度并且是wrap的情况。 + CGFloat tempSelfWidth = [self myCalcSubviewLeadingTrailingRect:horzGravity + selfSize:selfSize + pRect:&rect + sbv:sbv + paddingTrailing:paddingTrailing + paddingLeading:paddingLeading + sbvsc:sbvsc + lsc:lsc]; + + if (tempSelfWidth > maxSelfWidth) + maxSelfWidth = tempSelfWidth; + + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) {//特殊处理高度等于宽度的情况 - + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } - else if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) - {//高度依赖父视图高度 - rect.size.height = [sbvsc.heightSizeInner measureWith:selfSize.height - paddingVert]; - } - else if (sbvsc.heightSizeInner.dimeNumVal != nil) - { //计算出相对高度和上下位置。 - rect.size.height = sbvsc.heightSizeInner.measure; - } - else; - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + //再次特殊处理高度包裹的场景 + if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) + { + rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } //计算固定高度尺寸和浮动高度尺寸部分 - if (sbvsc.topPosInner.isRelativePos) { totalWeight += sbvsc.topPosInner.posNumVal.doubleValue; @@ -515,7 +454,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea rect.origin.y = pos; - if (sbvsc.weight > 0.0) + if (sbvsc.weight != 0.0) { totalWeight += sbvsc.weight; } @@ -565,10 +504,33 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } } + if (vertGravity == MyGravity_Vert_Fill) + { + BOOL canAddToNoWrapSbs = YES; + + if (sbvsc.weight != 0) + canAddToNoWrapSbs = NO; + + //判断是否是添加到参与布局视图包裹计算的子视图。 + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) + canAddToNoWrapSbs = NO; + + //如果子视图高度是包裹的也不进行扩展 + if (sbvsc.wrapContentHeight) + canAddToNoWrapSbs = NO; + + //如果子视图的最小高度就是自身则也不进行扩展。 + if (sbvsc.heightSizeInner.lBoundValInner.dimeSelfVal != nil) + canAddToNoWrapSbs = NO; + + if (canAddToNoWrapSbs) + [noWrapsbsSet addObject:sbv]; + } + sbvmyFrame.frame = rect; } - //在包裹宽度且总体比重不为0时则,则需要还原最小的宽度,这样就不会使得宽度在横竖屏或者多次计算后越来越宽。 + //在包裹高度且总体比重不为0时则,则需要还原最小的高度,这样就不会使得高度在横竖屏或者多次计算后越来高。 if (lsc.wrapContentHeight && totalWeight != 0) { CGFloat tempSelfHeight = paddingVert; @@ -578,6 +540,9 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:tempSelfHeight sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; } + + if (lsc.wrapContentWidth) + selfSize.width = maxSelfWidth + paddingLeading + paddingTrailing; //这里需要特殊处理当子视图的尺寸高度大于布局视图的高度的情况。 @@ -642,9 +607,47 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } //如果有浮动尺寸或者有压缩模式 - if (totalWeight != 0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingHeight, 0))) + if (totalWeight != 0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingHeight, 0)) || vertGravity != MyGravity_None) { - pos = paddingTop; + maxSelfWidth = 0; + CGFloat between = 0; //间距扩充 + CGFloat fill = 0; //尺寸扩充 + if (vertGravity == MyGravity_Vert_Center) + { + pos = (selfSize.height - fixedHeight - paddingVert)/2.0 + paddingTop; + } + else if (vertGravity == MyGravity_Vert_Window_Center) + { + if (self.window != nil) + { + pos = (CGRectGetHeight(self.window.bounds) - fixedHeight)/2.0; + + CGPoint pt = CGPointMake(0, pos); + pos = [self.window convertPoint:pt toView:self].y; + } + } + else if (vertGravity == MyGravity_Vert_Bottom) + { + pos = selfSize.height - fixedHeight - paddingBottom; + } + else if (vertGravity == MyGravity_Vert_Between) + { + pos = paddingTop; + + if (sbs.count > 1) + between = (selfSize.height - fixedHeight - paddingVert) / (sbs.count - 1); + } + else if (vertGravity == MyGravity_Vert_Fill) + { + pos = paddingTop; + if (noWrapsbsSet.count > 0) + fill = (selfSize.height - fixedHeight - paddingVert) / noWrapsbsSet.count; + } + else + { + pos = paddingTop; + } + for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; @@ -684,7 +687,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea rect.origin.y = pos; //分别处理相对高度和绝对高度 - if (weight > 0) + if (weight != 0) { CGFloat h = _myCGFloatRound((weight / totalWeight) * floatingHeight); floatingHeight -= h; @@ -695,6 +698,29 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:h sbvSize:rect.size selfLayoutSize:selfSize]; } + //加上扩充的宽度。 + if (fill != 0 && [noWrapsbsSet containsObject:sbv]) + rect.size.height += fill; + + + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + } + + //计算子视图宽度以及对齐 + CGFloat tempSelfWidth = [self myCalcSubviewLeadingTrailingRect:horzGravity + selfSize:selfSize + pRect:&rect + sbv:sbv + paddingTrailing:paddingTrailing + paddingLeading:paddingLeading + sbvsc:sbvsc + lsc:lsc]; + + if (tempSelfWidth > maxSelfWidth) + maxSelfWidth = tempSelfWidth; + pos += rect.size.height; //分别处理相对底部间距和绝对底部间距 @@ -739,6 +765,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } } + pos += between; //只有mgvert为between才加这个间距拉伸。 } sbvmyFrame.frame = rect; @@ -749,97 +776,132 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea pos += paddingBottom; if (lsc.wrapContentHeight) - { selfSize.height = pos; - } + + if (lsc.wrapContentWidth) + selfSize.width = maxSelfWidth + paddingLeading + paddingTrailing; return selfSize; } -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinearLayout*)lsc { - CGFloat subviewSpace = lsc.subviewHSpace; CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; CGFloat paddingHorz = paddingLeading + paddingTrailing; - CGFloat paddingVert = paddingTop + paddingBottom; MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; - - CGFloat fixedWidth = 0; //计算固定部分的高度 - CGFloat floatingWidth = 0; //浮动的高度。 - CGFloat totalWeight = 0; - - CGFloat maxSubviewHeight = 0; - CGFloat addSpace = 0; //用于压缩时的间距压缩增量。 - - //计算出固定的子视图宽度的总和以及宽度比例总和 + MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; + CGFloat fixedWidth = 0; //计算固定部分的宽度 + CGFloat totalWeight = 0; //剩余部分的总比重 + CGFloat addSpace = 0; //用于压缩时的间距压缩增量。 + //宽度不是包裹的子视图集合 + NSMutableSet *noWrapsbsSet = [NSMutableSet new]; + //固定宽度尺寸的子视图集合 NSMutableArray *fixedSizeSbs = [NSMutableArray new]; + //浮动宽度尺寸的子视图集合 NSMutableArray *flexedSizeSbs = [NSMutableArray new]; - CGFloat fixedSizeWidth = 0; //固定尺寸的宽度 + CGFloat fixedSizeWidth = 0; //固定尺寸视图的宽度 NSInteger fixedSpaceCount = 0; //固定间距的子视图数量。 CGFloat fixedSpaceWidth = 0; //固定间距的子视图的宽度。 + CGFloat baselinePos = CGFLOAT_MAX; //保存基线的值。 + CGFloat pos = paddingLeading; + CGFloat maxSelfHeight = 0; for (UIView *sbv in sbs) { + //计算出固定宽度部分以及weight部分。这里的宽度可能依赖高度。如果不是高度包裹则计算出所有高度。 + MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - + CGRect rect = sbvmyFrame.frame; + + //计算子视图的宽度,这里不管是否设置约束以及是否宽度是weight的都是进行计算。 + rect.size.width = [self myGetSubviewWidthSizeValue:sbv + sbvsc:sbvsc + lsc:lsc + selfSize:selfSize + paddingTop:paddingTop + paddingLeading:paddingLeading + paddingBottom:paddingBottom + paddingTrailing:paddingTrailing + sbvSize:rect.size]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + {//特殊处理高度等于宽度的情况 + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + } + + //计算子视图高度以及对齐 + CGFloat tempSelfHeight = [self myCalcSubviewTopBottomRect:vertGravity + selfSize:selfSize + pRect:&rect + sbv:sbv + paddingTop:paddingTop + paddingBottom:paddingBottom + baselinePos:baselinePos + sbvsc:sbvsc + lsc:lsc]; + if (tempSelfHeight > maxSelfHeight) + maxSelfHeight = tempSelfHeight; + + //如果垂直方向的对齐方式是基线对齐,那么就以第一个具有基线的视图作为标准位置。 + if (vertGravity == MyGravity_Vert_Baseline && baselinePos == CGFLOAT_MAX && self.baselineBaseView == sbv) + { + UIFont *sbvFont = [sbv valueForKey:@"font"]; + //这里要求baselineBaseView必须要具有font属性。 + //得到基线位置。 + baselinePos = rect.origin.y + (rect.size.height - sbvFont.lineHeight) / 2.0 + sbvFont.ascender; + + } + + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + } + + + //计算固定宽度尺寸和浮动宽度尺寸部分 if (sbvsc.leadingPosInner.isRelativePos) { totalWeight += sbvsc.leadingPosInner.posNumVal.doubleValue; + fixedWidth += sbvsc.leadingPosInner.offsetVal; } else { fixedWidth += sbvsc.leadingPosInner.absVal; + if (sbvsc.leadingPosInner.absVal != 0) { fixedSpaceCount += 1; fixedSpaceWidth += sbvsc.leadingPosInner.absVal; } + } - if (sbvsc.trailingPosInner.isRelativePos) - { - totalWeight += sbvsc.trailingPosInner.posNumVal.doubleValue; - fixedWidth += sbvsc.trailingPosInner.offsetVal; - } - else - { - fixedWidth += sbvsc.trailingPosInner.absVal; - if (sbvsc.trailingPosInner.absVal != 0) - { - fixedSpaceCount += 1; - fixedSpaceWidth += sbvsc.trailingPosInner.absVal; - } - - } + pos += sbvsc.leadingPosInner.absVal; + rect.origin.x = pos; - if (sbvsc.weight > 0.0) + + if (sbvsc.weight != 0.0) { totalWeight += sbvsc.weight; } else { - CGFloat vWidth = sbvmyFrame.width; - if (sbvsc.widthSizeInner.dimeNumVal != nil) - vWidth = sbvsc.widthSizeInner.measure; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner) - vWidth = [sbvsc.widthSizeInner measureWith:selfSize.width - paddingHorz]; - - vWidth = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:vWidth sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - sbvmyFrame.width = vWidth; - fixedWidth += vWidth; + fixedWidth += rect.size.width; //如果最小宽度不为自身并且宽度不是包裹的则可以进行缩小。 if (sbvsc.widthSizeInner.lBoundValInner.dimeSelfVal == nil) { - fixedSizeWidth += vWidth; - [fixedSizeSbs addObject:sbv]; + fixedSizeWidth += rect.size.width; + [fixedSizeSbs addObject:sbv]; } if (sbvsc.widthSizeInner.dimeSelfVal != nil) @@ -848,15 +910,64 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } } + pos += rect.size.width; + + if (sbvsc.trailingPosInner.isRelativePos) + { + totalWeight += sbvsc.trailingPosInner.posNumVal.doubleValue; + fixedWidth += sbvsc.trailingPosInner.offsetVal; + } + else + { + fixedWidth += sbvsc.trailingPosInner.absVal; + + if (sbvsc.trailingPosInner.absVal != 0) + { + fixedSpaceCount += 1; + fixedSpaceWidth += sbvsc.trailingPosInner.absVal; + } + + } + + pos += sbvsc.trailingPosInner.absVal; + if (sbv != sbs.lastObject) { fixedWidth += subviewSpace; + + pos += subviewSpace; + if (subviewSpace != 0) { fixedSpaceCount += 1; fixedSpaceWidth += subviewSpace; } } + + if (horzGravity == MyGravity_Horz_Fill) + { + BOOL canAddToNoWrapSbs = YES; + + if (sbvsc.weight != 0) + canAddToNoWrapSbs = NO; + + //判断是否是添加到参与布局视图包裹计算的子视图。 + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner) + canAddToNoWrapSbs = NO; + + //如果子视图宽度是包裹的也不进行扩展 + if (sbvsc.wrapContentWidth) + canAddToNoWrapSbs = NO; + + //如果子视图的最小宽度就是自身则也不进行扩展。 + if (sbvsc.widthSizeInner.lBoundValInner.dimeSelfVal != nil) + canAddToNoWrapSbs = NO; + + if (canAddToNoWrapSbs) + [noWrapsbsSet addObject:sbv]; + } + + sbvmyFrame.frame = rect; } //在包裹宽度且总体比重不为0时则,则需要还原最小的宽度,这样就不会使得宽度在横竖屏或者多次计算后越来越宽。 @@ -867,18 +978,23 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea tempSelfWidth += (sbs.count - 1) * subviewSpace; selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:tempSelfWidth sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; - + } - //剩余的可浮动的宽度,那些weight不为0的从这个高度来进行分发 + if (lsc.wrapContentHeight) + selfSize.height = maxSelfHeight + paddingTop + paddingBottom; + + //这里需要特殊处理当子视图的尺寸宽度大于布局视图的宽度的情况。 + + //剩余的可浮动的宽度,那些weight不为0的从这个宽度来进行分发 BOOL isWeightShrinkSpace = NO; //是否按比重缩小间距。。。 CGFloat weightShrinkSpaceTotalWidth = 0; - floatingWidth = selfSize.width - fixedWidth - paddingHorz; + CGFloat floatingWidth = selfSize.width - fixedWidth - paddingHorz; + //取出shrinkType中的模式和内容类型: + MySubviewsShrinkType sstMode = lsc.shrinkType & 0x0F; //压缩的模式 + MySubviewsShrinkType sstContent = lsc.shrinkType & 0xF0; //压缩内容 if (_myCGFloatLessOrEqual(floatingWidth, 0)) { - //取出shrinkType中的模式和内容类型: - MySubviewsShrinkType sstMode = lsc.shrinkType & 0x0F; //压缩的模式 - MySubviewsShrinkType sstContent = lsc.shrinkType & 0xF0; //压缩内容 //如果压缩方式为自动,但是浮动宽度子视图数量不为2则压缩类型无效。 if (sstMode == MySubviewsShrink_Auto && flexedSizeSbs.count != 2) sstMode = MySubviewsShrink_None; @@ -971,702 +1087,213 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } } - + floatingWidth = 0; } - CGFloat baselinePos = CGFLOAT_MAX; //保存基线的值。 - //调整所有子视图的宽度和高度。 - CGFloat pos = paddingLeading; - for (UIView *sbv in sbs) { - - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - - CGFloat leadingSpace = sbvsc.leadingPosInner.posNumVal.doubleValue; - CGFloat trailingSpace = sbvsc.trailingPosInner.posNumVal.doubleValue; - CGFloat weight = sbvsc.weight; - - CGRect rect = sbvmyFrame.frame; - - if (sbvsc.heightSizeInner.dimeNumVal != nil) - rect.size.height = sbvsc.heightSizeInner.measure; - - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) - rect.size.height= [sbvsc.heightSizeInner measureWith:selfSize.height - paddingVert]; - - - //计算出先对左边边距和绝对左边边距 - if ([self myIsRelativePos:leadingSpace]) + //如果有浮动尺寸或者有压缩模式 + if (totalWeight != 0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingWidth, 0)) || horzGravity != MyGravity_None) + { + maxSelfHeight = 0; + CGFloat between = 0; //间距扩充 + CGFloat fill = 0; //尺寸扩充 + if (horzGravity == MyGravity_Horz_Center) { - CGFloat leadingSpaceWeight = leadingSpace; - leadingSpace = _myCGFloatRound((leadingSpaceWeight / totalWeight) * floatingWidth); - floatingWidth -= leadingSpace; - totalWeight -= leadingSpaceWeight; - if (_myCGFloatLessOrEqual(leadingSpace, 0)) - leadingSpace = 0; - + pos = (selfSize.width - fixedWidth - paddingHorz)/2.0 + paddingLeading; } - else + else if (horzGravity == MyGravity_Horz_Window_Center) { - if (leadingSpace + sbvsc.leadingPosInner.offsetVal != 0) + if (self.window != nil) { - pos += addSpace; + pos = (CGRectGetWidth(self.window.bounds) - fixedWidth)/2.0; + + CGPoint pt = CGPointMake(pos, 0); + pos = [self.window convertPoint:pt toView:self].x; + - if (isWeightShrinkSpace) - { - pos += weightShrinkSpaceTotalWidth * (leadingSpace + sbvsc.leadingPosInner.offsetVal) / fixedSpaceWidth; - } } + } + else if (horzGravity == MyGravity_Horz_Trailing) + { + pos = selfSize.width - fixedWidth - paddingTrailing; + } + else if (horzGravity == MyGravity_Horz_Between) + { + pos = paddingLeading; + if (sbs.count > 1) + between = (selfSize.width - fixedWidth - paddingHorz) / (sbs.count - 1); } - - pos += [self myValidMargin:sbvsc.leadingPosInner sbv:sbv calcPos:leadingSpace + sbvsc.leadingPosInner.offsetVal selfLayoutSize:selfSize]; - - rect.origin.x = pos; - - - if (weight > 0) - { - CGFloat w = _myCGFloatRound((weight / totalWeight) * floatingWidth); - floatingWidth -= w; - totalWeight -= weight; - - if (_myCGFloatLessOrEqual(w, 0)) - w = 0; - - rect.size.width = w; - - } - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - - pos += rect.size.width; - - //计算相对的右边边距和绝对的右边边距 - if ([self myIsRelativePos:trailingSpace]) + else if (horzGravity == MyGravity_Horz_Fill) { - CGFloat trailingSpaceWeight = trailingSpace; - trailingSpace = _myCGFloatRound((trailingSpaceWeight / totalWeight) * floatingWidth); - floatingWidth -= trailingSpace; - totalWeight -= trailingSpaceWeight; - if (_myCGFloatLessOrEqual(trailingSpace, 0)) - trailingSpace = 0; + pos = paddingLeading; + if (noWrapsbsSet.count > 0) + fill = (selfSize.width - fixedWidth - paddingHorz) / noWrapsbsSet.count; } else { - if (trailingSpace + sbvsc.trailingPosInner.offsetVal != 0) - { - pos += addSpace; - - if (isWeightShrinkSpace) - { - pos += weightShrinkSpaceTotalWidth * (trailingSpace + sbvsc.trailingPosInner.offsetVal) / fixedSpaceWidth; - } - } + pos = paddingLeading; } - pos += [self myValidMargin:sbvsc.trailingPosInner sbv:sbv calcPos:trailingSpace + sbvsc.trailingPosInner.offsetVal selfLayoutSize:selfSize]; - - - if (sbv != sbs.lastObject) - { - pos += subviewSpace; + for (UIView *sbv in sbs) { - if (subviewSpace != 0) + MyFrame *sbvmyFrame = sbv.myFrame; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + + + CGFloat leadingSpace = sbvsc.leadingPosInner.posNumVal.doubleValue; + CGFloat trailingSpace = sbvsc.trailingPosInner.posNumVal.doubleValue; + CGFloat weight = sbvsc.weight; + CGRect rect = sbvmyFrame.frame; + + //分别处理相对顶部间距和绝对顶部间距 + if ([self myIsRelativePos:leadingSpace]) { - pos += addSpace; - - if (isWeightShrinkSpace) - { - pos += weightShrinkSpaceTotalWidth * subviewSpace / fixedSpaceWidth; - } + CGFloat topSpaceWeight = leadingSpace; + leadingSpace = _myCGFloatRound((topSpaceWeight / totalWeight) * floatingWidth); + floatingWidth -= leadingSpace; + totalWeight -= topSpaceWeight; + if (_myCGFloatLessOrEqual(leadingSpace, 0)) + leadingSpace = 0; } - } - - - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) - rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width ]; - - - //如果高度是浮动的则需要调整高度。 - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]] && sbvsc.heightSizeInner.dimeRelaVal.view != self) - { - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - } - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - - - //计算最高的高度。 - if (lsc.wrapContentHeight) - { - if (sbvsc.heightSizeInner.dimeRelaVal.view != self && (sbvsc.topPosInner.posVal == nil || sbvsc.bottomPosInner.posVal == nil)) + else { - maxSubviewHeight = [self myCalcSelfSize:maxSubviewHeight subviewSize:rect.size.height headPos:sbvsc.topPosInner centerPos:sbvsc.centerYPosInner tailPos:sbvsc.bottomPosInner]; + if (leadingSpace + sbvsc.leadingPosInner.offsetVal != 0) + { + pos += addSpace; + + if (isWeightShrinkSpace) + { + pos += weightShrinkSpaceTotalWidth * (leadingSpace + sbvsc.leadingPosInner.offsetVal) / fixedSpaceWidth; + } + } + } - } - else - { - [self myCalcSubviewTopBottomRect:vertGravity - selfSize:selfSize - rect_p:&rect - sbv:sbv - paddingBottom:paddingBottom - paddingTop:paddingTop - baselinePos:baselinePos - sbvsc:sbvsc - lsc:lsc]; + pos += [self myValidMargin:sbvsc.leadingPosInner sbv:sbv calcPos:leadingSpace + sbvsc.leadingPosInner.offsetVal selfLayoutSize:selfSize]; + rect.origin.x = pos; - //如果垂直方向的对齐方式是基线对齐,那么就以第一个具有基线的视图作为标准位置。 - if (vertGravity == MyGravity_Vert_Baseline && baselinePos == CGFLOAT_MAX && self.baselineBaseView == sbv) + //分别处理相对高度和绝对高度 + if (weight != 0) { - UIFont *sbvFont = [sbv valueForKey:@"font"]; - //这里要求baselineBaseView必须要具有font属性。 - //得到基线位置。 - baselinePos = rect.origin.y + (rect.size.height - sbvFont.lineHeight) / 2.0 + sbvFont.ascender; + CGFloat w = _myCGFloatRound((weight / totalWeight) * floatingWidth); + floatingWidth -= w; + totalWeight -= weight; + if (_myCGFloatLessOrEqual(w, 0)) + w = 0; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:w sbvSize:rect.size selfLayoutSize:selfSize]; } - - - } - - sbvmyFrame.frame = rect; - } - - pos += paddingTrailing; - - if (lsc.wrapContentWidth) - { - selfSize.width = pos; - } - - //调整所有子视图的高度。 - if (lsc.wrapContentHeight) - { - selfSize.height = maxSubviewHeight + paddingVert; - baselinePos = CGFLOAT_MAX; - - for (UIView *sbv in sbs) - { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - - CGRect rect = sbvmyFrame.frame; - [self myCalcSubviewTopBottomRect:vertGravity + //加上扩充的宽度。 + if (fill != 0 && [noWrapsbsSet containsObject:sbv]) + rect.size.width += fill; + + //特殊处理高度依赖宽度的情况。 + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + {//特殊处理高度等于宽度的情况 + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + } + + CGFloat tempSelfHeight = [self myCalcSubviewTopBottomRect:vertGravity selfSize:selfSize - rect_p:&rect + pRect:&rect sbv:sbv - paddingBottom:paddingBottom paddingTop:paddingTop + paddingBottom:paddingBottom baselinePos:baselinePos sbvsc:sbvsc lsc:lsc]; + if (tempSelfHeight > maxSelfHeight) + maxSelfHeight = tempSelfHeight; + + pos += rect.size.width; - sbvmyFrame.frame = rect; - - //如果垂直方向的对齐方式是基线对齐,那么就以第一个具有基线的视图作为标准位置。 - if (vertGravity == MyGravity_Vert_Baseline && baselinePos == CGFLOAT_MAX && self.baselineBaseView == sbv) + //计算相对的右边边距和绝对的右边边距 + if ([self myIsRelativePos:trailingSpace]) { - UIFont *sbvFont = [sbv valueForKey:@"font"]; - //这里要求baselineBaseView必须要具有font属性。 - //得到基线位置。 - baselinePos = rect.origin.y + (rect.size.height - sbvFont.lineHeight) / 2.0 + sbvFont.ascender; - + CGFloat trailingSpaceWeight = trailingSpace; + trailingSpace = _myCGFloatRound((trailingSpaceWeight / totalWeight) * floatingWidth); + floatingWidth -= trailingSpace; + totalWeight -= trailingSpaceWeight; + if (_myCGFloatLessOrEqual(trailingSpace, 0)) + trailingSpace = 0; } - - - } - - } - - - return selfSize; -} - - - --(CGSize)myLayoutSubviewsForVertGravity:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinearLayout*)lsc -{ - - CGFloat paddingTop = lsc.myLayoutTopPadding; - CGFloat paddingBottom = lsc.myLayoutBottomPadding; - CGFloat paddingLeading = lsc.myLayoutLeadingPadding; - CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - CGFloat paddingHorz = paddingLeading + paddingTrailing; - CGFloat paddingVert = paddingTop + paddingBottom; - CGFloat subviewSpace = lsc.subviewVSpace; - MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; - MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; - - CGFloat totalHeight = 0; - if (sbs.count > 1) - totalHeight += (sbs.count - 1) * subviewSpace; - - selfSize = [self myCalcMaxWrapWidth:sbs selfSize:selfSize paddingHorz:paddingHorz lsc:lsc]; - - CGFloat floatingHeight = selfSize.height - paddingVert - totalHeight; - if (_myCGFloatLessOrEqual(floatingHeight, 0)) - floatingHeight = 0; - - //调整子视图的宽度。并根据情况调整子视图的高度。并计算出固定高度和浮动高度。 - NSMutableSet *noWrapsbsSet = [NSMutableSet new]; - for (UIView *sbv in sbs) - { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - - BOOL canAddToNoWrapSbs = YES; - CGRect rect = sbvmyFrame.frame; - - [self myCalcLeadingTrailingRect:horzGravity - selfSize:selfSize - rect_p:&rect - sbv:sbv - paddingTrailing:paddingTrailing - paddingLeading:paddingLeading - sbvsc:sbvsc - lsc:lsc]; - - - if (sbvsc.heightSizeInner.dimeNumVal != nil) - rect.size.height = sbvsc.heightSizeInner.measure; - - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) - { - rect.size.height = [sbvsc.heightSizeInner measureWith:selfSize.height - paddingVert]; - canAddToNoWrapSbs = NO; - } - - - //高度等于宽度的情况。 - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) - { - rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; - } - - //如果子视图需要调整高度则调整高度 - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]] && sbvsc.weight == 0) - { - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - canAddToNoWrapSbs = NO; - } - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - - //如果子视图的最小高度就是自身则也不进行扩展。 - if (sbvsc.heightSizeInner.lBoundValInner.dimeSelfVal != nil) - { - canAddToNoWrapSbs = NO; - } - - - totalHeight += [self myValidMargin:sbvsc.topPosInner sbv:sbv calcPos:[sbvsc.topPosInner realPosIn:floatingHeight] selfLayoutSize:selfSize]; - - totalHeight += rect.size.height; - - totalHeight += [self myValidMargin:sbvsc.bottomPosInner sbv:sbv calcPos:[sbvsc.bottomPosInner realPosIn:floatingHeight] selfLayoutSize:selfSize]; - - sbvmyFrame.frame = rect; - - //如果子布局视图是wrap属性则不进行扩展。 - if (vertGravity == MyGravity_Vert_Fill && [sbv isKindOfClass:[MyBaseLayout class]]) - { - if (sbvsc.wrapContentHeight) + else { - canAddToNoWrapSbs = NO; + if (trailingSpace + sbvsc.trailingPosInner.offsetVal != 0) + { + pos += addSpace; + + if (isWeightShrinkSpace) + { + pos += weightShrinkSpaceTotalWidth * (trailingSpace + sbvsc.trailingPosInner.offsetVal) / fixedSpaceWidth; + } + } } - } - - if (canAddToNoWrapSbs) - [noWrapsbsSet addObject:sbv]; - - } - - - //根据对齐的方位来定位子视图的布局对齐 - CGFloat pos = 0; //位置偏移 - CGFloat between = 0; //间距扩充 - CGFloat fill = 0; //尺寸扩充 - if (vertGravity == MyGravity_Vert_Top) - { - pos = paddingTop; - } - else if (vertGravity == MyGravity_Vert_Center) - { - pos = (selfSize.height - totalHeight - paddingVert)/2.0 + paddingTop; - } - else if (vertGravity == MyGravity_Vert_Window_Center) - { - if (self.window != nil) - { - pos = (CGRectGetHeight(self.window.bounds) - totalHeight)/2.0; - - CGPoint pt = CGPointMake(0, pos); - pos = [self.window convertPoint:pt toView:self].y; + pos += [self myValidMargin:sbvsc.trailingPosInner sbv:sbv calcPos:trailingSpace + sbvsc.trailingPosInner.offsetVal selfLayoutSize:selfSize]; - } - } - else if (vertGravity == MyGravity_Vert_Bottom) - { - pos = selfSize.height - totalHeight - paddingBottom; - } - else if (vertGravity == MyGravity_Vert_Between) - { - pos = paddingTop; - - if (sbs.count > 1) - between = (selfSize.height - totalHeight - paddingVert) / (sbs.count - 1); - } - else if (vertGravity == MyGravity_Vert_Fill) - { - pos = paddingTop; - if (noWrapsbsSet.count > 0) - fill = (selfSize.height - totalHeight - paddingVert) / noWrapsbsSet.count; - } - else - { - pos = paddingTop; - } - - - - for (UIView *sbv in sbs) - { - - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - - pos += [self myValidMargin:sbvsc.topPosInner sbv:sbv calcPos:[sbvsc.topPosInner realPosIn:floatingHeight] selfLayoutSize:selfSize]; - - sbvmyFrame.top = pos; - - //加上扩充的宽度。 - if (fill != 0 && [noWrapsbsSet containsObject:sbv]) - sbvmyFrame.height += fill; - - pos += sbvmyFrame.height; - - - pos += [self myValidMargin:sbvsc.bottomPosInner sbv:sbv calcPos:[sbvsc.bottomPosInner realPosIn:floatingHeight] selfLayoutSize:selfSize]; - - if (sbv != sbs.lastObject) - pos += subviewSpace; - - pos += between; //只有mgvert为between才加这个间距拉伸。 - } - - return selfSize; - -} - - - --(CGSize)myLayoutSubviewsForHorzGravity:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinearLayout*)lsc -{ - CGFloat paddingTop = lsc.myLayoutTopPadding; - CGFloat paddingBottom = lsc.myLayoutBottomPadding; - CGFloat paddingLeading = lsc.myLayoutLeadingPadding; - CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - CGFloat paddingHorz = paddingLeading + paddingTrailing; - CGFloat paddingVert = paddingTop + paddingBottom; - CGFloat subviewSpace = lsc.subviewHSpace; - MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; - MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; - - - CGFloat totalWidth = 0; - if (sbs.count > 1) - totalWidth += (sbs.count - 1) * subviewSpace; - - - CGFloat floatingWidth = 0; - CGFloat maxSubviewHeight = 0; - - floatingWidth = selfSize.width - paddingHorz - totalWidth; - if (_myCGFloatLessOrEqual(floatingWidth, 0)) - floatingWidth = 0; - - //计算出固定的高度 - NSMutableSet *noWrapsbsSet = [NSMutableSet new]; - for (UIView *sbv in sbs) - { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - - BOOL canAddToNoWrapSbs = YES; - CGRect rect = sbvmyFrame.frame; - - if (sbvsc.widthSizeInner.dimeNumVal != nil) - rect.size.width = sbvsc.widthSizeInner.measure; - - if (sbvsc.heightSizeInner.dimeNumVal != nil) - rect.size.height = sbvsc.heightSizeInner.measure; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner) - { - rect.size.width= [sbvsc.widthSizeInner measureWith:selfSize.width - paddingHorz]; - canAddToNoWrapSbs = NO; - } - - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) - rect.size.height= [sbvsc.heightSizeInner measureWith:selfSize.height - paddingVert]; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; - - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - - //如果最小宽度不能被缩小则不加入。 - if (sbvsc.widthSizeInner.lBoundValInner.dimeSelfVal != nil) - { - canAddToNoWrapSbs = NO; - } - - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) - rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; - - //如果高度是浮动的则需要调整高度。 - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]] && sbvsc.heightSizeInner.dimeRelaVal.view != self) - { - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - } - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - - //计算以子视图为大小的情况 - if (lsc.wrapContentHeight && sbvsc.heightSizeInner.dimeRelaVal.view != self && (sbvsc.topPosInner.posVal == nil || sbvsc.bottomPosInner.posVal == nil)) - { - maxSubviewHeight = [self myCalcSelfSize:maxSubviewHeight subviewSize:rect.size.height headPos:sbvsc.topPosInner centerPos:sbvsc.centerYPosInner tailPos:sbvsc.bottomPosInner]; - } - - - totalWidth += [self myValidMargin:sbvsc.leadingPosInner sbv:sbv calcPos:[sbvsc.leadingPosInner realPosIn:floatingWidth] selfLayoutSize:selfSize]; - - totalWidth += rect.size.width; - - - totalWidth += [self myValidMargin:sbvsc.trailingPosInner sbv:sbv calcPos:[sbvsc.trailingPosInner realPosIn:floatingWidth] selfLayoutSize:selfSize]; - - - sbvmyFrame.frame = rect; - - //如果子视图是包裹属性则也不加入。 - if (horzGravity == MyGravity_Horz_Fill && [sbv isKindOfClass:[MyBaseLayout class]]) - { - if (sbvsc.wrapContentWidth) + //添加共有的子视图间距 + if (sbv != sbs.lastObject) { - canAddToNoWrapSbs = NO; + pos += subviewSpace; + + if (subviewSpace != 0) + { + pos += addSpace; + + if (isWeightShrinkSpace) + { + pos += weightShrinkSpaceTotalWidth * subviewSpace / fixedSpaceWidth; + } + } + + pos += between; //只有mgvert为between才加这个间距拉伸。 } + + sbvmyFrame.frame = rect; } - if (canAddToNoWrapSbs) - [noWrapsbsSet addObject:sbv]; - } + pos += paddingTrailing; - //调整自己的高度。 - if (lsc.wrapContentHeight) - { - selfSize.height = maxSubviewHeight + paddingVert; - } + if (lsc.wrapContentWidth) + selfSize.width = pos; - //根据对齐的方位来定位子视图的布局对齐 - CGFloat pos = 0; - CGFloat between = 0; - CGFloat fill = 0; - - if (horzGravity == MyGravity_Horz_Leading) - { - pos = paddingLeading; - } - else if (horzGravity == MyGravity_Horz_Center) - { - pos = (selfSize.width - totalWidth - paddingHorz)/2.0; - pos += paddingLeading; - } - else if (horzGravity == MyGravity_Horz_Window_Center) - { - if (self.window != nil) - { - pos = (CGRectGetWidth(self.window.bounds) - totalWidth)/2.0; - - CGPoint pt = CGPointMake(pos, 0); - pos = [self.window convertPoint:pt toView:self].x; - - //特殊处理窗口水平居中的场景。 - if ([MyBaseLayout isRTL]) - { - pos += (selfSize.width - CGRectGetWidth(self.window.bounds)); - } - - } - } - else if (horzGravity == MyGravity_Horz_Trailing) - { - pos = selfSize.width - totalWidth - paddingTrailing; - } - else if (horzGravity == MyGravity_Horz_Between) - { - pos = paddingLeading; - - if (sbs.count > 1) - between = (selfSize.width - totalWidth - paddingHorz) / (sbs.count - 1); - } - else if (horzGravity == MyGravity_Horz_Fill) - { - pos = paddingLeading; - if (noWrapsbsSet.count > 0) - fill = (selfSize.width - totalWidth - paddingHorz) / noWrapsbsSet.count; - } - else - { - pos = paddingLeading; - } - - CGFloat baselinePos = CGFLOAT_MAX; //保存基线的值。 - for (UIView *sbv in sbs) - { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - - pos += [self myValidMargin:sbvsc.leadingPosInner sbv:sbv calcPos:[sbvsc.leadingPosInner realPosIn:floatingWidth] selfLayoutSize:selfSize]; - - - CGRect rect = sbvmyFrame.frame; - - rect.origin.x = pos; - - [self myCalcSubviewTopBottomRect:vertGravity selfSize:selfSize rect_p:&rect sbv:sbv paddingBottom:paddingBottom paddingTop:paddingTop baselinePos:baselinePos sbvsc:sbvsc lsc:lsc]; - - if (fill != 0 && [noWrapsbsSet containsObject:sbv]) - rect.size.width += fill; - - - pos += rect.size.width; - - - pos += [self myValidMargin:sbvsc.trailingPosInner sbv:sbv calcPos:[sbvsc.trailingPosInner realPosIn:floatingWidth] selfLayoutSize:selfSize]; - - sbvmyFrame.frame = rect; - - - if (sbv != sbs.lastObject) - pos += subviewSpace; - - pos += between; //只有mghorz为between才加这个间距拉伸。 - - //如果垂直方向的对齐方式是基线对齐,那么就以第一个具有基线的视图作为标准位置。 - if (vertGravity == MyGravity_Vert_Baseline && baselinePos == CGFLOAT_MAX && self.baselineBaseView == sbv) - { - UIFont *sbvFont = [sbv valueForKey:@"font"]; - //这里要求baselineBaseView必须要具有font属性。 - //得到基线位置。 - baselinePos = rect.origin.y + (rect.size.height - sbvFont.lineHeight) / 2.0 + sbvFont.ascender; - - } - } + if (lsc.wrapContentHeight) + selfSize.height = maxSelfHeight + paddingTop + paddingBottom; return selfSize; } - - -- (void)myCalcLeadingTrailingRect:(MyGravity)horzGravity selfSize:(CGSize)selfSize rect_p:(CGRect *)rect_p sbv:(UIView *)sbv paddingTrailing:(CGFloat)paddingTrailing paddingLeading:(CGFloat)paddingLeading sbvsc:(UIView *)sbvsc lsc:(MyLinearLayout*)lsc +- (CGFloat)myCalcSubviewLeadingTrailingRect:(MyGravity)horzGravity selfSize:(CGSize)selfSize pRect:(CGRect *)pRect sbv:(UIView *)sbv paddingTrailing:(CGFloat)paddingTrailing paddingLeading:(CGFloat)paddingLeading sbvsc:(UIView *)sbvsc lsc:(MyLinearLayout*)lsc { - if (sbvsc.widthSizeInner.dimeNumVal != nil) - rect_p->size.width = sbvsc.widthSizeInner.measure; - //调整子视图的宽度,如果子视图为matchParent的话 - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner) - rect_p->size.width = [sbvsc.widthSizeInner measureWith:selfSize.width - paddingLeading - paddingTrailing]; + pRect->size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:lsc.myLayoutTopPadding paddingLeading:paddingLeading paddingBottom:lsc.myLayoutBottomPadding paddingTrailing:paddingTrailing sbvSize:pRect->size]; if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) - rect_p->size.width = selfSize.width - paddingLeading - paddingTrailing - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal; - - - rect_p->size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect_p->size.width sbvSize:rect_p->size selfLayoutSize:selfSize]; + pRect->size.width = selfSize.width - paddingLeading - paddingTrailing - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal; + pRect->size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:pRect->size.width sbvSize:pRect->size selfLayoutSize:selfSize]; - [self myCalcHorzGravity:[self myGetSubviewHorzGravity:sbv sbvsc:sbvsc horzGravity:horzGravity] sbv:sbv sbvsc:sbvsc paddingLeading:paddingLeading paddingTrailing:paddingTrailing selfSize:selfSize pRect:rect_p]; + return [self myCalcHorzGravity:[self myGetSubviewHorzGravity:sbv sbvsc:sbvsc horzGravity:horzGravity] sbv:sbv sbvsc:sbvsc paddingLeading:paddingLeading paddingTrailing:paddingTrailing selfSize:selfSize pRect:pRect]; } -- (void)myCalcSubviewTopBottomRect:(MyGravity)vertGravity selfSize:(CGSize)selfSize rect_p:(CGRect *)rect_p sbv:(UIView *)sbv paddingBottom:(CGFloat)paddingBottom paddingTop:(CGFloat)paddingTop baselinePos:(CGFloat)baselinePos sbvsc:(UIView *)sbvsc lsc:(MyLinearLayout*)lsc +- (CGFloat)myCalcSubviewTopBottomRect:(MyGravity)vertGravity selfSize:(CGSize)selfSize pRect:(CGRect *)pRect sbv:(UIView *)sbv paddingTop:(CGFloat)paddingTop paddingBottom:(CGFloat)paddingBottom baselinePos:(CGFloat)baselinePos sbvsc:(UIView *)sbvsc lsc:(MyLinearLayout*)lsc { - //计算高度 - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) - { - rect_p->size.height = [sbvsc.heightSizeInner measureWith:selfSize.height - paddingTop - paddingBottom]; - } - - - if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) - rect_p->size.height = selfSize.height - paddingTop - paddingBottom - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal; - - - rect_p->size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect_p->size.height sbvSize:rect_p->size selfLayoutSize:selfSize]; - - [self myCalcVertGravity:[self myGetSubviewVertGravity:sbv sbvsc:sbvsc vertGravity:vertGravity] sbv:sbv sbvsc:sbvsc paddingTop:paddingTop paddingBottom:paddingBottom baselinePos:baselinePos selfSize:selfSize pRect:rect_p]; -} + pRect->size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:lsc.myLayoutLeadingPadding paddingBottom:paddingBottom paddingTrailing:lsc.myLayoutTrailingPadding sbvSize:pRect->size]; --(CGFloat)myCalcSelfSize:(CGFloat)selfSize subviewSize:(CGFloat)subviewSize headPos:(MyLayoutPos*)headPos centerPos:(MyLayoutPos*)centerPos tailPos:(MyLayoutPos*)tailPos -{ - CGFloat totalWeight = 0; - CGFloat tempSize = subviewSize; - CGFloat hm = headPos.posNumVal.doubleValue; - CGFloat cm = centerPos.posNumVal.doubleValue; - CGFloat tm = tailPos.posNumVal.doubleValue; - - //这里是求父视图的最大尺寸,因此如果使用了相对边距的话,最大最小要参与计算。 - if (![self myIsRelativePos:hm]) - tempSize += hm; - else - totalWeight += hm; - - tempSize += headPos.offsetVal; - - - if (![self myIsRelativePos:cm]) - tempSize += cm; - else - totalWeight += cm; - - tempSize += centerPos.offsetVal; - - - if (![self myIsRelativePos:tm]) - tempSize += tm; - else - totalWeight += tm; - - tempSize += tailPos.offsetVal; - - //如果3个比重之和小于等于1则表示按比重分配宽度。 - if (_myCGFloatLessOrEqual(1, totalWeight)) - tempSize = 0; - else - tempSize /=(1 - totalWeight); - - - CGFloat leadingMargin = [self myValidMargin:headPos sbv:headPos.view calcPos:[headPos realPosIn:tempSize] selfLayoutSize:CGSizeZero]; - - CGFloat centerMargin = [self myValidMargin:centerPos sbv:centerPos.view calcPos:[centerPos realPosIn:tempSize] selfLayoutSize:CGSizeZero]; - - CGFloat trailingMargin = [self myValidMargin:tailPos sbv:tailPos.view calcPos:[tailPos realPosIn:tempSize] selfLayoutSize:CGSizeZero]; + if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) + pRect->size.height = selfSize.height - paddingTop - paddingBottom - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal; - tempSize = subviewSize + leadingMargin + centerMargin + trailingMargin; - if (_myCGFloatGreat(tempSize,selfSize)) - { - selfSize = tempSize; - } - return selfSize; + pRect->size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:pRect->size.height sbvSize:pRect->size selfLayoutSize:selfSize]; + return [self myCalcVertGravity:[self myGetSubviewVertGravity:sbv sbvsc:sbvsc vertGravity:vertGravity] sbv:sbv sbvsc:sbvsc paddingTop:paddingTop paddingBottom:paddingBottom baselinePos:baselinePos selfSize:selfSize pRect:pRect]; } -(void)myEqualizeSubviewsForVert:(BOOL)centered withSpace:(CGFloat)margin @@ -1752,8 +1379,6 @@ -(void)myEqualizeSubviewsForHorz:(BOOL)centered withSpace:(CGFloat)space -(void)myEqualizeSubviewsSpaceForVert:(BOOL)centered { - - //如果居中和不居中则拆分出来的片段是不一样的。 NSArray *sbs = [self myGetLayoutSubviews]; CGFloat fragments = centered ? sbs.count + 1 : sbs.count - 1; @@ -1797,9 +1422,4 @@ -(void)myEqualizeSubviewsSpaceForHorz:(BOOL)centered } } - - - - - @end diff --git a/MyLayout/Lib/MyPathLayout.m b/MyLayout/Lib/MyPathLayout.m index c01affc..cd6f3fd 100644 --- a/MyLayout/Lib/MyPathLayout.m +++ b/MyLayout/Lib/MyPathLayout.m @@ -557,35 +557,12 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( NSArray *sbs2 = sbs; MyPathLayout *lsc = self.myCurrentSizeClass; + CGFloat paddingTop = lsc.myLayoutTopPadding; + CGFloat paddingBottom = lsc.myLayoutBottomPadding; + CGFloat paddingLeading = lsc.myLayoutLeadingPadding; + CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - for (UIView *sbv in sbs) - { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - - if (!isEstimate) - { - sbvmyFrame.frame = sbv.bounds; - [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; - } - - if ([sbv isKindOfClass:[MyBaseLayout class]]) - { - - - if (pHasSubLayout != nil && (sbvsc.wrapContentHeight || sbvsc.wrapContentWidth)) - *pHasSubLayout = YES; - - if (isEstimate && (sbvsc.wrapContentWidth || sbvsc.wrapContentHeight)) - { - [(MyBaseLayout*)sbv sizeThatFits:sbvmyFrame.frame.size inSizeClass:sizeClass]; - if (sbvmyFrame.multiple) - { - sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为sizeThatFits执行后会还原,所以这里要重新设置 - } - } - } - } + [self myCalcSubviewsWrapContentSize:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs2 withCustomSetting:nil]; CGFloat minXPos = CGFLOAT_MAX; @@ -629,46 +606,25 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( CGRect rect = sbvmyFrame.frame; - if (sbvsc.widthSizeInner.dimeNumVal != nil) - rect.size.width = sbvsc.widthSizeInner.measure; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil) - { - if (sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner) - { - rect.size.width = [sbvsc.widthSizeInner measureWith:(selfSize.width - lsc.myLayoutLeftPadding - lsc.myLayoutRightPadding) ]; - } - else - { - rect.size.width = [sbvsc.widthSizeInner measureWith: sbvsc.widthSizeInner.dimeRelaVal.view.estimatedRect.size.width ]; - } - } - + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - if (sbvsc.heightSizeInner.dimeNumVal != nil) - rect.size.height = sbvsc.heightSizeInner.measure; - - - if (sbvsc.heightSizeInner.dimeRelaVal != nil) - { - if (sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) - { - rect.size.height = [sbvsc.heightSizeInner measureWith:(selfSize.height - lsc.myLayoutTopPadding - lsc.myLayoutBottomPadding) ]; - } - else - { - rect.size.height = [sbvsc.heightSizeInner measureWith:sbvsc.heightSizeInner.dimeRelaVal.view.estimatedRect.size.height ]; - } - } - - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) - { - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + {//特殊处理高度等于宽度的情况 + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + } + //中心点的位置。。 rect.origin.x = pt.x - rect.size.width * sbv.layer.anchorPoint.x - sbvsc.rightPosInner.absVal + sbvsc.leftPosInner.absVal; @@ -708,55 +664,26 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( CGRect rect = sbvmyFrame.frame; - if (sbvsc.widthSizeInner.dimeNumVal != nil) - rect.size.width = sbvsc.widthSizeInner.measure; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil) - { - if (sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner) - { - rect.size.width = [sbvsc.widthSizeInner measureWith:(selfSize.width - lsc.myLayoutLeftPadding - lsc.myLayoutRightPadding)]; - } - else - { - rect.size.width = [sbvsc.widthSizeInner measureWith:sbvsc.widthSizeInner.dimeRelaVal.view.estimatedRect.size.width]; - } - } + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - if (sbvsc.heightSizeInner.dimeNumVal != nil) - rect.size.height = sbvsc.heightSizeInner.measure; - - - if (sbvsc.heightSizeInner.dimeRelaVal != nil) - { - if (sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) - { - rect.size.height = [sbvsc.heightSizeInner measureWith:selfSize.height - lsc.myLayoutTopPadding - lsc.myLayoutBottomPadding]; - } - else if (sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) - { - rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; - } - else - { - rect.size.height = [sbvsc.heightSizeInner measureWith:sbvsc.heightSizeInner.dimeRelaVal.view.estimatedRect.size.height]; - } - } + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) - { - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + {//特殊处理高度等于宽度的情况 + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - //计算宽度等于高度的情况。 if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - { + {//特殊处理宽度等于高度的情况 rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; } + //位置在原点位置。。 rect.origin.x = (selfSize.width - lsc.myLayoutLeftPadding - lsc.myLayoutRightPadding)*self.coordinateSetting.origin.x - rect.size.width *sbv.layer.anchorPoint.x + sbvsc.leftPosInner.absVal + lsc.myLayoutLeftPadding - sbvsc.rightPosInner.absVal; diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 04f8412..6721d73 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -253,13 +253,19 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv //这里要更新左边最小和右边最大约束的情况。 MyLayoutPos *lBoundPos = sbvsc.leadingPosInner.lBoundValInner; MyLayoutPos *uBoundPos = sbvsc.trailingPosInner.uBoundValInner; + UIView *lBoundRelaView = lBoundPos.posRelaVal.view; + UIView *uBoundRelaView = uBoundPos.posRelaVal.view; if (lBoundPos.posRelaVal != nil && uBoundPos.posRelaVal != nil) { //让宽度缩小并在最小和最大的中间排列。 - CGFloat minLeading = [self myCalcSubView:lBoundPos.posRelaVal.view lsc:lsc gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; + CGFloat minLeading = [self myCalcSubView:lBoundRelaView lsc:lsc gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; + if (lBoundRelaView != nil && lBoundRelaView != self && [self myIsNoLayoutSubview:lBoundRelaView]) + minLeading -= lBoundPos.offsetVal; - CGFloat maxTrailing = [self myCalcSubView:uBoundPos.posRelaVal.view lsc:lsc gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; + CGFloat maxTrailing = [self myCalcSubView:uBoundRelaView lsc:lsc gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; + if (uBoundRelaView != nil && uBoundRelaView != self && [self myIsNoLayoutSubview:uBoundRelaView]) + maxTrailing += uBoundPos.offsetVal; //用maxRight减去minLeft得到的宽度再减去视图的宽度,然后让其居中。。如果宽度超过则缩小视图的宽度。 CGFloat intervalWidth = maxTrailing - minLeading; @@ -280,7 +286,9 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv else if (lBoundPos.posRelaVal != nil) { //得到左边的最小位置。如果当前的左边距小于这个位置则缩小视图的宽度。 - CGFloat minLeading = [self myCalcSubView:lBoundPos.posRelaVal.view lsc:lsc gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; + CGFloat minLeading = [self myCalcSubView:lBoundRelaView lsc:lsc gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; + if (lBoundRelaView != nil && lBoundRelaView != self && [self myIsNoLayoutSubview:lBoundRelaView]) + minLeading -= lBoundPos.offsetVal; if (_myCGFloatLess(sbvmyFrame.leading, minLeading)) @@ -292,7 +300,9 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv else if (uBoundPos.posRelaVal != nil) { //得到右边的最大位置。如果当前的右边距大于了这个位置则缩小视图的宽度。 - CGFloat maxTrailing = [self myCalcSubView:uBoundPos.posRelaVal.view lsc:lsc gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; + CGFloat maxTrailing = [self myCalcSubView:uBoundRelaView lsc:lsc gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; + if (uBoundRelaView != nil && uBoundRelaView != self && [self myIsNoLayoutSubview:uBoundRelaView]) + maxTrailing += uBoundPos.offsetVal; if (_myCGFloatGreat(sbvmyFrame.trailing, maxTrailing)) { @@ -301,7 +311,6 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv } } - } -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize @@ -439,12 +448,20 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL } //这里要更新上边最小和下边最大约束的情况。 - if (sbvsc.topPosInner.lBoundValInner.posRelaVal != nil && sbvsc.bottomPosInner.uBoundValInner.posRelaVal != nil) + MyLayoutPos *lBoundPos = sbvsc.topPosInner.lBoundValInner; + MyLayoutPos *uBoundPos = sbvsc.bottomPosInner.uBoundValInner; + UIView *lBoundRelaView = lBoundPos.posRelaVal.view; + UIView *uBoundRelaView = uBoundPos.posRelaVal.view; + + if (lBoundPos.posRelaVal != nil && uBoundPos.posRelaVal != nil) { //让宽度缩小并在最小和最大的中间排列。 - CGFloat minTop = [self myCalcSubView:sbvsc.topPosInner.lBoundValInner.posRelaVal.view lsc:lsc gravity:sbvsc.topPosInner.lBoundValInner.posRelaVal.pos selfSize:selfSize] + sbvsc.topPosInner.lBoundValInner.offsetVal; - - CGFloat maxBottom = [self myCalcSubView:sbvsc.bottomPosInner.uBoundValInner.posRelaVal.view lsc:lsc gravity:sbvsc.bottomPosInner.uBoundValInner.posRelaVal.pos selfSize:selfSize] - sbvsc.bottomPosInner.uBoundValInner.offsetVal; + CGFloat minTop = [self myCalcSubView:lBoundRelaView lsc:lsc gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; + if (lBoundRelaView != nil && lBoundRelaView != self && [self myIsNoLayoutSubview:lBoundRelaView]) + minTop -= lBoundPos.offsetVal; + CGFloat maxBottom = [self myCalcSubView:uBoundRelaView lsc:lsc gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; + if (uBoundRelaView != nil && uBoundRelaView != self && [self myIsNoLayoutSubview:uBoundRelaView]) + maxBottom += uBoundPos.offsetVal; //用maxRight减去minLeft得到的宽度再减去视图的宽度,然后让其居中。。如果宽度超过则缩小视图的宽度。 if (_myCGFloatLess(maxBottom - minTop, sbvmyFrame.height)) @@ -461,10 +478,12 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL } - else if (sbvsc.topPosInner.lBoundValInner.posRelaVal != nil) + else if (lBoundPos.posRelaVal != nil) { //得到左边的最小位置。如果当前的左边距小于这个位置则缩小视图的宽度。 - CGFloat minTop = [self myCalcSubView:sbvsc.topPosInner.lBoundValInner.posRelaVal.view lsc:lsc gravity:sbvsc.topPosInner.lBoundValInner.posRelaVal.pos selfSize:selfSize] + sbvsc.topPosInner.lBoundValInner.offsetVal; + CGFloat minTop = [self myCalcSubView:lBoundRelaView lsc:lsc gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; + if (lBoundRelaView != nil && lBoundRelaView != self && [self myIsNoLayoutSubview:lBoundRelaView]) + minTop -= lBoundPos.offsetVal; if (_myCGFloatLess(sbvmyFrame.top, minTop)) { @@ -473,10 +492,13 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL } } - else if (sbvsc.bottomPosInner.uBoundValInner.posRelaVal != nil) + else if (uBoundPos.posRelaVal != nil) { //得到右边的最大位置。如果当前的右边距大于了这个位置则缩小视图的宽度。 - CGFloat maxBottom = [self myCalcSubView:sbvsc.bottomPosInner.uBoundValInner.posRelaVal.view lsc:lsc gravity:sbvsc.bottomPosInner.uBoundValInner.posRelaVal.pos selfSize:selfSize] - sbvsc.bottomPosInner.uBoundValInner.offsetVal; + CGFloat maxBottom = [self myCalcSubView:uBoundRelaView lsc:lsc gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; + if (uBoundRelaView != nil && uBoundRelaView != self && [self myIsNoLayoutSubview:uBoundRelaView]) + maxBottom += uBoundPos.offsetVal; + if (_myCGFloatGreat(sbvmyFrame.bottom, maxBottom)) { sbvmyFrame.bottom = maxBottom; @@ -676,12 +698,27 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { if (sbvsc.leadingPosInner.posRelaVal != nil) - sbvmyFrame.leading = [self myCalcSubView:sbvsc.leadingPosInner.posRelaVal.view lsc:lsc gravity:sbvsc.leadingPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.leadingPosInner.absVal; + { + UIView *relaView = sbvsc.leadingPosInner.posRelaVal.view; + sbvmyFrame.leading = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.leadingPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.leadingPosInner.absVal; + + if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) + { + sbvmyFrame.leading -= sbvsc.leadingPosInner.absVal; + } + } else sbvmyFrame.leading = sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; if (sbvsc.trailingPosInner.posRelaVal != nil) + { + UIView *relaView = sbvsc.trailingPosInner.posRelaVal.view; sbvmyFrame.trailing = [self myCalcSubView:sbvsc.trailingPosInner.posRelaVal.view lsc:lsc gravity:sbvsc.trailingPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.trailingPosInner.absVal; + if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) + { + sbvmyFrame.trailing += sbvsc.trailingPosInner.absVal; + } + } else sbvmyFrame.trailing = selfSize.width - sbvsc.trailingPosInner.absVal - lsc.myLayoutTrailingPadding; @@ -725,7 +762,6 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc { if (sbvsc.heightSizeInner.dimeRelaVal != nil) { - sbvmyFrame.height = [sbvsc.heightSizeInner measureWith:[self myCalcSubView:sbvsc.heightSizeInner.dimeRelaVal.view lsc:lsc gravity:sbvsc.heightSizeInner.dimeRelaVal.dime selfSize:selfSize] ]; sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; @@ -748,12 +784,30 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { if (sbvsc.topPosInner.posRelaVal != nil) - sbvmyFrame.top = [self myCalcSubView:sbvsc.topPosInner.posRelaVal.view lsc:lsc gravity:sbvsc.topPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.topPosInner.absVal; + { + UIView *relaView = sbvsc.topPosInner.posRelaVal.view; + sbvmyFrame.top = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.topPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.topPosInner.absVal; + + if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) + { + sbvmyFrame.top -= sbvsc.topPosInner.absVal; + } + + } else sbvmyFrame.top = sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding; if (sbvsc.bottomPosInner.posRelaVal != nil) - sbvmyFrame.bottom = [self myCalcSubView:sbvsc.bottomPosInner.posRelaVal.view lsc:lsc gravity:sbvsc.bottomPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.bottomPosInner.absVal; + { + UIView *relaView = sbvsc.bottomPosInner.posRelaVal.view; + + sbvmyFrame.bottom = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.bottomPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.bottomPosInner.absVal; + + if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) + { + sbvmyFrame.bottom += sbvsc.bottomPosInner.absVal; + } + } else sbvmyFrame.bottom = selfSize.height - sbvsc.bottomPosInner.absVal - lsc.myLayoutBottomPadding; diff --git a/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m b/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m index 250e50c..e51c6e2 100644 --- a/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m +++ b/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m @@ -34,6 +34,9 @@ -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSStri // [self createRelativeRootLayout]; // [self createFloatRootLayout]; + //如果是代码实现autolayout的话必须要将translatesAutoresizingMaskIntoConstraints 设置为NO。 + _rootLayout.translatesAutoresizingMaskIntoConstraints = NO; + //设置布局视图的autolayout约束,这里是用iOS9提供的约束设置方法,您也可以用低级版本设置,以及用masonry来进行设置。 [_rootLayout.leftAnchor constraintEqualToAnchor:self.contentView.leftAnchor].active = YES; [_rootLayout.topAnchor constraintEqualToAnchor:self.contentView.topAnchor].active = YES; @@ -100,7 +103,6 @@ - (void)setSelected:(BOOL)selected animated:(BOOL)animated { -(void)createLinearRootLayout { _rootLayout= [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; - _rootLayout.translatesAutoresizingMaskIntoConstraints = NO; //通过代码形式来设置autolayout约束时必须要将这个属性设置为NO _rootLayout.topPadding = 5; _rootLayout.bottomPadding = 5; //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! @@ -151,7 +153,6 @@ -(void)createLinearRootLayout -(void)createRelativeRootLayout { _rootLayout = [MyRelativeLayout new]; - _rootLayout.translatesAutoresizingMaskIntoConstraints = NO; _rootLayout.topPadding = 5; _rootLayout.bottomPadding = 5; //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! diff --git a/MyLayoutDemo/LLTest3ViewController.m b/MyLayoutDemo/LLTest3ViewController.m index 49b78f6..837af1b 100644 --- a/MyLayoutDemo/LLTest3ViewController.m +++ b/MyLayoutDemo/LLTest3ViewController.m @@ -37,7 +37,7 @@ -(void)loadView 1.当使用gravity属性时意味着布局视图必须要有明确的尺寸才有意义,因为有确定的尺寸才能决定里面的子视图的停靠的方位。 2.布局视图的wrapContentHeight设置为YES时是和gravity上设置垂直停靠方向以及垂直填充是互斥的;而布局视图的wrapContentWidth设置为YES时是和gravity上设置水平停靠方向和水平填充是互斥的。 - 3.布局视图的gravity的属性的优先级要高于子视图的停靠和尺寸设置。 + 3.布局视图的gravity的属性的优先级要高于子视图的边距和尺寸设置,但是低于子视图的myAlignment属性的设置。 */ diff --git a/MyLayoutDemo/RLTest4ViewController.m b/MyLayoutDemo/RLTest4ViewController.m index b84800f..c023b1a 100644 --- a/MyLayoutDemo/RLTest4ViewController.m +++ b/MyLayoutDemo/RLTest4ViewController.m @@ -56,6 +56,7 @@ -(void)loadView MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + rootLayout.insetsPaddingFromSafeArea = ~UIRectEdgeBottom; //为了防止拉到底部时iPhoneX设备的抖动发生,不能将底部安全区叠加到padding中去。 rootLayout.widthSize.equalTo(scrollView.widthSize); rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); rootLayout.wrapContentHeight = YES; diff --git a/MyLayoutTests/MyFloatLayoutTestCase.m b/MyLayoutTests/MyFloatLayoutTestCase.m index 5c7042e..a0ee233 100644 --- a/MyLayoutTests/MyFloatLayoutTestCase.m +++ b/MyLayoutTests/MyFloatLayoutTestCase.m @@ -43,6 +43,132 @@ - (void)testExample { } + +-(void)testSubviewSizeDependent +{//测试子视图尺寸依赖 + + //垂直线性布局 + { + MyFloatLayout *rootLayout1 = [[MyFloatLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Vert]; + rootLayout1.wrapContentHeight = NO; + //1. 子视图宽度等于自身高度 + UILabel *label1 = [UILabel new]; + label1.myHeight = 100; + label1.widthSize.equalTo(label1.heightSize); + [rootLayout1 addSubview:label1]; + + + //2. 子视图高度等于自身宽度 + UILabel *label2 = [UILabel new]; + label2.wrapContentWidth = YES; + label2.heightSize.equalTo(label2.widthSize); + label2.text = @"hello World"; + [rootLayout1 addSubview:label2]; + + //3. 子视图高度等于兄弟视图高度, 子视图宽度等于兄弟视图宽度 + UILabel *label3 = [UILabel new]; + label3.heightSize.equalTo(label1.heightSize); + label3.widthSize.equalTo(label1.widthSize); + [rootLayout1 addSubview:label3]; + + //4. 子视图高度等于兄弟视图宽度, 子视图宽度等于兄弟视图高度 + UILabel *label4 = [UILabel new]; + label4.widthSize.equalTo(label2.heightSize).add(20); + label4.heightSize.equalTo(label2.widthSize).add(10).multiply(0.5); + [rootLayout1 addSubview:label4]; + + //5. 子视图宽度等于父视图宽度,高度等于宽度 + UILabel *label5 = [UILabel new]; + label5.widthSize.equalTo(rootLayout1.widthSize).add(-20); + label5.heightSize.equalTo(label5.widthSize); + [rootLayout1 addSubview:label5]; + + //6. 子视图高度等于父视图高度,宽度等于高度 + UILabel *label6 = [UILabel new]; + label6.heightSize.equalTo(rootLayout1.heightSize).multiply(0.5); + label6.widthSize.equalTo(label6.heightSize); + [rootLayout1 addSubview:label6]; + + [rootLayout1 layoutIfNeeded]; + + XCTAssertTrue(label1.frame.size.width == label1.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label1.frame)); + XCTAssertTrue(label2.frame.size.width == label2.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label2.frame)); + XCTAssertTrue(label3.frame.size.width == label1.frame.size.width && + label3.frame.size.height == label1.frame.size.height, @"label3.frame = %@",NSStringFromCGRect(label3.frame)); + XCTAssertTrue(label4.frame.size.width == (label2.frame.size.height + 20) && + label4.frame.size.height == (label2.frame.size.width * 0.5 + 10), @"label4.frame = %@",NSStringFromCGRect(label4.frame)); + + XCTAssertTrue(label5.frame.size.width == (rootLayout1.frame.size.width - 20) && + label5.frame.size.height == label5.frame.size.width, @"label5.frame = %@",NSStringFromCGRect(label5.frame)); + + XCTAssertTrue(label6.frame.size.width == label6.frame.size.height && + label6.frame.size.height == rootLayout1.frame.size.height * 0.5, @"label6.frame = %@",NSStringFromCGRect(label6.frame)); + } + + + //水平线性布局 + { + MyFloatLayout *rootLayout1 = [[MyFloatLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Horz]; + rootLayout1.wrapContentWidth = NO; + //1. 子视图宽度等于自身高度 + UILabel *label1 = [UILabel new]; + label1.myHeight = 100; + label1.widthSize.equalTo(label1.heightSize); + [rootLayout1 addSubview:label1]; + + + //2. 子视图高度等于自身宽度 + UILabel *label2 = [UILabel new]; + label2.wrapContentWidth = YES; + label2.heightSize.equalTo(label2.widthSize); + label2.text = @"hello World"; + [rootLayout1 addSubview:label2]; + + //3. 子视图高度等于兄弟视图高度, 子视图宽度等于兄弟视图宽度 + UILabel *label3 = [UILabel new]; + label3.heightSize.equalTo(label1.heightSize); + label3.widthSize.equalTo(label1.widthSize); + [rootLayout1 addSubview:label3]; + + //4. 子视图高度等于兄弟视图宽度, 子视图宽度等于兄弟视图高度 + UILabel *label4 = [UILabel new]; + label4.widthSize.equalTo(label2.heightSize).add(20); + label4.heightSize.equalTo(label2.widthSize).add(10).multiply(0.5); + [rootLayout1 addSubview:label4]; + + //5. 子视图宽度等于父视图宽度,高度等于宽度 + UILabel *label5 = [UILabel new]; + label5.widthSize.equalTo(rootLayout1.widthSize).add(-20); + label5.heightSize.equalTo(label5.widthSize); + [rootLayout1 addSubview:label5]; + + //6. 子视图高度等于父视图高度,宽度等于高度 + UILabel *label6 = [UILabel new]; + label6.heightSize.equalTo(rootLayout1.heightSize).multiply(0.5); + label6.widthSize.equalTo(label6.heightSize); + [rootLayout1 addSubview:label6]; + + + [rootLayout1 layoutIfNeeded]; + + XCTAssertTrue(label1.frame.size.width == label1.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label1.frame)); + XCTAssertTrue(label2.frame.size.width == label2.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label2.frame)); + XCTAssertTrue(label3.frame.size.width == label1.frame.size.width && + label3.frame.size.height == label1.frame.size.height, @"label3.frame = %@",NSStringFromCGRect(label3.frame)); + XCTAssertTrue(label4.frame.size.width == (label2.frame.size.height + 20) && + label4.frame.size.height == (label2.frame.size.width * 0.5 + 10), @"label4.frame = %@",NSStringFromCGRect(label4.frame)); + + XCTAssertTrue(label5.frame.size.width == (rootLayout1.frame.size.width - 20) && + label5.frame.size.height == label5.frame.size.width, @"label5.frame = %@",NSStringFromCGRect(label5.frame)); + + XCTAssertTrue(label6.frame.size.width == label6.frame.size.height && + label6.frame.size.height == rootLayout1.frame.size.height * 0.5, @"label6.frame = %@",NSStringFromCGRect(label6.frame)); + + } + +} + + -(void)testExample2 { MyFloatLayout *dectorInfoFloatLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m new file mode 100644 index 0000000..9c23460 --- /dev/null +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -0,0 +1,278 @@ +// +// MyFlowLayoutTestCase.m +// MyLayout +// +// Created by apple on 17/4/26. +// Copyright © 2017年 YoungSoft. All rights reserved. +// + +#import "MyLayoutTestCaseBase.h" + +@interface MyFlowLayoutTestCase : MyLayoutTestCaseBase + +@end + +@implementation MyFlowLayoutTestCase + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + +} + + +-(void)testSubviewSizeDependent +{//测试子视图尺寸依赖 + + //垂直线性布局 + { + MyFlowLayout *rootLayout1 = [[MyFlowLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Vert arrangedCount:4]; + rootLayout1.wrapContentHeight = NO; + //1. 子视图宽度等于自身高度 + UILabel *label1 = [UILabel new]; + label1.myHeight = 100; + label1.widthSize.equalTo(label1.heightSize); + [rootLayout1 addSubview:label1]; + + + //2. 子视图高度等于自身宽度 + UILabel *label2 = [UILabel new]; + label2.wrapContentWidth = YES; + label2.heightSize.equalTo(label2.widthSize); + label2.text = @"hello World"; + [rootLayout1 addSubview:label2]; + + //3. 子视图高度等于兄弟视图高度, 子视图宽度等于兄弟视图宽度 + UILabel *label3 = [UILabel new]; + label3.heightSize.equalTo(label1.heightSize); + label3.widthSize.equalTo(label1.widthSize); + [rootLayout1 addSubview:label3]; + + //4. 子视图高度等于兄弟视图宽度, 子视图宽度等于兄弟视图高度 + UILabel *label4 = [UILabel new]; + label4.widthSize.equalTo(label2.heightSize).add(20); + label4.heightSize.equalTo(label2.widthSize).add(10).multiply(0.5); + [rootLayout1 addSubview:label4]; + + //5. 子视图宽度等于父视图宽度,高度等于宽度 + UILabel *label5 = [UILabel new]; + label5.widthSize.equalTo(rootLayout1.widthSize).add(-20); + label5.heightSize.equalTo(label5.widthSize); + [rootLayout1 addSubview:label5]; + + //6. 子视图高度等于父视图高度,宽度等于高度 + UILabel *label6 = [UILabel new]; + label6.heightSize.equalTo(rootLayout1.heightSize).multiply(0.5); + label6.widthSize.equalTo(label6.heightSize); + [rootLayout1 addSubview:label6]; + + [rootLayout1 layoutIfNeeded]; + + XCTAssertTrue(label1.frame.size.width == label1.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label1.frame)); + XCTAssertTrue(label2.frame.size.width == label2.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label2.frame)); + XCTAssertTrue(label3.frame.size.width == label1.frame.size.width && + label3.frame.size.height == label1.frame.size.height, @"label3.frame = %@",NSStringFromCGRect(label3.frame)); + XCTAssertTrue(label4.frame.size.width == (label2.frame.size.height + 20) && + label4.frame.size.height == (label2.frame.size.width * 0.5 + 10), @"label4.frame = %@",NSStringFromCGRect(label4.frame)); + + XCTAssertTrue(label5.frame.size.width == (rootLayout1.frame.size.width - 20) && + label5.frame.size.height == label5.frame.size.width, @"label5.frame = %@",NSStringFromCGRect(label5.frame)); + + XCTAssertTrue(label6.frame.size.width == label6.frame.size.height && + label6.frame.size.height == rootLayout1.frame.size.height * 0.5, @"label6.frame = %@",NSStringFromCGRect(label6.frame)); + } + + + //水平线性布局 + { + MyFlowLayout *rootLayout1 = [[MyFlowLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Horz arrangedCount:4]; + rootLayout1.wrapContentWidth = NO; + //1. 子视图宽度等于自身高度 + UILabel *label1 = [UILabel new]; + label1.myHeight = 100; + label1.widthSize.equalTo(label1.heightSize); + [rootLayout1 addSubview:label1]; + + + //2. 子视图高度等于自身宽度 + UILabel *label2 = [UILabel new]; + label2.wrapContentWidth = YES; + label2.heightSize.equalTo(label2.widthSize); + label2.text = @"hello World"; + [rootLayout1 addSubview:label2]; + + //3. 子视图高度等于兄弟视图高度, 子视图宽度等于兄弟视图宽度 + UILabel *label3 = [UILabel new]; + label3.heightSize.equalTo(label1.heightSize); + label3.widthSize.equalTo(label1.widthSize); + [rootLayout1 addSubview:label3]; + + //4. 子视图高度等于兄弟视图宽度, 子视图宽度等于兄弟视图高度 + UILabel *label4 = [UILabel new]; + label4.widthSize.equalTo(label2.heightSize).add(20); + label4.heightSize.equalTo(label2.widthSize).add(10).multiply(0.5); + [rootLayout1 addSubview:label4]; + + //5. 子视图宽度等于父视图宽度,高度等于宽度 + UILabel *label5 = [UILabel new]; + label5.widthSize.equalTo(rootLayout1.widthSize).add(-20); + label5.heightSize.equalTo(label5.widthSize); + [rootLayout1 addSubview:label5]; + + //6. 子视图高度等于父视图高度,宽度等于高度 + UILabel *label6 = [UILabel new]; + label6.heightSize.equalTo(rootLayout1.heightSize).multiply(0.5); + label6.widthSize.equalTo(label6.heightSize); + [rootLayout1 addSubview:label6]; + + + [rootLayout1 layoutIfNeeded]; + + XCTAssertTrue(label1.frame.size.width == label1.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label1.frame)); + XCTAssertTrue(label2.frame.size.width == label2.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label2.frame)); + XCTAssertTrue(label3.frame.size.width == label1.frame.size.width && + label3.frame.size.height == label1.frame.size.height, @"label3.frame = %@",NSStringFromCGRect(label3.frame)); + XCTAssertTrue(label4.frame.size.width == (label2.frame.size.height + 20) && + label4.frame.size.height == (label2.frame.size.width * 0.5 + 10), @"label4.frame = %@",NSStringFromCGRect(label4.frame)); + + XCTAssertTrue(label5.frame.size.width == (rootLayout1.frame.size.width - 20) && + label5.frame.size.height == label5.frame.size.width, @"label5.frame = %@",NSStringFromCGRect(label5.frame)); + + XCTAssertTrue(label6.frame.size.width == label6.frame.size.height && + label6.frame.size.height == rootLayout1.frame.size.height * 0.5, @"label6.frame = %@",NSStringFromCGRect(label6.frame)); + + } + + //垂直线性布局 + { + MyFlowLayout *rootLayout1 = [[MyFlowLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Vert arrangedCount:0]; + rootLayout1.wrapContentHeight = NO; + //1. 子视图宽度等于自身高度 + UILabel *label1 = [UILabel new]; + label1.myHeight = 100; + label1.widthSize.equalTo(label1.heightSize); + [rootLayout1 addSubview:label1]; + + + //2. 子视图高度等于自身宽度 + UILabel *label2 = [UILabel new]; + label2.wrapContentWidth = YES; + label2.heightSize.equalTo(label2.widthSize); + label2.text = @"hello World"; + [rootLayout1 addSubview:label2]; + + //3. 子视图高度等于兄弟视图高度, 子视图宽度等于兄弟视图宽度 + UILabel *label3 = [UILabel new]; + label3.heightSize.equalTo(label1.heightSize); + label3.widthSize.equalTo(label1.widthSize); + [rootLayout1 addSubview:label3]; + + //4. 子视图高度等于兄弟视图宽度, 子视图宽度等于兄弟视图高度 + UILabel *label4 = [UILabel new]; + label4.widthSize.equalTo(label2.heightSize).add(20); + label4.heightSize.equalTo(label2.widthSize).add(10).multiply(0.5); + [rootLayout1 addSubview:label4]; + + //5. 子视图宽度等于父视图宽度,高度等于宽度 + UILabel *label5 = [UILabel new]; + label5.widthSize.equalTo(rootLayout1.widthSize).add(-20); + label5.heightSize.equalTo(label5.widthSize); + [rootLayout1 addSubview:label5]; + + //6. 子视图高度等于父视图高度,宽度等于高度 + UILabel *label6 = [UILabel new]; + label6.heightSize.equalTo(rootLayout1.heightSize).multiply(0.5); + label6.widthSize.equalTo(label6.heightSize); + [rootLayout1 addSubview:label6]; + + [rootLayout1 layoutIfNeeded]; + + XCTAssertTrue(label1.frame.size.width == label1.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label1.frame)); + XCTAssertTrue(label2.frame.size.width == label2.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label2.frame)); + XCTAssertTrue(label3.frame.size.width == label1.frame.size.width && + label3.frame.size.height == label1.frame.size.height, @"label3.frame = %@",NSStringFromCGRect(label3.frame)); + XCTAssertTrue(label4.frame.size.width == (label2.frame.size.height + 20) && + label4.frame.size.height == (label2.frame.size.width * 0.5 + 10), @"label4.frame = %@",NSStringFromCGRect(label4.frame)); + + XCTAssertTrue(label5.frame.size.width == (rootLayout1.frame.size.width - 20) && + label5.frame.size.height == label5.frame.size.width, @"label5.frame = %@",NSStringFromCGRect(label5.frame)); + + XCTAssertTrue(label6.frame.size.width == label6.frame.size.height && + label6.frame.size.height == rootLayout1.frame.size.height * 0.5, @"label6.frame = %@",NSStringFromCGRect(label6.frame)); + } + + + //水平线性布局 + { + MyFlowLayout *rootLayout1 = [[MyFlowLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Horz arrangedCount:0]; + rootLayout1.wrapContentWidth = NO; + //1. 子视图宽度等于自身高度 + UILabel *label1 = [UILabel new]; + label1.myHeight = 100; + label1.widthSize.equalTo(label1.heightSize); + [rootLayout1 addSubview:label1]; + + + //2. 子视图高度等于自身宽度 + UILabel *label2 = [UILabel new]; + label2.wrapContentWidth = YES; + label2.heightSize.equalTo(label2.widthSize); + label2.text = @"hello World"; + [rootLayout1 addSubview:label2]; + + //3. 子视图高度等于兄弟视图高度, 子视图宽度等于兄弟视图宽度 + UILabel *label3 = [UILabel new]; + label3.heightSize.equalTo(label1.heightSize); + label3.widthSize.equalTo(label1.widthSize); + [rootLayout1 addSubview:label3]; + + //4. 子视图高度等于兄弟视图宽度, 子视图宽度等于兄弟视图高度 + UILabel *label4 = [UILabel new]; + label4.widthSize.equalTo(label2.heightSize).add(20); + label4.heightSize.equalTo(label2.widthSize).add(10).multiply(0.5); + [rootLayout1 addSubview:label4]; + + //5. 子视图宽度等于父视图宽度,高度等于宽度 + UILabel *label5 = [UILabel new]; + label5.widthSize.equalTo(rootLayout1.widthSize).add(-20); + label5.heightSize.equalTo(label5.widthSize); + [rootLayout1 addSubview:label5]; + + //6. 子视图高度等于父视图高度,宽度等于高度 + UILabel *label6 = [UILabel new]; + label6.heightSize.equalTo(rootLayout1.heightSize).multiply(0.5); + label6.widthSize.equalTo(label6.heightSize); + [rootLayout1 addSubview:label6]; + + + [rootLayout1 layoutIfNeeded]; + + XCTAssertTrue(label1.frame.size.width == label1.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label1.frame)); + XCTAssertTrue(label2.frame.size.width == label2.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label2.frame)); + XCTAssertTrue(label3.frame.size.width == label1.frame.size.width && + label3.frame.size.height == label1.frame.size.height, @"label3.frame = %@",NSStringFromCGRect(label3.frame)); + XCTAssertTrue(label4.frame.size.width == (label2.frame.size.height + 20) && + label4.frame.size.height == (label2.frame.size.width * 0.5 + 10), @"label4.frame = %@",NSStringFromCGRect(label4.frame)); + + XCTAssertTrue(label5.frame.size.width == (rootLayout1.frame.size.width - 20) && + label5.frame.size.height == label5.frame.size.width, @"label5.frame = %@",NSStringFromCGRect(label5.frame)); + + XCTAssertTrue(label6.frame.size.width == label6.frame.size.height && + label6.frame.size.height == rootLayout1.frame.size.height * 0.5, @"label6.frame = %@",NSStringFromCGRect(label6.frame)); + + } + +} + + +@end diff --git a/MyLayoutTests/MyLinearLayoutTestCase.m b/MyLayoutTests/MyLinearLayoutTestCase.m index d634ffa..8caa4c8 100644 --- a/MyLayoutTests/MyLinearLayoutTestCase.m +++ b/MyLayoutTests/MyLinearLayoutTestCase.m @@ -56,6 +56,130 @@ - (void)testTable1 { } +-(void)testSubviewSizeDependent +{//测试子视图尺寸依赖 + + //垂直线性布局 + { + MyLinearLayout *rootLayout1 = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Vert]; + rootLayout1.wrapContentHeight = NO; + //1. 子视图宽度等于自身高度 + UILabel *label1 = [UILabel new]; + label1.myHeight = 100; + label1.widthSize.equalTo(label1.heightSize); + [rootLayout1 addSubview:label1]; + + + //2. 子视图高度等于自身宽度 + UILabel *label2 = [UILabel new]; + label2.wrapContentWidth = YES; + label2.heightSize.equalTo(label2.widthSize); + label2.text = @"hello World"; + [rootLayout1 addSubview:label2]; + + //3. 子视图高度等于兄弟视图高度, 子视图宽度等于兄弟视图宽度 + UILabel *label3 = [UILabel new]; + label3.heightSize.equalTo(label1.heightSize); + label3.widthSize.equalTo(label1.widthSize); + [rootLayout1 addSubview:label3]; + + //4. 子视图高度等于兄弟视图宽度, 子视图宽度等于兄弟视图高度 + UILabel *label4 = [UILabel new]; + label4.widthSize.equalTo(label2.heightSize).add(20); + label4.heightSize.equalTo(label2.widthSize).add(10).multiply(0.5); + [rootLayout1 addSubview:label4]; + + //5. 子视图宽度等于父视图宽度,高度等于宽度 + UILabel *label5 = [UILabel new]; + label5.widthSize.equalTo(rootLayout1.widthSize).add(-20); + label5.heightSize.equalTo(label5.widthSize); + [rootLayout1 addSubview:label5]; + + //6. 子视图高度等于父视图高度,宽度等于高度 + UILabel *label6 = [UILabel new]; + label6.heightSize.equalTo(rootLayout1.heightSize).multiply(0.5); + label6.widthSize.equalTo(label6.heightSize); + [rootLayout1 addSubview:label6]; + + [rootLayout1 layoutIfNeeded]; + + XCTAssertTrue(label1.frame.size.width == label1.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label1.frame)); + XCTAssertTrue(label2.frame.size.width == label2.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label2.frame)); + XCTAssertTrue(label3.frame.size.width == label1.frame.size.width && + label3.frame.size.height == label1.frame.size.height, @"label3.frame = %@",NSStringFromCGRect(label3.frame)); + XCTAssertTrue(label4.frame.size.width == (label2.frame.size.height + 20) && + label4.frame.size.height == (label2.frame.size.width * 0.5 + 10), @"label4.frame = %@",NSStringFromCGRect(label4.frame)); + + XCTAssertTrue(label5.frame.size.width == (rootLayout1.frame.size.width - 20) && + label5.frame.size.height == label5.frame.size.width, @"label5.frame = %@",NSStringFromCGRect(label5.frame)); + + XCTAssertTrue(label6.frame.size.width == label6.frame.size.height && + label6.frame.size.height == rootLayout1.frame.size.height * 0.5, @"label6.frame = %@",NSStringFromCGRect(label6.frame)); + } + + + //水平线性布局 + { + MyLinearLayout *rootLayout1 = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Horz]; + rootLayout1.wrapContentWidth = NO; + //1. 子视图宽度等于自身高度 + UILabel *label1 = [UILabel new]; + label1.myHeight = 100; + label1.widthSize.equalTo(label1.heightSize); + [rootLayout1 addSubview:label1]; + + + //2. 子视图高度等于自身宽度 + UILabel *label2 = [UILabel new]; + label2.wrapContentWidth = YES; + label2.heightSize.equalTo(label2.widthSize); + label2.text = @"hello World"; + [rootLayout1 addSubview:label2]; + + //3. 子视图高度等于兄弟视图高度, 子视图宽度等于兄弟视图宽度 + UILabel *label3 = [UILabel new]; + label3.heightSize.equalTo(label1.heightSize); + label3.widthSize.equalTo(label1.widthSize); + [rootLayout1 addSubview:label3]; + + //4. 子视图高度等于兄弟视图宽度, 子视图宽度等于兄弟视图高度 + UILabel *label4 = [UILabel new]; + label4.widthSize.equalTo(label2.heightSize).add(20); + label4.heightSize.equalTo(label2.widthSize).add(10).multiply(0.5); + [rootLayout1 addSubview:label4]; + + //5. 子视图宽度等于父视图宽度,高度等于宽度 + UILabel *label5 = [UILabel new]; + label5.widthSize.equalTo(rootLayout1.widthSize).add(-20); + label5.heightSize.equalTo(label5.widthSize); + [rootLayout1 addSubview:label5]; + + //6. 子视图高度等于父视图高度,宽度等于高度 + UILabel *label6 = [UILabel new]; + label6.heightSize.equalTo(rootLayout1.heightSize).multiply(0.5); + label6.widthSize.equalTo(label6.heightSize); + [rootLayout1 addSubview:label6]; + + + [rootLayout1 layoutIfNeeded]; + + XCTAssertTrue(label1.frame.size.width == label1.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label1.frame)); + XCTAssertTrue(label2.frame.size.width == label2.frame.size.height, @"label1.frame = %@",NSStringFromCGRect(label2.frame)); + XCTAssertTrue(label3.frame.size.width == label1.frame.size.width && + label3.frame.size.height == label1.frame.size.height, @"label3.frame = %@",NSStringFromCGRect(label3.frame)); + XCTAssertTrue(label4.frame.size.width == (label2.frame.size.height + 20) && + label4.frame.size.height == (label2.frame.size.width * 0.5 + 10), @"label4.frame = %@",NSStringFromCGRect(label4.frame)); + + XCTAssertTrue(label5.frame.size.width == (rootLayout1.frame.size.width - 20) && + label5.frame.size.height == label5.frame.size.width, @"label5.frame = %@",NSStringFromCGRect(label5.frame)); + + XCTAssertTrue(label6.frame.size.width == label6.frame.size.height && + label6.frame.size.height == rootLayout1.frame.size.height * 0.5, @"label6.frame = %@",NSStringFromCGRect(label6.frame)); + + } + +} + -(void)testWeight {//测试均分 From 3c74b2525c223eef71d61d6e82826254f8aef154 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Sun, 23 Jun 2019 09:03:54 +0800 Subject: [PATCH 030/115] =?UTF-8?q?1.=E9=87=8D=E6=9E=84=E7=BA=BF=E6=80=A7?= =?UTF-8?q?=E5=B8=83=E5=B1=80,=202.=E4=BF=AE=E5=A4=8D1.7.0=E7=9A=84BUG?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.h | 36 ++++---- MyLayout/Lib/MyBaseLayout.m | 88 +++++++++++++----- MyLayout/Lib/MyFloatLayout.m | 12 +-- MyLayout/Lib/MyFlowLayout.h | 2 +- MyLayout/Lib/MyFlowLayout.m | 4 +- MyLayout/Lib/MyLayoutSizeClass.h | 4 +- MyLayout/Lib/MyLayoutSizeClass.m | 10 +- MyLayout/Lib/MyLinearLayout.m | 33 +++++-- MyLayout/Lib/MyMaker.m | 4 +- MyLayout/Lib/MyTableLayout.h | 2 +- MyLayoutDemo/AllTest10HeaderView.m | 4 +- MyLayoutDemo/AllTest1TableViewCell.m | 6 +- .../AllTest1TableViewCellForAutoLayout.m | 6 +- MyLayoutDemo/AllTest1ViewController.m | 6 +- MyLayoutDemo/AllTest3ViewController.m | 8 +- MyLayoutDemo/AllTest5ViewController.m | 4 +- MyLayoutDemo/FLLTest4ViewController.m | 2 +- MyLayoutDemo/FOLTest7ViewController.m | 26 +++--- MyLayoutDemo/LLTest1ViewController.m | 4 +- MyLayoutDemo/LLTest2ViewController.m | 10 +- MyLayoutDemo/LLTest3ViewController.m | 6 +- MyLayoutDemo/LLTest4ViewController.m | 76 ++++++++------- MyLayoutDemo/RLTest2ViewController.m | 6 +- MyLayoutTests/MyLinearLayoutTestCase.m | 47 ++++++++++ MyLayoutTests/MyRelativeLayoutTestCase.m | 92 +++++++++++++++++++ 25 files changed, 353 insertions(+), 145 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index aead304..1978887 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -13,7 +13,7 @@ /* 几种视图类型的定义: -1.布局视图: 就是从MyBaseLayout派生而出的视图,目前MyLayout中一共有:线性布局、框架布局、相对布局、表格布局、流式布局、浮动布局、路径布局7种布局。 布局视图也是一个视图。 +1.布局视图: 就是从MyBaseLayout派生而出的视图,目前MyLayout中一共有:线性布局、框架布局、相对布局、表格布局、流式布局、浮动布局、路径布局、栅格布局8种布局。 布局视图也是一个视图。 2.非布局视图: 除上面说的7种布局视图外的所有视图和控件。 3.布局父视图: 如果某个视图的父视图是一个布局视图,那么这个父视图就是布局父视图。 4.非布局父视图:如果某个视图的父视图不是一个布局视图,那么这个父视图就是非布局父视图。 @@ -39,7 +39,7 @@ |--------------------+------------------+----------------------+---------------+-----------+--------------------+-------+-------| |Vert MyTableLayout | T,B,CY | L,R | L,R,T,B,CY | - | - | - |T,B | |--------------------+------------------+----------------------+---------------+-----------+--------------------+-------+-------| - |Horz MyTableLayout | L,R,CX | T,B | L,R,CX,T,B | - | - | L,R | - | + |Horz MyTableLayout | L,R,CX | T,B | L,R,CX,T,B | - | - | L,R | - | |--------------------+------------------+----------------------+---------------+-----------+--------------------+-------+-------| |MyFrameLayout | ALL | - | L,R,T,B,CX,CY | - | - | - | - | |--------------------+------------------+----------------------+---------------+-----------+--------------------+-------+-------| @@ -294,11 +294,11 @@ 定义A为操作的视图本身,B为A的兄弟视图,P为A的父视图。 +-------------+----------+--------------+---------------+------------+--------------+---------------+--------------+----------------------+ - | 对象 \ 值 | NSNumber |A.widthSize |A.heightSize |B.widthSize | B.heightSize | P.widthSize |P.heightSize |NSArray| + | 对象 \ 值 | NSNumber |A.widthSize |A.heightSize |B.widthSize | B.heightSize | P.widthSize |P.heightSize |NSArray| +-------------+----------+--------------+---------------+------------+--------------+---------------+--------------+----------------------+ - |A.widthSize | ALL |ALL |FR/R/FL-H/FO |FR/R/FO/P | R |L/FR/R/FL/FO/P | R |R | + |A.widthSize | ALL |ALL |ALL |ALL | ALL |ALL |ALL |R | +-------------+----------+--------------+---------------+------------+--------------+---------------+--------------+----------------------+ - |A.heightSize | ALL |FR/R/FL-V/FO/L|ALL |R |FR/R/FO/P |R |L/FR/R/FL/FO/P|R | + |A.heightSize | ALL |ALL |ALL |ALL |ALL |ALL |ALL |R | +-------------+----------+--------------+---------------+------------+--------------+---------------+--------------+----------------------+ 上表中所有的布局尺寸的值都支持设置为数值,而且所有布局下的子视图的宽度和高度尺寸都可以设置为等于自身的宽度和高度尺寸,布局库这里做了特殊处理,是不会造成循环引用的。比如: @@ -548,7 +548,8 @@ 建议您用这个属性设置视图的隐藏的显示而不用系统默认的hidden来进行设置。 */ -@property(nonatomic, assign) MyVisibility myVisibility; +@property(nonatomic, assign) MyVisibility visibility; +@property(nonatomic, assign) MyVisibility myVisibility MYDEPRECATED("use visibility instead"); /** @@ -564,12 +565,17 @@ 5. 在水平流式布局和水平浮动布局中用来设置一列内的左、中、右、水平拉伸对齐。(如果流式父布局视图设置了arrangedGravity,子视图时设置了这个属性则这个属性优先级最高) */ -@property(nonatomic, assign) MyGravity myAlignment; +@property(nonatomic, assign) MyGravity alignment; +@property(nonatomic, assign) MyGravity myAlignment MYDEPRECATED("use alignment instead"); /** 视图在父布局视图中布局完成后也就是视图的frame更新完成后执行的block,执行完block后会被重置为nil。通过在viewLayoutCompleteBlock中我们可以得到这个视图真实的frame值,当然您也可以在里面进行其他业务逻辑的操作和属性的获取和更新。block方法中layout参数就是父布局视图,而v就是视图本身,block中这两个参数目的是为了防止循环引用的问题。 + + 不再建议使用这个block进行获取子视图最终frame值,因为这个block只会执行一次,所以得到的frame值可能不准确。 + 建议通过KVO来观察布局视图的isLayouting属性来获取布局完成后子视图的frame值。 + */ @property(nonatomic,copy) void (^viewLayoutCompleteBlock)(MyBaseLayout* layout, UIView *v); @@ -632,9 +638,11 @@ #endif /** - 只是适配UI-RTL ,不是显示字RTL + 直接更新window下所有布局视图的RTL特性。 */ -+ (void)myUpArabicUI:(BOOL)isArabicUI inWindow:(UIWindow *)window; ++ (void)updateRTL:(BOOL)isRTL inWindow:(UIWindow *)window; ++ (void)myUpArabicUI:(BOOL)isArabicUI inWindow:(UIWindow *)window MYDEPRECATED("use updateRTL:inWindow: instead"); + /* 布局视图里面的padding属性用来设置布局视图的内边距。内边距是指布局视图里面的子视图离自己距离。外边距则是视图与父视图之间的距离。 @@ -854,7 +862,7 @@ /** - *判断当前是否正在布局中,如果正在布局中则返回YES,否则返回NO + *判断当前是否正在布局中,如果正在布局中则返回YES,否则返回NO。 我们可以通过KVO的方式来监听这个属性的变化,以便获取布局完成后的真实frame值。 */ @property(nonatomic,assign,readonly) BOOL isMyLayouting; @@ -1013,13 +1021,5 @@ @end -/** - 只是适配UI-RTL ,不是显示字RTL - */ - -@interface UIWindow (MyBaseUpUIRTL) --(void)myUpBasisUIViewMyLayout:(BOOL)isRTL; - -@end diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index bd772f7..76b2198 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -19,6 +19,17 @@ void* _myObserverContextC = (void*)20175283; +/** + 窗口对RTL的支持。 + */ + +@interface UIWindow (MyLayoutExt) + +-(void)myUpdateRTL:(BOOL)isRTL; + +@end + + @implementation UIView(MyLayoutExt) -(MyLayoutPos*)topPos @@ -400,18 +411,18 @@ -(void)setNoLayout:(BOOL)noLayout } --(MyVisibility)myVisibility +-(MyVisibility)visibility { - return self.myCurrentSizeClass.myVisibility; + return self.myCurrentSizeClass.visibility; } --(void)setMyVisibility:(MyVisibility)myVisibility +-(void)setVisibility:(MyVisibility)visibility { UIView *sc = self.myCurrentSizeClass; - if (sc.myVisibility != myVisibility) + if (sc.visibility != visibility) { - sc.myVisibility = myVisibility; - if (myVisibility == MyVisibility_Visible) + sc.visibility = visibility; + if (visibility == MyVisibility_Visible) self.hidden = NO; else self.hidden = YES; @@ -419,24 +430,42 @@ -(void)setMyVisibility:(MyVisibility)myVisibility if (self.superview != nil) [ self.superview setNeedsLayout]; } +} +-(MyVisibility)myVisibility +{ + return self.visibility; } --(MyGravity)myAlignment +-(void)setMyVisibility:(MyVisibility)myVisibility { - return self.myCurrentSizeClass.myAlignment; + self.visibility = myVisibility; } --(void)setMyAlignment:(MyGravity)myAlignment +-(MyGravity)alignment +{ + return self.myCurrentSizeClass.alignment; +} + +-(void)setAlignment:(MyGravity)alignment { UIView *sc = self.myCurrentSizeClass; - if (sc.myAlignment != myAlignment) + if (sc.alignment != alignment) { - sc.myAlignment = myAlignment; + sc.alignment = alignment; if (self.superview != nil) [ self.superview setNeedsLayout]; } +} + +-(void)setMyAlignment:(MyGravity)myAlignment +{ + self.alignment = myAlignment; +} +-(MyGravity)myAlignment +{ + return self.alignment; } @@ -742,6 +771,7 @@ -(CGFloat)myEstimatedHeight + @implementation MyBaseLayout { MyLayoutTouchEventDelegate *_touchEventDelegate; @@ -777,9 +807,13 @@ +(void)setIsRTL:(BOOL)isRTL [MyViewSizeClass setIsRTL:isRTL]; } ++ (void)updateRTL:(BOOL)isRTL inWindow:(UIWindow *)window +{ + [window myUpdateRTL:isRTL]; +} + (void)myUpArabicUI:(BOOL)isArabicUI inWindow:(UIWindow *)window { - [window myUpBasisUIViewMyLayout:isArabicUI]; + [self updateRTL:isArabicUI inWindow:window]; } @@ -2066,7 +2100,7 @@ -(void)layoutSubviews } - if (sbvsc.myVisibility == MyVisibility_Gone && !sbv.isHidden) + if (sbvsc.visibility == MyVisibility_Gone && !sbv.isHidden) { sbv.bounds = CGRectMake(sbvOldBounds.origin.x, sbvOldBounds.origin.y, 0, 0); } @@ -2327,7 +2361,7 @@ -(BOOL)myIsRelativePos:(CGFloat)margin -(MyGravity)myGetSubviewVertGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc vertGravity:(MyGravity)vertGravity { - MyGravity sbvVertAligement = sbvsc.myAlignment & MyGravity_Horz_Mask; + MyGravity sbvVertAligement = sbvsc.alignment & MyGravity_Horz_Mask; MyGravity sbvVertGravity = MyGravity_Vert_Top; if (vertGravity != MyGravity_None) @@ -2442,7 +2476,7 @@ -(CGFloat)myCalcVertGravity:(MyGravity)vertGravity -(MyGravity)myGetSubviewHorzGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc horzGravity:(MyGravity)horzGravity { - MyGravity sbvHorzAligement = [self myConvertLeftRightGravityToLeadingTrailing:sbvsc.myAlignment & MyGravity_Vert_Mask]; + MyGravity sbvHorzAligement = [self myConvertLeftRightGravityToLeadingTrailing:sbvsc.alignment & MyGravity_Vert_Mask]; MyGravity sbvHorzGravity = MyGravity_Horz_Leading; if (horzGravity != MyGravity_None) @@ -2545,7 +2579,7 @@ -(CGFloat)myCalcHorzGravity:(MyGravity)horzGravity -(void)myCalcSizeOfWrapContentSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc sbvmyFrame:(MyFrame*)sbvmyFrame { - if (sbvsc.myVisibility == MyVisibility_Gone) + if (sbvsc.visibility == MyVisibility_Gone) { sbvmyFrame.width = 0; sbvmyFrame.height = 0; @@ -3100,11 +3134,11 @@ -(BOOL)myIsNoLayoutSubview:(UIView*)sbv if (sbv.isHidden) { - return sbvsc.myVisibility != MyVisibility_Invisible; + return sbvsc.visibility != MyVisibility_Invisible; } else { - return sbvsc.myVisibility == MyVisibility_Gone; + return sbvsc.visibility == MyVisibility_Gone; } } @@ -3755,18 +3789,24 @@ -(NSString*)description return [NSString stringWithFormat:@"leading:%g, top:%g, width:%g, height:%g, trailing:%g, bottom:%g",_leading,_top,_width,_height,_trailing,_bottom]; } @end -@implementation UIWindow (MyBaseUpUIRTL) --(void)myUpBasisUIViewMyLayout:(BOOL)isRTL +@implementation UIWindow (MyLayoutExt) + + +-(void)myUpdateRTL:(BOOL)isRTL { - [MyBaseLayout setIsRTL:isRTL]; - [self mySetBasisUISubviewsNeedLayoutRTL:self]; + BOOL oldRTL = [MyBaseLayout isRTL]; + if (oldRTL != isRTL) + { + [MyBaseLayout setIsRTL:isRTL]; + [self mySetNeedLayoutAllSubviews:self]; + } } --(void)mySetBasisUISubviewsNeedLayoutRTL:(UIView *)v +-(void)mySetNeedLayoutAllSubviews:(UIView *)v { NSArray *sbs = v.subviews; for (UIView *sv in sbs) @@ -3775,7 +3815,7 @@ -(void)mySetBasisUISubviewsNeedLayoutRTL:(UIView *)v { [sv setNeedsLayout]; } - [self mySetBasisUISubviewsNeedLayoutRTL:sv]; + [self mySetNeedLayoutAllSubviews:sv]; } } @end diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 1f109e7..d3ea365 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -537,7 +537,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( CGRect rect = sbvmyFrame.frame; //只要有一个子视图设置了对齐,就会做对齐处理,否则不会,这里这样做是为了对后面的对齐计算做优化。 - sbvHasAlignment |= ((sbvsc.myAlignment & MyGravity_Horz_Mask) > MyGravity_Vert_Top); + sbvHasAlignment |= ((sbvsc.alignment & MyGravity_Horz_Mask) > MyGravity_Vert_Top); //如果是RTL的场景则默认是右对齐的。 if (sbvsc.isReverseFloat) @@ -911,7 +911,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( if (sbvmyFrame.height > lineMaxHeight) lineMaxHeight = sbvmyFrame.height; - lineHasAlignment |= ((sbvsc.myAlignment & MyGravity_Horz_Mask) > MyGravity_Vert_Top); + lineHasAlignment |= ((sbvsc.alignment & MyGravity_Horz_Mask) > MyGravity_Vert_Top); } //设置行内的对齐 @@ -922,7 +922,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - switch (sbvsc.myAlignment & MyGravity_Horz_Mask) { + switch (sbvsc.alignment & MyGravity_Horz_Mask) { case MyGravity_Vert_Center: sbvmyFrame.top += (lineMaxHeight - sbvmyFrame.height) / 2.0; break; @@ -1036,7 +1036,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( CGRect rect = sbvmyFrame.frame; //只要有一个子视图设置了对齐,就会做对齐处理,否则不会,这里这样做是为了对后面的对齐计算做优化。 - sbvHasAlignment |= ((sbvsc.myAlignment & MyGravity_Vert_Mask) > MyGravity_Horz_Left); + sbvHasAlignment |= ((sbvsc.alignment & MyGravity_Vert_Mask) > MyGravity_Horz_Left); if (sbvsc.reverseFloat) { @@ -1384,7 +1384,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( if (sbvmyFrame.width > lineMaxWidth) lineMaxWidth = sbvmyFrame.width; - lineHasAlignment |= ((sbvsc.myAlignment & MyGravity_Vert_Mask) > MyGravity_Horz_Left); + lineHasAlignment |= ((sbvsc.alignment & MyGravity_Vert_Mask) > MyGravity_Horz_Left); } //设置行内的对齐 @@ -1395,7 +1395,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - switch ([self myConvertLeftRightGravityToLeadingTrailing:sbvsc.myAlignment & MyGravity_Vert_Mask]) { + switch ([self myConvertLeftRightGravityToLeadingTrailing:sbvsc.alignment & MyGravity_Vert_Mask]) { case MyGravity_Horz_Center: sbvmyFrame.leading += (lineMaxWidth - sbvmyFrame.width) / 2.0; break; diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index c0397c7..0dda772 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -207,7 +207,7 @@ MyGravity_Horz_Fill 两端对齐 MyGravity_Horz_Between 数量约束垂直流式布局有效,子视图会紧凑进行排列,当设置为这个属性值时,子视图的x轴的位置总是从对应行的上一列的结尾开始,而不是上一列的最宽位置开始。 @endcode - @note 如果您想单独设置某个子视图在排内的对齐方式则请使用子视图的扩展属性myAlignment。 + @note 如果您想单独设置某个子视图在排内的对齐方式则请使用子视图的扩展属性alignment。 */ @property(nonatomic,assign) MyGravity arrangedGravity; diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 68dccb5..1a6c19e 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -365,7 +365,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo } } - MyGravity sbvVertAlignment = sbvsc.myAlignment & MyGravity_Horz_Mask; + MyGravity sbvVertAlignment = sbvsc.alignment & MyGravity_Horz_Mask; if (sbvVertAlignment == MyGravity_None) sbvVertAlignment = vertAlignment; if (vertAlignment == MyGravity_Vert_Between) @@ -533,7 +533,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa } - MyGravity sbvHorzAlignment = [self myConvertLeftRightGravityToLeadingTrailing:sbvsc.myAlignment & MyGravity_Vert_Mask]; + MyGravity sbvHorzAlignment = [self myConvertLeftRightGravityToLeadingTrailing:sbvsc.alignment & MyGravity_Vert_Mask]; if (sbvHorzAlignment == MyGravity_None) sbvHorzAlignment = horzAlignment; if (horzAlignment == MyGravity_Horz_Between) diff --git a/MyLayout/Lib/MyLayoutSizeClass.h b/MyLayout/Lib/MyLayoutSizeClass.h index 42167e6..84e294f 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.h +++ b/MyLayout/Lib/MyLayoutSizeClass.h @@ -79,8 +79,8 @@ @property(nonatomic, assign) BOOL useFrame; @property(nonatomic, assign) BOOL noLayout; -@property(nonatomic, assign) MyVisibility myVisibility; -@property(nonatomic, assign) MyGravity myAlignment; +@property(nonatomic, assign) MyVisibility visibility; +@property(nonatomic, assign) MyGravity alignment; @property(nonatomic, copy) void (^viewLayoutCompleteBlock)(MyBaseLayout* layout, UIView *v); diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index 2ee5b38..0acc726 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -489,7 +489,7 @@ -(void)setWrapContentSize:(BOOL)wrapContentSize -(NSString*)debugDescription { - NSString*dbgDesc = [NSString stringWithFormat:@"\nView:\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\nweight=%f\nuseFrame=%@\nnoLayout=%@\nmyVisibility=%c\nmyAlignment=%hu\nwrapContentWidth=%@\nwrapContentHeight=%@\nreverseFloat=%@\nclearFloat=%@", + NSString*dbgDesc = [NSString stringWithFormat:@"\nView:\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\nweight=%f\nuseFrame=%@\nnoLayout=%@\nvisibility=%c\nalignment=%hu\nwrapContentWidth=%@\nwrapContentHeight=%@\nreverseFloat=%@\nclearFloat=%@", self.topPosInner, self.leadingPosInner, self.bottomPosInner, @@ -501,8 +501,8 @@ -(NSString*)debugDescription self.weight, self.useFrame ? @"YES":@"NO", self.noLayout? @"YES":@"NO", - self.myVisibility, - self.myAlignment, + self.visibility, + self.alignment, self.wrapContentWidth ? @"YES":@"NO", self.wrapContentHeight ? @"YES":@"NO", self.reverseFloat ? @"YES":@"NO", @@ -535,8 +535,8 @@ - (id)copyWithZone:(NSZone *)zone lsc->_wrapHeight = self.wrapHeight; lsc.useFrame = self.useFrame; lsc.noLayout = self.noLayout; - lsc.myVisibility = self.myVisibility; - lsc.myAlignment = self.myAlignment; + lsc.visibility = self.visibility; + lsc.alignment = self.alignment; lsc.weight = self.weight; lsc.reverseFloat = self.isReverseFloat; lsc.clearFloat = self.clearFloat; diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 29fd451..c106ed5 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -414,8 +414,14 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea sbvsc:sbvsc lsc:lsc]; - if (tempSelfWidth > maxSelfWidth) + + + if ((tempSelfWidth > maxSelfWidth) && + (lsc.widthSizeInner == nil || (sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) && + (sbvsc.leadingPosInner.posVal == nil || sbvsc.trailingPosInner.posVal == nil)) + { maxSelfWidth = tempSelfWidth; + } if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) {//特殊处理高度等于宽度的情况 @@ -607,7 +613,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } //如果有浮动尺寸或者有压缩模式 - if (totalWeight != 0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingHeight, 0)) || vertGravity != MyGravity_None) + if (totalWeight != 0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingHeight, 0)) || vertGravity != MyGravity_None || lsc.wrapContentWidth) { maxSelfWidth = 0; CGFloat between = 0; //间距扩充 @@ -718,8 +724,12 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea sbvsc:sbvsc lsc:lsc]; - if (tempSelfWidth > maxSelfWidth) + if ((tempSelfWidth > maxSelfWidth) && + (lsc.widthSizeInner == nil || (sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) && + (sbvsc.leadingPosInner.posVal == nil || sbvsc.trailingPosInner.posVal == nil)) + { maxSelfWidth = tempSelfWidth; + } pos += rect.size.height; @@ -845,8 +855,14 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea baselinePos:baselinePos sbvsc:sbvsc lsc:lsc]; - if (tempSelfHeight > maxSelfHeight) + + if ((tempSelfHeight > maxSelfHeight) && + (lsc.heightSizeInner == nil || (sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) && + (sbvsc.topPosInner.posVal == nil || sbvsc.bottomPosInner.posVal == nil)) + { maxSelfHeight = tempSelfHeight; + } + //如果垂直方向的对齐方式是基线对齐,那么就以第一个具有基线的视图作为标准位置。 if (vertGravity == MyGravity_Vert_Baseline && baselinePos == CGFLOAT_MAX && self.baselineBaseView == sbv) @@ -1094,7 +1110,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } //如果有浮动尺寸或者有压缩模式 - if (totalWeight != 0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingWidth, 0)) || horzGravity != MyGravity_None) + if (totalWeight != 0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingWidth, 0)) || horzGravity != MyGravity_None || lsc.wrapContentHeight) { maxSelfHeight = 0; CGFloat between = 0; //间距扩充 @@ -1206,8 +1222,13 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea baselinePos:baselinePos sbvsc:sbvsc lsc:lsc]; - if (tempSelfHeight > maxSelfHeight) + + if ((tempSelfHeight > maxSelfHeight) && + (lsc.heightSizeInner == nil || (sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) && + (sbvsc.topPosInner.posVal == nil || sbvsc.bottomPosInner.posVal == nil)) + { maxSelfHeight = tempSelfHeight; + } pos += rect.size.width; diff --git a/MyLayout/Lib/MyMaker.m b/MyLayout/Lib/MyMaker.m index 5d86b51..1914bcd 100644 --- a/MyLayout/Lib/MyMaker.m +++ b/MyLayout/Lib/MyMaker.m @@ -237,12 +237,12 @@ -(MyMaker*)baseline -(MyMaker*)visibility { - return [self addMethod:@"myVisibility"]; + return [self addMethod:@"visibility"]; } -(MyMaker*)alignment { - return [self addMethod:@"myAlignment"]; + return [self addMethod:@"alignment"]; } diff --git a/MyLayout/Lib/MyTableLayout.h b/MyLayout/Lib/MyTableLayout.h index 38b0f44..6ddfa77 100644 --- a/MyLayout/Lib/MyTableLayout.h +++ b/MyLayout/Lib/MyTableLayout.h @@ -12,7 +12,7 @@ /** 表格布局行列索引描述扩展对象。 */ -@interface NSIndexPath(MyTableLayoutEx) +@interface NSIndexPath(MyTableLayoutExt) /** diff --git a/MyLayoutDemo/AllTest10HeaderView.m b/MyLayoutDemo/AllTest10HeaderView.m index c2d88a3..b029559 100644 --- a/MyLayoutDemo/AllTest10HeaderView.m +++ b/MyLayoutDemo/AllTest10HeaderView.m @@ -180,8 +180,8 @@ - (void)setModel:(AllTest10Model *)model { [_browLabel sizeToFit]; NSString *giveLikeText = model.giveLikeNames.count > 0 ? [NSString stringWithFormat:@"%@等点了👍",[model.giveLikeNames componentsJoinedByString:@"、"]] : @""; - _giveLikeLayout.myVisibility = model.giveLikeNames.count > 0 ? MyVisibility_Visible : MyVisibility_Gone; - _nineFlowLayout.myVisibility = model.commentsImageUrls.count > 0 ? MyVisibility_Visible : MyVisibility_Gone; + _giveLikeLayout.visibility = model.giveLikeNames.count > 0 ? MyVisibility_Visible : MyVisibility_Gone; + _nineFlowLayout.visibility = model.commentsImageUrls.count > 0 ? MyVisibility_Visible : MyVisibility_Gone; _giveLikeLabel.text = giveLikeText; [_giveLikeLabel sizeToFit]; [self setCountWithImageArray:model.commentsImageUrls]; diff --git a/MyLayoutDemo/AllTest1TableViewCell.m b/MyLayoutDemo/AllTest1TableViewCell.m index 57b8346..2ca167a 100644 --- a/MyLayoutDemo/AllTest1TableViewCell.m +++ b/MyLayoutDemo/AllTest1TableViewCell.m @@ -53,7 +53,7 @@ -(void)setModel:(AllTest1DataModel*)model isImageMessageHidden:(BOOL)isImageMess if (model.imageMessage.length == 0) { - self.imageMessageImageView.myVisibility = MyVisibility_Gone; + self.imageMessageImageView.visibility = MyVisibility_Gone; } else { @@ -61,11 +61,11 @@ -(void)setModel:(AllTest1DataModel*)model isImageMessageHidden:(BOOL)isImageMess [self.imageMessageImageView sizeToFit]; if (isImageMessageHidden) { - self.imageMessageImageView.myVisibility = MyVisibility_Gone; + self.imageMessageImageView.visibility = MyVisibility_Gone; } else { - self.imageMessageImageView.myVisibility = MyVisibility_Visible; + self.imageMessageImageView.visibility = MyVisibility_Visible; } } diff --git a/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m b/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m index e51c6e2..508b4f0 100644 --- a/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m +++ b/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m @@ -65,7 +65,7 @@ -(void)setModel:(AllTest1DataModel*)model isImageMessageHidden:(BOOL)isImageMess if (model.imageMessage.length == 0) { - self.imageMessageImageView.myVisibility = MyVisibility_Gone; + self.imageMessageImageView.visibility = MyVisibility_Gone; } else { @@ -73,11 +73,11 @@ -(void)setModel:(AllTest1DataModel*)model isImageMessageHidden:(BOOL)isImageMess [self.imageMessageImageView sizeToFit]; if (isImageMessageHidden) { - self.imageMessageImageView.myVisibility = MyVisibility_Gone; + self.imageMessageImageView.visibility = MyVisibility_Gone; } else { - self.imageMessageImageView.myVisibility = MyVisibility_Visible; + self.imageMessageImageView.visibility = MyVisibility_Visible; } } diff --git a/MyLayoutDemo/AllTest1ViewController.m b/MyLayoutDemo/AllTest1ViewController.m index 381fe7d..3f5dab9 100644 --- a/MyLayoutDemo/AllTest1ViewController.m +++ b/MyLayoutDemo/AllTest1ViewController.m @@ -339,10 +339,10 @@ -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath * -(void)handleTableHeaderViewLayoutClick:(MyBaseLayout*)sender { UILabel *label1 = [sender viewWithTag:1000]; - if (label1.myVisibility == MyVisibility_Visible) - label1.myVisibility = MyVisibility_Gone; + if (label1.visibility == MyVisibility_Visible) + label1.visibility = MyVisibility_Gone; else - label1.myVisibility = MyVisibility_Visible; + label1.visibility = MyVisibility_Visible; [UIView animateWithDuration:0.3 animations:^{ diff --git a/MyLayoutDemo/AllTest3ViewController.m b/MyLayoutDemo/AllTest3ViewController.m index e7cc966..890246d 100644 --- a/MyLayoutDemo/AllTest3ViewController.m +++ b/MyLayoutDemo/AllTest3ViewController.m @@ -485,18 +485,18 @@ -(void)handleTouchCancel:(MyBaseLayout*)sender -(void)handleResetShow:(UIButton *)sender { - self.invisibleButton.myVisibility = MyVisibility_Visible; - self.goneButton.myVisibility = MyVisibility_Visible; + self.invisibleButton.visibility = MyVisibility_Visible; + self.goneButton.visibility = MyVisibility_Visible; } -(void)handleInvisible:(UIButton*)sender { - sender.myVisibility = MyVisibility_Invisible; + sender.visibility = MyVisibility_Invisible; } -(void)handleGone:(UIButton*)sender { - sender.myVisibility = MyVisibility_Gone; + sender.visibility = MyVisibility_Gone; } -(void)handleLeftFlexed:(UISegmentedControl*)segmented diff --git a/MyLayoutDemo/AllTest5ViewController.m b/MyLayoutDemo/AllTest5ViewController.m index f357d43..36fa6b9 100644 --- a/MyLayoutDemo/AllTest5ViewController.m +++ b/MyLayoutDemo/AllTest5ViewController.m @@ -57,9 +57,9 @@ -(void)loadView [rootLayout addSubview:v3]; //v3视图在其他任何iPhone设备横屏都不参与布局 - [v3 fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact].myVisibility = MyVisibility_Gone; + [v3 fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact].visibility = MyVisibility_Gone; //只有iphone6Plus的横屏才参与布局 - [v3 fetchLayoutSizeClass:MySizeClass_wRegular | MySizeClass_hCompact copyFrom:MySizeClass_wAny | MySizeClass_hAny].myVisibility = MyVisibility_Visible; + [v3 fetchLayoutSizeClass:MySizeClass_wRegular | MySizeClass_hCompact copyFrom:MySizeClass_wAny | MySizeClass_hAny].visibility = MyVisibility_Visible; //针对iPhone设备的所有横屏的高度都是Compact的,而宽度则是任意,因此下面的设置横屏情况下布局变为水平布局。 //虽然fetchLayoutSizeClass方法真实返回的是MyLayoutSize或者其派生类,但是仍然可以用视图以及布局来设置其中的属性 diff --git a/MyLayoutDemo/FLLTest4ViewController.m b/MyLayoutDemo/FLLTest4ViewController.m index 4cfe7a7..2b78abe 100644 --- a/MyLayoutDemo/FLLTest4ViewController.m +++ b/MyLayoutDemo/FLLTest4ViewController.m @@ -144,7 +144,7 @@ -(void)createFlowLayout1:(MyLinearLayout*)rootLayout rememberLabel.textColor = [CFTool color:4]; rememberLabel.font = [CFTool font:15]; rememberLabel.weight = 1; - rememberLabel.myAlignment = MyGravity_Vert_Bottom; //流式布局通过arrangedGravity设置每行的对齐方式,如果某个子视图不想使用默认的对齐方式则可以通过myAlignment属性来单独设置对齐方式,这个例子中所有都是居中对齐,但是这个标题则是底部对齐。 + rememberLabel.alignment = MyGravity_Vert_Bottom; //流式布局通过arrangedGravity设置每行的对齐方式,如果某个子视图不想使用默认的对齐方式则可以通过alignment属性来单独设置对齐方式,这个例子中所有都是居中对齐,但是这个标题则是底部对齐。 [rememberLabel sizeToFit]; [flowLayout addSubview:rememberLabel]; diff --git a/MyLayoutDemo/FOLTest7ViewController.m b/MyLayoutDemo/FOLTest7ViewController.m index 9543405..e6df937 100644 --- a/MyLayoutDemo/FOLTest7ViewController.m +++ b/MyLayoutDemo/FOLTest7ViewController.m @@ -20,7 +20,7 @@ @implementation FOLTest7ViewController -(void)loadView { /* - 这个例子主要给大家演示,在浮动布局中也可以支持一行(列)内的子视图的对齐方式的设置了。我们可以借助子视图的myAlignment属性来设置其在浮动布局行(列)内的对齐方式。 + 这个例子主要给大家演示,在浮动布局中也可以支持一行(列)内的子视图的对齐方式的设置了。我们可以借助子视图的alignment属性来设置其在浮动布局行(列)内的对齐方式。 这里的对齐的标准都是以当前行(列)内最高(宽)的子视图为参考来进行(列)对齐的。 在垂直浮动布局里面的子视图的行内对齐只能设置MyGravity_Vert_Top, MyGravity_Vert_Center, MyGravity_Vert_Bottom, MyGravity_Vert_Fill这几种对齐方式。 @@ -80,7 +80,7 @@ -(MyFloatLayout*)createVertFloatLayout:(MyLinearLayout*)rootLayout UIImageView *logoImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"p1-12"]]; logoImageView.layer.borderColor = [CFTool color:4].CGColor; logoImageView.layer.borderWidth = 1; - logoImageView.myAlignment = MyGravity_Vert_Center; //在浮动的一行内垂直居中对齐。 + logoImageView.alignment = MyGravity_Vert_Center; //在浮动的一行内垂直居中对齐。 logoImageView.myMargin = 10; //四周的边距都设置为10. logoImageView.mySize = CGSizeMake(80, 36); [floatLayout addSubview:logoImageView]; @@ -88,7 +88,7 @@ -(MyFloatLayout*)createVertFloatLayout:(MyLinearLayout*)rootLayout UILabel *brandLabel = [UILabel new]; brandLabel.text = @"千奈美官方旗舰店"; [brandLabel sizeToFit]; - brandLabel.myAlignment = MyGravity_Vert_Center; //在浮动的一行内垂直居中对齐。 + brandLabel.alignment = MyGravity_Vert_Center; //在浮动的一行内垂直居中对齐。 brandLabel.myVertMargin = 10; [floatLayout addSubview:brandLabel]; @@ -97,7 +97,7 @@ -(MyFloatLayout*)createVertFloatLayout:(MyLinearLayout*)rootLayout [attentionButton sizeToFit]; attentionButton.reverseFloat = YES; //关注放在右边,所以浮动到右边。 attentionButton.myMargin = 10; - attentionButton.myAlignment = MyGravity_Vert_Center; //在浮动的一行内垂直居中对齐。 + attentionButton.alignment = MyGravity_Vert_Center; //在浮动的一行内垂直居中对齐。 [floatLayout addSubview:attentionButton]; //单独一行。 @@ -160,13 +160,13 @@ -(MyFloatLayout*)createVertFloatLayout:(MyLinearLayout*)rootLayout signatureLabel.textColor = [CFTool color:4]; [signatureLabel sizeToFit]; signatureLabel.myHorzMargin = 10; - signatureLabel.myAlignment = MyGravity_Vert_Center; + signatureLabel.alignment = MyGravity_Vert_Center; [floatLayout addSubview:signatureLabel]; UIImageView *moreImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"next"]]; moreImageView.reverseFloat = YES; moreImageView.myHorzMargin = 10; - moreImageView.myAlignment = MyGravity_Vert_Center; + moreImageView.alignment = MyGravity_Vert_Center; [floatLayout addSubview:moreImageView]; @@ -174,7 +174,7 @@ -(MyFloatLayout*)createVertFloatLayout:(MyLinearLayout*)rootLayout moreLabel.text = @"进店看看"; [moreLabel sizeToFit]; moreLabel.reverseFloat = YES; - moreLabel.myAlignment = MyGravity_Vert_Center; + moreLabel.alignment = MyGravity_Vert_Center; [floatLayout addSubview:moreLabel]; @@ -188,12 +188,12 @@ -(MyFloatLayout*)createVertFloatLayout:(MyLinearLayout*)rootLayout // UIImageView *commentImageView1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"minions4"]]; - commentImageView1.myAlignment = MyGravity_Vert_Fill; //这里使用填充对齐,表明会和这行里面高度最高的那个子视图的高度保持一致。 + commentImageView1.alignment = MyGravity_Vert_Fill; //这里使用填充对齐,表明会和这行里面高度最高的那个子视图的高度保持一致。 commentImageView1.myLeft = 10; [floatLayout addSubview:commentImageView1]; UIImageView *commentImageView2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"minions3"]]; - commentImageView2.myAlignment = MyGravity_Vert_Fill; //这里使用填充对齐,表明会和这行里面高度最高的那个子视图的高度保持一致。 + commentImageView2.alignment = MyGravity_Vert_Fill; //这里使用填充对齐,表明会和这行里面高度最高的那个子视图的高度保持一致。 commentImageView2.myLeft = 10; [floatLayout addSubview:commentImageView2]; @@ -206,7 +206,7 @@ -(MyFloatLayout*)createVertFloatLayout:(MyLinearLayout*)rootLayout { UIImageView *starImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"section2"]]; starImageView.mySize = CGSizeMake(20, 20); - starImageView.myAlignment = MyGravity_Vert_Bottom; //这里底部对齐,表明子视图和一行内最高的子视图保持底部对齐。 + starImageView.alignment = MyGravity_Vert_Bottom; //这里底部对齐,表明子视图和一行内最高的子视图保持底部对齐。 starImageView.myLeft = 5; [floatLayout addSubview:starImageView]; } @@ -247,15 +247,15 @@ -(MyFloatLayout*)createHorzFloatLayout:(MyLinearLayout*)rootLayout switch (i) { case 0: case 1: - imageView.myAlignment = MyGravity_Horz_Center; + imageView.alignment = MyGravity_Horz_Center; break; case 2: case 3: - imageView.myAlignment = MyGravity_Horz_Right; + imageView.alignment = MyGravity_Horz_Right; break; case 4: case 5: - imageView.myAlignment = MyGravity_Horz_Fill; + imageView.alignment = MyGravity_Horz_Fill; default: break; } diff --git a/MyLayoutDemo/LLTest1ViewController.m b/MyLayoutDemo/LLTest1ViewController.m index 17091af..7057715 100644 --- a/MyLayoutDemo/LLTest1ViewController.m +++ b/MyLayoutDemo/LLTest1ViewController.m @@ -133,12 +133,12 @@ - (void)viewDidLoad { - (void)RTLAction { // 当前view的window - [MyBaseLayout myUpArabicUI:YES inWindow:self.view.window]; + [MyBaseLayout updateRTL:YES inWindow:self.view.window]; } - (void)LTRAction { // 这个适合APP 使用appdelegate 中的window - [MyBaseLayout myUpArabicUI:NO inWindow:[UIApplication sharedApplication].delegate.window]; + [MyBaseLayout updateRTL:NO inWindow:[UIApplication sharedApplication].delegate.window]; } - (void)didReceiveMemoryWarning { diff --git a/MyLayoutDemo/LLTest2ViewController.m b/MyLayoutDemo/LLTest2ViewController.m index 4d01695..1d9c262 100644 --- a/MyLayoutDemo/LLTest2ViewController.m +++ b/MyLayoutDemo/LLTest2ViewController.m @@ -395,7 +395,7 @@ -(void)createSection6:(MyLinearLayout*)contentLayout baselineLabel.wrapContentSize = YES; baselineLabel.font = [CFTool font:20]; baselineLabel.backgroundColor = [CFTool color:5]; - baselineLabel.myAlignment = MyGravity_Vert_Center; //标准视图垂直居中。 + baselineLabel.alignment = MyGravity_Vert_Center; //标准视图垂直居中。 [baselineLayout addSubview:baselineLabel]; UILabel *rightLabel = [UILabel new]; @@ -451,7 +451,7 @@ -(void)createSection8:(MyLinearLayout*)contentLayout UIView *hiddenView = [UIView new]; hiddenView.backgroundColor = [CFTool color:3]; - hiddenView.myVisibility = MyVisibility_Gone; + hiddenView.visibility = MyVisibility_Gone; hiddenView.myTop = 20; hiddenView.myLeading = hiddenView.myTrailing = 0; hiddenView.myHeight = 800; @@ -483,15 +483,15 @@ -(void)handleLabelShrink:(UIButton*)sender -(void)handleHideAndShowMore:(UIButton*)sender { - if (self.hiddenView.myVisibility == MyVisibility_Visible) + if (self.hiddenView.visibility == MyVisibility_Visible) { - self.hiddenView.myVisibility = MyVisibility_Gone; + self.hiddenView.visibility = MyVisibility_Gone; [sender setTitle:NSLocalizedString(@"Show more》", @"") forState:UIControlStateNormal]; [sender sizeToFit]; } else { - self.hiddenView.myVisibility = MyVisibility_Visible; + self.hiddenView.visibility = MyVisibility_Visible; [sender setTitle:NSLocalizedString(@"Close up《", @"") forState:UIControlStateNormal]; [sender sizeToFit]; } diff --git a/MyLayoutDemo/LLTest3ViewController.m b/MyLayoutDemo/LLTest3ViewController.m index 837af1b..975aa88 100644 --- a/MyLayoutDemo/LLTest3ViewController.m +++ b/MyLayoutDemo/LLTest3ViewController.m @@ -37,7 +37,7 @@ -(void)loadView 1.当使用gravity属性时意味着布局视图必须要有明确的尺寸才有意义,因为有确定的尺寸才能决定里面的子视图的停靠的方位。 2.布局视图的wrapContentHeight设置为YES时是和gravity上设置垂直停靠方向以及垂直填充是互斥的;而布局视图的wrapContentWidth设置为YES时是和gravity上设置水平停靠方向和水平填充是互斥的。 - 3.布局视图的gravity的属性的优先级要高于子视图的边距和尺寸设置,但是低于子视图的myAlignment属性的设置。 + 3.布局视图的gravity的属性的优先级要高于子视图的边距和尺寸设置,但是低于子视图的alignment属性的设置。 */ @@ -169,7 +169,7 @@ -(void)createVertGravityLayout:(MyLinearLayout*)contentLayout UILabel *v2 = [self createLabel:NSLocalizedString(@"always alignment to left", @"") backgroundColor:[CFTool color:6]]; v2.myHeight = 20; - v2.myAlignment = MyGravity_Horz_Left; //对于垂直布局里面的子视图可以通过这个属性来设置水平对齐的方位,这样即使布局视图设置了gravity属性,这个视图的对齐都不会受到影响。 + v2.alignment = MyGravity_Horz_Left; //对于垂直布局里面的子视图可以通过这个属性来设置水平对齐的方位,这样即使布局视图设置了gravity属性,这个视图的对齐都不会受到影响。 [self.vertGravityLayout addSubview:v2]; UILabel *v3 = [self createLabel:NSLocalizedString(@"test text3 test text3 test text3", @"") backgroundColor:[CFTool color:7]]; @@ -257,7 +257,7 @@ -(void)createHorzGravityLayout:(MyLinearLayout*)contentLayout UILabel *v2 = [self createLabel:NSLocalizedString(@"always alignment to top", @"") backgroundColor:[CFTool color:6]]; v2.wrapContentHeight = YES; v2.myWidth = 60; - v2.myAlignment = MyGravity_Vert_Top; //对于水平布局里面的子视图可以通过这个属性来设置垂直对齐的方位,这样即使布局视图设置了gravity属性,这个视图的对齐都不会受到影响。 + v2.alignment = MyGravity_Vert_Top; //对于水平布局里面的子视图可以通过这个属性来设置垂直对齐的方位,这样即使布局视图设置了gravity属性,这个视图的对齐都不会受到影响。 [self.horzGravityLayout addSubview:v2]; diff --git a/MyLayoutDemo/LLTest4ViewController.m b/MyLayoutDemo/LLTest4ViewController.m index 85c6eab..f8195ce 100644 --- a/MyLayoutDemo/LLTest4ViewController.m +++ b/MyLayoutDemo/LLTest4ViewController.m @@ -18,44 +18,52 @@ @interface LLTest4ViewController () @implementation LLTest4ViewController --(void)loadView -{ - /* - 这个例子详细说明wrapContentHeight和wrapContentWidth的包裹属性的设置、以及边界线性的设定、以及布局中可局部缩放背景图片的设定方法。 - */ - - self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 - - [super loadView]; - - self.view.backgroundColor = [UIColor whiteColor]; - - UIView *contentView = [UIView new]; - contentView.backgroundColor = [CFTool color:5]; - [self.view addSubview:contentView]; - contentView.wrapContentWidth = YES; - contentView.wrapContentHeight = YES; //如果一个非布局父视图里面有布局子视图,那么这个非布局父视图也是可以设置wrapContentHeight和wrapContentWidth的,他表示的意义是这个非布局父视图的尺寸由里面的布局子视图的尺寸来决定的。这个功能是在1.3.3版本支持的。 还有一个场景是非布局父视图是一个UIScrollView。他是左右滚动的,但是滚动视图的高度是由里面的布局子视图确定的,而宽度则是和窗口保持一致。这样只需要将滚动视图的宽度设置为和屏幕保持一致,高度设置为wrapContentHeight,并且把一个水平线性布局添加到滚动视图即可。 - - - self.rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - self.rootLayout.layer.borderWidth = 1; - self.rootLayout.layer.borderColor = [UIColor lightGrayColor].CGColor; - self.rootLayout.wrapContentHeight = YES; - self.rootLayout.wrapContentWidth = YES; //布局的高度和宽度由子视图决定 - self.rootLayout.myTop = 10; - self.rootLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); - self.rootLayout.zeroPadding = NO; //这个属性设置为NO时表示当布局视图的尺寸是wrap也就是由子视图决定时并且在没有任何子视图是不会参与布局视图高度的计算的。您可以在这个DEMO的测试中将所有子视图都删除掉,看看效果,然后注释掉这句代码看看效果。 - self.rootLayout.subviewVSpace = 5; - [contentView addSubview:self.rootLayout]; - - [self.rootLayout addSubview:[self addWrapContentLayout]]; - -} - - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. + + MyLinearLayout *layout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + layout.backgroundColor = [UIColor redColor]; + layout.gravity = MyGravity_Horz_Center; + layout.padding = UIEdgeInsetsMake(15, 0, 0, 0); + layout.subviewVSpace = 12; + layout.myHorzMargin = 0; + layout.myTop = 100; + [self.view addSubview:layout]; + + + UILabel *timeLabel = UILabel.new; + timeLabel.myHorzMargin = 0; + timeLabel.wrapContentHeight = YES; + timeLabel.textAlignment = NSTextAlignmentCenter; + timeLabel.text = @"剩余时间为"; + [layout addSubview:timeLabel]; + + // 汇率 + MyLinearLayout *convertLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + convertLayout.backgroundColor = [UIColor greenColor]; + convertLayout.wrapContentHeight = YES; + convertLayout.gravity = MyGravity_Vert_Center; + convertLayout.subviewHSpace = 7; + [layout addSubview:convertLayout]; + + NSArray *items = @[@"$454", @"^sdsf"]; + for (int i=0; i"; + [convertLayout addSubview:btn]; + } + } } - (void)didReceiveMemoryWarning { diff --git a/MyLayoutDemo/RLTest2ViewController.m b/MyLayoutDemo/RLTest2ViewController.m index 9ec3a25..486e20b 100644 --- a/MyLayoutDemo/RLTest2ViewController.m +++ b/MyLayoutDemo/RLTest2ViewController.m @@ -222,18 +222,18 @@ -(void)handleHidden:(UIButton*)sender { if (self.visibilitySwitch.isOn) { - self.visibilityButton.myVisibility = MyVisibility_Gone; + self.visibilityButton.visibility = MyVisibility_Gone; } else { - self.visibilityButton.myVisibility = MyVisibility_Invisible; + self.visibilityButton.visibility = MyVisibility_Invisible; } } -(void)handleShow:(UIButton*)sender { - self.visibilityButton.myVisibility = MyVisibility_Visible; + self.visibilityButton.visibility = MyVisibility_Visible; } /* diff --git a/MyLayoutTests/MyLinearLayoutTestCase.m b/MyLayoutTests/MyLinearLayoutTestCase.m index 8caa4c8..a82ce18 100644 --- a/MyLayoutTests/MyLinearLayoutTestCase.m +++ b/MyLayoutTests/MyLinearLayoutTestCase.m @@ -180,6 +180,53 @@ -(void)testSubviewSizeDependent } +-(void)testSubviewSizeDependent2 +{ + //测试隐藏、比重、尺寸依赖。 + + MyLinearLayout *layout2 = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 200) orientation:MyOrientation_Horz]; + layout2.wrapContentWidth = NO; + + + UIButton *zoneBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + zoneBtn.titleLabel.font = [UIFont systemFontOfSize:13]; + zoneBtn.titleLabel.textAlignment = NSTextAlignmentCenter; + + UILabel *nameLab = [[UILabel alloc] initWithFrame:CGRectZero]; + nameLab.numberOfLines = 1.0; + nameLab.font = [UIFont systemFontOfSize:18]; + nameLab.textAlignment = NSTextAlignmentCenter; + + UIButton *placeholderBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + + zoneBtn.myLeft = 20; + zoneBtn.myCenterY = 0; + zoneBtn.widthSize.equalTo(zoneBtn.widthSize).add(20); + zoneBtn.heightSize.equalTo(zoneBtn.heightSize).add(3); + + nameLab.myCenterY = 0; + nameLab.weight = 1.0; + nameLab.heightSize.equalTo(nameLab.heightSize); + + placeholderBtn.myCenterY = 0; + placeholderBtn.myRight = 20; + placeholderBtn.widthSize.equalTo(zoneBtn.widthSize); + placeholderBtn.heightSize.equalTo(zoneBtn.heightSize); + + [layout2 addSubview:zoneBtn]; + [layout2 addSubview:nameLab]; + [layout2 addSubview:placeholderBtn]; + + zoneBtn.visibility = MyVisibility_Gone; + placeholderBtn.visibility = MyVisibility_Gone; + + [layout2 layoutIfNeeded]; + + XCTAssertTrue(nameLab.frame.size.width == layout2.frame.size.width && + nameLab.center.y == layout2.frame.size.height * 0.5, @"nameLab.frame = %@",NSStringFromCGRect(nameLab.frame)); + +} + -(void)testWeight {//测试均分 diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index 84c9230..2271561 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -843,6 +843,98 @@ -(void)testDemo1 } +-(void)testhideandubound +{ + //测试视图隐藏以及 + { + UIButton *zoneBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + zoneBtn.titleLabel.font = [UIFont systemFontOfSize:13]; + zoneBtn.titleLabel.textAlignment = NSTextAlignmentCenter; + + UILabel *nameLab = [[UILabel alloc] initWithFrame:CGRectZero]; + nameLab.numberOfLines = 1.0; + nameLab.font = [UIFont systemFontOfSize:18]; + nameLab.textAlignment = NSTextAlignmentCenter; + + UIButton *placeholderBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + + MyRelativeLayout *layout2 = [[MyRelativeLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 100)]; + + zoneBtn.myLeft = 20; + zoneBtn.myCenterY = 0; + zoneBtn.widthSize.equalTo(zoneBtn.widthSize).add(20); + zoneBtn.heightSize.equalTo(zoneBtn.heightSize).add(3); + + nameLab.myCenterY = 0; + nameLab.leftPos.equalTo(zoneBtn.rightPos).offset(15); + nameLab.rightPos.equalTo(placeholderBtn.leftPos).offset(15); + nameLab.heightSize.equalTo(nameLab.heightSize); + + placeholderBtn.myCenterY = 0; + placeholderBtn.myRight = 20; + placeholderBtn.widthSize.equalTo(zoneBtn.widthSize); + placeholderBtn.heightSize.equalTo(zoneBtn.heightSize); + + [layout2 addSubview:zoneBtn]; + [layout2 addSubview:nameLab]; + [layout2 addSubview:placeholderBtn]; + + zoneBtn.visibility = MyVisibility_Gone; + placeholderBtn.visibility = MyVisibility_Gone; + + [layout2 layoutIfNeeded]; + + XCTAssertTrue(nameLab.frame.size.width == layout2.frame.size.width - 40 && + nameLab.center.y == layout2.frame.size.height * 0.5, @"nameLab.frame = %@",NSStringFromCGRect(nameLab.frame)); + } + + { + UIButton *zoneBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + zoneBtn.titleLabel.font = [UIFont systemFontOfSize:13]; + zoneBtn.titleLabel.textAlignment = NSTextAlignmentCenter; + + UILabel *nameLab = [[UILabel alloc] initWithFrame:CGRectZero]; + nameLab.numberOfLines = 1.0; + nameLab.font = [UIFont systemFontOfSize:18]; + nameLab.textAlignment = NSTextAlignmentCenter; + + UIButton *placeholderBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + + MyRelativeLayout *layout2 = [[MyRelativeLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 100)]; + + zoneBtn.myLeft = 20; + zoneBtn.myCenterY = 0; + zoneBtn.widthSize.equalTo(zoneBtn.widthSize).add(20); + zoneBtn.heightSize.equalTo(zoneBtn.heightSize).add(3); + + nameLab.myCenterY = 0; + nameLab.wrapContentSize = YES; + nameLab.leftPos.lBound(zoneBtn.rightPos, 15); + nameLab.rightPos.uBound(placeholderBtn.leftPos, 15); + nameLab.heightSize.equalTo(nameLab.heightSize); + nameLab.text = @"这是阿斯蒂芬阿道夫阿斯蒂芬安防安防阿斯蒂芬安防大师傅阿斯蒂芬阿斯蒂芬安防"; + + placeholderBtn.myCenterY = 0; + placeholderBtn.myRight = 20; + placeholderBtn.widthSize.equalTo(zoneBtn.widthSize); + placeholderBtn.heightSize.equalTo(zoneBtn.heightSize); + + [layout2 addSubview:zoneBtn]; + [layout2 addSubview:nameLab]; + [layout2 addSubview:placeholderBtn]; + + zoneBtn.visibility = MyVisibility_Gone; + placeholderBtn.visibility = MyVisibility_Gone; + + [layout2 layoutIfNeeded]; + + XCTAssertTrue(nameLab.frame.size.width == layout2.frame.size.width - 40 && + nameLab.center.y == layout2.frame.size.height * 0.5, @"nameLab.frame = %@",NSStringFromCGRect(nameLab.frame)); + + } + +} + -(void)testBaseline { MyRelativeLayout *relaLayout = [MyRelativeLayout new]; From db5f6ac97ce18505caeaa0acd909651f6a8c5e5d Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Sun, 23 Jun 2019 22:09:47 +0800 Subject: [PATCH 031/115] =?UTF-8?q?1.=E9=87=8D=E6=9E=84=E7=BA=BF=E6=80=A7?= =?UTF-8?q?=E5=B8=83=E5=B1=80=EF=BC=8C2.=E4=BF=AE=E5=A4=8D1.7.0=E7=9A=84bu?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayoutDemo/LLTest4ViewController.m | 95 ++++++++++++-------------- MyLayoutTests/MyLinearLayoutTestCase.m | 62 +++++++++++++++-- 2 files changed, 99 insertions(+), 58 deletions(-) diff --git a/MyLayoutDemo/LLTest4ViewController.m b/MyLayoutDemo/LLTest4ViewController.m index f8195ce..9ab7916 100644 --- a/MyLayoutDemo/LLTest4ViewController.m +++ b/MyLayoutDemo/LLTest4ViewController.m @@ -18,52 +18,44 @@ @interface LLTest4ViewController () @implementation LLTest4ViewController +-(void)loadView +{ + /* + 这个例子详细说明wrapContentHeight和wrapContentWidth的包裹属性的设置、以及边界线性的设定、以及布局中可局部缩放背景图片的设定方法。 + */ + + self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + + [super loadView]; + + self.view.backgroundColor = [UIColor whiteColor]; + + UIView *contentView = [UIView new]; + contentView.backgroundColor = [CFTool color:5]; + [self.view addSubview:contentView]; + contentView.wrapContentWidth = YES; + contentView.wrapContentHeight = YES; //如果一个非布局父视图里面有布局子视图,那么这个非布局父视图也是可以设置wrapContentHeight和wrapContentWidth的,他表示的意义是这个非布局父视图的尺寸由里面的布局子视图的尺寸来决定的。这个功能是在1.3.3版本支持的。 还有一个场景是非布局父视图是一个UIScrollView。他是左右滚动的,但是滚动视图的高度是由里面的布局子视图确定的,而宽度则是和窗口保持一致。这样只需要将滚动视图的宽度设置为和屏幕保持一致,高度设置为wrapContentHeight,并且把一个水平线性布局添加到滚动视图即可。 + + + self.rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + self.rootLayout.layer.borderWidth = 1; + self.rootLayout.layer.borderColor = [UIColor lightGrayColor].CGColor; + self.rootLayout.wrapContentHeight = YES; + self.rootLayout.wrapContentWidth = YES; //布局的高度和宽度由子视图决定 + self.rootLayout.myTop = 10; + self.rootLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); + self.rootLayout.zeroPadding = NO; //这个属性设置为NO时表示当布局视图的尺寸是wrap也就是由子视图决定时并且在没有任何子视图是不会参与布局视图高度的计算的。您可以在这个DEMO的测试中将所有子视图都删除掉,看看效果,然后注释掉这句代码看看效果。 + self.rootLayout.subviewVSpace = 5; + [contentView addSubview:self.rootLayout]; + + [self.rootLayout addSubview:[self addWrapContentLayout]]; + +} + - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. - - MyLinearLayout *layout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - layout.backgroundColor = [UIColor redColor]; - layout.gravity = MyGravity_Horz_Center; - layout.padding = UIEdgeInsetsMake(15, 0, 0, 0); - layout.subviewVSpace = 12; - layout.myHorzMargin = 0; - layout.myTop = 100; - [self.view addSubview:layout]; - - - UILabel *timeLabel = UILabel.new; - timeLabel.myHorzMargin = 0; - timeLabel.wrapContentHeight = YES; - timeLabel.textAlignment = NSTextAlignmentCenter; - timeLabel.text = @"剩余时间为"; - [layout addSubview:timeLabel]; - - // 汇率 - MyLinearLayout *convertLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; - convertLayout.backgroundColor = [UIColor greenColor]; - convertLayout.wrapContentHeight = YES; - convertLayout.gravity = MyGravity_Vert_Center; - convertLayout.subviewHSpace = 7; - [layout addSubview:convertLayout]; - - NSArray *items = @[@"$454", @"^sdsf"]; - for (int i=0; i"; - [convertLayout addSubview:btn]; - } - } } - (void)didReceiveMemoryWarning { @@ -82,7 +74,7 @@ -(MyLinearLayout*)addWrapContentLayout wrapContentLayout.wrapContentWidth = YES; //布局的高度和宽度由子视图决定 wrapContentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); wrapContentLayout.subviewHSpace = 5; - + /* 布局视图的backgroundImage的属性的内部实现是通过设置视图的layer的content属性来实现的。因此如果我们希望实现具有拉升效果的 @@ -163,7 +155,7 @@ -(void)handleAction:(UIButton*)sender } else if (sender.tag == 300) { - MyLinearLayout*actionLayout = (MyLinearLayout*)sender.superview; + MyLinearLayout*actionLayout = (MyLinearLayout*)sender.superview; [actionLayout removeFromSuperview]; } else if (sender.tag == 400) @@ -180,13 +172,12 @@ -(void)handleAction:(UIButton*)sender /* -#pragma mark - Navigation - -// In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. -} -*/ + #pragma mark - Navigation + // In a storyboard-based application, you will often want to do a little preparation before navigation + - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. + } + */ @end diff --git a/MyLayoutTests/MyLinearLayoutTestCase.m b/MyLayoutTests/MyLinearLayoutTestCase.m index a82ce18..3c49857 100644 --- a/MyLayoutTests/MyLinearLayoutTestCase.m +++ b/MyLayoutTests/MyLinearLayoutTestCase.m @@ -247,7 +247,7 @@ -(void)testWeight { button.backgroundColor = [UIColor greenColor]; } - [button setTitle:[NSString stringWithFormat:@"%zi",i] forState:UIControlStateNormal]; + [button setTitle:[NSString stringWithFormat:@"%i",i] forState:UIControlStateNormal]; button.heightSize.equalTo(rootLayout1.heightSize); [rootLayout1 addSubview:button]; } @@ -263,16 +263,66 @@ -(void)testWeight } +-(void)testWrapContentHeight2 +{ + MyLinearLayout *layout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 0) orientation:MyOrientation_Vert]; + layout.backgroundColor = [UIColor redColor]; + layout.gravity = MyGravity_Horz_Center; + layout.padding = UIEdgeInsetsMake(15, 0, 0, 0); + layout.subviewVSpace = 12; + + + UILabel *timeLabel = UILabel.new; + timeLabel.myHorzMargin = 0; + timeLabel.wrapContentHeight = YES; + timeLabel.textAlignment = NSTextAlignmentCenter; + timeLabel.text = @"剩余时间为"; + [layout addSubview:timeLabel]; + + // 汇率 + MyLinearLayout *convertLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + convertLayout.backgroundColor = [UIColor greenColor]; + convertLayout.wrapContentHeight = YES; + convertLayout.gravity = MyGravity_Vert_Center; + convertLayout.subviewHSpace = 7; + [layout addSubview:convertLayout]; + + NSArray *items = @[@"$454", @"^sdsf"]; + for (int i=0; i"; + [convertLayout addSubview:btn]; + } + } + + [layout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(layout.frame, CGRectMake(0,0,375,81)), @"the layout.frame = %@",NSStringFromCGRect(layout.frame)); + XCTAssertTrue(CGRectEqualToRect(convertLayout.frame, CGRectMake(105,47.5,165,33.5)), @"the convertLayout.frame = %@",NSStringFromCGRect(convertLayout.frame)); + + XCTAssertTrue(CGRectEqualToRect(timeLabel.frame, CGRectMake(0,15,375,20.5)), @"the timeLabel.frame = %@",NSStringFromCGRect(timeLabel.frame)); + XCTAssertTrue(CGRectEqualToRect(convertLayout.subviews[1].frame, CGRectMake(76,6.5,18.5,20.5)), @"the convertLayout.subviews[1].frame = %@",NSStringFromCGRect(convertLayout.subviews[1].frame)); + +} - (void)testPerformanceExample { // This is an example of a performance test case. - [self measureBlock:^{ - // Put the code you want to measure the time of here. - - }]; - +// [self measureBlock:^{ +// // Put the code you want to measure the time of here. +// +// }]; +// } From e613eabf8d516134f7002e7898465e1021d98081 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Sun, 23 Jun 2019 22:57:40 +0800 Subject: [PATCH 032/115] =?UTF-8?q?1.=E9=87=8D=E6=9E=84=E7=BA=BF=E6=80=A7?= =?UTF-8?q?=E5=B8=83=E5=B1=80=EF=BC=8C=202.=E4=BF=AE=E5=A4=8D1.7.0?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 76b2198..8836e76 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -2730,13 +2730,13 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview } else { - rectSelf.size.width = [lsc.widthSizeInner measureWith:lsc.widthSizeInner.dimeRelaVal.view.estimatedRect.size.width]; + rectSelf.size.width = [lsc.widthSizeInner measureWith:lsc.widthSizeInner.dimeRelaVal.view.myEstimatedWidth]; } isAdjust = YES; } else rectSelf.size.width = lsc.widthSizeInner.measure; - + } //这里要判断自己的宽度设置了最小和最大宽度依赖于父视图的情况。如果有这种情况,则父视图在变化时也需要调整自身。 @@ -2823,7 +2823,7 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview } else { - rectSelf.size.height = [lsc.heightSizeInner measureWith:lsc.heightSizeInner.dimeRelaVal.view.estimatedRect.size.height]; + rectSelf.size.height = [lsc.heightSizeInner measureWith:lsc.heightSizeInner.dimeRelaVal.view.myEstimatedHeight]; } isAdjust = YES; } From 3ff96829f4e8bfef50b38078309a45620ca78c3d Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Tue, 25 Jun 2019 21:57:57 +0800 Subject: [PATCH 033/115] =?UTF-8?q?1.=E7=BA=BF=E6=80=A7=E5=B8=83=E5=B1=80?= =?UTF-8?q?=E9=87=8D=E6=9E=84=EF=BC=8C2.=E4=BF=AE=E5=A4=8D1.7.0=E7=9A=84BU?= =?UTF-8?q?G?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 22 ++++++++++++++++++++++ MyLayout.podspec | 2 +- MyLayout/Info.plist | 2 +- MyLayout/Lib/MyBaseLayout.m | 3 ++- MyLayout/Lib/MyLayout.h | 2 +- MyLayoutDemo/Info.plist | 2 +- 6 files changed, 28 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ed7a4d..27f1b77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,28 @@ **MyLayout**的所有版本的变更日志都将会在这里记录. --- +## [V1.8.0](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.8.0)(2019/06/25) + +#### Fixed + +1. 重构线性布局,精简实现逻辑和代码。 +2. 针对各种布局下的子视图的尺寸约束能力做了扩展。原先版本中只有相对布局中的子视图可以设置尺寸依赖任意其他子视图,而其他布局中的子视图只有有限的约束依赖能力。新版本中这些约束依赖得到增强,几乎所有布局下的子视图都可以支持自身宽度等于自身高度,以及尺寸依赖其他子视图的情况。[issue#94](https://github.com/youngsoft/MyLinearLayout/issues/94) +3. 修复当将布局视图作为UIScrollView下的容器视图同时UIScrollView支持放大缩小能力时,在屏幕旋转时可能会产生的BUG。[issue#93](https://github.com/youngsoft/MyLinearLayout/issues/93) +4. 修复了布局视图的尺寸自适应能力和AutoLayout结合后,布局视图添加删除子视图后要手动代码进行布局视图尺寸自适应的刷新问题。[issue#95](https://github.com/youngsoft/MyLinearLayout/issues/95) +5. 修复相对布局子视图隐藏时,其他依赖这个子视图的子视图的位置和尺寸不正确更新的问题。 +6. 修复UIImageView的宽度固定高度自适应的问题。 +7. 支持通过对isLayouting进行KVO监听来实现布局的通知处理机制,我们可以通过KVO布局视图的isLayouting属性来或者布局完成后子视图的frame以及布局视图的frame值了。 +8. 下列方法或属性名被列为过期,并推荐使用新的方法名和属性名: + +``` ++[MyBaseLayout myUpArabicUI:(BOOL)isArabicUI inWindow:(UIWindow *)window] ==> +[MyBaseLayout updateRTL:(BOOL)isRTL inWindow:(UIWindow *)window] + +-[UIView myVisibility] ==> -[UIView visibility] + +-[UIView myAlignment] == > -[UIView alignment] + +``` + ## [V1.7.0](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.7.0)(2019/05/16) #### Added diff --git a/MyLayout.podspec b/MyLayout.podspec index eb673a1..db12297 100644 --- a/MyLayout.podspec +++ b/MyLayout.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "MyLayout" - s.version = "1.7.0" + s.version = "1.8.0" s.summary = "MyLayout is an iOS UI framework integrates the functions with Android,AutoLayout,SizeClass,HTML CSS float and flexbox,UIView UITableView." s.description = <<-DESC diff --git a/MyLayout/Info.plist b/MyLayout/Info.plist index 6718324..47276bf 100644 --- a/MyLayout/Info.plist +++ b/MyLayout/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.7.0 + 1.8.0 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 8836e76..bc70c5f 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -1085,9 +1085,10 @@ -(void)layoutAnimationWithDuration:(NSTimeInterval)duration }; self.endLayoutBlock = ^{ - + [UIView commitAnimations]; }; + } -(MyBorderline*)topBorderline diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index b6a16cd..3180e1b 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -37,7 +37,7 @@ */ -//Current version is 1.8.0beta, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.8.0, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. #ifndef MyLayout_MyLayout_h diff --git a/MyLayoutDemo/Info.plist b/MyLayoutDemo/Info.plist index 325e420..326dd71 100644 --- a/MyLayoutDemo/Info.plist +++ b/MyLayoutDemo/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.7.0 + 1.8.0 CFBundleSignature ???? CFBundleVersion From 56e54f9da08b8d91f1aec6ca2a09e12b3b254238 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Tue, 17 Sep 2019 19:09:10 +0800 Subject: [PATCH 034/115] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8DBUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout.xcodeproj/project.pbxproj | 24 +- MyLayout/Lib/MyBaseLayout.h | 68 +- MyLayout/Lib/MyBaseLayout.m | 277 +++++-- MyLayout/Lib/MyFlexLayout.h | 91 +++ MyLayout/Lib/MyFlexLayout.m | 709 ++++++++++++++++++ MyLayout/Lib/MyFloatLayout.h | 32 +- MyLayout/Lib/MyFloatLayout.m | 141 ++-- MyLayout/Lib/MyFlowLayout.h | 9 +- MyLayout/Lib/MyFlowLayout.m | 523 +++++++++---- MyLayout/Lib/MyLayout.h | 1 + MyLayout/Lib/MyLayoutDef.h | 12 +- MyLayout/Lib/MyLayoutPos.h | 27 + MyLayout/Lib/MyLayoutPos.m | 8 + MyLayout/Lib/MyLayoutSize.h | 62 +- MyLayout/Lib/MyLayoutSize.m | 118 +++ MyLayout/Lib/MyLayoutSizeClass.h | 3 +- MyLayout/Lib/MyLayoutSizeClass.m | 28 +- MyLayout/Lib/MyLayoutSizeInner.h | 10 + MyLayout/Lib/MyLinearLayout.h | 4 + MyLayout/Lib/MyLinearLayout.m | 255 +++++-- MyLayout/Lib/MyMaker.h | 3 - MyLayout/Lib/MyMaker.m | 5 - MyLayout/Lib/MyRelativeLayout.m | 77 +- MyLayoutDemo/AllTest1ViewController.m | 4 +- MyLayoutDemo/FLLTest1ViewController.m | 12 + MyLayoutDemo/FLLTest3ViewController.m | 99 +-- MyLayoutDemo/FLLTest9ViewController.h | 14 + MyLayoutDemo/FLLTest9ViewController.m | 267 +++++++ MyLayoutDemo/FOLTest6ViewController.m | 17 +- MyLayoutDemo/LLTest2ViewController.m | 102 +-- MyLayoutDemo/LLTest3ViewController.m | 27 +- MyLayoutDemo/LLTest4ViewController.m | 67 +- MyLayoutDemo/ViewController.m | 4 + .../zh-Hans.lproj/Localizable.strings | 1 + MyLayoutTests/MyFlowLayoutTestCase.m | 30 + MyLayoutTests/MyFrameLayoutTestCase.m | 78 ++ MyLayoutTests/MyLinearLayoutTestCase.m | 135 ++++ MyLayoutTests/MyRelativeLayoutTestCase.m | 38 + 38 files changed, 2736 insertions(+), 646 deletions(-) create mode 100644 MyLayout/Lib/MyFlexLayout.h create mode 100644 MyLayout/Lib/MyFlexLayout.m create mode 100644 MyLayoutDemo/FLLTest9ViewController.h create mode 100644 MyLayoutDemo/FLLTest9ViewController.m diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index 625c3d3..bbcf709 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -162,8 +162,12 @@ 208157BD1F586AA700E945B6 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157BC1F586AA700E945B6 /* DetailViewController.m */; }; 208157C31F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; 208157C41F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; + 20A45EC52318FCA50026A18C /* MyFlexLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DF42402318F4EA0078CAA0 /* MyFlexLayout.m */; }; 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */ = {isa = PBXBuildFile; fileRef = 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */; }; 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */; }; + 20DF423E2318A6000078CAA0 /* FLLTest9ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DF423D2318A6000078CAA0 /* FLLTest9ViewController.m */; }; + 20DF42412318F4EA0078CAA0 /* MyFlexLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 20DF423F2318F4EA0078CAA0 /* MyFlexLayout.h */; }; + 20DF42422318F4EA0078CAA0 /* MyFlexLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DF42402318F4EA0078CAA0 /* MyFlexLayout.m */; }; 20F0DFFD2111749A00CFCE8C /* AllTest11ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F0DFFC2111749A00CFCE8C /* AllTest11ViewController.m */; }; 20F0E00021120A8D00CFCE8C /* FLLTest8ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F0DFFF21120A8D00CFCE8C /* FLLTest8ViewController.m */; }; 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F783551F60399700BE5B31 /* GLTest3ViewController.m */; }; @@ -211,13 +215,13 @@ 182225AE1E77E5930081AA4B /* MyTableLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MyTableLayout.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 182225AF1E77E5930081AA4B /* MyBaseLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MyBaseLayout.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 182225B01E77E5930081AA4B /* MyLayoutPos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutPos.h; sourceTree = ""; }; - 182225B11E77E5930081AA4B /* MyBaseLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyBaseLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225B11E77E5930081AA4B /* MyBaseLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyBaseLayout.m; sourceTree = ""; }; 182225B21E77E5930081AA4B /* MyLinearLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyLinearLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 182225B31E77E5930081AA4B /* MyLayoutDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutDef.h; sourceTree = ""; }; 182225B41E77E5930081AA4B /* MyFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFlowLayout.m; sourceTree = ""; }; 182225B51E77E5930081AA4B /* MyRelativeLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyRelativeLayout.m; sourceTree = ""; }; 182225B61E77E5930081AA4B /* MyPathLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyPathLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 182225B71E77E5930081AA4B /* MyFrameLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFrameLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 182225B71E77E5930081AA4B /* MyFrameLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFrameLayout.m; sourceTree = ""; }; 182225B81E77E5930081AA4B /* MyLayoutInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutInner.h; sourceTree = ""; }; 182225B91E77E5930081AA4B /* MyFloatLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MyFloatLayout.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 182225BA1E77E5930081AA4B /* MyFrameLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyFrameLayout.h; sourceTree = ""; }; @@ -407,6 +411,10 @@ 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo8.gif; sourceTree = ""; }; 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest7ViewController.h; sourceTree = ""; }; 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest7ViewController.m; sourceTree = ""; }; + 20DF423C2318A5EE0078CAA0 /* FLLTest9ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest9ViewController.h; sourceTree = ""; }; + 20DF423D2318A6000078CAA0 /* FLLTest9ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest9ViewController.m; sourceTree = ""; }; + 20DF423F2318F4EA0078CAA0 /* MyFlexLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyFlexLayout.h; sourceTree = ""; }; + 20DF42402318F4EA0078CAA0 /* MyFlexLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyFlexLayout.m; sourceTree = ""; }; 20F0DFFB2111749A00CFCE8C /* AllTest11ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AllTest11ViewController.h; sourceTree = ""; }; 20F0DFFC2111749A00CFCE8C /* AllTest11ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest11ViewController.m; sourceTree = ""; }; 20F0DFFE21120A8D00CFCE8C /* FLLTest8ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLLTest8ViewController.h; sourceTree = ""; }; @@ -595,6 +603,8 @@ 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */, 20F0DFFE21120A8D00CFCE8C /* FLLTest8ViewController.h */, 20F0DFFF21120A8D00CFCE8C /* FLLTest8ViewController.m */, + 20DF423C2318A5EE0078CAA0 /* FLLTest9ViewController.h */, + 20DF423D2318A6000078CAA0 /* FLLTest9ViewController.m */, ); name = FlowLayoutDemo; sourceTree = ""; @@ -785,6 +795,8 @@ 18D684001C4F421400A48BB4 /* MyLayout.h */, 182225AB1E77E5930081AA4B /* MyFlowLayout.h */, 182225B41E77E5930081AA4B /* MyFlowLayout.m */, + 20DF423F2318F4EA0078CAA0 /* MyFlexLayout.h */, + 20DF42402318F4EA0078CAA0 /* MyFlexLayout.m */, 182225AC1E77E5930081AA4B /* MyLinearLayout.h */, 182225B21E77E5930081AA4B /* MyLinearLayout.m */, 182225AD1E77E5930081AA4B /* MyFloatLayout.h */, @@ -894,6 +906,7 @@ 205E0C5F20B90347001A8B99 /* MyGrid.h in Headers */, 182DB6421EF7876200E2D65D /* MyGridLayout.h in Headers */, 205642861F4CFF9B00E8BDDE /* MyBorderline.h in Headers */, + 20DF42412318F4EA0078CAA0 /* MyFlexLayout.h in Headers */, 18C15AF81EDF141A00AADEAC /* MyMaker.h in Headers */, 18C15AF71EDF141600AADEAC /* MyLayoutSizeClass.h in Headers */, 18C15AF91EDF142000AADEAC /* MyDimeScale.h in Headers */, @@ -1106,6 +1119,7 @@ 2056430B1F4E53CD00E8BDDE /* MyGridNode.m in Sources */, 205643171F55A03000E8BDDE /* MyLayoutMath.m in Sources */, 18C15AFF1EDF144B00AADEAC /* MyRelativeLayout.m in Sources */, + 20DF42422318F4EA0078CAA0 /* MyFlexLayout.m in Sources */, 182DB6441EF7876200E2D65D /* MyGridLayout.m in Sources */, 18C15B001EDF144B00AADEAC /* MyPathLayout.m in Sources */, 18C15B011EDF144B00AADEAC /* MyFrameLayout.m in Sources */, @@ -1152,6 +1166,7 @@ 18D3C95E1EDF07F800D3DE43 /* FOLTest5ViewController.m in Sources */, 18D3C99C1EDF09BE00D3DE43 /* CFTool.m in Sources */, 18D3C9141EDF074900D3DE43 /* LLTest4ViewController.m in Sources */, + 20DF423E2318A6000078CAA0 /* FLLTest9ViewController.m in Sources */, 18D3C9931EDF08F800D3DE43 /* ViewController.m in Sources */, 18D3C93B1EDF07C000D3DE43 /* FLLTest3ViewController.m in Sources */, 205643181F55A16400E8BDDE /* MyLayoutMath.m in Sources */, @@ -1177,6 +1192,7 @@ 18D3C9891EDF084000D3DE43 /* AllTest5ViewController.m in Sources */, 182225CC1E77E5930081AA4B /* MyRelativeLayout.m in Sources */, 18D3C94C1EDF07E700D3DE43 /* PLTest4ViewController.m in Sources */, + 20A45EC52318FCA50026A18C /* MyFlexLayout.m in Sources */, 2056430C1F4E8B1E00E8BDDE /* MyGridNode.m in Sources */, 182225D11E77E5930081AA4B /* MyLayoutSizeClass.m in Sources */, 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */, @@ -1479,7 +1495,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutDemo; + PRODUCT_BUNDLE_IDENTIFIER = com.meituan.MyLayoutDemo; PRODUCT_NAME = MyLayoutDemo; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1501,7 +1517,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_BUNDLE_IDENTIFIER = com.youngsoft.MyLayoutDemo; + PRODUCT_BUNDLE_IDENTIFIER = com.meituan.MyLayoutDemo; PRODUCT_NAME = MyLayoutDemo; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index 1978887..310e506 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -314,12 +314,12 @@ /** - *视图的宽度布局尺寸对象,可以通过其中的euqalTo方法来设置NSNumber,MyLayoutSize,NSArray,nil这四种值 + *视图的宽度布局尺寸对象,可以通过其中的euqalTo方法来设置NSNumber,MyLayoutSize,NSArray,MyLayoutExtremeSize,UIView,nil这六种值 */ @property(nonatomic, readonly) MyLayoutSize *widthSize; /** - *视图的高度布局尺寸对象,可以通过其中的euqalTo方法来设置NSNumber,MyLayoutSize,NSArray,nil这四种值 + *视图的高度布局尺寸对象,可以通过其中的euqalTo方法来设置NSNumber,MyLayoutSize,NSArray,MyLayoutExtremeSize,UIView,nil这六种值 */ @property(nonatomic, readonly) MyLayoutSize *heightSize; @@ -452,7 +452,6 @@ @property(nonatomic, assign) IBInspectable CGFloat weight; - /** 设置视图不受布局父视图的布局约束控制和不再参与视图的布局,所有设置的其他扩展属性都将失效而必须用frame来设置视图的位置和尺寸,默认值是NO。这个属性主要用于某些视图希望在布局视图中进行特殊处理和进行自定义的设置的场景。比如一个垂直线性布局下有A,B,C三个子视图设置如下: @@ -559,9 +558,9 @@ 2. 在垂直线性布局中只支持左、中、右、水平拉伸对齐。(如果父布局视图设置了gravity,子视图设置了这个属性则这个属性优先级最高) - 3. 在水平线性布局中只支持上、中、下、垂直拉伸对齐。(如果父布局视图设置了gravity,子视图设置了这个属性则这个属性优先级最高) + 3. 在水平线性布局中只支持上、中、下、垂直拉伸、基线对齐。(如果父布局视图设置了gravity,子视图设置了这个属性则这个属性优先级最高) - 4. 在垂直流式布局和垂直浮动布局中用来设置一行内的上、中、下、垂直拉伸对齐。(如果流式父布局视图设置了arrangedGravity,子视图设置了这个属性则这个属性优先级最高) + 4. 在垂直流式布局和垂直浮动布局中用来设置一行内的上、中、下、垂直拉伸、基线对齐。(如果流式父布局视图设置了arrangedGravity,子视图设置了这个属性则这个属性优先级最高) 5. 在水平流式布局和水平浮动布局中用来设置一列内的左、中、右、水平拉伸对齐。(如果流式父布局视图设置了arrangedGravity,子视图时设置了这个属性则这个属性优先级最高) */ @@ -623,7 +622,7 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs 的方法,要求派生类去重载这个方法,这样不同的派生类就可以实现不同的应用场景,这就是布局视图的核心实现机制。 - MyLayout布局库根据实际中常见的场景实现了7种不同的布局视图派生类他们分别是:线性布局、表格布局、相对布局、框架布局、流式布局、浮动布局、路径布局。 + MyLayout布局库根据实际中常见的场景实现了8种不同的布局视图派生类他们分别是:线性布局、表格布局、相对布局、框架布局、流式布局、浮动布局、路径布局、栅格布局。 */ @interface MyBaseLayout : UIView @@ -746,7 +745,7 @@ 布局里面的所有子视图的整体停靠方向以及填充,所谓停靠是指布局视图里面的所有子视图整体在布局视图中的位置,系统默认的停靠是在布局视图的左上角。 @note - 只有框架布局、线性布局、表格布局、流式布局、浮动布局支持gravity属性,相对布局和路径布局不支持。 + 只有框架布局、线性布局、表格布局、流式布局、浮动布局、栅格布局支持gravity属性,相对布局和路径布局不支持。 1. MyGravity_Vert_Top,MyGravity_Vert_Center,MyGravity_Vert_Bottom 表示整体垂直居上,居中,居下 (支持:框架布局,线性布局,表格布局,流式布局,垂直浮动布局) @@ -756,10 +755,14 @@ 4. MyGravity_Horz_Between 表示每列之间的列间距都被拉伸,以便使里面的子视图水平方向填充满整个布局视图。 (支持:水平线性布局,水平表格布局,流式布局) - 5. MyGravity_Vert_Fill 表示布局会拉伸子视图的高度,以便使里面的子视图垂直方向填充满整个布局视图的高度或者子视图平分布局视图的高度。(支持:框架布局,水平线性布局,水平表格布局,流式布局) + 5. MyGravity_Vert_Around 表示每行之间的行间距都被拉伸,以便使里面的子视图垂直方向填充满整个布局视图,首尾子视图和父视图的间距是子视图兄弟之间的一半。 (支持:垂直线性布局,垂直表格布局,流式布局) + + 6. MyGravity_Horz_Around 表示每列之间的列间距都被拉伸,以便使里面的子视图水平方向填充满整个布局视图,首尾子视图和父视图的间距是子视图兄弟之间的一半。 (支持:水平线性布局,水平表格布局,流式布局) + + 7. MyGravity_Vert_Fill 表示布局会拉伸子视图的高度,以便使里面的子视图垂直方向填充满整个布局视图的高度或者子视图平分布局视图的高度。(支持:框架布局,水平线性布局,水平表格布局,流式布局) - 6. MyGravity_Horz_Fill 表示布局会拉伸子视图的宽度,以便使里面的子视图水平方向填充满整个布局视图的宽度或者子视图平分布局视图的宽度。 (支持:框架布局,垂直线性布局,垂直表格布局,流式布局) - 7. MyGravity_Vert_Baseline 表示布局里面的子视图都基线对齐,目前只支持水平线性布局。 + 8. MyGravity_Horz_Fill 表示布局会拉伸子视图的宽度,以便使里面的子视图水平方向填充满整个布局视图的宽度或者子视图平分布局视图的宽度。 (支持:框架布局,垂直线性布局,垂直表格布局,流式布局) + 9. MyGravity_Vert_Baseline 表示布局里面的子视图都基线对齐,目前只支持水平线性布局。 */ @property(nonatomic, assign) IBInspectable MyGravity gravity; @@ -1023,3 +1026,48 @@ +//布局视图拖动器类,用来实现布局内的视图的拖动封装。用于实现布局子视图的拖放处理。 +//布局视图的拖动器类,只支持那些按顺序添加的布局视图,不支持相对布局、框架布局、栅格布局、路径布局。 +//一般情况下我们要实现布局内子视图的: +// 1.UIControlEventTouchDown 事件来处理拖动开始 +// 2.UIControlEventTouchDragInside UIControlEventTouchDragOutside 事件来处理拖动进行中 +// 3. UIControlEventTouchUpInside UIControlEventTouchCancel 事件来处理拖动结束。 + +@interface MyLayoutDragger:NSObject + +//子视图拖动时,拖动区域当前所归属的子视图位置索引。 +@property(nonatomic, assign, readonly) NSUInteger currentIndex; +//子视图拖动时,拖动视图的老的位置索引。 +@property(nonatomic, assign, readonly) NSUInteger oldIndex; + +//当前是否正在拖动中。 +@property(nonatomic, assign, readonly) BOOL hasDragging; + +//设置拖动时不会调整的子视图列表。也就是说数组中指定的子视图在拖动时不会被移动而是总是固定在原有的位置。 +@property(nonatomic,strong) NSArray *exclusiveViews; + +//设置拖动时位置调整的动画时长,默认是0.2秒,设置为0时拖动不产生动画效果。 +@property(nonatomic, assign) NSTimeInterval animateDuration; + +//当拖动的视图和现有视图重叠时是否支持悬停功能,默认为NO。当开启开关后,并且oldIndex和currentIndex相等时则处于悬停状态。开启悬停功能的目的是为了支持一些替换或者更新的能力。 +@property(nonatomic, assign) BOOL canHover; + +//开始拖动,请在子视图view的拖动开始事件处调用这个方法,其中view指定要开始拖动的视图。 +-(void)dragView:(UIView *)view withEvent:(UIEvent *)event; +//拖动中,请在子视图view的拖动过程事件中调用这个方法,其中的view指定拖动中的视图。 +-(void)dragginView:(UIView *)view withEvent:(UIEvent *)event; +//结束拖动,请在子视图view的结束拖动事件中调用这个方法,其中的view指定要结束拖动的视图。 +-(void)dropView:(UIView *)view withEvent:(UIEvent *)event; + +@end + + +@interface MyBaseLayout(MyLayoutDragger) + +//创建一个布局视图拖动器。要求拖动的视图必须是布局视图中的子视图。 +-(MyLayoutDragger*)createLayoutDragger; + +@end + + + diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index bc70c5f..73dc46f 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -19,6 +19,19 @@ void* _myObserverContextC = (void*)20175283; +@interface MyLayoutDragger() + +@property(nonatomic, assign) NSUInteger currentIndex; +@property(nonatomic, assign) NSUInteger oldIndex; +@property(nonatomic, assign) BOOL hasDragging; + +@property(nonatomic, weak) MyBaseLayout *layout; + + +@end + + + /** 窗口对RTL的支持。 */ @@ -351,12 +364,9 @@ -(BOOL)wrapContentSize -(void)setWrapContentSize:(BOOL)wrapContentSize { UIView *sc = self.myCurrentSizeClass; - if (sc.wrapContentSize != wrapContentSize) - { - sc.wrapContentSize = wrapContentSize; - if (self.superview != nil) - [self.superview setNeedsLayout]; - } + sc.wrapContentSize = wrapContentSize; + if (self.superview != nil) + [self.superview setNeedsLayout]; } -(CGFloat)weight @@ -376,7 +386,6 @@ -(void)setWeight:(CGFloat)weight } - -(BOOL)useFrame { return self.myCurrentSizeClass.useFrame; @@ -504,10 +513,6 @@ -(void)resetMyLayoutSettingInSizeClass:(MySizeClass)sizeClass } - - - - -(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass { return [self fetchLayoutSizeClass:sizeClass copyFrom:0xFF]; @@ -1358,6 +1363,16 @@ -(void)setTouchCancelTarget:(id)target action:(SEL)action } +-(MyLayoutDragger*)createLayoutDragger +{ + MyLayoutDragger *dragger = [MyLayoutDragger new]; + dragger.currentIndex = -1; + dragger.oldIndex = -1; + dragger.hasDragging = NO; + dragger.layout = self; + return dragger; +} + @@ -1477,11 +1492,8 @@ -(void)setWrapContentWidth:(BOOL)wrapContentWidth -(void)setWrapContentSize:(BOOL)wrapContentSize { MyBaseLayout *lsc = self.myCurrentSizeClass; - if (lsc.wrapContentSize != wrapContentSize) - { - lsc.wrapContentSize = wrapContentSize; - [self setNeedsLayout]; - } + lsc.wrapContentSize = wrapContentSize; + [self setNeedsLayout]; } @@ -2122,7 +2134,6 @@ -(void)layoutSubviews if (newSelfSize.width != CGFLOAT_MAX && (lsc.wrapContentWidth || lsc.wrapContentHeight)) { - //因为布局子视图的新老尺寸计算在上面有两种不同的方法,因此这里需要考虑两种计算的误差值,而这两种计算的误差值是不超过1/屏幕精度的。 //因此我们认为当二者的值超过误差时我们才认为有尺寸变化。 BOOL isWidthAlter = _myCGFloatErrorNotEqual(newSelfSize.width, oldSelfSize.width, sSizeError); @@ -2383,7 +2394,8 @@ -(MyGravity)myGetSubviewVertGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc vertGravit if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { - sbvVertGravity = MyGravity_Vert_Fill; + if (sbvsc.heightSizeInner.dimeVal == nil && !sbvsc.wrapContentHeight) + sbvVertGravity = MyGravity_Vert_Fill; } else if (sbvsc.centerYPosInner.posVal != nil) { @@ -2420,6 +2432,32 @@ -(CGFloat)myCalcVertGravity:(MyGravity)vertGravity CGFloat bottomMargin = [self myValidMargin:sbvsc.bottomPosInner sbv:sbv calcPos:[sbvsc.bottomPosInner realPosIn:selfSize.height - paddingTop - paddingBottom] selfLayoutSize:selfSize]; + + //垂直压缩。 + CGFloat fixedHeight = topMargin + centerMargin + bottomMargin + pRect->size.height; + if (fixedHeight > selfSize.height) + { + CGFloat floatingHeight = selfSize.height - fixedHeight; + CGFloat totalShrink = sbvsc.topPosInner.shrink + sbvsc.centerYPosInner.shrink + sbvsc.bottomPosInner.shrink + sbvsc.heightSizeInner.shrink; + if (totalShrink != 0.0) + { + topMargin += (sbvsc.topPosInner.shrink / totalShrink) * floatingHeight; + centerMargin += (sbvsc.centerYPosInner.shrink / totalShrink) * floatingHeight; + bottomMargin += (sbvsc.bottomPosInner.shrink / totalShrink) * floatingHeight; + pRect->size.height += (sbvsc.heightSizeInner.shrink / totalShrink) * floatingHeight; + } + } + + //如果是设置垂直拉伸则,如果子视图有约束则不受影响,否则就变为和填充一个意思。 + if (vertGravity == MyGravity_Vert_Stretch) + { + if (sbvsc.wrapContentHeight || sbvsc.heightSizeInner.dimeVal != nil) + vertGravity = MyGravity_Vert_Top; + else + vertGravity = MyGravity_Vert_Fill; + } + + //确保设置基线对齐的视图都是UILabel,UITextField,UITextView if (baselinePos == CGFLOAT_MAX && vertGravity == MyGravity_Vert_Baseline) vertGravity = MyGravity_Vert_Top; @@ -2498,7 +2536,8 @@ -(MyGravity)myGetSubviewHorzGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc horzGravit if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { - sbvHorzGravity = MyGravity_Horz_Fill; + if (sbvsc.widthSizeInner.dimeVal == nil && !sbvsc.wrapContentWidth) + sbvHorzGravity = MyGravity_Horz_Fill; } else if (sbvsc.centerXPosInner.posVal != nil) { @@ -2534,6 +2573,30 @@ -(CGFloat)myCalcHorzGravity:(MyGravity)horzGravity CGFloat trailingMargin = [self myValidMargin:sbvsc.trailingPosInner sbv:sbv calcPos:[sbvsc.trailingPosInner realPosIn:selfSize.width - paddingHorz] selfLayoutSize:selfSize]; + //水平压缩。 + CGFloat fixedWidth = leadingMargin + centerMargin + trailingMargin + pRect->size.width; + if (fixedWidth > selfSize.width) + { + CGFloat floatingWidth = selfSize.width - fixedWidth; + CGFloat totalShrink = sbvsc.leadingPosInner.shrink + sbvsc.centerXPosInner.shrink + sbvsc.trailingPosInner.shrink + sbvsc.widthSizeInner.shrink; + if (totalShrink != 0.0) + { + leadingMargin += (sbvsc.leadingPosInner.shrink / totalShrink) * floatingWidth; + centerMargin += (sbvsc.centerXPosInner.shrink / totalShrink) * floatingWidth; + trailingMargin += (sbvsc.trailingPosInner.shrink / totalShrink) * floatingWidth; + pRect->size.width += (sbvsc.widthSizeInner.shrink / totalShrink) * floatingWidth; + } + } + + //如果是设置水平拉伸则,如果子视图有约束则不受影响,否则就变为和填充一个意思。 + if (horzGravity == MyGravity_Horz_Stretch) + { + if (sbvsc.wrapContentWidth || sbvsc.widthSizeInner.dimeVal != nil) + horzGravity = MyGravity_Horz_Fill; + else + horzGravity = MyGravity_Horz_Leading; + } + if (horzGravity == MyGravity_Horz_Leading) { @@ -2643,10 +2706,13 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize if (lsc.leadingPosInner.posVal != nil && lsc.trailingPosInner.posVal != nil) { - CGFloat leadingMargin = [lsc.leadingPosInner realPosIn:rectSuper.size.width]; - CGFloat trailingMargin = [lsc.trailingPosInner realPosIn:rectSuper.size.width]; - size.width = rectSuper.size.width - leadingMargin - trailingMargin; - size.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:size.width sbvSize:size selfLayoutSize:rectSuper.size]; + if (!lsc.wrapContentWidth && lsc.widthSizeInner.dimeVal == nil) + { + CGFloat leadingMargin = [lsc.leadingPosInner realPosIn:rectSuper.size.width]; + CGFloat trailingMargin = [lsc.trailingPosInner realPosIn:rectSuper.size.width]; + size.width = rectSuper.size.width - leadingMargin - trailingMargin; + size.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:size.width sbvSize:size selfLayoutSize:rectSuper.size]; + } } @@ -2671,11 +2737,13 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize if (lsc.topPosInner.posVal != nil && lsc.bottomPosInner.posVal != nil) { - CGFloat topMargin = [lsc.topPosInner realPosIn:rectSuper.size.height]; - CGFloat bottomMargin = [lsc.bottomPosInner realPosIn:rectSuper.size.height]; - size.height = rectSuper.size.height - topMargin - bottomMargin; - size.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:size.height sbvSize:size selfLayoutSize:rectSuper.size]; - + if (!lsc.wrapContentHeight && lsc.heightSizeInner.dimeVal == nil) + { + CGFloat topMargin = [lsc.topPosInner realPosIn:rectSuper.size.height]; + CGFloat bottomMargin = [lsc.bottomPosInner realPosIn:rectSuper.size.height]; + size.height = rectSuper.size.height - topMargin - bottomMargin; + size.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:size.height sbvSize:size selfLayoutSize:rectSuper.size]; + } } if (size.height < 0) @@ -2755,9 +2823,11 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview if (lsc.leadingPosInner.posVal != nil && lsc.trailingPosInner.posVal != nil) { isAdjust = YES; - lsc.wrapContentWidth = NO; - rectSelf.size.width = rectSuper.size.width - leadingMargin - trailingMargin; - rectSelf.size.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:rectSelf.size.width sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; + if (!lsc.wrapContentWidth && lsc.widthSizeInner.dimeVal == nil) + { + rectSelf.size.width = rectSuper.size.width - leadingMargin - trailingMargin; + rectSelf.size.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:rectSelf.size.width sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; + } #if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) @@ -2843,9 +2913,11 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview if (lsc.topPosInner.posVal != nil && lsc.bottomPosInner.posVal != nil) { isAdjust = YES; - lsc.wrapContentHeight = NO; - rectSelf.size.height = rectSuper.size.height - topMargin - bottomMargin; - rectSelf.size.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:rectSelf.size.height sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; + if (!lsc.wrapContentHeight && lsc.heightSizeInner.dimeVal == nil) + { + rectSelf.size.height = rectSuper.size.height - topMargin - bottomMargin; + rectSelf.size.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:rectSelf.size.height sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; + } #if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) @@ -2978,7 +3050,7 @@ -(CGFloat)myGetBoundLimitMeasure:(MyLayoutSize*)boundDime sbv:(UIView*)sbv dimeT return value; MyLayoutValueType lValueType = boundDime.dimeValType; - if (lValueType == MyLayoutValueType_NSNumber) + if (lValueType == MyLayoutValueType_NSNumber || lValueType == MyLayoutValueType_Extreme) { value = boundDime.dimeNumVal.doubleValue; } @@ -3017,11 +3089,11 @@ -(CGFloat)myGetBoundLimitMeasure:(MyLayoutSize*)boundDime sbv:(UIView*)sbv dimeT { if (boundDime.dimeRelaVal.dime == MyGravity_Horz_Fill) { - value = boundDime.dimeRelaVal.view.estimatedRect.size.width; + value = boundDime.dimeRelaVal.view.myEstimatedWidth; } else { - value = boundDime.dimeRelaVal.view.estimatedRect.size.height; + value = boundDime.dimeRelaVal.view.myEstimatedHeight; } } @@ -3471,12 +3543,12 @@ -(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sb if ([sbv isKindOfClass:[MyBaseLayout class]]) { - if (sbvsc.wrapContentHeight && (sbvsc.heightSizeInner.dimeVal != nil || (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil))) + if (sbvsc.wrapContentHeight && sbvsc.heightSizeInner.dimeVal != nil) { sbvsc.wrapContentHeight = NO; } - if (sbvsc.wrapContentWidth && (sbvsc.widthSizeInner.dimeVal != nil || (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil))) + if (sbvsc.wrapContentWidth && sbvsc.widthSizeInner.dimeVal != nil) { sbvsc.wrapContentWidth = NO; } @@ -3644,15 +3716,19 @@ -(void)myCalcSubViewRect:(UIView*)sbv } //宽度不依赖布局并且没有同时设置左右边距则参与最大宽度计算。 - if ((sbvsc.widthSizeInner.dimeRelaVal.view != self) && - (sbvsc.leadingPosInner.posVal == nil || sbvsc.trailingPosInner.posVal == nil)) + if ((sbvsc.widthSizeInner.dimeVal != nil && sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) || sbvsc.wrapContentWidth) { if (_myCGFloatLess(pMaxWrapSize->width, sbvmyFrame.width + sbvsc.leadingPosInner.absVal + sbvsc.centerXPosInner.absVal + sbvsc.trailingPosInner.absVal + paddingLeading + paddingTrailing)) pMaxWrapSize->width = sbvmyFrame.width + sbvsc.leadingPosInner.absVal + sbvsc.centerXPosInner.absVal + sbvsc.trailingPosInner.absVal + paddingLeading + paddingTrailing; - if (_myCGFloatLess(pMaxWrapSize->width,sbvmyFrame.trailing + sbvsc.trailingPosInner.absVal + paddingTrailing)) + //只有不居中和底部对齐才比较底部。 + if (sbvsc.centerXPosInner.posVal == nil && + sbvsc.trailingPosInner.posVal == nil && + _myCGFloatLess(pMaxWrapSize->width,sbvmyFrame.trailing + sbvsc.trailingPosInner.absVal + paddingTrailing)) + { pMaxWrapSize->width = sbvmyFrame.trailing + sbvsc.trailingPosInner.absVal + paddingTrailing; + } } } @@ -3667,14 +3743,18 @@ -(void)myCalcSubViewRect:(UIView*)sbv } //高度不依赖布局并且没有同时设置上下边距则参与最大高度计算。 - if ((sbvsc.heightSizeInner.dimeRelaVal.view != self) && - (sbvsc.topPosInner.posVal == nil || sbvsc.bottomPosInner.posVal == nil)) + if ((sbvsc.heightSizeInner.dimeVal != nil && sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) || sbvsc.wrapContentHeight) { if (_myCGFloatLess(pMaxWrapSize->height, sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.centerYPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom)) pMaxWrapSize->height = sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.centerYPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom; - if (_myCGFloatLess(pMaxWrapSize->height, sbvmyFrame.bottom + sbvsc.bottomPosInner.absVal + paddingBottom)) + //只有在不居中对齐和底部对齐时才比较底部。 + if (sbvsc.centerYPosInner.posVal == nil && + sbvsc.bottomPosInner.posVal == nil && + _myCGFloatLess(pMaxWrapSize->height, sbvmyFrame.bottom + sbvsc.bottomPosInner.absVal + paddingBottom)) + { pMaxWrapSize->height = sbvmyFrame.bottom + sbvsc.bottomPosInner.absVal + paddingBottom; + } } } } @@ -3821,3 +3901,110 @@ -(void)mySetNeedLayoutAllSubviews:(UIView *)v } @end + +@implementation MyLayoutDragger + + +//开始拖动 +-(void)dragView:(UIView *)view withEvent:(UIEvent *)event +{ + if (self.layout == nil) + return; + + self.oldIndex = [self.layout.subviews indexOfObject:view]; + self.currentIndex = self.oldIndex; + self.hasDragging = NO; +} + +//拖动中,在拖动时要排除移动的子视图序列,动画的时长。返回是否拖动成功。 +-(void)dragginView:(UIView *)view withEvent:(UIEvent *)event +{ + if (self.layout == nil) + return; + + self.hasDragging = YES; + + //取出拖动时当前的位置点。 + CGPoint pt = [[event touchesForView:view].anyObject locationInView:self.layout]; + + UIView *sbv2 = nil; //sbv2保存拖动时手指所在的视图。 + //判断当前手指在具体视图的位置。这里要排除self.addButton的位置(因为这个按钮将固定不调整)。 + for (UIView *sbv in self.layout.subviews) + { + if (sbv != view && view.useFrame && ![self.exclusiveViews containsObject:sbv]) + { + CGRect rc1 = sbv.frame; + if (CGRectContainsPoint(rc1, pt)) + { + sbv2 = sbv; + break; + } + } + } + + //如果拖动的控件sender和手指下当前其他的兄弟控件有重合时则意味着需要将当前控件插入到手指下的sbv2所在的位置,并且调整sbv2的位置。 + if (sbv2 != nil) + { + if (self.animateDuration > 0) + [self.layout layoutAnimationWithDuration:self.animateDuration]; + + //得到要移动的视图的位置索引。 + self.currentIndex = [self.layout.subviews indexOfObjectIdenticalTo:sbv2]; + if (self.oldIndex != self.currentIndex) + { + self.oldIndex = self.currentIndex; + } + else + { + if (!self.canHover) + { + if (sbv2.center.x > view.center.x) + self.currentIndex = self.oldIndex + 1; + } + } + + for (NSInteger i = self.layout.subviews.count - 1; i > self.currentIndex; i--) + { + [self.layout exchangeSubviewAtIndex:i withSubviewAtIndex:i - 1]; + } + + //因为sender在bringSubviewToFront后变为了最后一个子视图,因此要调整正确的位置。 + //经过上面的sbv2的位置调整完成后,需要重新激发布局视图的布局,因此这里要设置autoresizesSubviews为YES。 + self.layout.autoresizesSubviews = YES; + view.useFrame = NO; + view.noLayout = YES; + //这里设置为YES表示布局时不会改变sender的真实位置而只是在布局视图中占用一个位置和尺寸,正是因为只是占用位置,因此会调整其他视图的位置。 + [self.layout layoutIfNeeded]; + + } + + //在进行sender的位置调整时,要把sender移动到最顶端,也就子视图数组的的最后。同时布局视图不能激发子视图布局,因此要把autoresizesSubviews设置为NO,同时因为要自定义sender的位置,因此要把useFrame设置为YES,并且恢复noLayout为NO。 + [self.layout bringSubviewToFront:view]; //把拖动的子视图放在最后,这样这个子视图在移动时就会在所有兄弟视图的上面。 + self.layout.autoresizesSubviews = NO; //在拖动时不要让布局视图激发布局 + view.useFrame = YES; //因为拖动时,拖动的控件需要自己确定位置,不能被布局约束,因此必须要将useFrame设置为YES下面的center设置才会有效。 + view.center = pt; //因为useFrame设置为了YES所有这里可以直接调整center,从而实现了位置的自定义设置。 + view.noLayout = NO; //恢复noLayout为NO。 +} + +//结束拖动 +-(void)dropView:(UIView *)view withEvent:(UIEvent *)event +{ + if (self.layout == nil) + return; + + if (!self.hasDragging) + return; + self.hasDragging = NO; + + //当抬起时,需要让拖动的子视图调整到正确的顺序,并重新参与布局,因此这里要把拖动的子视图的useFrame设置为NO,同时把布局视图的autoresizesSubviews还原为YES。 + for (NSInteger i = self.layout.subviews.count - 1; i > self.currentIndex; i--) + { + [self.layout exchangeSubviewAtIndex:i withSubviewAtIndex:i - 1]; + } + + view.useFrame = NO; //让拖动的子视图重新参与布局,将useFrame设置为NO + self.layout.autoresizesSubviews = YES; //让布局视图可以重新激发布局,这里还原为YES。 +} + + +@end diff --git a/MyLayout/Lib/MyFlexLayout.h b/MyLayout/Lib/MyFlexLayout.h new file mode 100644 index 0000000..66ed488 --- /dev/null +++ b/MyLayout/Lib/MyFlexLayout.h @@ -0,0 +1,91 @@ +// +// MyFlexLayout.h +// MyLayout +// +// Created by oubaiquan on 2019/8/30. +// Copyright © 2019 YoungSoft. All rights reserved. +// + +#import "MyFlowLayout.h" + + +@interface MyFlexItem:NSObject + ++(CGFloat)auto; + +-(MyFlexItem* (^)(NSInteger))order; +-(MyFlexItem* (^)(CGFloat))flex_grow; +-(MyFlexItem* (^)(CGFloat))flex_shrink; +-(MyFlexItem* (^)(CGFloat))flex_basis; +-(MyFlexItem* (^)(int))align_self; + +-(MyFlexItem* (^)(CGFloat))width; +-(MyFlexItem* (^)(CGFloat))height; +-(MyFlexItem* (^)(CGFloat))margin_top; +-(MyFlexItem* (^)(CGFloat))margin_bottom; +-(MyFlexItem* (^)(CGFloat))margin_left; +-(MyFlexItem* (^)(CGFloat))margin_right; + + +-(__kindof UIView* (^)(UIView*))addTo; + +@property(nonatomic, weak, readonly) __kindof UIView *view; + +@end + +@class MyFlexLayout; + +@interface MyFlex:MyFlexItem + ++(int)row; ++(int)row_reverse; ++(int)column; ++(int)column_reverse; + ++(int)nowrap; ++(int)wrap; ++(int)wrap_reverse; + ++(int)flex_start; ++(int)flex_end; ++(int)center; ++(int)space_between; ++(int)sapce_around; ++(int)baseline; ++(int)stretch; + + +-(MyFlex* (^)(int))flex_direction; + +-(MyFlex* (^)(int))flex_wrap; + +-(MyFlex* (^)(int))flex_flow; + +-(MyFlex* (^)(int))justify_content; + +-(MyFlex* (^)(int))align_items; + +-(MyFlex* (^)(int))align_content; + +-(MyFlex* (^)(UIEdgeInsets))padding; +-(MyFlex* (^)(CGFloat))vert_space; +-(MyFlex* (^)(CGFloat))horz_space; + + +@property(nonatomic, weak, readonly) MyFlexLayout *layout; + +@end + + +@interface UIView(MyFlexLayout) + +@property(nonatomic, readonly, strong) MyFlexItem *flexItem; + +@end + +//row必须指定宽度如果没有则是和父视图等宽,如果没有指定高度则高度自适应。column则反之。 +@interface MyFlexLayout:MyFlowLayout + +@property(nonatomic, readonly, strong, readonly) MyFlex *flex; + +@end diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m new file mode 100644 index 0000000..c1395c6 --- /dev/null +++ b/MyLayout/Lib/MyFlexLayout.m @@ -0,0 +1,709 @@ +// +// MyFlexLayout.m +// MyLayout +// +// Created by oubaiquan on 2019/8/30. +// Copyright © 2019 YoungSoft. All rights reserved. +// + +#import "MyFlexLayout.h" +#import "MyLayoutInner.h" +#import + +const char * const ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM = "ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM"; + + +static const int _sauto = -1; + +static const int _srow = 0; +static const int _srow_reverse = 2; +static const int _scolumn = 1; +static const int _scolumn_reverse = 3; + +static const int _snowrap = 0; +static const int _swrap = 4; +static const int _swrap_reverse = 12; + +static const int _sflex_start = 0; +static const int _sflex_end = 1; +static const int _scenter = 2; +static const int _sspace_between = 3; +static const int _sspace_around = 4; +static const int _sbaseline = 5; +static const int _sstretch = 6; + + +@implementation MyFlexItem +{ + @package + int _align_self; + NSInteger _order; + CGFloat _flex_grow; + CGFloat _flex_shrink; + CGFloat _flex_basis; + CGFloat _width; + CGFloat _height; + + __weak UIView *_view; +} + ++(CGFloat)auto +{ + return _sauto; +} + + +-(instancetype)initWithView:(UIView*)view; +{ + self = [super init]; + if (self != nil) + { + _order = 0; + _flex_grow = 0; + _flex_basis = _sauto; + _flex_shrink = 1; + _align_self = _sauto; + _view = view; + _width = CGFLOAT_MAX; + _height = CGFLOAT_MAX; + } + return self; +} + +-(MyFlexItem* (^)(NSInteger))order +{ + return ^id(NSInteger val) { + self->_order = val; + return self; + }; +} + +-(MyFlexItem* (^)(CGFloat))flex_grow +{ + return ^id(CGFloat val) { + self->_flex_grow = val; + return self; + }; +} + +-(MyFlexItem* (^)(CGFloat))flex_shrink +{ + return ^id(CGFloat val) { + self->_flex_shrink = val; + return self; + }; +} + +-(MyFlexItem* (^)(CGFloat))flex_basis +{ + return ^id(CGFloat val) { + self->_flex_basis = val; + return self; + }; +} + +-(MyFlexItem* (^)(int))align_self +{ + return ^id(int val) { + self->_align_self = val; + return self; + }; +} + +-(__kindof UIView* (^)(UIView*))addTo +{ + return ^(UIView *val) { + + if (_width != CGFLOAT_MAX) + { + if (_width == MyLayoutSize.fill) + self->_view.widthSize.equalTo(val); + else if (_width < 1 && _width > 0) + self->_view.widthSize.equalTo(val.widthSize).multiply(_width); + else; + } + + if (_height != CGFLOAT_MAX) + { + if (_height == MyLayoutSize.fill) + self->_view.heightSize.equalTo(val); + else if (_height < 1 && _height > 0) + self->_view.heightSize.equalTo(val.heightSize).multiply(_height); + else; + } + + [val addSubview:self->_view]; + return self->_view; + }; +} + +-(MyFlexItem* (^)(CGFloat))width +{ + return ^id(CGFloat val) { + _width = val; + if (_width == MyLayoutSize.fill) + { + if (self->_view.superview) + self->_view.widthSize.equalTo(self->_view.superview); + } + else if (_width == MyLayoutSize.wrap) + { + self->_view.wrapContentWidth = YES; + } + else + { + if (_width < 1 && _width > 0) + { + if (self->_view.superview) + self->_view.widthSize.equalTo(self->_view.superview).multiply(_width); + } + else + self->_view.myWidth = _width; + } + return self; + }; +} + +-(MyFlexItem* (^)(CGFloat))height +{ + return ^id(CGFloat val) { + _height = val; + if (_height == MyLayoutSize.fill) + { + if (self->_view.superview) + self->_view.heightSize.equalTo(self->_view.superview); + } + else if (_height == MyLayoutSize.wrap) + { + self->_view.wrapContentHeight = YES; + } + else + { + if (_height < 1 && _height > 0) + { + if (self->_view.superview) + self->_view.heightSize.equalTo(self->_view.superview).multiply(_height); + } + else + self->_view.myHeight = _height; + } + return self; + }; +} + +-(MyFlexItem* (^)(CGFloat))margin_top +{ + return ^id(CGFloat val) { + self->_view.myTop = val; + return self; + }; +} + +-(MyFlexItem* (^)(CGFloat))margin_bottom +{ + return ^id(CGFloat val) { + self->_view.myBottom = val; + return self; + }; +} + +-(MyFlexItem* (^)(CGFloat))margin_left +{ + return ^id(CGFloat val) { + self->_view.myLeft = val; + return self; + }; +} + +-(MyFlexItem* (^)(CGFloat))margin_right +{ + return ^id(CGFloat val) { + self->_view.myRight = val; + return self; + }; +} + +-(UIView*)view +{ + return self->_view; +} + +@end + + +@implementation MyFlex +{ + @package + int _flex_direction; + int _flex_wrap; + int _justify_content; + int _align_items; + int _align_content; +} + ++(int)row +{ + return _srow; +} + ++(int)row_reverse +{ + return _srow_reverse; +} ++(int)column +{ + return _scolumn; +} ++(int)column_reverse +{ + return _scolumn_reverse; +} + ++(int)nowrap +{ + return _snowrap; +} ++(int)wrap +{ + return _swrap; +} ++(int)wrap_reverse +{ + return _swrap_reverse; +} + ++(int)flex_start +{ + return _sflex_start; +} ++(int)flex_end +{ + return _sflex_end; +} ++(int)center +{ + return _scenter; +} ++(int)space_between +{ + return _sspace_between; +} ++(int)sapce_around +{ + return _sspace_around; +} ++(int)baseline +{ + return _sbaseline; +} ++(int)stretch +{ + return _sstretch; +} + +-(instancetype)initWithView:(UIView*)view +{ + self = [super initWithView:view]; + if (self != nil) + { + _flex_direction = _srow; + _flex_wrap = _snowrap; + _justify_content = _sflex_start; + _align_items = _sstretch; + _align_content = _sstretch; + } + return self; +} + +-(MyFlexLayout*)layout +{ + return (MyFlexLayout*)_view; +} + +-(MyFlex* (^)(int))flex_direction +{ + return ^id(int val){ + self->_flex_direction = val; + return self; + }; +} + +-(MyFlex* (^)(int))flex_wrap +{ + return ^id(int val){ + self->_flex_wrap = val; + return self; + }; +} + +-(MyFlex* (^)(int))flex_flow +{ + return ^id(int val) { + //取方向值。 + int direction = val & 0x03; + //取换行值。 + int wrap = val & 0x0c; + return self.flex_direction(direction).flex_wrap(wrap); + }; +} + +-(MyFlex* (^)(int))justify_content +{ + return ^id(int val) { + self->_justify_content = val; + return self; + }; +} + +-(MyFlex* (^)(int))align_items +{ + return ^id(int val) { + self->_align_items = val; + return self; + }; +} + +-(MyFlex* (^)(int))align_content +{ + return ^id(int val) { + self->_align_content = val; + return self; + }; +} + +-(MyFlex* (^)(UIEdgeInsets))padding +{ + return ^id(UIEdgeInsets val) { + self.layout.padding = val; + return self; + }; +} + +-(MyFlex* (^)(CGFloat))vert_space +{ + return ^id(CGFloat val) { + self.layout.subviewVSpace = val; + return self; + }; +} + +-(MyFlex* (^)(CGFloat))horz_space +{ + return ^id(CGFloat val) { + self.layout.subviewHSpace = val; + return self; + }; +} + +@end + +@implementation UIView(MyFlexLayout) + +-(UIView* (^)(UIView*))add +{ + return ^id(UIView* val) { + [self addSubview:val]; + return self; + }; +} + +-(MyFlexItem*)flexItem +{ + MyFlexItem *obj = nil; + if ([self isKindOfClass:[MyFlexLayout class]] ) + { + obj = ((MyFlexLayout*)self).flex; + } + else + { + obj = (MyFlexItem*)objc_getAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM); + if (obj == nil) + { + obj = [[MyFlexItem alloc] initWithView:self]; + objc_setAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + } + return obj; +} + +@end + + + +@implementation MyFlexLayout + +-(instancetype)init +{ + self = [super init]; + if (self != nil) + { + _flex = [[MyFlex alloc] initWithView:self]; + self.orientation = MyOrientation_Vert; + self.arrangedCount = NSIntegerMax; //单行 + } + return self; +} + + +-(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs +{ + MyFlexLayout *lsc = self.myCurrentSizeClass; + + //最先设置方向。 + switch (self.flex->_flex_direction) { + case _scolumn_reverse: //column_reverse + lsc.orientation = MyOrientation_Horz; + lsc.layoutTransform = CGAffineTransformMake(1,0,0,-1,0,0); + break; + case _scolumn: //column; + lsc.orientation = MyOrientation_Horz; + lsc.layoutTransform = CGAffineTransformIdentity; + break; + case _srow_reverse: //row_reverse + lsc.orientation = MyOrientation_Vert; + lsc.layoutTransform = CGAffineTransformMake(-1,0,0,1,0,0); + break; + case _srow: + default: + lsc.orientation = MyOrientation_Vert; + lsc.layoutTransform = CGAffineTransformIdentity; + break; + } + + int flex_wrap = self.flex->_flex_wrap; + + //处理子视图的flexitem设置。 + if (sbs == nil) + sbs = [self myGetLayoutSubviews]; + + //按order排序。 + [sbs sortWithOptions:NSSortStable usingComparator:^NSComparisonResult(UIView* _Nonnull obj1, UIView* _Nonnull obj2) { + + return obj1.flexItem->_order - obj2.flexItem->_order; + }]; + + for (UIView *sbv in sbs) + { + MyFlexItem *flexItem = sbv.flexItem; + UIView *sbvsc = sbv.myCurrentSizeClass; + + //flex_grow,如果子视图有设置grow则父视图的换行不起作用。 + sbvsc.weight = flexItem->_flex_grow; + if (flexItem->_flex_grow != 0) + { + flex_wrap = _snowrap; + } + + //flex_shrink + if (lsc.orientation == MyOrientation_Vert) + { + sbvsc.widthSize.shrink = flexItem->_flex_shrink !=_sauto?flexItem->_flex_shrink:0; + } + else + { + sbvsc.heightSize.shrink = flexItem->_flex_shrink !=_sauto?flexItem->_flex_shrink:0; + } + + //伸缩基准值设置。 + if (flexItem->_flex_basis != _sauto) + { + if (lsc.orientation == MyOrientation_Vert) + { + if (flexItem->_flex_basis < 1) + sbvsc.widthSize.equalTo(lsc.widthSize).multiply(flexItem->_flex_basis); + else + sbvsc.widthSize.equalTo(@(flexItem->_flex_basis)); + } + else + { + if (flexItem->_flex_basis < 1) + sbvsc.heightSize.equalTo(lsc.heightSize).multiply(flexItem->_flex_basis); + else + sbvsc.heightSize.equalTo(@(flexItem->_flex_basis)); + } + } + + //对齐方式设置。 + switch (flexItem->_align_self) { + case _sauto: + sbvsc.alignment = MyGravity_None; + break; + case _sflex_start: + sbvsc.alignment = (lsc.orientation == MyOrientation_Vert)? MyGravity_Vert_Top : MyGravity_Horz_Leading; + break; + case _sflex_end: + sbvsc.alignment = (lsc.orientation == MyOrientation_Vert)? MyGravity_Vert_Bottom : MyGravity_Horz_Trailing; + break; + case _scenter: + sbvsc.alignment = (lsc.orientation == MyOrientation_Vert)? MyGravity_Vert_Center : MyGravity_Horz_Center; + break; + case _sbaseline: + sbvsc.alignment = (lsc.orientation == MyOrientation_Vert)? MyGravity_Vert_Baseline : MyGravity_None; + break; + case _sstretch: + sbvsc.alignment = (lsc.orientation == MyOrientation_Vert)? MyGravity_Vert_Stretch : MyGravity_Horz_Stretch; + break; + default: + break; + } + } + + + //再次处理布局视图的其他属性设置,这里因为子视图的一些特性会影响布局视图的属性设置,所以这里放在子视图后面。 + + //设置换行,如果子视图有grow则不支持换行。 + switch (flex_wrap) { + case _swrap: + lsc.arrangedCount = 0; + lsc.layoutTransform = CGAffineTransformIdentity; + break; + case _swrap_reverse: + lsc.arrangedCount = 0; + lsc.layoutTransform = (lsc.orientation == MyOrientation_Vert)? CGAffineTransformMake(-1,0,0,1,0,0):CGAffineTransformMake(1,0,0,-1,0,0); + break; + case _snowrap: + default: + lsc.arrangedCount = NSIntegerMax; + lsc.layoutTransform = CGAffineTransformIdentity; + break; + } + + //设置主轴的水平对齐和拉伸 + MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; + MyGravity horzGravity = lsc.gravity & MyGravity_Vert_Mask; + + switch (self.flex->_justify_content) { + case _sflex_end: + if (lsc.orientation == MyOrientation_Vert) + lsc.gravity = MyGravity_Horz_Trailing | vertGravity; + else + lsc.gravity = MyGravity_Vert_Bottom | horzGravity; + break; + case _scenter: + if (lsc.orientation == MyOrientation_Vert) + lsc.gravity = MyGravity_Horz_Center | vertGravity; + else + lsc.gravity = MyGravity_Vert_Center | horzGravity; + break; + case _sspace_between: + if (lsc.orientation == MyOrientation_Vert) + lsc.gravity = MyGravity_Horz_Between | vertGravity; + else + lsc.gravity = MyGravity_Vert_Between | horzGravity; + break; + case _sspace_around: + if (lsc.orientation == MyOrientation_Vert) + lsc.gravity = MyGravity_Horz_Around | vertGravity; + else + lsc.gravity = MyGravity_Vert_Around | horzGravity; + break; + case _sflex_start: + if (lsc.orientation == MyOrientation_Vert) + lsc.gravity = MyGravity_Horz_Leading | vertGravity; + else + lsc.gravity = MyGravity_Vert_Top | horzGravity; + default: + break; + } + + //次轴的对齐处理。 + MyGravity vertArrangedGravity = lsc.arrangedGravity & MyGravity_Horz_Mask; + MyGravity horzArrangedGravity = lsc.arrangedGravity & MyGravity_Vert_Mask; + + switch (self.flex->_align_items) { + case _sflex_end: + if (lsc.orientation == MyOrientation_Vert) + lsc.arrangedGravity = MyGravity_Vert_Bottom | horzArrangedGravity; + else + lsc.arrangedGravity = MyGravity_Horz_Trailing | vertArrangedGravity; + break; + case _scenter: + if (lsc.orientation == MyOrientation_Vert) + lsc.arrangedGravity = MyGravity_Vert_Center | horzArrangedGravity; + else + lsc.arrangedGravity = MyGravity_Horz_Center | vertArrangedGravity; + break; + case _sbaseline: + if (lsc.orientation == MyOrientation_Vert) + lsc.arrangedGravity = MyGravity_Vert_Baseline | horzArrangedGravity; + else + lsc.arrangedGravity = MyGravity_Horz_Leading | vertArrangedGravity; + break; + case _sflex_start: + if (lsc.orientation == MyOrientation_Vert) + lsc.arrangedGravity = MyGravity_Vert_Top | horzArrangedGravity; + else + lsc.arrangedGravity = MyGravity_Horz_Leading | vertArrangedGravity; + break; + case _sstretch: + default: + if (lsc.orientation == MyOrientation_Vert) + lsc.arrangedGravity = MyGravity_Vert_Stretch | horzArrangedGravity; + else + lsc.arrangedGravity = MyGravity_Horz_Stretch | vertArrangedGravity; + break; + } + + vertGravity = lsc.gravity & MyGravity_Horz_Mask; + horzGravity = lsc.gravity & MyGravity_Vert_Mask; + //只有换行才有用,单行不起作用。 + if (lsc.arrangedCount == 0) + { + switch (self.flex->_align_content) { + case _sflex_end: + if (lsc.orientation == MyOrientation_Horz) + lsc.gravity = MyGravity_Horz_Trailing | vertGravity; + else + lsc.gravity = MyGravity_Vert_Bottom | horzGravity; + break; + case _scenter: + if (lsc.orientation == MyOrientation_Horz) + lsc.gravity = MyGravity_Horz_Center | vertGravity; + else + lsc.gravity = MyGravity_Vert_Center | horzGravity; + break; + case _sspace_between: + if (lsc.orientation == MyOrientation_Horz) + lsc.gravity = MyGravity_Horz_Between | vertGravity; + else + lsc.gravity = MyGravity_Vert_Between | horzGravity; + break; + case _sspace_around: + if (lsc.orientation == MyOrientation_Horz) + lsc.gravity = MyGravity_Horz_Around | vertGravity; + else + lsc.gravity = MyGravity_Vert_Around | horzGravity; + break; + case _sflex_start: + if (lsc.orientation == MyOrientation_Horz) + lsc.gravity = MyGravity_Horz_Leading | vertGravity; + else + lsc.gravity = MyGravity_Vert_Top | horzGravity; + break; + case _sstretch: + default: + if (lsc.orientation == MyOrientation_Horz) + lsc.gravity = MyGravity_Horz_Stretch | vertGravity; + else + lsc.gravity = MyGravity_Vert_Stretch | horzGravity; + break; + } + } + else + { + if (lsc.orientation == MyOrientation_Horz) + { + lsc.gravity = vertGravity; + } + else + { + lsc.gravity = horzGravity; + } + } + + return [super calcLayoutRect:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; +} + + + +@end diff --git a/MyLayout/Lib/MyFloatLayout.h b/MyLayout/Lib/MyFloatLayout.h index 9c5490a..fa9e9e4 100644 --- a/MyLayout/Lib/MyFloatLayout.h +++ b/MyLayout/Lib/MyFloatLayout.h @@ -104,21 +104,6 @@ @property(nonatomic,assign) IBInspectable MyOrientation orientation; - - -/** - 不做布局边界尺寸的限制,子视图不会自动换行。因此当设置为YES时,子视图需要明确设置clearFloat来实现主动换行的处理。默认为NO。这个属性设置的意义使得我们可以自定义子视图的换行,而不是让子视图根据布局视图的尺寸限制自动换行。 - - 1. 当布局的orientation为MyOrientation_Vert并且wrapContentWidth为YES时,这个属性设置为YES才生效。 - - 2. 当布局的orientation为MyOrientation_Horz并且wrapContentHeight为YES时,这个属性设置为YES才生效。 - - @note 当属性设置为YES时,子视图不能将扩展属性reverseFloat设置为YES,同时不能设置weight属性,否则将导致结果异常。 - @note 这个属性设置为YES时,在左右浮动布局中,子视图只能向左浮动,并且没有右边界的限制,因此如果子视图没有clearFloat时则总是排列在前一个子视图的右边,并不会自动换行,因此为了让这个属性生效,布局视图必须要同时设置wrapContentWidth为YES。 - @note 这个属性设置为YES时,在上下浮动布局中,子视图只能向上浮动,并且没有下边界的限制,因此如果子视图没有设置clearFloat时则总是排列在前一个子视图的下边,并不会自动换行,因此为了让这个属性生效,布局视图必须要同时设置wrapContentHeight为YES. - */ -@property(nonatomic,assign) IBInspectable BOOL noBoundaryLimit; - /** 在一些应用场景中我们希望子视图的宽度是固定的但间距是浮动的,这样就尽可能在一排中容纳更多的子视图。比如设置每个子视图的宽度固定为80,那么在小屏幕下每排只能放3个,而大屏幕则每排能放4个或者5个子视图。 因此您可以通过如下方法来设置子视图的固定尺寸和最小最大浮动间距。这个方法会根据您当前布局的方向不同而具有不同的意义: @@ -140,3 +125,20 @@ @end +@interface MyFloatLayout(MyDeprecated) + + +/** + 不做布局边界尺寸的限制,子视图不会自动换行。因此当设置为YES时,子视图需要明确设置clearFloat来实现主动换行的处理。默认为NO。这个属性设置的意义使得我们可以自定义子视图的换行,而不是让子视图根据布局视图的尺寸限制自动换行。 + + 1. 当布局的orientation为MyOrientation_Vert并且wrapContentWidth为YES时,这个属性设置为YES才生效。 + + 2. 当布局的orientation为MyOrientation_Horz并且wrapContentHeight为YES时,这个属性设置为YES才生效。 + + @note 当属性设置为YES时,子视图不能将扩展属性reverseFloat设置为YES,同时不能设置weight属性,否则将导致结果异常。 + @note 这个属性设置为YES时,在左右浮动布局中,子视图只能向左浮动,并且没有右边界的限制,因此如果子视图没有clearFloat时则总是排列在前一个子视图的右边,并不会自动换行,因此为了让这个属性生效,布局视图必须要同时设置wrapContentWidth为YES。 + @note 这个属性设置为YES时,在上下浮动布局中,子视图只能向上浮动,并且没有下边界的限制,因此如果子视图没有设置clearFloat时则总是排列在前一个子视图的下边,并不会自动换行,因此为了让这个属性生效,布局视图必须要同时设置wrapContentHeight为YES. + */ +@property(nonatomic,assign) IBInspectable BOOL noBoundaryLimit MYDEPRECATED("此属性已经过期,请直接设置布局视图的wrapContentWidth或者wrapContentHeight为YES即可"); + +@end diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index d3ea365..95585f5 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -95,17 +95,12 @@ -(MyOrientation)orientation -(void)setNoBoundaryLimit:(BOOL)noBoundaryLimit { - MyFloatLayout *lsc = self.myCurrentSizeClass; - if (lsc.noBoundaryLimit != noBoundaryLimit) - { - lsc.noBoundaryLimit = noBoundaryLimit; - [self setNeedsLayout]; - } + NSLog(@"属性已经过期!请直接设置wrapContentWidth或者wrapContentHeight即可"); } -(BOOL)noBoundaryLimit { - return self.myCurrentSizeClass.noBoundaryLimit; + return NO; } @@ -458,12 +453,8 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( CGFloat paddingHorz = paddingLeading + paddingTrailing; // CGFloat paddingVert = paddingTop + paddingBottom; - BOOL hasBoundaryLimit = YES; - if (lsc.wrapContentWidth && lsc.noBoundaryLimit) - hasBoundaryLimit = NO; - //如果没有边界限制我们将高度设置为最大。。 - if (!hasBoundaryLimit) + if (lsc.wrapContentWidth) selfSize.width = CGFLOAT_MAX; @@ -475,31 +466,6 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( //设置子视图的宽度和高度。 [self myCalcFloatLayoutSubviewsSize:sbs lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing subviewSize:subviewSize isWidth:YES]; - //遍历所有的子视图,查看是否有子视图的宽度会比视图自身要宽,如果有且有包裹属性则扩充自身的宽度 - if (lsc.wrapContentWidth && hasBoundaryLimit) - { - CGFloat maxContentWidth = selfSize.width - paddingHorz; - for (UIView *sbv in sbs) - { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - - CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; - CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; - CGFloat sbvWidth = sbvmyFrame.width; - - if (_myCGFloatGreat(leadingSpace + sbvWidth + trailingSpace, maxContentWidth) && - (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) && - sbvsc.weight == 0) - { - maxContentWidth = leadingSpace + sbvWidth + trailingSpace; - } - } - - selfSize.width = paddingHorz + maxContentWidth; - } - - //左边候选区域数组,保存的是CGRect值。 NSMutableArray *leadingCandidateRects = [NSMutableArray new]; //为了计算方便总是把最左边的个虚拟区域作为一个候选区域 @@ -543,8 +509,8 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( if (sbvsc.isReverseFloat) { #ifdef DEBUG - //异常崩溃:当布局视图设置了noBoundaryLimit为YES时子视图不能设置逆向浮动 - NSCAssert(hasBoundaryLimit, @"Constraint exception!!, vertical float layout:%@ can not set noBoundaryLimit to YES when the subview:%@ set reverseFloat to YES.",self, sbv); + //异常崩溃:当布局视图设置了wrapContentWidth为YES时子视图不能设置逆向浮动 + NSCAssert(!lsc.wrapContentWidth, @"Constraint exception!!, vertical float layout:%@ can not set wrapContentWidth to YES when the subview:%@ set reverseFloat to YES.",self, sbv); #endif CGPoint nextPoint = {selfSize.width - paddingTrailing, leadingLastYOffset}; @@ -733,10 +699,9 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( if (sbvsc.weight != 0) { #ifdef DEBUG - //异常崩溃:当布局视图设置了noBoundaryLimit为YES时子视图不能设置weight大于0 - NSCAssert(hasBoundaryLimit, @"Constraint exception!!, vertical float layout:%@ can not set noBoundaryLimit to YES when the subview:%@ set weight big than zero.",self, sbv); + //异常崩溃:当布局视图设置了wrapContentWidth为YES时子视图不能设置weight大于0 + NSCAssert(!lsc.wrapContentWidth, @"Constraint exception!!, vertical float layout:%@ can not set wrapContentWidth to YES when the subview:%@ set weight big than zero.",self, sbv); #endif - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:(trailingCandidateXBoundary - nextPoint.x + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace sbvSize:rect.size selfLayoutSize:selfSize]; //特殊处理高度等于宽度,并且高度依赖宽度的情况。 @@ -852,12 +817,11 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( maxWidth -= horzSpace; } - maxHeight += paddingBottom; maxWidth += paddingTrailing; - - if (!hasBoundaryLimit) + if (lsc.wrapContentWidth) selfSize.width = maxWidth; + maxHeight += paddingBottom; if (lsc.wrapContentHeight) selfSize.height = maxHeight; else @@ -882,7 +846,6 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( sbv.myFrame.top += addYPos; } } - } @@ -917,12 +880,22 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( //设置行内的对齐 if (lineHasAlignment) { + CGFloat baselinePos = CGFLOAT_MAX; for (NSInteger i = lineFirstIndex; i <= idxnum.integerValue; i++) { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - switch (sbvsc.alignment & MyGravity_Horz_Mask) { + MyGravity sbvVertAlignment = sbvsc.alignment & MyGravity_Horz_Mask; + UIFont *sbvFont = nil; + if (sbvVertAlignment == MyGravity_Vert_Baseline) + { + sbvFont = [self myGetSubviewFont:sbv]; + if (sbvFont == nil) + sbvVertAlignment = MyGravity_Vert_Top; + } + + switch (sbvVertAlignment) { case MyGravity_Vert_Center: sbvmyFrame.top += (lineMaxHeight - sbvmyFrame.height) / 2.0; break; @@ -932,6 +905,20 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( case MyGravity_Vert_Fill: sbvmyFrame.height = lineMaxHeight; break; + case MyGravity_Vert_Stretch: + { + if (!sbvsc.wrapContentHeight && sbvsc.heightSizeInner.dimeVal == nil) + sbvmyFrame.height = lineMaxHeight; + } + break; + case MyGravity_Vert_Baseline: + { + if (baselinePos == CGFLOAT_MAX) + baselinePos = sbvmyFrame.top + (sbvmyFrame.height - sbvFont.lineHeight) / 2.0 + sbvFont.ascender; + else + sbvmyFrame.top = baselinePos - sbvFont.ascender - (sbvmyFrame.height - sbvFont.lineHeight) / 2; + } + break; default: break; } @@ -957,12 +944,8 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( // CGFloat paddingHorz = paddingLeading + paddingTrailing; CGFloat paddingVert = paddingTop + paddingBottom; - BOOL hasBoundaryLimit = YES; - if (lsc.wrapContentHeight && lsc.noBoundaryLimit) - hasBoundaryLimit = NO; - //如果没有边界限制我们将高度设置为最大。。 - if (!hasBoundaryLimit) + if (lsc.wrapContentHeight) selfSize.height = CGFLOAT_MAX; //支持浮动垂直间距。 @@ -973,38 +956,12 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( //设置子视图的宽度和高度。 [self myCalcFloatLayoutSubviewsSize:sbs lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing subviewSize:subviewSize isWidth:NO]; - //遍历所有的子视图,查看是否有子视图的宽度会比视图自身要宽,如果有且有包裹属性则扩充自身的宽度 - if (lsc.wrapContentHeight && hasBoundaryLimit) - { - CGFloat maxContentHeight = selfSize.height - paddingVert; - for (UIView *sbv in sbs) - { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - - CGFloat topSpace = sbvsc.topPosInner.absVal; - CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; - CGFloat sbvHeight = sbvmyFrame.height; - - if (_myCGFloatGreat(topSpace + sbvHeight + bottomSpace, maxContentHeight) && - (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) && - sbvsc.weight == 0) - { - maxContentHeight = topSpace + sbvHeight + bottomSpace; - } - } - - selfSize.height = paddingVert + maxContentHeight; - } - - - //上边候选区域数组,保存的是CGRect值。 NSMutableArray *topCandidateRects = [NSMutableArray new]; //为了计算方便总是把最上边的个虚拟区域作为一个候选区域 [topCandidateRects addObject:[NSValue valueWithCGRect:CGRectMake(paddingLeading, paddingTop,CGFLOAT_MAX,0)]]; - //右边候选区域数组,保存的是CGRect值。 + //下边候选区域数组,保存的是CGRect值。 NSMutableArray *bottomCandidateRects = [NSMutableArray new]; //为了计算方便总是把最下边的个虚拟区域作为一个候选区域,如果没有边界限制则 [bottomCandidateRects addObject:[NSValue valueWithCGRect:CGRectMake(paddingLeading, selfSize.height - paddingBottom, CGFLOAT_MAX, 0)]]; @@ -1041,8 +998,8 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( if (sbvsc.reverseFloat) { #ifdef DEBUG - //异常崩溃:当布局视图设置了noBoundaryLimit为YES时子视图不能设置逆向浮动 - NSCAssert(hasBoundaryLimit, @"Constraint exception!!, horizontal float layout:%@ can not set noBoundaryLimit to YES when the subview:%@ set reverseFloat to YES.",self, sbv); + //异常崩溃:当布局视图设置了wrapContentHeight为YES时子视图不能设置逆向浮动 + NSCAssert(!lsc.wrapContentHeight, @"Constraint exception!!, horizontal float layout:%@ can not set wrapContentHeight to YES when the subview:%@ set reverseFloat to YES.",self, sbv); #endif CGPoint nextPoint = {topLastXOffset, selfSize.height - paddingBottom}; @@ -1121,9 +1078,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( { sbvl.topBorderline = self.intelligentBorderline; } - } - } } @@ -1215,8 +1170,8 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( { #ifdef DEBUG - //异常崩溃:当布局视图设置了noBoundaryLimit为YES时子视图不能设置weight大于0 - NSCAssert(hasBoundaryLimit, @"Constraint exception!!, horizontal float layout:%@ can not set noBoundaryLimit to YES when the subview:%@ set weight big than zero.",self, sbv); + //异常崩溃:当布局视图设置了wrapContentHeight为YES时子视图不能设置weight大于0 + NSCAssert(!lsc.wrapContentHeight, @"Constraint exception!!, horizontal float layout:%@ can not set wrapContentHeight to YES when the subview:%@ set weight big than zero.",self, sbv); #endif rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:(bottomCandidateYBoundary - nextPoint.y + sbvsc.heightSizeInner.addVal) * sbvsc.weight - topSpace - bottomSpace sbvSize:rect.size selfLayoutSize:selfSize]; @@ -1254,7 +1209,6 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( sbvl.bottomBorderline = self.intelligentBorderline; } } - } } @@ -1291,8 +1245,6 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( cRect = CGRectUnion(cRect, candidateRect); cRect.size.height += cMaxY - candidateMinY; //要加上重叠部分来增加高度,否则会出现高度不正确的问题。 } - - } //记录每一列的最大子视图位置的索引值。 @@ -1325,12 +1277,11 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( maxHeight -= vertSpace; } - maxWidth += paddingTrailing; - maxHeight += paddingBottom; - if (!hasBoundaryLimit) + if (lsc.wrapContentHeight) selfSize.height = maxHeight; - + + maxWidth += paddingTrailing; if (lsc.wrapContentWidth) selfSize.width = maxWidth; else @@ -1405,6 +1356,12 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( case MyGravity_Horz_Fill: sbvmyFrame.width = lineMaxWidth; break; + case MyGravity_Horz_Stretch: + { + if (!sbvsc.wrapContentWidth && sbvsc.widthSizeInner == nil) + sbvmyFrame.width = lineMaxWidth; + } + break; default: break; } diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index 0dda772..f573e57 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -30,7 +30,7 @@ @endcode 2.垂直内容约束流式布局. - orientation为MyOrientation_Vert,arrangedCount为0,支持wrapContentHeight,不支持wrapContentWidth,支持autoArrange。 + orientation为MyOrientation_Vert,arrangedCount为0,支持wrapContentHeight,支持wrapContentWidth,支持autoArrange。 @code 垂直内容约束流式布局 => @@ -64,7 +64,7 @@ @endcode 4.水平内容约束流式布局 - orientation为MyOrientation_Horz,arrangedCount为0,不支持wrapContentHeight,支持wrapContentWidth,支持autoArrange。 + orientation为MyOrientation_Horz,arrangedCount为0,支持wrapContentHeight,支持wrapContentWidth,支持autoArrange。 @code 水平内容约束流式布局 @@ -197,7 +197,9 @@ MyGravity_Vert_Center 垂直居中对齐 MyGravity_Vert_Bottom 底部对齐 MyGravity_Vert_Fill 两端对齐 + MyGravity_Vert_Baseline 基线对齐,以每一行的第一个带有文字的视图作为基线进行对齐。 MyGravity_Vert_Between 数量约束垂直流式布局有效,子视图会紧凑进行排列,当设置为这个属性值时,子视图的y轴的位置总是从对应列的上一行的结尾开始,而不是上一行的最高位置开始。 + MyGravity_Vert_Around 如果行内子视图没有设置高度约束,则子视图的高度填充整行,否则按子视图的高度是高度约束决定。 @endcode 2. 如果是水平流式布局则表示每排内子视图的左中右对齐方式,这里的对齐基础是以每排中的最宽的子视图为基准。这个属性只支持: @code @@ -206,6 +208,7 @@ MyGravity_Horz_Right 右边对齐 MyGravity_Horz_Fill 两端对齐 MyGravity_Horz_Between 数量约束垂直流式布局有效,子视图会紧凑进行排列,当设置为这个属性值时,子视图的x轴的位置总是从对应行的上一列的结尾开始,而不是上一列的最宽位置开始。 + MyGravity_Horz_Around 如果列内子视图没有设置宽度约束,则子视图的宽度填充整行,否则按子视图的宽度是宽度约束决定。 @endcode @note 如果您想单独设置某个子视图在排内的对齐方式则请使用子视图的扩展属性alignment。 @@ -236,5 +239,3 @@ @end - - diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 1a6c19e..451cc34 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -260,17 +260,72 @@ - (void)myCalcHorzLayoutSinglelineWeight:(CGSize)selfSize totalFloatHeight:(CGFl } +- (void)myCalcVertLayoutSinglelineWidthShrink:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalShrink:(CGFloat)totalShrink sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count +{ + if (_myCGFloatGreatOrEqual(totalFloatWidth, 0.0)) + totalShrink = 0.0; + + if (totalShrink == 0.0) + return; + + //如果有压缩则调整子视图的宽度。 + for (NSInteger j = startIndex - count; j < startIndex; j++) + { + UIView *sbv = sbs[j]; + MyFrame *sbvmyFrame = sbv.myFrame; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + + if (sbvsc.widthSizeInner.shrink != 0.0) + { + sbvmyFrame.width += (sbvsc.widthSizeInner.shrink / totalShrink) * totalFloatWidth; + if (sbvmyFrame.width < 0.0) + sbvmyFrame.width = 0.0; + } + } +} -- (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFloat)rowMaxHeight rowMaxWidth:(CGFloat)rowMaxWidth horzGravity:(MyGravity)horzGravity vertAlignment:(MyGravity)vertAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +- (void)myCalcHorzLayoutSinglelineHeightShrink:(CGSize)selfSize totalFloatHeight:(CGFloat)totalFloatHeight totalShrink:(CGFloat)totalShrink sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count { + if (_myCGFloatGreatOrEqual(totalFloatHeight, 0.0)) + totalShrink = 0.0; + + if (totalShrink == 0.0) + return; + //如果有压缩则调整子视图的高度。 + for (NSInteger j = startIndex - count; j < startIndex; j++) + { + UIView *sbv = sbs[j]; + MyFrame *sbvmyFrame = sbv.myFrame; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + + if (sbvsc.heightSizeInner.shrink != 0.0) + { + sbvmyFrame.height += (sbvsc.heightSizeInner.shrink / totalShrink) * totalFloatHeight; + if (sbvmyFrame.height < 0.0) + sbvmyFrame.height = 0.0; + } + } +} + + +- (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFloat)rowMaxHeight rowMaxWidth:(CGFloat)rowMaxWidth rowTotalShrink:(CGFloat)rowTotalShrink horzGravity:(MyGravity)horzGravity vertAlignment:(MyGravity)vertAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +{ CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; CGFloat paddingHorz = paddingLeading + paddingTrailing; - + + CGFloat floatingWidth = selfSize.width - rowMaxWidth - paddingHorz; + if (_myCGFloatGreatOrEqual(floatingWidth, 0.0)) + rowTotalShrink = 0.0; + + if (rowTotalShrink != 0.0) + rowMaxWidth = selfSize.width - paddingHorz; + + CGFloat addXPos = 0; //多出来的空隙区域,用于停靠处理。 CGFloat addXFill = 0; //多出来的平均区域,用于拉伸间距或者尺寸 - BOOL averageArrange = (horzGravity == MyGravity_Horz_Fill); + BOOL averageArrange = (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch); if (!averageArrange || lsc.arrangedCount == 0) { @@ -287,13 +342,27 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo break; case MyGravity_Horz_Between: { - //总宽度减去最大的宽度。再除以数量表示每个应该扩展的空间。最后一行无效(如果最后一行的数量和其他行的数量一样除外)。 - if ((startIndex != sbs.count || count == lsc.arrangedCount) && count > 1) + //总宽度减去最大的宽度。再除以数量表示每个应该扩展的空间。最后一行无效(如果最后一行的数量和其他行的数量一样以及总共就只有一行除外)。 + if ((startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) { addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / (count - 1); } } break; + case MyGravity_Horz_Around: + { + //多于一个拉伸间距,只有一个则居中处理。 + if (count > 1) + { + addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / count; + addXPos = addXFill / 2.0; + } + else + { + addXPos = (selfSize.width - paddingHorz - rowMaxWidth) / 2; + } + } + break; default: break; } @@ -306,11 +375,13 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo { addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / count; } - } } - + //压缩减少的尺寸汇总。 + CGFloat totalShrinkSize = 0; + //基线位置 + CGFloat baselinePos = CGFLOAT_MAX; //将整行的位置进行调整。 for (NSInteger j = startIndex - count; j < startIndex; j++) { @@ -371,21 +442,48 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo if (vertAlignment == MyGravity_Vert_Between) sbvVertAlignment = MyGravity_Vert_Between; - if ((sbvVertAlignment != MyGravity_None && sbvVertAlignment != MyGravity_Vert_Top) || _myCGFloatNotEqual(addXPos, 0) || _myCGFloatNotEqual(addXFill, 0)) + UIFont *sbvFont = nil; + if (sbvVertAlignment == MyGravity_Vert_Baseline) + { + sbvFont = [self myGetSubviewFont:sbv]; + if (sbvFont == nil) + sbvVertAlignment = MyGravity_Vert_Top; + } + + if ((sbvVertAlignment != MyGravity_None && sbvVertAlignment != MyGravity_Vert_Top) || _myCGFloatNotEqual(addXPos, 0.0) || _myCGFloatNotEqual(addXFill, 0.0) || rowTotalShrink != 0.0) { sbvmyFrame.leading += addXPos; + //处理对间距的压缩 + if (rowTotalShrink != 0.0) + { + if (sbvsc.leadingPosInner.shrink != 0.0) + totalShrinkSize += (sbvsc.leadingPosInner.shrink / rowTotalShrink) * floatingWidth; + + sbvmyFrame.leading += totalShrinkSize; + + if (sbvsc.trailingPosInner.shrink != 0.0) + totalShrinkSize += (sbvsc.trailingPosInner.shrink / rowTotalShrink) * floatingWidth; + } + //内容约束布局并且是拉伸尺寸。。 if (lsc.arrangedCount == 0 && averageArrange) { //只拉伸宽度不拉伸间距 - sbvmyFrame.width += addXFill; + if (horzGravity == MyGravity_Horz_Stretch) + { + if (!sbvsc.wrapContentWidth && sbvsc.widthSizeInner.dimeVal == nil) + sbvmyFrame.width += addXFill; + } + else + { + sbvmyFrame.width += addXFill; + } if (j != startIndex - count) { sbvmyFrame.leading += addXFill * (j - (startIndex - count)); - } } else @@ -394,12 +492,10 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo sbvmyFrame.leading += addXFill * (j - (startIndex - count)); } - switch (sbvVertAlignment) { case MyGravity_Vert_Center: { sbvmyFrame.top += (rowMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal - sbvmyFrame.height) / 2; - } break; case MyGravity_Vert_Bottom: @@ -412,26 +508,48 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rowMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } break; + case MyGravity_Vert_Stretch: + { + if (!sbvsc.wrapContentHeight && sbvsc.heightSizeInner.dimeVal == nil) + { + sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rowMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + } + } + break; + case MyGravity_Vert_Baseline: + { + if (baselinePos == CGFLOAT_MAX) + baselinePos = sbvmyFrame.top + (sbvmyFrame.height - sbvFont.lineHeight) / 2.0 + sbvFont.ascender; + else + sbvmyFrame.top = baselinePos - sbvFont.ascender - (sbvmyFrame.height - sbvFont.lineHeight) / 2; + } + break; default: break; } } } - } -- (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloat)colMaxWidth colMaxHeight:(CGFloat)colMaxHeight vertGravity:(MyGravity)vertGravity horzAlignment:(MyGravity)horzAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +- (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloat)colMaxWidth colMaxHeight:(CGFloat)colMaxHeight colTotalShrink:(CGFloat)colTotalShrink vertGravity:(MyGravity)vertGravity horzAlignment:(MyGravity)horzAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc { CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingVert = paddingTop + paddingBottom; + + CGFloat floatingHeight = selfSize.height - colMaxHeight - paddingVert; + if (_myCGFloatGreatOrEqual(floatingHeight, 0.0)) + colTotalShrink = 0.0; + + if (colTotalShrink != 0.0) + colMaxHeight = selfSize.height - paddingVert; + CGFloat addYPos = 0; CGFloat addYFill = 0; - BOOL averageArrange = (vertGravity == MyGravity_Vert_Fill); - + BOOL averageArrange = (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch); if (!averageArrange || lsc.arrangedCount == 0) { switch (vertGravity) { @@ -447,13 +565,26 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa break; case MyGravity_Vert_Between: { - //总高度减去最大的高度。再除以数量表示每个应该扩展的空间。最后一行无效(如果数量和单行的数量相等除外)。 - if ((startIndex != sbs.count || count == lsc.arrangedCount) && count > 1) + //总高度减去最大的高度。再除以数量表示每个应该扩展的空间。最后一列无效(如果最后一列的数量和其他列的数量一样以及总共就只有一列除外)。 + if ((startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) { addYFill = (selfSize.height - paddingVert - colMaxHeight) / (count - 1); } - } + break; + case MyGravity_Vert_Around: + { + if (count > 1) + { + addYFill = (selfSize.height - paddingVert - colMaxHeight) / count; + addYPos = addYFill / 2.0; + } + else + { + addYPos = (selfSize.height - paddingVert - colMaxHeight) / 2; + } + } + break; default: break; } @@ -465,14 +596,11 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa { addYFill = (selfSize.height - paddingVert - colMaxHeight) / count; } - } - } - - - + //压缩减少的尺寸汇总。 + CGFloat totalShrinkSize = 0; //将整行的位置进行调整。 for (NSInteger j = startIndex - count; j < startIndex; j++) { @@ -525,9 +653,6 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa sbvl.leadingBorderline = self.intelligentBorderline; } - - - } } } @@ -539,19 +664,39 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa if (horzAlignment == MyGravity_Horz_Between) sbvHorzAlignment = MyGravity_Horz_Between; - if ((sbvHorzAlignment != MyGravity_None && sbvHorzAlignment != MyGravity_Horz_Leading) || _myCGFloatNotEqual(addYPos, 0) || _myCGFloatNotEqual(addYFill, 0) ) + if ((sbvHorzAlignment != MyGravity_None && sbvHorzAlignment != MyGravity_Horz_Leading) || _myCGFloatNotEqual(addYPos, 0.0) || _myCGFloatNotEqual(addYFill, 0.0) || colTotalShrink != 0.0) { sbvmyFrame.top += addYPos; + //处理对间距的压缩 + if (colTotalShrink != 0.0) + { + if (sbvsc.topPosInner.shrink != 0.0) + totalShrinkSize += (sbvsc.topPosInner.shrink / colTotalShrink) * floatingHeight; + + sbvmyFrame.top += totalShrinkSize; + + if (sbvsc.bottomPosInner.shrink != 0.0) + totalShrinkSize += (sbvsc.bottomPosInner.shrink / colTotalShrink) * floatingHeight; + } + if (lsc.arrangedCount == 0 && averageArrange) { //只拉伸宽度不拉伸间距 - sbvmyFrame.height += addYFill; + + if (vertGravity == MyGravity_Vert_Stretch) + { + if (!sbvsc.wrapContentHeight && sbvsc.heightSizeInner.dimeVal == nil) + sbvmyFrame.height += addYFill; + } + else + { + sbvmyFrame.height += addYFill; + } if (j != startIndex - count) { sbvmyFrame.top += addYFill * (j - (startIndex - count)); - } } else @@ -564,7 +709,6 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa case MyGravity_Horz_Center: { sbvmyFrame.leading += (colMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal - sbvmyFrame.width) / 2; - } break; case MyGravity_Horz_Trailing: @@ -577,6 +721,14 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:colMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } break; + case MyGravity_Horz_Stretch: + { + if (!sbvsc.wrapContentWidth && sbvsc.widthSizeInner.dimeVal == nil) + { + sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:colMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + } + } + break; default: break; } @@ -747,7 +899,8 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; CGFloat rowMaxHeight = 0; //某一行的最高值。 - CGFloat rowMaxWidth = 0; //某一行的最宽值 + CGFloat rowMaxWidth = 0; //某一行的最宽值。 + CGFloat maxWidth = 0; //所有行中最宽的值。 MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; @@ -860,8 +1013,10 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb place += horzSpace; place += paddingTrailing; + maxWidth = place; + //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的宽度和布局视图保持一致。 - if (place - selfSize.width > 0.0001) + if (!lsc.wrapContentWidth && (place - selfSize.width > 0.0001)) { xPos = paddingLeading; yPos += vertSpace; @@ -870,7 +1025,7 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb [arrangeIndexSet addIndex:i - arrangedIndex]; //计算前面每行的gravity情况。 - [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; //计算单独的sbv的宽度是否大于整体的宽度。如果大于则缩小宽度。 if (_myCGFloatGreat(leadingSpace + trailingSpace + rect.size.width, selfSize.width - paddingHorz)) @@ -919,14 +1074,18 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb arrangedIndex++; - - + } + + //内容填充约束布局的宽度包裹计算。 + if (lsc.wrapContentWidth) + { + selfSize.width = maxWidth; } //最后一行 [arrangeIndexSet addIndex:i - arrangedIndex]; - [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; if (lsc.wrapContentHeight) @@ -945,7 +1104,7 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb { addYPos = selfSize.height - paddingBottom - rowMaxHeight - yPos; } - else if (vertGravity == MyGravity_Vert_Fill) + else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) { if (arrangeIndexSet.count > 0) fill = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / arrangeIndexSet.count; @@ -955,10 +1114,15 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb if (arrangeIndexSet.count > 1) between = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / (arrangeIndexSet.count - 1); } + else if (vertGravity == MyGravity_Vert_Around) + { + if (arrangeIndexSet.count > 1) + between = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / arrangeIndexSet.count; + } if (addYPos != 0 || between != 0 || fill != 0) { - int line = 0; + int lineidx = 0; NSUInteger lastIndex = 0; for (int i = 0; i < sbs.count; i++) { @@ -973,14 +1137,27 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb if (lastIndex != index) { lastIndex = index; - line ++; + lineidx ++; } - sbvmyFrame.height += fill; - sbvmyFrame.top += fill * line; + if (vertGravity == MyGravity_Vert_Stretch) + { + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + if (!sbvsc.wrapContentHeight && sbvsc.heightSizeInner == nil) + sbvmyFrame.height += fill; + } + else + { + sbvmyFrame.height += fill; + } + sbvmyFrame.top += fill * lineidx; - sbvmyFrame.top += between * line; + sbvmyFrame.top += between * lineidx; + if (vertGravity == MyGravity_Vert_Around && lineidx == 0) + { + sbvmyFrame.top += (between / 2.0); + } } } @@ -1065,6 +1242,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst NSInteger arrangedIndex = 0; NSInteger i = 0; + CGFloat rowTotalShrink = 0.0; //某一行的总压缩比重。 CGFloat rowTotalWeight = 0; CGFloat rowTotalFixedWidth = 0; for (; i < sbs.count; i++) @@ -1083,19 +1261,23 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedCount]; } + if (rowTotalShrink != 0 && !averageArrange) + { + [self myCalcVertLayoutSinglelineWidthShrink:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalShrink:rowTotalShrink sbs:sbs startIndex:i count:arrangedCount]; + } + rowTotalWeight = 0; rowTotalFixedWidth = 0; - + rowTotalShrink = 0; } CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; - + //计算每行的宽度。 if (sbvsc.weight != 0) { - rowTotalWeight += sbvsc.weight; } else @@ -1115,7 +1297,6 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; } @@ -1137,20 +1318,32 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst sbvmyFrame.frame = rect; - arrangedIndex++; - + + //计算总的压缩比 + if (!averageArrange) + { + rowTotalShrink += sbvsc.leadingPosInner.shrink + sbvsc.trailingPosInner.shrink; + if (sbvsc.weight != 0) + rowTotalShrink += sbvsc.widthSizeInner.shrink; + } } //最后一行。 + if (arrangedIndex < arrangedCount) + rowTotalFixedWidth -= horzSpace; + if (rowTotalWeight != 0 && !averageArrange) { - if (arrangedIndex < arrangedCount) - rowTotalFixedWidth -= horzSpace; - [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; } + //如果有压缩子视图的处理则需要压缩子视图。 + if (rowTotalShrink != 0 && !averageArrange) + { + [self myCalcVertLayoutSinglelineWidthShrink:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalShrink:rowTotalShrink sbs:sbs startIndex:i count:arrangedIndex]; + } + //每列的下一个位置。 NSMutableArray *nextPointOfRows = nil; if (autoArrange) @@ -1165,6 +1358,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst CGFloat pageWidth = 0; //页宽。 CGFloat averageWidth = (selfSize.width - paddingHorz - (arrangedCount - 1) * horzSpace) / arrangedCount; arrangedIndex = 0; + rowTotalShrink = 0; i = 0; for (; i < sbs.count; i++) { @@ -1209,15 +1403,14 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst } } - xPos = paddingLeading + pageWidth; - //计算每行的gravity情况。 - [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + rowMaxHeight = 0; rowMaxWidth = 0; - + rowTotalShrink = 0; } @@ -1232,7 +1425,6 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:averageWidth - leadingSpace - trailingSpace sbvSize:rect.size selfLayoutSize:selfSize]; } - if (pagingItemHeight != 0) rect.size.height = pagingItemHeight; else @@ -1243,7 +1435,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst //再算一次宽度。 if (!averageArrange) { - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; } //特殊处理宽度和高度相互依赖的情况。。 @@ -1253,7 +1445,6 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } - if (!averageArrange && sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) {//特殊处理宽度等于高度的情况 rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; @@ -1331,24 +1522,24 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst if (arrangedIndex != (arrangedCount - 1) && !autoArrange) xPos += horzSpace; - - if (_myCGFloatLess(rowMaxWidth, (xPos - paddingLeading))) rowMaxWidth = (xPos - paddingLeading); if (_myCGFloatLess(maxWidth, xPos)) maxWidth = xPos; - - - + sbvmyFrame.frame = rect; - arrangedIndex++; + //这里只对间距进行压缩比重的计算。 + if (!averageArrange) + { + rowTotalShrink += sbvsc.leadingPosInner.shrink + sbvsc.trailingPosInner.shrink; + } } //最后一行 - [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; maxHeight += paddingBottom; @@ -1371,7 +1562,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst CGFloat addYPos = 0; CGFloat between = 0; CGFloat fill = 0; - int arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); + int arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); //行数 if (vertGravity == MyGravity_Vert_Center) { @@ -1381,18 +1572,21 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst { addYPos = selfSize.height - maxHeight; } - else if (vertGravity == MyGravity_Vert_Fill) + else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) { if (arranges > 0) fill = (selfSize.height - maxHeight) / arranges; } else if (vertGravity == MyGravity_Vert_Between) { - if (arranges > 1) between = (selfSize.height - maxHeight) / (arranges - 1); } - + else if (vertGravity == MyGravity_Vert_Around) + { + if (arranges > 1) + between = (selfSize.height - maxHeight) / arranges; + } if (addYPos != 0 || between != 0 || fill != 0) { @@ -1402,17 +1596,30 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst MyFrame *sbvmyFrame = sbv.myFrame; - int lines = i / arrangedCount; - sbvmyFrame.height += fill; - sbvmyFrame.top += fill * lines; + int lineidx = i / arrangedCount; + if (vertGravity == MyGravity_Vert_Stretch) + { + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + if (!sbvsc.wrapContentHeight && sbvsc.heightSizeInner == nil) + sbvmyFrame.height += fill; + } + else + { + sbvmyFrame.height += fill; + } + sbvmyFrame.top += fill * lineidx; sbvmyFrame.top += addYPos; - sbvmyFrame.top += between * lines; + sbvmyFrame.top += between * lineidx; + //如果是vert_around那么第0行应该添加一半的between值。 + if (vertGravity == MyGravity_Vert_Around && lineidx == 0) + { + sbvmyFrame.top += (between / 2.0); + } } } - } if (lsc.wrapContentWidth && !averageArrange) @@ -1433,10 +1640,6 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst return selfSize; } - - - - -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc { @@ -1450,6 +1653,7 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb CGFloat yPos = paddingTop; CGFloat colMaxWidth = 0; //某一列的最宽值。 CGFloat colMaxHeight = 0; //某一列的最高值 + CGFloat maxHeight = 0; //所有列的最宽行 MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; @@ -1460,8 +1664,6 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; CGFloat subviewSize = [self myCalcMaxMinSubviewSizeForContent:selfSize.height - paddingVert lsc:(MyFlowLayoutViewSizeClass*)lsc space:&vertSpace]; - - if (lsc.autoArrange) { @@ -1476,7 +1678,6 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb NSCAssert(sbvsc.weight == 0, @"Constraint exception!! horizontal flow layout:%@ 's subview:%@ can't set weight when the autoArrange set to YES",self, sbv); #endif - CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; CGRect rect = sbvmyFrame.frame; @@ -1495,11 +1696,8 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb } [sbs setArray:[self myGetAutoArrangeSubviews:sbs selfSize:selfSize.height - paddingVert space:vertSpace]]; - } - - NSMutableIndexSet *arrangeIndexSet = [NSMutableIndexSet new]; NSInteger arrangedIndex = 0; NSInteger i = 0; @@ -1509,7 +1707,6 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; @@ -1568,8 +1765,10 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb place += vertSpace; place += paddingBottom; + maxHeight = place; + //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的宽度和布局视图保持一致。 - if (place - selfSize.height > 0.0001) + if (!lsc.wrapContentHeight && (place - selfSize.height > 0.0001)) { yPos = paddingTop; xPos += horzSpace; @@ -1578,7 +1777,7 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb //计算每行的gravity情况。 [arrangeIndexSet addIndex:i - arrangedIndex]; - [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; //计算单独的sbv的高度是否大于整体的高度。如果大于则缩小高度。 if (_myCGFloatGreat(topSpace + bottomSpace + rect.size.height, selfSize.height - paddingVert)) @@ -1612,20 +1811,20 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb if (_myCGFloatLess(colMaxHeight, (yPos - paddingTop))) colMaxHeight = (yPos - paddingTop); - - sbvmyFrame.frame = rect; arrangedIndex++; - - + } + + if (lsc.wrapContentHeight) + { + selfSize.height = maxHeight; } //最后一行 [arrangeIndexSet addIndex:i - arrangedIndex]; - [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - + [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; if (lsc.wrapContentWidth) selfSize.width = xPos + paddingTrailing + colMaxWidth; @@ -1643,7 +1842,7 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb { addXPos = selfSize.width - paddingTrailing - colMaxWidth - xPos; } - else if (horzGravity == MyGravity_Horz_Fill) + else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) { if (arrangeIndexSet.count > 0) fill = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / arrangeIndexSet.count; @@ -1653,11 +1852,15 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb if (arrangeIndexSet.count > 1) between = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / (arrangeIndexSet.count - 1); } - + else if (horzGravity == MyGravity_Horz_Around) + { + if (arrangeIndexSet.count > 1) + between = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / arrangeIndexSet.count; + } if (addXPos != 0 || between != 0 || fill != 0) { - int line = 0; + int lineidx = 0; NSUInteger lastIndex = 0; for (int i = 0; i < sbs.count; i++) { @@ -1671,20 +1874,32 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb if (lastIndex != index) { lastIndex = index; - line ++; + lineidx ++; + } + + if (horzGravity == MyGravity_Horz_Stretch) + { + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + if (!sbvsc.wrapContentWidth && sbvsc.widthSizeInner == nil) + sbvmyFrame.width += fill; + } + else + { + sbvmyFrame.width += fill; } + sbvmyFrame.leading += fill * lineidx; - sbvmyFrame.width += fill; - sbvmyFrame.leading += fill * line; + sbvmyFrame.leading += between * lineidx; - sbvmyFrame.leading += between * line; + if (horzGravity == MyGravity_Horz_Around && lineidx == 0) + { + sbvmyFrame.leading += (between / 2.0); + } } } - } - return selfSize; } @@ -1763,8 +1978,9 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst NSInteger arrangedIndex = 0; NSInteger i = 0; - CGFloat rowTotalWeight = 0; - CGFloat rowTotalFixedHeight = 0; + CGFloat colTotalWeight = 0; + CGFloat colTotalFixedHeight = 0; + CGFloat colTotalShrink = 0.0; //某一行的总压缩比重。 for (; i < sbs.count; i++) { UIView *sbv = sbs[i]; @@ -1775,13 +1991,19 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst { arrangedIndex = 0; - if (rowTotalWeight != 0 && !averageArrange) + if (colTotalWeight != 0 && !averageArrange) { - [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - rowTotalFixedHeight totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedCount]; + [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedCount]; } - rowTotalWeight = 0; - rowTotalFixedHeight = 0; + if (colTotalShrink != 0 && !averageArrange) + { + [self myCalcHorzLayoutSinglelineHeightShrink:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalShrink:colTotalShrink sbs:sbs startIndex:i count:arrangedCount]; + } + + colTotalWeight = 0; + colTotalFixedHeight = 0; + colTotalShrink = 0; } @@ -1789,7 +2011,6 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; CGRect rect = sbvmyFrame.frame; - if (pagingItemWidth != 0) rect.size.width = pagingItemWidth; else @@ -1800,12 +2021,10 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst if (sbvsc.weight != 0) { - - rowTotalWeight += sbvsc.weight; + colTotalWeight += sbvsc.weight; } else { - if (subviewSize != 0) rect.size.height = subviewSize; else if (pagingItemHeight != 0) @@ -1828,30 +2047,41 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; } - - rowTotalFixedHeight += rect.size.height; + colTotalFixedHeight += rect.size.height; } - rowTotalFixedHeight += topSpace + bottomSpace; + colTotalFixedHeight += topSpace + bottomSpace; if (arrangedIndex != (arrangedCount - 1)) - rowTotalFixedHeight += vertSpace; + colTotalFixedHeight += vertSpace; sbvmyFrame.frame = rect; - arrangedIndex++; + //计算总的压缩比 + if (!averageArrange) + { + colTotalShrink += sbvsc.topPosInner.shrink + sbvsc.bottomPosInner.shrink; + if (sbvsc.weight != 0) + colTotalShrink += sbvsc.heightSizeInner.shrink; + } } //最后一行。 - if (rowTotalWeight != 0 && !averageArrange) + + if (arrangedIndex < arrangedCount) + colTotalFixedHeight -= vertSpace; + + if (colTotalWeight != 0 && !averageArrange) { - if (arrangedIndex < arrangedCount) - rowTotalFixedHeight -= vertSpace; - - [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - rowTotalFixedHeight totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; + [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; + } + + if (colTotalShrink != 0 && !averageArrange) + { + [self myCalcHorzLayoutSinglelineHeightShrink:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalShrink:colTotalShrink sbs:sbs startIndex:i count:arrangedIndex]; } //每行的下一个位置。 @@ -1868,6 +2098,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst CGFloat pageHeight = 0; //页高 CGFloat averageHeight = (selfSize.height - paddingVert - (arrangedCount - 1) * vertSpace) / arrangedCount; arrangedIndex = 0; + colTotalShrink = 0; i = 0; for (; i < sbs.count; i++) { @@ -1914,12 +2145,12 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst yPos = paddingTop + pageHeight; - //计算每行的gravity情况。 - [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; colMaxWidth = 0; colMaxHeight = 0; + colTotalShrink = 0; } CGFloat topSpace = sbvsc.topPosInner.absVal; @@ -1931,7 +2162,6 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst if (averageArrange) { - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:averageHeight - topSpace - bottomSpace sbvSize:rect.size selfLayoutSize:selfSize]; if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) @@ -2018,14 +2248,17 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst sbvmyFrame.frame = rect; - - arrangedIndex++; + //这里只对间距进行压缩比重的计算。 + if (!averageArrange) + { + colTotalShrink += sbvsc.topPosInner.shrink + sbvsc.bottomPosInner.shrink; + } } //最后一列 - [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; if (lsc.wrapContentHeight && !averageArrange) { @@ -2074,7 +2307,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst { addXPos = selfSize.width - maxWidth; } - else if (horzGravity == MyGravity_Horz_Fill) + else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) { if (arranges > 0) fill = (selfSize.width - maxWidth) / arranges; @@ -2084,6 +2317,11 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst if (arranges > 1) between = (selfSize.width - maxWidth) / (arranges - 1); } + else if (horzGravity == MyGravity_Horz_Around) + { + if (arranges > 1) + between = (selfSize.width - maxWidth) / arranges; + } if (addXPos != 0 || between != 0 || fill != 0) { @@ -2093,23 +2331,34 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst MyFrame *sbvmyFrame = sbv.myFrame; - int lines = i / arrangedCount; - sbvmyFrame.width += fill; - sbvmyFrame.leading += fill * lines; + int lineidx = i / arrangedCount; + if (horzGravity == MyGravity_Horz_Stretch) + { + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + if (!sbvsc.wrapContentWidth && sbvsc.widthSizeInner == nil) + sbvmyFrame.width += fill; + } + else + { + sbvmyFrame.width += fill; + } + sbvmyFrame.leading += fill * lineidx; sbvmyFrame.leading += addXPos; - sbvmyFrame.leading += between * lines; + sbvmyFrame.leading += between * lineidx; + //如果是horz_around那么第0行应该添加一半的between值。 + if (horzGravity == MyGravity_Horz_Around && lineidx == 0) + { + sbvmyFrame.leading += (between / 2.0); + } } } } - return selfSize; } - - @end diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index 3180e1b..d405f8c 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -53,6 +53,7 @@ #import "MyRelativeLayout.h" #import "MyTableLayout.h" #import "MyFlowLayout.h" +#import "MyFlexLayout.h" #import "MyFloatLayout.h" #import "MyPathLayout.h" #import "MyGridLayout.h" diff --git a/MyLayout/Lib/MyLayoutDef.h b/MyLayout/Lib/MyLayoutDef.h index 493ad4b..c1bccce 100644 --- a/MyLayout/Lib/MyLayoutDef.h +++ b/MyLayout/Lib/MyLayoutDef.h @@ -84,8 +84,12 @@ typedef enum : unsigned short { MyGravity_Horz_Leading = 32, /**尾部对齐,对于阿拉伯国家来说是和Left等价的,对于非阿拉伯国家则是和Right等价的*/ MyGravity_Horz_Trailing = 64, + /**水平间距拉伸,并且头尾部分为其他部分间距的一半,如果只有一个子视图则变为水平居中停靠*/ + MyGravity_Horz_Around = 128, /**水平宽度填充*/ MyGravity_Horz_Fill = MyGravity_Horz_Left | MyGravity_Horz_Center | MyGravity_Horz_Right, + /**水平宽度拉伸,它跟宽度填充的区别是如果子视图指定了宽度则不会被拉伸*/ + MyGravity_Horz_Stretch = MyGravity_Horz_Left | MyGravity_Horz_Right, /**水平掩码,用来获取水平方向的枚举值*/ MyGravity_Horz_Mask = 0xFF00, @@ -102,8 +106,12 @@ typedef enum : unsigned short { MyGravity_Vert_Between = 16 << 8, /**基线对齐,只支持水平线性布局,指定基线对齐必须要指定出一个基线标准的子视图*/ MyGravity_Vert_Baseline = 32 << 8, + /**垂直间距拉伸,并且头尾部分为其他部分间距的一半, 如果只有一个子视图则变为垂直居中停靠*/ + MyGravity_Vert_Around = 64 << 8, /**垂直高度填充*/ MyGravity_Vert_Fill = MyGravity_Vert_Top | MyGravity_Vert_Center | MyGravity_Vert_Bottom, + /**垂直高度拉伸,它跟高度填充的区别是如果子视图指定了高度则不会被拉伸*/ + MyGravity_Vert_Stretch = MyGravity_Vert_Top | MyGravity_Vert_Bottom, /**垂直掩码,用来获取垂直方向的枚举值*/ MyGravity_Vert_Mask = 0x00FF, @@ -240,7 +248,6 @@ typedef enum : unsigned char{ }MySizeClass; - //内部使用 typedef enum : unsigned char { @@ -251,4 +258,7 @@ typedef enum : unsigned char MyLayoutValueType_Array, MyLayoutValueType_UILayoutSupport, MyLayoutValueType_SafeArea, + MyLayoutValueType_Extreme, + MyLayoutValueType_LayoutDimeDetach, + MyLayoutValueType_Weight, }MyLayoutValueType; diff --git a/MyLayout/Lib/MyLayoutPos.h b/MyLayout/Lib/MyLayoutPos.h index 88bce5a..de934f1 100644 --- a/MyLayout/Lib/MyLayoutPos.h +++ b/MyLayout/Lib/MyLayoutPos.h @@ -236,6 +236,33 @@ */ @property(nonatomic, assign, getter=isActive) BOOL active; +/** + 在布局视图的宽度或者高度是固定的情况下,当某一列或者行中的所有子视图的间距值和尺寸超过父视图的尺寸时子视图的间距压缩比重,默认值为0表示不压缩。数字越大表明压缩的比重越大。目前只有线性布局和框架布局和流式布局中的子视图支持这个属性,而且这特性只在子视图的间距超过布局视图时才有效。 + + 子视图设置shrink属性时要注意如下几点: + + - 垂直线性布局中的子视图设置为非0时,表明当所有子视图的高度高于父布局视图时会对子视图的高度进行按比例压缩。 + + - 水平线性布局中的子视图设置为非0时,表明当所有子视图的宽度宽于父布局视图时会对子视图的宽度进行按比例压缩。 + + - 垂直流式布局中的子视图设置为非0时,表明当子视图所在行中的所有子视图的宽度宽于父布局视图时会对子视图的宽度进行按比例压缩。 + + - 水平流式布局中的子视图设置为非0时,表明当子视图所在列中的所有子视图的高度高于父布局视图时会对子视图的高度进行按比例压缩。 + + @note + 假设某个水平线性布局的宽度是100,其中有子视图A,B,C的宽度约束分别为:50,50,30,并且对应的shrink值分别为:0,1,2。因为三个子视图的 + 宽度总和为130已经超过父布局30的宽度。因此需要对A,B,C分别进行压缩处理。那A,B,C视图需要压缩的值分别为: + A: 30 * (0/(0+1+2)) = 0 + B: 30 * (1/(0+1+2)) = 10 + C: 30 * (2/(0+1+2)) = 20 + + 这样最终布局完成时A,B,C三个子视图的最终宽度分别为: 50, 40(50-10), 10(30-20)。最终三个子视图的总和不会再超出父视图的宽度了。 + + @note + shrink属性和子视图的weight属性的区别时,前者在剩余空间不足时起作用,后者在有剩余空间时起作用。 + */ +@property(nonatomic, assign) CGFloat shrink; + //通过如下属性获取上面方法设置的值。 @property(nonatomic, strong, readonly) id posVal; diff --git a/MyLayout/Lib/MyLayoutPos.m b/MyLayout/Lib/MyLayoutPos.m index ff615a3..666016c 100644 --- a/MyLayout/Lib/MyLayoutPos.m +++ b/MyLayout/Lib/MyLayoutPos.m @@ -40,6 +40,7 @@ -(id)init _offsetVal = 0; _lBoundVal = nil; _uBoundVal = nil; + _shrink = 0.0; } return self; @@ -179,6 +180,11 @@ -(void)setActive:(BOOL)active } } +-(CGFloat)shrink +{ + return self.isActive ? _shrink : 0; +} + -(id)posVal { return self.isActive ? _posVal : nil; @@ -208,6 +214,7 @@ -(id)copyWithZone:(NSZone *)zone MyLayoutPos *lp = [[[self class] allocWithZone:zone] init]; lp.view = self.view; lp->_active = _active; + lp->_shrink = _shrink; lp->_pos = _pos; lp->_posValType = _posValType; lp->_posVal = _posVal; @@ -540,6 +547,7 @@ -(void)__clear _offsetVal = 0; _lBoundVal = nil; _uBoundVal = nil; + _shrink = 0; [self setNeedsLayout]; } diff --git a/MyLayout/Lib/MyLayoutSize.h b/MyLayout/Lib/MyLayoutSize.h index 7b63823..e4f61cb 100644 --- a/MyLayout/Lib/MyLayoutSize.h +++ b/MyLayout/Lib/MyLayoutSize.h @@ -8,6 +8,7 @@ #import "MyLayoutDef.h" +@class MyLayoutExtremeSize; /** *视图的布局尺寸类,用来设置视图在布局视图中宽度和高度的尺寸值。布局尺寸类是对尺寸的一个抽象,一个尺寸不一定描述为一个具体的数值,也有可能描述为和另外一个尺寸相等也就是依赖另外一个尺寸,同时一个尺寸可能也会有最大和最小值的限制等等。因此用MyLayoutSize类来描述这种尺寸的抽象概念。 @@ -63,7 +64,7 @@ /** - 设置尺寸的具体值,这个具体值可以设置为NSNumber, MyLayoutSize以及NSArray数组,UIView和nil值。 + 设置尺寸的具体值,这个具体值可以设置为NSNumber, MyLayoutSize以及NSArray数组,UIView, MyLayoutExtremeSize和nil值。 1. 设置为NSNumber值表示指定具体的宽度或者高度数值 @@ -72,8 +73,11 @@ 3. 设置为NSArray数组的概念就是所有数组里面的子视图的尺寸平分父视图的尺寸。只有相对布局里面的子视图才支持这种设置。 4. 设置为UIView的概念就是尺寸依赖于指定视图的相对应的尺寸。 - - 5. 设置为nil时则清除设置的具体值。 + 5. 设置为MyLayoutExtremeSize值表示取数组中所有元素尺寸中的最大的一个或者最小的一个元素的尺寸值。 + 这个对象从NSArray对象的Category属性:myMaxSize和myMinSize中获取。同时要求数组中的元素只能是MyLayoutSize或者NSNumber。 + 如果元素中有一个值为MyLayoutSize.wrap则表示自身的自适应尺寸也参与比较。 + 这个设置还有一个要求就是数组中的元素值如果是MyLayoutSize的话则要求这个尺寸必须在本视图之前就计算好的约束尺寸,否则可能设置无效。 + 6. 设置为nil时则清除设置的具体值。 */ -(MyLayoutSize* (^)(id val))equalTo; @@ -95,7 +99,7 @@ -(MyLayoutSize* (^)(CGFloat val))min; /** - 设置尺寸的最小边界值,如果尺寸对象没有设置最小边界值,那么最小边界默认就是无穷小-CGFLOAT_MAX。lBound方法除了能设置为数值外,还可以设置为MyLayoutSize值,并且还可以指定增量值和倍数值。 + 设置尺寸的最小边界值,如果尺寸对象没有设置最小边界值,那么最小边界默认就是无穷小-CGFLOAT_MAX。lBound方法除了能设置为数值外,还可以设置为MyLayoutSize值和MyLayoutExtremeSize值和nil值,并且还可以指定增量值和倍数值。 1. 比如我们有一个UILabel的宽度是由内容决定的,但是最小的宽度大于等于父视图的宽度,则设置为: @code @@ -133,7 +137,7 @@ /** - 设置尺寸的最大边界值,如果尺寸对象没有设置最大边界值,那么最大边界默认就是无穷大CGFLOAT_MAX。uBound方法除了能设置为数值外,还可以设置为MyLayoutSize值和nil值,并且还可以指定增量值和倍数值。 + 设置尺寸的最大边界值,如果尺寸对象没有设置最大边界值,那么最大边界默认就是无穷大CGFLOAT_MAX。uBound方法除了能设置为数值外,还可以设置为MyLayoutSize值和MyLayoutExtremeSize值和nil值,并且还可以指定增量值和倍数值。 1. 比如我们有一个UILabel的宽度是由内容决定的,但是最大的宽度小于等于父视图的宽度,则设置为: @code @@ -177,6 +181,33 @@ */ @property(nonatomic, assign, getter=isActive) BOOL active; +/** + 在布局视图的宽度或者高度是固定的情况下,当某一列或者行中的所有子视图尺寸超过父视图的尺寸时子视图的尺寸压缩比重,默认值为0表示不压缩。数字越大表明压缩的比重越大。目前只有线性布局和框架布局和流式布局中的子视图支持这个属性,而且这特性只在子视图尺寸超过布局视图时才有效。 + + 子视图设置shrink属性时要注意如下几点: + + - 垂直线性布局中的子视图设置为非0时,表明当所有子视图的高度高于父布局视图时会对子视图的高度进行按比例压缩。 + + - 水平线性布局中的子视图设置为非0时,表明当所有子视图的宽度宽于父布局视图时会对子视图的宽度进行按比例压缩。 + + - 垂直流式布局中的子视图设置为非0时,表明当子视图所在行中的所有子视图的宽度宽于父布局视图时会对子视图的宽度进行按比例压缩。 + + - 水平流式布局中的子视图设置为非0时,表明当子视图所在列中的所有子视图的高度高于父布局视图时会对子视图的高度进行按比例压缩。 + + @note + 假设某个水平线性布局的宽度是100,其中有子视图A,B,C的宽度约束分别为:50,50,30,并且对应的shrink值分别为:0,1,2。因为三个子视图的 + 宽度总和为130已经超过父布局30的宽度。因此需要对A,B,C分别进行压缩处理。那A,B,C视图需要压缩的值分别为: + A: 30 * (0/(0+1+2)) = 0 + B: 30 * (1/(0+1+2)) = 10 + C: 30 * (2/(0+1+2)) = 20 + + 这样最终布局完成时A,B,C三个子视图的最终宽度分别为: 50, 40(50-10), 10(30-20)。最终三个子视图的总和不会再超出父视图的宽度了。 + + @note + shrink属性和子视图的weight属性的区别时,前者在剩余空间不足时起作用,后者在有剩余空间时起作用。 + */ +@property(nonatomic, assign) CGFloat shrink; + //上面方法设置的属性的获取。 @property(nonatomic, strong, readonly) id dimeVal; @@ -185,8 +216,27 @@ @property(nonatomic, assign, readonly) CGFloat minVal; @property(nonatomic, assign, readonly) CGFloat maxVal; - +@end + +@interface MyLayoutSize(Detach) +//从布局尺寸中分离出一个尺寸对象来。这个分离出来的尺寸值是源尺寸对象的值乘以multival再加上addVal。这个方法用于下面数组元素的构造 +-(MyLayoutSize* (^)(CGFloat addVal, CGFloat multiVal))detach; @end + + +/** + 我们可以从一个数组中获取众多尺寸的最大最小的尺寸值。 + 这里要求数组的元素只能是MyLayoutSize或者NSNumber两种对象类型的值。 + */ +@interface NSArray(MyLayoutExtremeSize) + +//从数组中得到最小的尺寸值。 +@property(nonatomic, readonly) MyLayoutExtremeSize *myMinSize; +//从数组中得到最小的尺寸值。 +@property(nonatomic, readonly) MyLayoutExtremeSize *myMaxSize; + +@end + diff --git a/MyLayout/Lib/MyLayoutSize.m b/MyLayout/Lib/MyLayoutSize.m index 47aebec..cd2750a 100644 --- a/MyLayout/Lib/MyLayoutSize.m +++ b/MyLayout/Lib/MyLayoutSize.m @@ -9,6 +9,7 @@ #import "MyLayoutSize.h" #import "MyLayoutSizeInner.h" #import "MyBaseLayout.h" +#import "MyLayoutInner.h" #import "MyLayoutMath.h" @@ -52,6 +53,7 @@ -(id)init _multiVal = 1; _lBoundVal = nil; _uBoundVal = nil; + _shrink = 0.0; } return self; @@ -202,6 +204,10 @@ -(void)setActive:(BOOL)active } } +-(CGFloat)shrink +{ + return _active ? _shrink : 0.0; +} -(id)dimeVal @@ -236,6 +242,7 @@ -(id)copyWithZone:(NSZone *)zone MyLayoutSize *ld = [[[self class] allocWithZone:zone] init]; ld.view = self.view; ld->_active = _active; + ld->_shrink = _shrink; ld->_dime = _dime; ld->_addVal = _addVal; ld->_multiVal = _multiVal; @@ -271,6 +278,10 @@ -(NSNumber*)dimeNumVal if (_dimeValType == MyLayoutValueType_NSNumber) return _dimeVal; + + if (_dimeValType == MyLayoutValueType_Extreme) + return @([((MyLayoutExtremeSize*)_dimeVal) getExtremeSizeFrom:self]); + return nil; } @@ -383,6 +394,10 @@ -(MyLayoutSize*)__equalTo:(id)val { _dimeValType = MyLayoutValueType_Array; } + else if ([val isKindOfClass:[MyLayoutExtremeSize class]]) + { + _dimeValType = MyLayoutValueType_Extreme; + } else { _dimeValType = MyLayoutValueType_Nil; @@ -489,6 +504,7 @@ -(void)__clear _lBoundVal = nil; _uBoundVal = nil; _dimeVal = nil; + _shrink = 0; _dimeValType = MyLayoutValueType_Nil; [self setNeedsLayout]; @@ -592,7 +608,109 @@ -(NSString*)description } +@end + + +@implementation MyLayoutSize(Detach) + +-(MyLayoutSize* (^)(CGFloat addVal, CGFloat multiVal))detach +{ + return ^id(CGFloat addVal, CGFloat multiVal){ + + MyLayoutSize *ld = [[[self class] allocWithZone:nil] init]; + ld->_addVal = addVal; + ld->_multiVal = multiVal; + ld->_dimeVal = self; + ld->_dimeValType = MyLayoutValueType_LayoutDimeDetach; + return ld; + }; +} @end + +@implementation MyLayoutExtremeSize +{ + NSArray *_sizes; + BOOL _isMax; +} + +-(instancetype)initWith:(NSArray *)sizes isMax:(BOOL)isMax +{ + self = [self init]; + if (self != nil) + { + _sizes = sizes; + _isMax = isMax; + } + + return self; +} + + +-(CGFloat)getExtremeSizeFrom:(MyLayoutSize *)layoutSize +{ + CGFloat retVal = _isMax ? -CGFLOAT_MAX : CGFLOAT_MAX; + + for (id size in _sizes) + { + CGFloat val = 0; + if ([size isKindOfClass:[NSNumber class]]) + { + val = [(NSNumber*)size doubleValue]; + if (val == MyLayoutSize.wrap) + {//特殊的自适应值。 + CGSize sz = [layoutSize.view sizeThatFits:CGSizeZero]; + if (layoutSize.dime == MyGravity_Horz_Fill) + val = sz.width; + else + val = sz.height; + } + + retVal = _isMax ? _myCGFloatMax(val, retVal) : _myCGFloatMin(val, retVal); + } + else if ([size isKindOfClass:[MyLayoutSize class]]) + { + MyLayoutSize *lsize = (MyLayoutSize *)size; + if (lsize.dimeValType == MyLayoutValueType_LayoutDimeDetach) + { + MyLayoutSize *llsize = (MyLayoutSize *)lsize.dimeVal; + val = (llsize.dime == MyGravity_Horz_Fill) ? llsize.view.myEstimatedWidth : llsize.view.myEstimatedHeight; + val *= lsize.multiVal; + val += lsize.addVal; + } + else + { + val = (lsize.dime == MyGravity_Horz_Fill) ? lsize.view.myEstimatedWidth : lsize.view.myEstimatedHeight; + } + + retVal = _isMax ? _myCGFloatMax(val, retVal) : _myCGFloatMin(val, retVal); + + } + else + { + NSAssert(NO, @"oops!, invalid type, only support NSNumber or MyLayoutSize"); + } + } + + return retVal; +} + +@end + + +@implementation NSArray(MyLayoutExtremeSize) + +-(MyLayoutExtremeSize *)myMinSize +{ + return [[MyLayoutExtremeSize alloc] initWith:self isMax:NO]; +} + +-(MyLayoutExtremeSize *)myMaxSize +{ + return [[MyLayoutExtremeSize alloc] initWith:self isMax:YES]; +} + + +@end diff --git a/MyLayout/Lib/MyLayoutSizeClass.h b/MyLayout/Lib/MyLayoutSizeClass.h index 84e294f..c6e479f 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.h +++ b/MyLayout/Lib/MyLayoutSizeClass.h @@ -84,7 +84,7 @@ @property(nonatomic, copy) void (^viewLayoutCompleteBlock)(MyBaseLayout* layout, UIView *v); -//线性布局和浮动布局子视图专用 +//线性布局和浮动布局和流式布局子视图专用 @property(nonatomic, assign) CGFloat weight; //浮动布局子视图专用 @@ -179,7 +179,6 @@ @property(nonatomic, assign) CGFloat subviewSize; @property(nonatomic, assign) CGFloat minSpace; @property(nonatomic, assign) CGFloat maxSpace; -@property(nonatomic,assign) BOOL noBoundaryLimit; @end diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index 0acc726..68f8ca1 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -434,21 +434,13 @@ -(void)setWrapContentWidth:(BOOL)wrapContentWidth if (wrapContentWidth) { -#ifdef MY_USEPREFIXMETHOD - self.widthSize.myEqualTo(self.widthSize); -#else - self.widthSize.equalTo(self.widthSize); -#endif + [self.widthSize __equalTo:self.widthSize]; } else { if (self.widthSizeInner.dimeSelfVal != nil) { -#ifdef MY_USEPREFIXMETHOD - self.widthSizeInner.myEqualTo(nil); -#else - self.widthSizeInner.equalTo(nil); -#endif + [self.widthSizeInner __equalTo:nil]; } } } @@ -916,25 +908,9 @@ - (id)copyWithZone:(NSZone *)zone lsc.subviewSize = self.subviewSize; lsc.minSpace = self.minSpace; lsc.maxSpace = self.maxSpace; - lsc.noBoundaryLimit = self.noBoundaryLimit; - return lsc; } - --(NSString*)debugDescription -{ - NSString *dbgDesc = [super debugDescription]; - - dbgDesc = [NSString stringWithFormat:@"%@\nFloatLayout: \nnoBoundaryLimit=%@", - dbgDesc, - self.noBoundaryLimit ? @"YES":@"NO"]; - - return dbgDesc; -} - - - @end diff --git a/MyLayout/Lib/MyLayoutSizeInner.h b/MyLayout/Lib/MyLayoutSizeInner.h index 3fd7990..75e1a7c 100644 --- a/MyLayout/Lib/MyLayoutSizeInner.h +++ b/MyLayout/Lib/MyLayoutSizeInner.h @@ -47,3 +47,13 @@ -(CGFloat)measureWith:(CGFloat)size; @end + +@interface MyLayoutExtremeSize:NSObject + +-(instancetype)initWith:(NSArray *)sizes isMax:(BOOL)isMax; + +//获取极限值 +-(CGFloat)getExtremeSizeFrom:(MyLayoutSize *)layoutSize; + +@end + diff --git a/MyLayout/Lib/MyLinearLayout.h b/MyLayout/Lib/MyLinearLayout.h index 9ca73f5..61ae207 100644 --- a/MyLayout/Lib/MyLinearLayout.h +++ b/MyLayout/Lib/MyLinearLayout.h @@ -143,6 +143,10 @@ A的最终topPos = 10 - 40 *(10/30) = -3 D的最终topPos = 20 - 40 *(20/30) = -7 @endcode + + @note + 你可以将子视图的尺寸和位置的shrink属性设置为非0,这样这些子视图的尺寸的和位置的压缩策略将优先于这个属性的设置。一旦有子视图设置压缩策略则这个属性设置将失效。 + */ @property(nonatomic, assign) MySubviewsShrinkType shrinkType; diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index c106ed5..3cc1742 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -240,7 +240,6 @@ - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation { //只要同时设置了左右边距或者设置了宽度或者设置了子视图宽度填充则应该把wrapContentWidth置为NO if ((sbvsc.widthSizeInner.dimeVal != nil) || - (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) || (gravity == MyGravity_Horz_Fill) ) { @@ -266,7 +265,6 @@ - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation { //只要同时设置了高度或者上下边距或者父视图的填充属性则应该把wrapContentHeight置为NO if ((sbvsc.heightSizeInner.dimeVal != nil) || - (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) || (gravity == MyGravity_Vert_Fill) ) { @@ -369,6 +367,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea CGFloat fixedHeight = 0; //计算固定部分的高度 CGFloat totalWeight = 0; //剩余部分的总比重 + CGFloat totalShrink = 0; //总的压缩比重 CGFloat addSpace = 0; //用于压缩时的间距压缩增量。 CGFloat maxSelfWidth = 0; @@ -416,9 +415,11 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea + + + if ((tempSelfWidth > maxSelfWidth) && - (lsc.widthSizeInner == nil || (sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) && - (sbvsc.leadingPosInner.posVal == nil || sbvsc.trailingPosInner.posVal == nil)) + ((sbvsc.widthSizeInner.dimeVal != nil && sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) || sbvsc.wrapContentWidth)) { maxSelfWidth = tempSelfWidth; } @@ -453,9 +454,10 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea fixedSpaceCount += 1; fixedSpaceHeight += sbvsc.topPosInner.absVal; } - } + totalShrink += sbvsc.topPosInner.shrink; + pos += sbvsc.topPosInner.absVal; rect.origin.y = pos; @@ -467,6 +469,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea else { fixedHeight += rect.size.height; + totalShrink += sbvsc.heightSizeInner.shrink; //如果最小高度不为自身并且高度不是包裹的则可以进行缩小。 if (sbvsc.heightSizeInner.lBoundValInner.dimeSelfVal == nil) @@ -492,8 +495,8 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea fixedSpaceCount += 1; fixedSpaceHeight += sbvsc.bottomPosInner.absVal; } - } + totalShrink += sbvsc.bottomPosInner.shrink; pos += sbvsc.bottomPosInner.absVal; @@ -510,7 +513,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } } - if (vertGravity == MyGravity_Vert_Fill) + if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) { BOOL canAddToNoWrapSbs = YES; @@ -529,6 +532,10 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea if (sbvsc.heightSizeInner.lBoundValInner.dimeSelfVal != nil) canAddToNoWrapSbs = NO; + //对于尺寸拉升来说,只要设置了高度约束就都不拉升。 + if (vertGravity == MyGravity_Vert_Stretch && sbvsc.heightSizeInner.dimeVal != nil) + canAddToNoWrapSbs = NO; + if (canAddToNoWrapSbs) [noWrapsbsSet addObject:sbv]; } @@ -536,19 +543,30 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea sbvmyFrame.frame = rect; } - //在包裹高度且总体比重不为0时则,则需要还原最小的高度,这样就不会使得高度在横竖屏或者多次计算后越来高。 - if (lsc.wrapContentHeight && totalWeight != 0) + if (lsc.wrapContentHeight) { - CGFloat tempSelfHeight = paddingVert; - if (sbs.count > 1) - tempSelfHeight += (sbs.count - 1) * subviewSpace; + if (totalWeight != 0) + { //在包裹高度且总体比重不为0时则,则需要还原最小的高度,这样就不会使得高度在横竖屏或者多次计算后越来高。 + CGFloat tempSelfHeight = paddingVert; + if (sbs.count > 1) + tempSelfHeight += (sbs.count - 1) * subviewSpace; + + selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:tempSelfHeight sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + } + else + { + selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:fixedHeight + paddingVert sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + } - selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:tempSelfHeight sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + //如果是高度自适应则不需要压缩。 + totalShrink = 0.0; } if (lsc.wrapContentWidth) - selfSize.width = maxSelfWidth + paddingLeading + paddingTrailing; + { + selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:maxSelfWidth + paddingLeading + paddingTrailing sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + } //这里需要特殊处理当子视图的尺寸高度大于布局视图的高度的情况。 @@ -558,13 +576,18 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea //取出shrinkType中的模式和内容类型: MySubviewsShrinkType sstMode = lsc.shrinkType & 0x0F; //压缩的模式 MySubviewsShrinkType sstContent = lsc.shrinkType & 0xF0; //压缩内容 + + //如果子视图设置了压缩比重则ssMode不起作用 + if (totalShrink != 0.0) + sstMode = MySubviewsShrink_None; + if (_myCGFloatLessOrEqual(floatingHeight, 0)) { if (sstMode != MySubviewsShrink_None) { if (sstContent == MySubviewsShrink_Size) {//压缩尺寸 - if (fixedSizeSbs.count > 0 && totalWeight != 0 && floatingHeight < 0 && selfSize.height > 0) + if (fixedSizeSbs.count > 0 && floatingHeight < 0 && selfSize.height > 0) { if (sstMode == MySubviewsShrink_Average) {//均分。 @@ -608,12 +631,23 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } - - floatingHeight = 0; + if (totalShrink == 0.0) + floatingHeight = 0; + } + else + { + //如果不需要压缩则压缩比设置为0 + totalShrink = 0.0; + } + + //如果是总的压缩比重不为0则认为固定高度和布局视图高度保持一致。 + if (totalShrink != 0.0) + { + fixedHeight = selfSize.height - paddingVert; } //如果有浮动尺寸或者有压缩模式 - if (totalWeight != 0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingHeight, 0)) || vertGravity != MyGravity_None || lsc.wrapContentWidth) + if (totalWeight != 0.0 || totalShrink != 0.0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingHeight, 0)) || vertGravity != MyGravity_None || lsc.wrapContentWidth) { maxSelfWidth = 0; CGFloat between = 0; //间距扩充 @@ -643,7 +677,20 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea if (sbs.count > 1) between = (selfSize.height - fixedHeight - paddingVert) / (sbs.count - 1); } - else if (vertGravity == MyGravity_Vert_Fill) + else if (vertGravity == MyGravity_Vert_Around) + { + //around停靠中如果子视图数量大于1则间距均分,并且首尾子视图和父视图的间距为均分的一半,如果子视图数量为1则一个子视图垂直居中。 + if (sbs.count > 1) + { + between = (selfSize.height - fixedHeight - paddingVert) / sbs.count; + pos = paddingTop + between / 2; + } + else + { + pos = (selfSize.height - fixedHeight - paddingVert)/2.0 + paddingTop; + } + } + else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) { pos = paddingTop; if (noWrapsbsSet.count > 0) @@ -670,8 +717,6 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea { CGFloat topSpaceWeight = topSpace; topSpace = _myCGFloatRound((topSpaceWeight / totalWeight) * floatingHeight); - floatingHeight -= topSpace; - totalWeight -= topSpaceWeight; if (_myCGFloatLessOrEqual(topSpace, 0)) topSpace = 0; } @@ -686,18 +731,21 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea pos += weightShrinkSpaceTotalHeight * (topSpace + sbvsc.topPosInner.offsetVal) / fixedSpaceHeight; } } - } - pos += [self myValidMargin:sbvsc.topPosInner sbv:sbv calcPos:topSpace + sbvsc.topPosInner.offsetVal selfLayoutSize:selfSize]; + topSpace += sbvsc.topPosInner.offsetVal; + if (totalShrink != 0.0 && sbvsc.topPosInner.shrink != 0.0) + { + topSpace += (sbvsc.topPosInner.shrink / totalShrink) * floatingHeight; + } + + pos += [self myValidMargin:sbvsc.topPosInner sbv:sbv calcPos:topSpace selfLayoutSize:selfSize]; rect.origin.y = pos; //分别处理相对高度和绝对高度 if (weight != 0) { CGFloat h = _myCGFloatRound((weight / totalWeight) * floatingHeight); - floatingHeight -= h; - totalWeight -= weight; if (_myCGFloatLessOrEqual(h, 0)) h = 0; @@ -708,6 +756,12 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea if (fill != 0 && [noWrapsbsSet containsObject:sbv]) rect.size.height += fill; + if (totalShrink != 0.0 && sbvsc.heightSizeInner.shrink != 0.0) + { + rect.size.height += (sbvsc.heightSizeInner.shrink / totalShrink) * floatingHeight; + if (rect.size.height < 0.0) + rect.size.height = 0.0; + } if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) {//特殊处理宽度等于高度的情况 @@ -725,8 +779,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea lsc:lsc]; if ((tempSelfWidth > maxSelfWidth) && - (lsc.widthSizeInner == nil || (sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) && - (sbvsc.leadingPosInner.posVal == nil || sbvsc.trailingPosInner.posVal == nil)) + ((sbvsc.widthSizeInner.dimeVal != nil && sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) || sbvsc.wrapContentWidth)) { maxSelfWidth = tempSelfWidth; } @@ -738,11 +791,8 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea { CGFloat bottomSpaceWeight = bottomSpace; bottomSpace = _myCGFloatRound((bottomSpaceWeight / totalWeight) * floatingHeight); - floatingHeight -= bottomSpace; - totalWeight -= bottomSpaceWeight; if ( _myCGFloatLessOrEqual(bottomSpace, 0)) bottomSpace = 0; - } else { @@ -755,10 +805,15 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea pos += weightShrinkSpaceTotalHeight * (bottomSpace + sbvsc.bottomPosInner.offsetVal) / fixedSpaceHeight; } } - } - pos += [self myValidMargin:sbvsc.bottomPosInner sbv:sbv calcPos:bottomSpace + sbvsc.bottomPosInner.offsetVal selfLayoutSize:selfSize]; + bottomSpace += sbvsc.bottomPosInner.offsetVal; + if (totalShrink != 0.0 && sbvsc.bottomPosInner.shrink != 0.0) + { + bottomSpace += (sbvsc.bottomPosInner.shrink / totalShrink) * floatingHeight; + } + + pos += [self myValidMargin:sbvsc.bottomPosInner sbv:sbv calcPos:bottomSpace selfLayoutSize:selfSize]; //添加共有的子视图间距 if (sbv != sbs.lastObject) @@ -804,8 +859,10 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea CGFloat paddingHorz = paddingLeading + paddingTrailing; MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; + CGFloat fixedWidth = 0; //计算固定部分的宽度 CGFloat totalWeight = 0; //剩余部分的总比重 + CGFloat totalShrink = 0; //总的压缩比重 CGFloat addSpace = 0; //用于压缩时的间距压缩增量。 //宽度不是包裹的子视图集合 @@ -857,8 +914,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea lsc:lsc]; if ((tempSelfHeight > maxSelfHeight) && - (lsc.heightSizeInner == nil || (sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) && - (sbvsc.topPosInner.posVal == nil || sbvsc.bottomPosInner.posVal == nil)) + ((sbvsc.heightSizeInner.dimeVal != nil && sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) || sbvsc.wrapContentHeight)) { maxSelfHeight = tempSelfHeight; } @@ -898,9 +954,10 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea fixedSpaceCount += 1; fixedSpaceWidth += sbvsc.leadingPosInner.absVal; } - } + totalShrink += sbvsc.leadingPosInner.shrink; + pos += sbvsc.leadingPosInner.absVal; rect.origin.x = pos; @@ -912,6 +969,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea else { fixedWidth += rect.size.width; + totalShrink += sbvsc.widthSizeInner.shrink; //如果最小宽度不为自身并且宽度不是包裹的则可以进行缩小。 if (sbvsc.widthSizeInner.lBoundValInner.dimeSelfVal == nil) @@ -942,8 +1000,8 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea fixedSpaceCount += 1; fixedSpaceWidth += sbvsc.trailingPosInner.absVal; } - } + totalShrink += sbvsc.trailingPosInner.shrink; pos += sbvsc.trailingPosInner.absVal; @@ -960,7 +1018,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } } - if (horzGravity == MyGravity_Horz_Fill) + if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) { BOOL canAddToNoWrapSbs = YES; @@ -979,6 +1037,9 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea if (sbvsc.widthSizeInner.lBoundValInner.dimeSelfVal != nil) canAddToNoWrapSbs = NO; + if (horzGravity == MyGravity_Horz_Stretch && sbvsc.widthSizeInner.dimeVal != nil) + canAddToNoWrapSbs = NO; + if (canAddToNoWrapSbs) [noWrapsbsSet addObject:sbv]; } @@ -987,21 +1048,32 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } //在包裹宽度且总体比重不为0时则,则需要还原最小的宽度,这样就不会使得宽度在横竖屏或者多次计算后越来越宽。 - if (lsc.wrapContentWidth && totalWeight != 0) + if (lsc.wrapContentWidth) { - CGFloat tempSelfWidth = paddingHorz; - if (sbs.count > 1) - tempSelfWidth += (sbs.count - 1) * subviewSpace; + if (totalWeight != 0) + { + CGFloat tempSelfWidth = paddingHorz; + if (sbs.count > 1) + tempSelfWidth += (sbs.count - 1) * subviewSpace; + + selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:tempSelfWidth sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + } + else + { + selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:fixedWidth + paddingHorz sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + } - selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:tempSelfWidth sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + //如果是宽度自适应则不需要压缩。 + totalShrink = 0.0; } if (lsc.wrapContentHeight) - selfSize.height = maxSelfHeight + paddingTop + paddingBottom; - - //这里需要特殊处理当子视图的尺寸宽度大于布局视图的宽度的情况。 + { + selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:maxSelfHeight + paddingTop + paddingBottom sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + } + //这里需要特殊处理当子视图的尺寸宽度大于布局视图的宽度的情况. //剩余的可浮动的宽度,那些weight不为0的从这个宽度来进行分发 BOOL isWeightShrinkSpace = NO; //是否按比重缩小间距。。。 CGFloat weightShrinkSpaceTotalWidth = 0; @@ -1009,6 +1081,11 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea //取出shrinkType中的模式和内容类型: MySubviewsShrinkType sstMode = lsc.shrinkType & 0x0F; //压缩的模式 MySubviewsShrinkType sstContent = lsc.shrinkType & 0xF0; //压缩内容 + + //如果子视图设置了压缩比重则ssMode不起作用 + if (totalShrink != 0.0) + sstMode = MySubviewsShrink_None; + if (_myCGFloatLessOrEqual(floatingWidth, 0)) { //如果压缩方式为自动,但是浮动宽度子视图数量不为2则压缩类型无效。 @@ -1019,7 +1096,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea { if (sstContent == MySubviewsShrink_Size) { - if (fixedSizeSbs.count > 0 && totalWeight != 0 && floatingWidth < 0 && selfSize.width > 0) + if (fixedSizeSbs.count > 0 && floatingWidth < 0 && selfSize.width > 0) { //均分。 if (sstMode == MySubviewsShrink_Average) @@ -1095,22 +1172,30 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea weightShrinkSpaceTotalWidth = floatingWidth; } } - } else { ; } - } - - - - floatingWidth = 0; + + if (totalShrink == 0.0) + floatingWidth = 0; + } + else + { + //如果不需要压缩则压缩比设置为0 + totalShrink = 0.0; } + //如果是总的压缩比重不为0则认为固定宽度和布局视图宽度保持一致。 + if (totalShrink != 0.0) + { + fixedWidth = selfSize.width - paddingHorz; + } + //如果有浮动尺寸或者有压缩模式 - if (totalWeight != 0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingWidth, 0)) || horzGravity != MyGravity_None || lsc.wrapContentHeight) + if (totalWeight != 0.0 || totalShrink != 0.0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingWidth, 0)) || horzGravity != MyGravity_None || lsc.wrapContentHeight) { maxSelfHeight = 0; CGFloat between = 0; //间距扩充 @@ -1127,8 +1212,6 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea CGPoint pt = CGPointMake(pos, 0); pos = [self.window convertPoint:pt toView:self].x; - - } } else if (horzGravity == MyGravity_Horz_Trailing) @@ -1142,7 +1225,20 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea if (sbs.count > 1) between = (selfSize.width - fixedWidth - paddingHorz) / (sbs.count - 1); } - else if (horzGravity == MyGravity_Horz_Fill) + else if (horzGravity == MyGravity_Horz_Around) + { + //around停靠中如果子视图数量大于1则间距均分,并且首尾子视图和父视图的间距为均分的一半,如果子视图数量为1则一个子视图垂直居中。 + if (sbs.count > 1) + { + between = (selfSize.width - fixedWidth - paddingHorz) / sbs.count; + pos = paddingLeading + between / 2.0; + } + else + { + pos = (selfSize.width - fixedWidth - paddingHorz)/2.0 + paddingLeading; + } + } + else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) { pos = paddingLeading; if (noWrapsbsSet.count > 0) @@ -1169,8 +1265,6 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea { CGFloat topSpaceWeight = leadingSpace; leadingSpace = _myCGFloatRound((topSpaceWeight / totalWeight) * floatingWidth); - floatingWidth -= leadingSpace; - totalWeight -= topSpaceWeight; if (_myCGFloatLessOrEqual(leadingSpace, 0)) leadingSpace = 0; } @@ -1187,16 +1281,19 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } } + leadingSpace += sbvsc.leadingPosInner.offsetVal; + if (totalShrink != 0.0 && sbvsc.leadingPosInner.shrink != 0.0) + { + leadingSpace += (sbvsc.leadingPosInner.shrink / totalShrink) * floatingWidth; + } - pos += [self myValidMargin:sbvsc.leadingPosInner sbv:sbv calcPos:leadingSpace + sbvsc.leadingPosInner.offsetVal selfLayoutSize:selfSize]; + pos += [self myValidMargin:sbvsc.leadingPosInner sbv:sbv calcPos:leadingSpace selfLayoutSize:selfSize]; rect.origin.x = pos; //分别处理相对高度和绝对高度 if (weight != 0) { CGFloat w = _myCGFloatRound((weight / totalWeight) * floatingWidth); - floatingWidth -= w; - totalWeight -= weight; if (_myCGFloatLessOrEqual(w, 0)) w = 0; @@ -1207,6 +1304,13 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea if (fill != 0 && [noWrapsbsSet containsObject:sbv]) rect.size.width += fill; + if (totalShrink != 0.0 && sbvsc.widthSizeInner.shrink != 0.0) + { + rect.size.width += (sbvsc.widthSizeInner.shrink / totalShrink) * floatingWidth; + if (rect.size.width < 0.0) + rect.size.width = 0.0; + } + //特殊处理高度依赖宽度的情况。 if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) {//特殊处理高度等于宽度的情况 @@ -1224,8 +1328,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea lsc:lsc]; if ((tempSelfHeight > maxSelfHeight) && - (lsc.heightSizeInner == nil || (sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) && - (sbvsc.topPosInner.posVal == nil || sbvsc.bottomPosInner.posVal == nil)) + ((sbvsc.heightSizeInner.dimeVal != nil && sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) || sbvsc.wrapContentHeight)) { maxSelfHeight = tempSelfHeight; } @@ -1237,8 +1340,6 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea { CGFloat trailingSpaceWeight = trailingSpace; trailingSpace = _myCGFloatRound((trailingSpaceWeight / totalWeight) * floatingWidth); - floatingWidth -= trailingSpace; - totalWeight -= trailingSpaceWeight; if (_myCGFloatLessOrEqual(trailingSpace, 0)) trailingSpace = 0; } @@ -1254,8 +1355,13 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } } } + trailingSpace += sbvsc.trailingPosInner.offsetVal; + if (totalShrink != 0.0 && sbvsc.trailingPosInner.shrink != 0.0) + { + trailingSpace += (sbvsc.trailingPosInner.shrink / totalShrink) * floatingWidth; + } - pos += [self myValidMargin:sbvsc.trailingPosInner sbv:sbv calcPos:trailingSpace + sbvsc.trailingPosInner.offsetVal selfLayoutSize:selfSize]; + pos += [self myValidMargin:sbvsc.trailingPosInner sbv:sbv calcPos:trailingSpace selfLayoutSize:selfSize]; //添加共有的子视图间距 if (sbv != sbs.lastObject) @@ -1272,7 +1378,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea } } - pos += between; //只有mgvert为between才加这个间距拉伸。 + pos += between; //只有gravity为between或者around才加这个间距拉伸。 } sbvmyFrame.frame = rect; @@ -1297,7 +1403,12 @@ - (CGFloat)myCalcSubviewLeadingTrailingRect:(MyGravity)horzGravity selfSize:(CGS pRect->size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:lsc.myLayoutTopPadding paddingLeading:paddingLeading paddingBottom:lsc.myLayoutBottomPadding paddingTrailing:paddingTrailing sbvSize:pRect->size]; if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) - pRect->size.width = selfSize.width - paddingLeading - paddingTrailing - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal; + { + if (sbvsc.widthSizeInner.dimeVal == nil && !sbvsc.wrapContentWidth) + { + pRect->size.width = selfSize.width - paddingLeading - paddingTrailing - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal; + } + } pRect->size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:pRect->size.width sbvSize:pRect->size selfLayoutSize:selfSize]; @@ -1309,8 +1420,12 @@ - (CGFloat)myCalcSubviewTopBottomRect:(MyGravity)vertGravity selfSize:(CGSize)se pRect->size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:lsc.myLayoutLeadingPadding paddingBottom:paddingBottom paddingTrailing:lsc.myLayoutTrailingPadding sbvSize:pRect->size]; if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) - pRect->size.height = selfSize.height - paddingTop - paddingBottom - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal; - + { + if (sbvsc.heightSizeInner.dimeVal == nil && !sbvsc.wrapContentHeight) + { + pRect->size.height = selfSize.height - paddingTop - paddingBottom - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal; + } + } pRect->size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:pRect->size.height sbvSize:pRect->size selfLayoutSize:selfSize]; diff --git a/MyLayout/Lib/MyMaker.h b/MyLayout/Lib/MyMaker.h index 8903506..d61d4a4 100644 --- a/MyLayout/Lib/MyMaker.h +++ b/MyLayout/Lib/MyMaker.h @@ -82,9 +82,6 @@ -(MyMaker*)clearFloat; -//浮动布局独有。 --(MyMaker*)noBoundaryLimit; - //赋值操支持NSNumber,UIView,MyLayoutPos,MyLayoutSize, NSArray[MyLayoutSize] -(MyMaker* (^)(id val))equalTo; -(MyMaker* (^)(id val))min; diff --git a/MyLayout/Lib/MyMaker.m b/MyLayout/Lib/MyMaker.m index 1914bcd..631b795 100644 --- a/MyLayout/Lib/MyMaker.m +++ b/MyLayout/Lib/MyMaker.m @@ -143,11 +143,6 @@ -(MyMaker*)clearFloat return [self addMethod:@"clearFloat"]; } --(MyMaker*)noBoundaryLimit -{ - return [self addMethod:@"noBoundaryLimit"]; -} - -(MyMaker*)topPadding { diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 6721d73..6eeff0a 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -39,14 +39,14 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbvsc.wrapContentWidth) { - //只要同时设置了左右边距或者设置了宽度则应该把wrapContentWidth置为NO - if ((sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) || sbvsc.widthSizeInner.dimeVal != nil) + //只要设置了宽度则应该把wrapContentWidth置为NO + if (sbvsc.widthSizeInner.dimeVal != nil) sbvsc.wrapContentWidth = NO; } if (sbvsc.wrapContentHeight) { - if ((sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) || sbvsc.heightSizeInner.dimeVal != nil) + if (sbvsc.heightSizeInner.dimeVal != nil) sbvsc.wrapContentHeight = NO; } @@ -720,10 +720,24 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc } } else - sbvmyFrame.trailing = selfSize.width - sbvsc.trailingPosInner.absVal - lsc.myLayoutTrailingPadding; + { + //如果设置了宽度则认为trailing是尾部间距。 + if (sbvmyFrame.width != CGFLOAT_MAX) + { + sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width + sbvsc.trailingPosInner.absVal; + } + else + { + sbvmyFrame.trailing = selfSize.width - sbvsc.trailingPosInner.absVal - lsc.myLayoutTrailingPadding; + } + } - sbvmyFrame.width = sbvmyFrame.trailing - sbvmyFrame.leading; - sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + //只有在没有设置宽度时才计算宽度。 + if (sbvsc.widthSizeInner.dimeVal == nil && !sbvsc.wrapContentWidth) + { + sbvmyFrame.width = sbvmyFrame.trailing - sbvmyFrame.leading; + sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + } if ([self myIsNoLayoutSubview:sbv]) { @@ -809,10 +823,24 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc } } else - sbvmyFrame.bottom = selfSize.height - sbvsc.bottomPosInner.absVal - lsc.myLayoutBottomPadding; + { + //如果设置了高度则认为bottom是尾部间距。 + if (sbvmyFrame.height != CGFLOAT_MAX) + { + sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height + sbvsc.bottomPosInner.absVal; + } + else + { + sbvmyFrame.bottom = selfSize.height - sbvsc.bottomPosInner.absVal - lsc.myLayoutBottomPadding; + } + } - sbvmyFrame.height = sbvmyFrame.bottom - sbvmyFrame.top; - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + //只有在没有设置高度时才计算高度。 + if (sbvsc.heightSizeInner.dimeVal == nil && !sbvsc.wrapContentHeight) + { + sbvmyFrame.height = sbvmyFrame.bottom - sbvmyFrame.top; + sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + } if ([self myIsNoLayoutSubview:sbv]) { @@ -1254,11 +1282,21 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize } else if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { - if (_myCGFloatLess(maxWidth, fabs(sbvmyFrame.trailing) + sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding)) + //如果设置有宽度则宽度参与最大!!!!!! + if (sbvsc.wrapContentWidth || sbvsc.widthSizeInner.dimeVal != nil) { - maxWidth = fabs(sbvmyFrame.trailing) + sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; + if (_myCGFloatLess(maxWidth, sbvmyFrame.leading + sbvmyFrame.width + sbvmyFrame.trailing + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding)) + { + maxWidth = sbvmyFrame.leading + sbvmyFrame.width + sbvmyFrame.trailing + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding; + } + } + else + { + if (_myCGFloatLess(maxWidth, fabs(sbvmyFrame.trailing) + sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding)) + { + maxWidth = fabs(sbvmyFrame.trailing) + sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; + } } - } else if (sbvsc.trailingPosInner.posVal != nil) { @@ -1307,9 +1345,20 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize } else if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { - if (_myCGFloatLess(maxHeight, fabs(sbvmyFrame.bottom) + sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding)) + //如果设置有高度则高度参与最大!!!!!! + if (sbvsc.wrapContentHeight || sbvsc.heightSizeInner.dimeVal != nil) { - maxHeight = fabs(sbvmyFrame.bottom) + sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding; + if (_myCGFloatLess(maxHeight, sbvmyFrame.top + sbvmyFrame.height + sbvmyFrame.bottom + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding)) + { + maxHeight = sbvmyFrame.top + sbvmyFrame.height + sbvmyFrame.bottom + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding; + } + } + else + { + if (_myCGFloatLess(maxHeight, fabs(sbvmyFrame.bottom) + sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding)) + { + maxHeight = fabs(sbvmyFrame.bottom) + sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding; + } } } else if (sbvsc.bottomPosInner.posVal != nil) diff --git a/MyLayoutDemo/AllTest1ViewController.m b/MyLayoutDemo/AllTest1ViewController.m index 3f5dab9..2445915 100644 --- a/MyLayoutDemo/AllTest1ViewController.m +++ b/MyLayoutDemo/AllTest1ViewController.m @@ -243,12 +243,12 @@ -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSI if ([UIDevice currentDevice].systemVersion.floatValue < 8) { //如果您的系统要求最低支持到iOS7那么需要通过-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 来评估高度,因此请不要使用- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath 这个方法来初始化UITableviewCell,否则可能造成系统崩溃!!! - cell = (AllTest1TableViewCell*)[tableView dequeueReusableCellWithIdentifier:identifiers[rand()%2]]; + cell = (AllTest1TableViewCell*)[tableView dequeueReusableCellWithIdentifier:identifiers[0]]; } else { //如果你最低支持到iOS8那么请用这个方法来初始化一个UITableviewCell,用这个方法要记得调用registerClass来注册UITableviewCell,否则可能会返回nil - cell = (AllTest1TableViewCell*)[tableView dequeueReusableCellWithIdentifier:identifiers[rand()%2] forIndexPath:indexPath]; + cell = (AllTest1TableViewCell*)[tableView dequeueReusableCellWithIdentifier:identifiers[0] forIndexPath:indexPath]; } diff --git a/MyLayoutDemo/FLLTest1ViewController.m b/MyLayoutDemo/FLLTest1ViewController.m index f3d65a4..e3310c0 100644 --- a/MyLayoutDemo/FLLTest1ViewController.m +++ b/MyLayoutDemo/FLLTest1ViewController.m @@ -172,6 +172,9 @@ -(void)handleAdjustVertGravity:(id)sender vertGravity = MyGravity_Vert_Between; break; case MyGravity_Vert_Between: + vertGravity = MyGravity_Vert_Around; + break; + case MyGravity_Vert_Around: vertGravity = MyGravity_Vert_Fill; break; case MyGravity_Vert_Fill: @@ -209,6 +212,9 @@ -(void)handleAdjustHorzGravity:(id)sender horzGravity = MyGravity_Horz_Between; break; case MyGravity_Horz_Between: + horzGravity = MyGravity_Horz_Around; + break; + case MyGravity_Horz_Around: horzGravity = MyGravity_Horz_Fill; break; case MyGravity_Horz_Fill: @@ -350,6 +356,9 @@ -(NSString*)gravityInfo:(MyGravity)gravity case MyGravity_Vert_Between: vertGravityStr = @"MyGravity_Vert_Between"; break; + case MyGravity_Vert_Around: + vertGravityStr = @"MyGravity_Vert_Around"; + break; case MyGravity_Vert_Window_Center: vertGravityStr = @"MyGravity_Vert_Window_Center"; break; @@ -375,6 +384,9 @@ -(NSString*)gravityInfo:(MyGravity)gravity case MyGravity_Horz_Between: horzGravityStr = @"MyGravity_Horz_Between"; break; + case MyGravity_Horz_Around: + horzGravityStr = @"MyGravity_Horz_Around"; + break; case MyGravity_Horz_Window_Center: horzGravityStr = @"MyGravity_Horz_Window_Center"; break; diff --git a/MyLayoutDemo/FLLTest3ViewController.m b/MyLayoutDemo/FLLTest3ViewController.m index e7b3b4d..2d9b637 100644 --- a/MyLayoutDemo/FLLTest3ViewController.m +++ b/MyLayoutDemo/FLLTest3ViewController.m @@ -10,15 +10,15 @@ #import "MyLayout.h" #import "CFTool.h" + @interface FLLTest3ViewController () @property(nonatomic, strong) MyFlowLayout *flowLayout; -@property(nonatomic, assign) NSInteger oldIndex; -@property(nonatomic, assign) NSInteger currentIndex; -@property(nonatomic, assign) BOOL hasDrag; @property(nonatomic, strong) UIButton *addButton; +@property(nonatomic, strong) MyLayoutDragger *dragger; + @end @implementation FLLTest3ViewController @@ -85,6 +85,11 @@ - (void)viewDidLoad { self.addButton = [self createAddButton]; [self.flowLayout addSubview:self.addButton]; + //创建一个布局拖动器。 + self.dragger = [self.flowLayout createLayoutDragger]; + self.dragger.exclusiveViews = @[self.addButton]; + self.dragger.animateDuration = 0.2; + } @@ -146,97 +151,21 @@ -(void)handleAddTagButton:(id)sender - (IBAction)handleTouchDown:(UIButton*)sender withEvent:(UIEvent*)event { - //在按下时记录当前要拖动的控件的索引。 - self.oldIndex = [self.flowLayout.subviews indexOfObject:sender]; - self.currentIndex = self.oldIndex; - self.hasDrag = NO; - + //拖动子视图开始处理。 + [self.dragger dragView:sender withEvent:event]; } - (IBAction)handleTouchUp:(UIButton*)sender withEvent:(UIEvent*)event { - if (!self.hasDrag) - return; - - //当抬起时,需要让拖动的子视图调整到正确的顺序,并重新参与布局,因此这里要把拖动的子视图的useFrame设置为NO,同时把布局视图的autoresizesSubviews还原为YES。 - - //调整索引。 - for (NSInteger i = self.flowLayout.subviews.count - 1; i > self.currentIndex; i--) - { - [self.flowLayout exchangeSubviewAtIndex:i withSubviewAtIndex:i - 1]; - } - - sender.useFrame = NO; //让拖动的子视图重新参与布局,将useFrame设置为NO - self.flowLayout.autoresizesSubviews = YES; //让布局视图可以重新激发布局,这里还原为YES。 - - + //停止子视图拖动处理。 + [self.dragger dropView:sender withEvent:event]; } - (IBAction)handleTouchDrag:(UIButton*)sender withEvent:(UIEvent*)event { - self.hasDrag = YES; - - NSLog(@"AAA:%@", event); - //取出拖动时当前的位置点。 - CGPoint pt = [[event touchesForView:sender].anyObject locationInView:self.flowLayout]; - - UIView *sbv2 = nil; //sbv2保存拖动时手指所在的视图。 - //判断当前手指在具体视图的位置。这里要排除self.addButton的位置(因为这个按钮将固定不调整)。 - for (UIView *sbv in self.flowLayout.subviews) - { - if (sbv != sender && sender.useFrame && sbv != self.addButton) - { - CGRect rc1 = sbv.frame; - if (CGRectContainsPoint(rc1, pt)) - { - sbv2 = sbv; - break; - } - } - } - - //如果拖动的控件sender和手指下当前其他的兄弟控件有重合时则意味着需要将当前控件插入到手指下的sbv2所在的位置,并且调整sbv2的位置。 - if (sbv2 != nil) - { - - [self.flowLayout layoutAnimationWithDuration:0.2]; - - //得到要移动的视图的位置索引。 - self.currentIndex = [self.flowLayout.subviews indexOfObjectIdenticalTo:sbv2]; - - if (self.oldIndex != self.currentIndex) - { - self.oldIndex = self.currentIndex; - } - else - { - self.currentIndex = self.oldIndex + 1; - } - - - - //因为sender在bringSubviewToFront后变为了最后一个子视图,因此要调整正确的位置。 - for (NSInteger i = self.flowLayout.subviews.count - 1; i > self.currentIndex; i--) - { - [self.flowLayout exchangeSubviewAtIndex:i withSubviewAtIndex:i - 1]; - } - - //经过上面的sbv2的位置调整完成后,需要重新激发布局视图的布局,因此这里要设置autoresizesSubviews为YES。 - self.flowLayout.autoresizesSubviews = YES; - sender.useFrame = NO; - sender.noLayout = YES; //这里设置为YES表示布局时不会改变sender的真实位置而只是在布局视图中占用一个位置和尺寸,正是因为只是占用位置,因此会调整其他视图的位置。 - [self.flowLayout layoutIfNeeded]; - - } - - //在进行sender的位置调整时,要把sender移动到最顶端,也就子视图数组的的最后。同时布局视图不能激发子视图布局,因此要把autoresizesSubviews设置为NO,同时因为要自定义sender的位置,因此要把useFrame设置为YES,并且恢复noLayout为NO。 - [self.flowLayout bringSubviewToFront:sender]; //把拖动的子视图放在最后,这样这个子视图在移动时就会在所有兄弟视图的上面。 - self.flowLayout.autoresizesSubviews = NO; //在拖动时不要让布局视图激发布局 - sender.useFrame = YES; //因为拖动时,拖动的控件需要自己确定位置,不能被布局约束,因此必须要将useFrame设置为YES下面的center设置才会有效。 - sender.center = pt; //因为useFrame设置为了YES所有这里可以直接调整center,从而实现了位置的自定义设置。 - sender.noLayout = NO; //恢复noLayout为NO。 - + //子视图拖动中处理。 + [self.dragger dragginView:sender withEvent:event]; } - (IBAction)handleTouchDownRepeat:(UIButton*)sender withEvent:(UIEvent*)event { diff --git a/MyLayoutDemo/FLLTest9ViewController.h b/MyLayoutDemo/FLLTest9ViewController.h new file mode 100644 index 0000000..41ae62c --- /dev/null +++ b/MyLayoutDemo/FLLTest9ViewController.h @@ -0,0 +1,14 @@ +// +// FLLTest9ViewController.h +// MyLayoutDemo +// +// Created by oubaiquan on 2018/8/1. +// Copyright © 2018年 YoungSoft. All rights reserved. +// + +#import + +/*9.FlexLayout - flex box*/ +@interface FLLTest9ViewController : UIViewController + +@end diff --git a/MyLayoutDemo/FLLTest9ViewController.m b/MyLayoutDemo/FLLTest9ViewController.m new file mode 100644 index 0000000..b30ffc1 --- /dev/null +++ b/MyLayoutDemo/FLLTest9ViewController.m @@ -0,0 +1,267 @@ +// +// FLLTest9ViewController.m +// MyLayoutDemo +// +// Created by oubaiquan on 2018/8/1. +// Copyright © 2018年 YoungSoft. All rights reserved. +// + +#import "FLLTest9ViewController.h" +#import "MyLayout.h" +#import "CFTool.h" + +@interface FLLTest9ViewController () + +-(UIButton*)createActionButton:(NSString*)title action:(SEL)action; + + +@end + +@implementation FLLTest9ViewController + +//创建动作操作按钮。 +-(UIButton*)createActionButton:(NSString*)title action:(SEL)action +{ + UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; + [button setTitle:title forState:UIControlStateNormal]; + button.titleLabel.font = [CFTool font:14]; + [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside]; + button.myHeight = 30; + button.layer.borderColor = [UIColor lightGrayColor].CGColor; + button.layer.borderWidth = 0.5; + + return button; + +} + + +-(void)loadView +{ + [super loadView]; + + self.view.backgroundColor = [UIColor whiteColor]; + + MyFlexLayout *rootLayout = MyFlexLayout.new.flex + .flex_direction(MyFlex.column) + .flex_wrap(MyFlex.nowrap) + .width(MyLayoutSize.fill) + .height(MyLayoutSize.fill) + .addTo(self.view); + + MyFlexLayout *actionLayout = MyFlexLayout.new.flex + .flex_direction(MyFlex.row) + .flex_wrap(MyFlex.wrap) + .width(MyLayoutSize.fill) + .height(MyLayoutSize.wrap) + .addTo(rootLayout); + + + [self createActionButton:NSLocalizedString(@"flex-direction", @"") action:@selector(handleFlex_Direction:)].flexItem + .width(1/3.0) + .addTo(actionLayout); + [self createActionButton:NSLocalizedString(@"flex-wrap", @"") action:@selector(handleFlex_Wrap:)].flexItem + .width(1/3.0) + .addTo(actionLayout); + + [self createActionButton:NSLocalizedString(@"justify-content", @"") action:@selector(handleJustify_Content:)].flexItem + .width(1/3.0) + .addTo(actionLayout); + + + [self createActionButton:NSLocalizedString(@"align-items", @"") action:@selector(handleAlign_Items:)].flexItem + .width(1/3.0) + .addTo(actionLayout); + + [self createActionButton:NSLocalizedString(@"align-content", @"") action:@selector(handleAlign_Content:)].flexItem + .width(1/3.0) + .addTo(actionLayout); + + + MyFlexLayout *contentLayout = MyFlexLayout.new.flex + .vert_space(10) + .horz_space(10) + .flex_wrap(MyFlex.wrap) + .width(MyLayoutSize.fill) + .flex_grow(1) + .addTo(rootLayout); + + + for (int i = 0; i < 6; i++) + { + UILabel *label = UILabel.new.flexItem + .width(100) + .height(100) + .addTo(contentLayout); + + label.backgroundColor = [UIColor redColor]; + + } + + + + + +// +// //添加容器。 +// MyFlexLayout *contentLayout = MyFlexLayout.new.flex +// .width(MyLayoutSize.fill) +// .height(MyLayoutSize.) +// +// + + +// +// //添加操作按钮。 +// MyFlowLayout *actionLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:2]; +// actionLayout.wrapContentHeight = YES; +// actionLayout.gravity = MyGravity_Horz_Fill; //所有子视图水平填充,也就是所有子视图的宽度相等。 +// actionLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); +// actionLayout.subviewHSpace = 5; +// actionLayout.subviewVSpace = 5; +// [rootLayout addSubview:actionLayout]; +// +// [actionLayout addSubview: +// ]; +// [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"adjust arrangedCount", @"") +// action:@selector(handleAdjustArrangedCount:)]]; +// [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"adjust vert gravity", @"") +// action:@selector(handleAdjustVertGravity:)]]; +// [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"adjust horz gravity", @"") +// action:@selector(handleAdjustHorzGravity:)]]; +// [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"adjust align", @"") +// action:@selector(handleAdjustArrangeGravity:)]]; +// [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"adjust spacing", @"") +// action:@selector(handleAdjustMargin:)]]; +// +// UILabel *flowLayoutSetLabel = [UILabel new]; +// flowLayoutSetLabel.font = [CFTool font:13]; +// flowLayoutSetLabel.textColor = [UIColor redColor]; +// flowLayoutSetLabel.adjustsFontSizeToFitWidth = YES; +// flowLayoutSetLabel.wrapContentHeight = YES; +// flowLayoutSetLabel.numberOfLines = 5; +// [rootLayout addSubview:flowLayoutSetLabel]; +// self.flowLayoutSetLabel = flowLayoutSetLabel; +// +// UIScrollView *scrollView = [UIScrollView new]; +// scrollView.alwaysBounceHorizontal = YES; +// scrollView.alwaysBounceVertical = YES; +// scrollView.weight = 1; //占用剩余高度。 +// scrollView.myTop = 10; +// [rootLayout addSubview:scrollView]; +// +// +// MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; +// flowLayout.backgroundColor = [CFTool color:0]; +// flowLayout.frame = CGRectMake(0, 0, 800, 800); +// flowLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); +// flowLayout.subviewVSpace = 5; +// flowLayout.subviewHSpace = 5; +// [scrollView addSubview:flowLayout]; +// self.flowLayout = flowLayout; +// +// NSArray *imageArray = @[@"minions1",@"minions2",@"minions3",@"minions4",@"head1"]; +// for (int i = 0; i < 30; i++) +// { +// UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageArray[random()%5]]]; +// [imageView sizeToFit]; +// imageView.layer.borderColor = [CFTool color:5].CGColor; +// imageView.layer.borderWidth = 0.5; +// [self.flowLayout addSubview:imageView]; +// } +// +// +// [self flowlayoutInfo]; +// +// +// +// +// MyFlexLayout *layout = MyFlexLayout.new.flex +// .flex_wrap(MyFlex.wrap) +// .justify_content(MyFlex.space_between) +// .flex_direction(MyFlex.row) +// .align_items(MyFlex.center) +// .align_content(MyFlex.stretch) +// .padding(UIEdgeInsetsMake(10, 10, 10, 10)) +// .vert_space(10) +// .horz_space(10) +// .margin_left(0) +// .margin_right(0) +// .margin_top(0) +// .margin_bottom(0) +// .addTo(self.view); +// +// for (int i = 0; i < 2; i++) +// { +// UILabel *label = UILabel.new.flexItem +// .width(600) +// .height(200) +// .order(2-i) +// .align_self(MyFlex.flex_start) +// .flex_grow(1) +// .flex_shrink(1) +// .flex_basis(100) +// .addTo(layout); +// +// label.text = [NSString stringWithFormat:@"%d",i]; +// label.backgroundColor = UIColor.redColor; +// } +// + +} + +- (void)viewDidLoad { + self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +#pragma mark -- Handle Method + +-(void)handleFlex_Direction:(id)sender +{ + + + +} + +-(void)handleFlex_Wrap:(id)sender +{ + + +} + +-(void)handleJustify_Content:(id)sender +{ + + +} + +-(void)handleAlign_Items:(id)sender +{ + +} + + +-(void)handleAlign_Content:(id)sender +{ + +} + + +@end diff --git a/MyLayoutDemo/FOLTest6ViewController.m b/MyLayoutDemo/FOLTest6ViewController.m index ed1b805..bb5c4b9 100644 --- a/MyLayoutDemo/FOLTest6ViewController.m +++ b/MyLayoutDemo/FOLTest6ViewController.m @@ -72,14 +72,13 @@ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { -(void)createUserProfile1Layout:(MyLinearLayout*)rootLayout { - //这个例子建立一个只向上浮动的浮动布局视图,注意这里要想布局高度由子视图包裹的话则必须要同时设置noBoundaryLimit为YES。 - //在常规情况下,如果使用左右浮动布局时,要求必须有明确的宽度,也就是不要用wrapContentWidth。同样使用上下浮动布局时,要求必须要有明确的高度,也就是不要用wrapContentHeight。这样设置明确宽度或者高度的原因是浮动布局需要根据这些宽度或者高度的约束自动换行浮动。但是在实践的场景中,有时候我们在浮动方向上没有尺寸约束限制,而是人为的来控制子视图的换行,并且还要布局视图的宽度和高度具有包裹属性,那么这时候我们就可以用浮动布局的noBoundaryLimit属性来进行控制了。 - //设置noBoundaryLimit为YES时必要同时设置包裹属性。具体情况见属性noBoundaryLimit的说明。 + //这个例子建立一个只向上浮动的浮动布局视图,注意这里要想布局高度由子视图包裹的话则必须要设置布局视图的wrapContentHeight为YES。 + //当在水平浮动布局中设置wrapContentHeight为YES时,子视图不能逆向浮动只能向上浮动,并且子视图的weight不能设置为非0. + //当在水平浮动布局中设置wrapContentHeight为YES时,需要我们设置某个子视图的clearFloat为YES进行手动换行处理。 MyFloatLayout *contentLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Horz]; contentLayout.backgroundColor = [UIColor whiteColor]; - contentLayout.noBoundaryLimit = YES; - contentLayout.wrapContentHeight = YES; //对于上下浮动布局来说,如果只想向上浮动,而高度又希望是由子视图决定,则必须要设置noBoundaryLimit的值为YES。 + contentLayout.wrapContentHeight = YES; contentLayout.myHorzMargin = 0; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); contentLayout.subviewHSpace = 5; @@ -235,11 +234,11 @@ -(void)createUserProfile2Layout:(MyLinearLayout*)rootLayout -(void)createUserProfile3Layout:(MyLinearLayout*)rootLayout { - //这个例子里面上下浮动布局还是可以设置wrapContentHeight的,并且这里用了viewLayoutCompleteBlock来实现一些特殊化处理。 + //这个例用了viewLayoutCompleteBlock来实现一些特殊化处理。 MyFloatLayout *contentLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Horz]; contentLayout.backgroundColor = [UIColor whiteColor]; - contentLayout.wrapContentHeight = YES; //虽然说上下浮动布局一般要明确有高度,但是我们依然可以用wrapContentHeight属性,这时候布局视图的高度就是子视图里面高度最高的子视图了。 + contentLayout.wrapContentHeight = YES; contentLayout.myHorzMargin = 0; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); [rootLayout addSubview:contentLayout]; @@ -277,6 +276,7 @@ -(void)createUserProfile3Layout:(MyLinearLayout*)rootLayout nameLabel.text = @"欧阳大哥"; nameLabel.font = [CFTool font:17]; nameLabel.textColor = [CFTool color:4]; + nameLabel.clearFloat = YES; [nameLabel sizeToFit]; [contentLayout addSubview:nameLabel]; @@ -293,12 +293,9 @@ -(void)createUserProfile3Layout:(MyLinearLayout*)rootLayout detailLabel.textColor = [CFTool color:2]; detailLabel.font = [CFTool font:20]; detailLabel.adjustsFontSizeToFitWidth = YES; - detailLabel.reverseFloat = YES; [detailLabel sizeToFit]; [contentLayout addSubview:detailLabel]; - - } diff --git a/MyLayoutDemo/LLTest2ViewController.m b/MyLayoutDemo/LLTest2ViewController.m index 1d9c262..8e0c51e 100644 --- a/MyLayoutDemo/LLTest2ViewController.m +++ b/MyLayoutDemo/LLTest2ViewController.m @@ -21,91 +21,33 @@ @interface LLTest2ViewController () @implementation LLTest2ViewController --(void)loadView -{ - /* - 本例子用来实现将一个布局视图嵌入到一个UIScrollView里面的功能。 - 我们可以把一个布局视图作为一个子视图加入到UIScrollView中,布局库内部会根据布局视图的尺寸自动调整UIScrollView的contentSize。如果您不想调整contentSize则请将布局视图的adjustScrollViewContentSizeMode属性设置为MyAdjustScrollViewContentSizeModeNo。 - */ - - UIScrollView *scrollView = [UIScrollView new]; - scrollView.backgroundColor = [UIColor whiteColor]; - self.view = scrollView; - - /* - 这里的contentLayout是非布局视图UIScrollView的子视图。因为同时设置了myHorzMargin为0表示宽度和UIScrollView是保持一致;而高度则因为垂直线性布局的wrapContentHeight属性设置来确定,表示垂直线性布局的高度等于里面的所有子视图高度;而其中的x,y轴的位置则因为没有设置默认是0。 - */ - MyLinearLayout *contentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - contentLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); //设置布局内的子视图离自己的边距. - contentLayout.myHorzMargin = 0; //同时指定左右边距为0表示宽度和父视图一样宽 - contentLayout.heightSize.lBound(scrollView.heightSize, 10, 1); //高度虽然是wrapContentHeight的。但是最小的高度不能低于父视图的高度加10. - [scrollView addSubview:contentLayout]; - self.contentLayout = contentLayout; - - - /* - 布局视图里面的padding属性用来设置布局视图的内边距。内边距是指布局视图里面的子视图离自己距离。外边距则是视图与父视图之间的距离。 - 内边距是在自己的尺寸内离子视图的距离,而外边距则不是自己尺寸内离其他视图的距离。下面是内边距和外边距的效果图: - - ^ - | topMargin - | width - +------------------------------+ - | |------------> - | l r | rightMargin - | e topPadding i | - | f g | - | t +---------------+ h | -<----------| P | | t | - leftMargin| a | | P | - | d | subviews | a | height - | d | content | d | - | i | | d | - | n | | i | - | g +---------------+ n | - | g | - | bottomPadding | - +------------------------------+ - |bottomMargin - | - V - - - 如果一个布局视图中的每个子视图都离自己有一定的距离就可以通过设置布局视图的内边距来实现,而不需要为每个子视图都设置外边距。 - - */ - - - //垂直线性布局直接添加子视图 - [self createSection1:contentLayout]; - - //垂直线性布局套水平线性布局 - [self createSection2:contentLayout]; - - //垂直线性布局套垂直线性布局 - [self createSection3:contentLayout]; - - //垂直线性布局套水平线性布局 - [self createSection4:contentLayout]; - - //垂直线性布局套水平线性布局,水平线性布局利用相对边距实现左右布局 - [self createSection5:contentLayout]; - - //水平线性布局中的基线对齐 - [self createSection6:contentLayout]; - - //对子视图的高度的缩放调整 - [self createSection7:contentLayout]; - - //子视图的显示和隐藏 - [self createSection8:contentLayout]; - -} - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. + + //创建一个视图。 + MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + rootLayout.myMargin = 0; + [self.view addSubview:rootLayout]; + + UIView *v1 = [UIView new]; + v1.myCenter = CGPointMake(0, 0); + v1.backgroundColor = [UIColor redColor]; + v1.widthSize.equalTo(@[rootLayout.widthSize, rootLayout.heightSize].myMinSize).multiply(0.5); + v1.heightSize.equalTo(v1.widthSize); + [rootLayout addSubview:v1]; + + UILabel *label = [UILabel new]; + label.myCenterX = 0; + label.myBottom = MyLayoutPos.safeAreaMargin; + label.text = @"您好!!!"; + label.backgroundColor = [UIColor redColor]; + label.widthSize.equalTo(@[@(MyLayoutSize.wrap), v1.widthSize.detach(0, 0.5)].myMaxSize); + label.wrapContentHeight = YES; + [rootLayout addSubview:label]; + } - (void)didReceiveMemoryWarning { diff --git a/MyLayoutDemo/LLTest3ViewController.m b/MyLayoutDemo/LLTest3ViewController.m index 975aa88..fb89d20 100644 --- a/MyLayoutDemo/LLTest3ViewController.m +++ b/MyLayoutDemo/LLTest3ViewController.m @@ -32,11 +32,14 @@ -(void)loadView 3.假设某个垂直线性布局有A,B,C三个子视图,并且我们希望这三个子视图整体垂直居中。第一个方法是为设置A的myTop=0.5和设置C的myBottom=0.5;第二个方法是只需要设置布局视图的gravity的值为MyGravity_Vert_Center就可以实现了。 4.假设某个垂直线性布局有A,B,C三个子视图,我们希望这三个子视图整体居中。我们就只需要将布局视图的gravity值设置为MyGravity_Center就可以了。 5.假设某个垂直线性布局有A,B,C三个子视图,我们希望这三个子视图的宽度都和布局视图一样宽。第一个方法是分别为每个子视图的myLeft和myRight设置为0;第二个方法是只需要设置布局视图的gravity的值为MyGravity_Horz_Fill就可以了。 + 6.假设某个垂直线性布局有A,B,C三个子视图,我们希望这三个子视图高度不变但是垂直间距填充满整个布局视图。解决的方法是将布局视图的gravity的值设置为MyGravity_Vert_Between就可以实现了。 + 7.假设某个垂直线性布局有A,B,C三个子视图,我们希望这三个子视图高度不变但是垂直间距填充满整个布局视图,并且第一个子视图的上间距和最后一个子视图的下间距是间距的一半。解决的方法是将布局视图的gravity的值设置为MyGravity_Vert_Around就可以实现了。 + 通过上面的几个场景我们可以看出gravity属性的设置可以在很大程度上简化布局视图里面的子视图的布局属性的设置的,通过gravity属性的设置我们可以控制布局视图里面所有子视图的整体停靠方向和填充的尺寸。在使用gravity属性时需要明确如下几个条件: 1.当使用gravity属性时意味着布局视图必须要有明确的尺寸才有意义,因为有确定的尺寸才能决定里面的子视图的停靠的方位。 - 2.布局视图的wrapContentHeight设置为YES时是和gravity上设置垂直停靠方向以及垂直填充是互斥的;而布局视图的wrapContentWidth设置为YES时是和gravity上设置水平停靠方向和水平填充是互斥的。 + 2.布局视图的wrapContentHeight设置为YES时是和gravity上设置垂直停靠方向以及垂直填充是互斥的;而布局视图的wrapContentWidth设置为YES时是和gravity上设置水平停靠方向和水平填充是互斥的。(也有特殊情况就是布局视图设置了最小尺寸限制时才有效) 3.布局视图的gravity的属性的优先级要高于子视图的边距和尺寸设置,但是低于子视图的alignment属性的设置。 */ @@ -129,6 +132,7 @@ -(void)createVertLayoutGravityActionLayout:(MyLinearLayout*)contentLayout NSLocalizedString(@"screen vert center",@""), NSLocalizedString(@"screen horz center",@""), NSLocalizedString(@"between",@""), + NSLocalizedString(@"around",@""), NSLocalizedString(@"horz fill",@""), NSLocalizedString(@"vert fill", @"")]; @@ -217,6 +221,7 @@ -(void)createHorzLayoutGravityActionLayout:(MyLinearLayout*)contentLayout NSLocalizedString(@"screen vert center",@""), NSLocalizedString(@"screen horz center",@""), NSLocalizedString(@"between",@""), + NSLocalizedString(@"around",@""), NSLocalizedString(@"horz fill",@""), NSLocalizedString(@"vert fill", @"")]; @@ -329,10 +334,13 @@ -(void)handleVertLayoutGravity:(UIButton*)button case 9: //垂直间距拉伸 vertGravity = MyGravity_Vert_Between; break; - case 10: //水平填充 + case 10: //垂直间距环绕 + vertGravity = MyGravity_Vert_Around; + break; + case 11: //水平填充 horzGravity = MyGravity_Horz_Fill; break; - case 11: //垂直填充 + case 12: //垂直填充 vertGravity = MyGravity_Vert_Fill; //这里模拟器顶部出现黑线,真机是不会出现的。。 break; default: @@ -382,10 +390,13 @@ -(void)handleHorzLayoutGravity:(UIButton*)button case 9: //水平间距拉伸 horzGravity = MyGravity_Horz_Between; break; - case 10: //水平填充 + case 10: //水平间距环绕 + horzGravity = MyGravity_Horz_Around; + break; + case 11: //水平填充 horzGravity = MyGravity_Horz_Fill; break; - case 11: + case 12: vertGravity = MyGravity_Vert_Fill; break; default: @@ -470,6 +481,9 @@ -(NSString*)gravityText:(MyGravity)gravity prefixText:(NSString*)prefixText case MyGravity_Vert_Between: vertGravityStr = @"MyGravity_Vert_Between"; break; + case MyGravity_Vert_Around: + vertGravityStr = @"MyGravity_Vert_Around"; + break; case MyGravity_Vert_Window_Center: vertGravityStr = @"MyGravity_Vert_Window_Center"; break; @@ -495,6 +509,9 @@ -(NSString*)gravityText:(MyGravity)gravity prefixText:(NSString*)prefixText case MyGravity_Horz_Between: horzGravityStr = @"MyGravity_Horz_Between"; break; + case MyGravity_Horz_Around: + horzGravityStr = @"MyGravity_Horz_Around"; + break; case MyGravity_Horz_Window_Center: horzGravityStr = @"MyGravity_Horz_Window_Center"; break; diff --git a/MyLayoutDemo/LLTest4ViewController.m b/MyLayoutDemo/LLTest4ViewController.m index 9ab7916..5e9c5dc 100644 --- a/MyLayoutDemo/LLTest4ViewController.m +++ b/MyLayoutDemo/LLTest4ViewController.m @@ -18,44 +18,51 @@ @interface LLTest4ViewController () @implementation LLTest4ViewController --(void)loadView -{ - /* - 这个例子详细说明wrapContentHeight和wrapContentWidth的包裹属性的设置、以及边界线性的设定、以及布局中可局部缩放背景图片的设定方法。 - */ + + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. - self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 - [super loadView]; - self.view.backgroundColor = [UIColor whiteColor]; + MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + rootLayout.wrapContentWidth = YES; + rootLayout.myVertMargin = 0; + rootLayout.backgroundColor = [UIColor redColor]; + [self.view addSubview:rootLayout]; + rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); + rootLayout.topPadding = MyLayoutPos.safeAreaMargin + 100; + + + UILabel *l1 = [UILabel new]; + l1.text = @"您好"; + l1.backgroundColor = [UIColor blueColor]; + l1.wrapContentSize = YES; + [rootLayout addSubview:l1]; + + UILabel *l3 = [UILabel new]; + l3.text = @"ak"; + l3.wrapContentSize = YES; + l3.topPos.equalTo(l1.bottomPos).offset(10); + l3.leftPos.equalTo(l1.leftPos); + l3.backgroundColor = [UIColor greenColor]; + [rootLayout addSubview:l3]; + + UILabel *l2 = [UILabel new]; + l2.text = @"2019-04-03"; + [l2 sizeToFit]; + [rootLayout addSubview:l2]; + l2.topPos.equalTo(l1.topPos); + l2.rightPos.equalTo(l3.rightPos); + l2.rightPos.min(-1 *(l2.frame.size.width + 30 + 50)); + + - UIView *contentView = [UIView new]; - contentView.backgroundColor = [CFTool color:5]; - [self.view addSubview:contentView]; - contentView.wrapContentWidth = YES; - contentView.wrapContentHeight = YES; //如果一个非布局父视图里面有布局子视图,那么这个非布局父视图也是可以设置wrapContentHeight和wrapContentWidth的,他表示的意义是这个非布局父视图的尺寸由里面的布局子视图的尺寸来决定的。这个功能是在1.3.3版本支持的。 还有一个场景是非布局父视图是一个UIScrollView。他是左右滚动的,但是滚动视图的高度是由里面的布局子视图确定的,而宽度则是和窗口保持一致。这样只需要将滚动视图的宽度设置为和屏幕保持一致,高度设置为wrapContentHeight,并且把一个水平线性布局添加到滚动视图即可。 - self.rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - self.rootLayout.layer.borderWidth = 1; - self.rootLayout.layer.borderColor = [UIColor lightGrayColor].CGColor; - self.rootLayout.wrapContentHeight = YES; - self.rootLayout.wrapContentWidth = YES; //布局的高度和宽度由子视图决定 - self.rootLayout.myTop = 10; - self.rootLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); - self.rootLayout.zeroPadding = NO; //这个属性设置为NO时表示当布局视图的尺寸是wrap也就是由子视图决定时并且在没有任何子视图是不会参与布局视图高度的计算的。您可以在这个DEMO的测试中将所有子视图都删除掉,看看效果,然后注释掉这句代码看看效果。 - self.rootLayout.subviewVSpace = 5; - [contentView addSubview:self.rootLayout]; - [self.rootLayout addSubview:[self addWrapContentLayout]]; -} - - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view. } - (void)didReceiveMemoryWarning { diff --git a/MyLayoutDemo/ViewController.m b/MyLayoutDemo/ViewController.m index 439d467..e6f15ef 100644 --- a/MyLayoutDemo/ViewController.m +++ b/MyLayoutDemo/ViewController.m @@ -43,6 +43,7 @@ #import "FLLTest6ViewController.h" #import "FLLTest7ViewController.h" #import "FLLTest8ViewController.h" +#import "FLLTest9ViewController.h" #import "AllTest1ViewController.h" @@ -193,6 +194,9 @@ -(NSArray*)demoTypeList }, @{@"title":NSLocalizedString(@"8.FlowLayout - Flex space", @""), @"class":[FLLTest8ViewController class] + }, + @{@"title":NSLocalizedString(@"9.FlowLayout - Flexbox", @""), + @"class":[FLLTest9ViewController class] } ] }, diff --git a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings index 56fe993..26788f5 100644 --- a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings +++ b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings @@ -107,6 +107,7 @@ "screen horz center" ="屏幕水平居中"; "space" = "间距调整"; "between" = "间距拉伸"; +"around" = "间距环绕"; "test text1"="测试文本1"; "always alignment to left"="总是停靠在左边"; "always alignment to top"="总是停靠在上边"; diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index 9c23460..77d9892 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -30,6 +30,36 @@ - (void)testExample { } +-(void)testWrapContentSize +{ + //测试内容约束布局的宽度自适应和高度自适应的设置。 + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; + rootLayout.wrapContentSize = YES; + rootLayout.padding = UIEdgeInsetsMake(10, 20, 30, 40); + rootLayout.subviewHSpace = 5; + rootLayout.subviewVSpace = 5; + + for (int i = 0; i < 3; i++) + { + UIView *v = [UIView new]; + v.mySize = CGSizeMake(100, 100 * (i+1)); + [rootLayout addSubview:v]; + } + + [rootLayout layoutIfNeeded]; + + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,20+40+3*100 + 2*5 ,10+30+300)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + + rootLayout.orientation = MyOrientation_Horz; + + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,20+40+100, 10+30+100+200+300+2*5)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + +} + -(void)testSubviewSizeDependent {//测试子视图尺寸依赖 diff --git a/MyLayoutTests/MyFrameLayoutTestCase.m b/MyLayoutTests/MyFrameLayoutTestCase.m index f3c3a23..7fca77a 100644 --- a/MyLayoutTests/MyFrameLayoutTestCase.m +++ b/MyLayoutTests/MyFrameLayoutTestCase.m @@ -162,6 +162,84 @@ -(void)testSizeDependent } +-(void)testWrapContent2 +{ + MyFrameLayout * dataview = [[MyFrameLayout alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 0)]; + dataview.heightSize.min([UIScreen mainScreen].bounds.size.height); + dataview.wrapContentHeight = YES; + //上面在滚动视图下。 + + MyLinearLayout * dataContentV = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + dataContentV.topPadding = 64; + dataContentV.bottomPadding = 64; // + 10; + dataContentV.myCenterX = 0; + dataContentV.myCenterY = 0; + dataContentV.wrapContentHeight = YES; + dataContentV.myHorzMargin = 0; + [dataview addSubview:dataContentV]; + + + MyLinearLayout * subrootview1 = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + subrootview1.gravity = MyGravity_Horz_Fill; + subrootview1.wrapContentHeight = YES; + subrootview1.myHorzMargin = 0; + subrootview1.padding = UIEdgeInsetsMake(0, 10, 0, 10); + [dataContentV addSubview:subrootview1]; + + + UILabel * view1 = [UILabel new]; + view1.myTop = 120; + view1.myHeight = 140 + 180; + [subrootview1 addSubview:view1]; + + + UILabel * view2 = [UILabel new]; + view2.myHeight = 160 + 200; + [subrootview1 addSubview:view2]; + + + UILabel * subrootview2 = [UILabel new]; + subrootview2.myHeight = 150; + subrootview2.myHorzMargin = 0; + subrootview2.text = @"subrootview2"; + [dataContentV addSubview:subrootview2]; + + view2.hidden = YES; + subrootview2.hidden = YES; + + [dataview layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(dataview.frame, CGRectMake(0,0,375,667)), @"dataview rect is:%@", NSStringFromCGRect(dataview.frame)); + XCTAssertTrue(CGRectEqualToRect(dataContentV.frame, CGRectMake(0,49.5,375,568)), @"dataContentV rect is:%@", NSStringFromCGRect(dataContentV.frame)); + + + subrootview2.hidden = NO; + + [dataview layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(dataview.frame, CGRectMake(0,0,375,718)), @"dataview rect is:%@", NSStringFromCGRect(dataview.frame)); + XCTAssertTrue(CGRectEqualToRect(dataContentV.frame, CGRectMake(0,0,375,718)), @"dataContentV rect is:%@", NSStringFromCGRect(dataContentV.frame)); + + + view2.hidden = NO; + subrootview2.hidden = YES; + + [dataview layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(dataview.frame, CGRectMake(0,0,375,928)), @"dataview rect is:%@", NSStringFromCGRect(dataview.frame)); + XCTAssertTrue(CGRectEqualToRect(dataContentV.frame, CGRectMake(0,0,375,928)), @"dataContentV rect is:%@", NSStringFromCGRect(dataContentV.frame)); + + + view2.hidden = YES; + subrootview2.hidden = YES; + + [dataview layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(dataview.frame, CGRectMake(0,0,375,667)), @"dataview rect is:%@", NSStringFromCGRect(dataview.frame)); + XCTAssertTrue(CGRectEqualToRect(dataContentV.frame, CGRectMake(0,49.5,375,568)), @"dataContentV rect is:%@", NSStringFromCGRect(dataContentV.frame)); + +} + -(void)testPerformanceExample { [self measureBlock:^{ diff --git a/MyLayoutTests/MyLinearLayoutTestCase.m b/MyLayoutTests/MyLinearLayoutTestCase.m index 3c49857..24ee661 100644 --- a/MyLayoutTests/MyLinearLayoutTestCase.m +++ b/MyLayoutTests/MyLinearLayoutTestCase.m @@ -312,6 +312,141 @@ -(void)testWrapContentHeight2 XCTAssertTrue(CGRectEqualToRect(timeLabel.frame, CGRectMake(0,15,375,20.5)), @"the timeLabel.frame = %@",NSStringFromCGRect(timeLabel.frame)); XCTAssertTrue(CGRectEqualToRect(convertLayout.subviews[1].frame, CGRectMake(76,6.5,18.5,20.5)), @"the convertLayout.subviews[1].frame = %@",NSStringFromCGRect(convertLayout.subviews[1].frame)); +} + +-(void)testWrapGravityMinMaxShrink +{ + //测试自适应,停靠,最大和最小。 + MyLinearLayout *testLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + testLayout.widthSize.min(200).max(300); + testLayout.heightSize.min(40).max(100); + testLayout.shrinkType = MySubviewsShrink_Average; + testLayout.subviewHSpace = 10; + testLayout.wrapContentHeight = YES; + testLayout.gravity = MyGravity_Center; + + + UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; + [button setTitle:@"点我" forState:UIControlStateNormal]; + [button sizeToFit]; + [testLayout addSubview:button]; + + + UILabel *label1 = [[UILabel alloc] init]; + label1.wrapContentSize = YES; + label1.text = @"文本1"; + label1.backgroundColor = [UIColor grayColor]; + [testLayout addSubview:label1]; + + UILabel *label2 = [[UILabel alloc] init]; + label2.text = @"文本2"; + label2.wrapContentSize = YES; + label2.backgroundColor = [UIColor cyanColor]; + [label2 sizeToFit]; + [testLayout addSubview:label2]; + + [testLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(testLayout.frame, CGRectMake(0,0,200,40)), @"the testLayout.frame = %@",NSStringFromCGRect(testLayout.frame)); + XCTAssertTrue(CGRectEqualToRect(button.frame, CGRectMake(28,3,37,34)), @"the button.frame = %@",NSStringFromCGRect(button.frame)); + XCTAssertTrue(CGRectEqualToRect(label1.frame, CGRectMake(75,10,42.5,20.5)), @"the label1.frame = %@",NSStringFromCGRect(label1.frame)); + + //字体高度扩高。文字超长。 + button.titleLabel.font = [UIFont systemFontOfSize:30]; + label1.text = @"文本111111111111"; + [button sizeToFit]; + + [testLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(testLayout.frame, CGRectMake(0,0,251.5,48)), @"the testLayout.frame = %@",NSStringFromCGRect(testLayout.frame)); + XCTAssertTrue(CGRectEqualToRect(button.frame, CGRectMake(0,0,61,48)), @"the button.frame = %@",NSStringFromCGRect(button.frame)); + XCTAssertTrue(CGRectEqualToRect(label1.frame, CGRectMake(71,14,125.5,20.5)), @"the label1.frame = %@",NSStringFromCGRect(label1.frame)); + + +// label1.text = @"文本111111111111111111111111111"; +// label1.mySize = CGSizeMake(400, 20.5); +// [testLayout layoutIfNeeded]; +// +// XCTAssertTrue(CGRectEqualToRect(testLayout.frame, CGRectMake(0,0,330,48)), @"the testLayout.frame = %@",NSStringFromCGRect(testLayout.frame)); +// XCTAssertTrue(CGRectEqualToRect(button.frame, CGRectMake(0,0,44.5,48)), @"the button.frame = %@",NSStringFromCGRect(button.frame)); +// XCTAssertTrue(CGRectEqualToRect(label1.frame, CGRectMake(54.5,14,237,20.5)), @"the label1.frame = %@",NSStringFromCGRect(label1.frame)); + +} + +-(void)testBetweenAndAround +{ + //测试布局视图的gravity属性的between和around特性。 + + MyLinearLayout *layout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 100, 100) orientation:MyOrientation_Vert]; + layout.wrapContentSize = NO; + + //一个子视图下的垂直和水平的差异。 + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(30, 30); + [layout addSubview:v1]; + + layout.orientation = MyOrientation_Vert; + layout.gravity = MyGravity_Vert_Between; + [layout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,0,30,30)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + + + layout.orientation = MyOrientation_Horz; + layout.gravity = MyGravity_Horz_Between; + [layout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,0,30,30)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + + + layout.orientation = MyOrientation_Vert; + layout.gravity = MyGravity_Vert_Around; + layout.wrapContentSize = NO; + [layout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,35,30,30)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + + + layout.orientation = MyOrientation_Horz; + layout.gravity = MyGravity_Horz_Around; + layout.wrapContentSize = NO; + [layout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(35,0,30,30)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + + + //两个子视图 + UIView *v2 = [UIView new]; + v2.mySize = CGSizeMake(30, 30); + [layout addSubview:v2]; + + layout.orientation = MyOrientation_Vert; + layout.gravity = MyGravity_Vert_Between; + layout.wrapContentSize = NO; + [layout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,70,30,30)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + + + layout.orientation = MyOrientation_Horz; + layout.gravity = MyGravity_Horz_Between; + layout.wrapContentSize = NO; + [layout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(70,0,30,30)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + + + layout.orientation = MyOrientation_Vert; + layout.gravity = MyGravity_Vert_Around; + layout.wrapContentSize = NO; + [layout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,60,30,30)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + + + layout.orientation = MyOrientation_Horz; + layout.gravity = MyGravity_Horz_Around; + layout.wrapContentSize = NO; + [layout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(60,0,30,30)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + + + + + } - (void)testPerformanceExample { diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index 2271561..14050c4 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -1001,6 +1001,44 @@ -(void)testMaxHeightAndWidth XCTAssertTrue(CGSizeEqualToSize(vv.estimatedRect.size, label.estimatedRect.size)); +} + +-(void)testMaxAndMin +{ + +// MyRelativeLayout *rootLayout = [MyRelativeLayout new]; +// rootLayout.wrapContentWidth = YES; +// rootLayout.myVertMargin = 0; +// rootLayout.backgroundColor = [UIColor redColor]; +// [self.view addSubview:rootLayout]; +// rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); +// rootLayout.topPadding = MyLayoutPos.safeAreaMargin + 100; +// +// +// UILabel *l1 = [UILabel new]; +// l1.text = @"您好"; +// l1.backgroundColor = [UIColor blueColor]; +// l1.wrapContentSize = YES; +// [rootLayout addSubview:l1]; +// +// UILabel *l3 = [UILabel new]; +// l3.text = @"ak"; +// l3.wrapContentSize = YES; +// l3.topPos.equalTo(l1.bottomPos).offset(10); +// l3.leftPos.equalTo(l1.leftPos); +// l3.backgroundColor = [UIColor greenColor]; +// [rootLayout addSubview:l3]; +// +// UILabel *l2 = [UILabel new]; +// l2.text = @"2019-04-03"; +// [l2 sizeToFit]; +// [rootLayout addSubview:l2]; +// l2.topPos.equalTo(l1.topPos); +// l2.rightPos.equalTo(l3.rightPos); +// l2.rightPos.min(-1 *(l2.frame.size.width + 30 + 50)); +// + + } - (void)testPerformanceExample { From 13c4381a2d60cac3ec1317b8d077d5fed2211579 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Wed, 18 Sep 2019 09:23:07 +0800 Subject: [PATCH 035/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 4 +-- MyLayoutTests/MyFrameLayoutTestCase.m | 44 +++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 73dc46f..5d24216 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -3716,7 +3716,7 @@ -(void)myCalcSubViewRect:(UIView*)sbv } //宽度不依赖布局并且没有同时设置左右边距则参与最大宽度计算。 - if ((sbvsc.widthSizeInner.dimeVal != nil && sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) || sbvsc.wrapContentWidth) + if ((sbvsc.widthSizeInner.dimeVal != nil && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) || sbvsc.wrapContentWidth) { if (_myCGFloatLess(pMaxWrapSize->width, sbvmyFrame.width + sbvsc.leadingPosInner.absVal + sbvsc.centerXPosInner.absVal + sbvsc.trailingPosInner.absVal + paddingLeading + paddingTrailing)) @@ -3743,7 +3743,7 @@ -(void)myCalcSubViewRect:(UIView*)sbv } //高度不依赖布局并且没有同时设置上下边距则参与最大高度计算。 - if ((sbvsc.heightSizeInner.dimeVal != nil && sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) || sbvsc.wrapContentHeight) + if ((sbvsc.heightSizeInner.dimeVal != nil && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) || sbvsc.wrapContentHeight) { if (_myCGFloatLess(pMaxWrapSize->height, sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.centerYPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom)) pMaxWrapSize->height = sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.centerYPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom; diff --git a/MyLayoutTests/MyFrameLayoutTestCase.m b/MyLayoutTests/MyFrameLayoutTestCase.m index 7fca77a..d010351 100644 --- a/MyLayoutTests/MyFrameLayoutTestCase.m +++ b/MyLayoutTests/MyFrameLayoutTestCase.m @@ -240,6 +240,50 @@ -(void)testWrapContent2 } +-(void)testWrapContent3 +{ + //测试一个布局视图的尺寸是包裹的,同时里面的子视图设置了宽高。 + MyFrameLayout *rootLayout = [MyFrameLayout new]; + rootLayout.wrapContentSize = YES; + rootLayout.padding = UIEdgeInsetsMake(10, 20, 30, 40); + + //1.同时设置了上下和左右。没有设置高度。 + UIView *v1 = [UIView new]; + v1.myLeft = 10; + v1.myRight = 20; + v1.myTop = 30; + v1.myBottom = 40; + [rootLayout addSubview:v1]; + + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,90,110)), @"rootLayout rect is:%@", NSStringFromCGRect(rootLayout.frame)); + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(30,40,0,0)), @"v1 rect is:%@", NSStringFromCGRect(v1.frame)); + + + + UIView *v2 = [UIView new]; + v2.myLeft = 40; + v2.myRight = 30; + v2.myTop = 20; + v2.myBottom = 10; + v2.myWidth = 100; + v2.myHeight = 200; + [rootLayout addSubview:v2]; + + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,230,270)), @"rootLayout rect is:%@", NSStringFromCGRect(rootLayout.frame)); + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(30,40,140,160)), @"v1 rect is:%@", NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(60,30,100,200)), @"v2 rect is:%@", NSStringFromCGRect(v2.frame)); + + + + + //测试一个布局视图的尺寸是非包裹的,同时里面的子视图设置了宽高。 + +} + -(void)testPerformanceExample { [self measureBlock:^{ From a9a1ddb6ed114fd38b83364d93a811f57deb6051 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Wed, 18 Sep 2019 19:53:04 +0800 Subject: [PATCH 036/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayoutDemo/LLTest2ViewController.m | 270 ++++++++++++++--------- MyLayoutDemo/LLTest4ViewController.m | 67 +++--- MyLayoutTests/MyRelativeLayoutTestCase.m | 24 ++ 3 files changed, 218 insertions(+), 143 deletions(-) diff --git a/MyLayoutDemo/LLTest2ViewController.m b/MyLayoutDemo/LLTest2ViewController.m index 8e0c51e..49ac203 100644 --- a/MyLayoutDemo/LLTest2ViewController.m +++ b/MyLayoutDemo/LLTest2ViewController.m @@ -21,33 +21,91 @@ @interface LLTest2ViewController () @implementation LLTest2ViewController +-(void)loadView +{ + /* + 本例子用来实现将一个布局视图嵌入到一个UIScrollView里面的功能。 + 我们可以把一个布局视图作为一个子视图加入到UIScrollView中,布局库内部会根据布局视图的尺寸自动调整UIScrollView的contentSize。如果您不想调整contentSize则请将布局视图的adjustScrollViewContentSizeMode属性设置为MyAdjustScrollViewContentSizeModeNo。 + */ + + UIScrollView *scrollView = [UIScrollView new]; + scrollView.backgroundColor = [UIColor whiteColor]; + self.view = scrollView; + + /* + 这里的contentLayout是非布局视图UIScrollView的子视图。因为同时设置了myHorzMargin为0表示宽度和UIScrollView是保持一致;而高度则因为垂直线性布局的wrapContentHeight属性设置来确定,表示垂直线性布局的高度等于里面的所有子视图高度;而其中的x,y轴的位置则因为没有设置默认是0。 + */ + MyLinearLayout *contentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + contentLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); //设置布局内的子视图离自己的边距. + contentLayout.myHorzMargin = 0; //同时指定左右边距为0表示宽度和父视图一样宽 + contentLayout.heightSize.lBound(scrollView.heightSize, 10, 1); //高度虽然是wrapContentHeight的。但是最小的高度不能低于父视图的高度加10. + [scrollView addSubview:contentLayout]; + self.contentLayout = contentLayout; + + + /* + 布局视图里面的padding属性用来设置布局视图的内边距。内边距是指布局视图里面的子视图离自己距离。外边距则是视图与父视图之间的距离。 + 内边距是在自己的尺寸内离子视图的距离,而外边距则不是自己尺寸内离其他视图的距离。下面是内边距和外边距的效果图: + + ^ + | topMargin + | width + +------------------------------+ + | |------------> + | l r | rightMargin + | e topPadding i | + | f g | + | t +---------------+ h | + <----------| P | | t | + leftMargin| a | | P | + | d | subviews | a | height + | d | content | d | + | i | | d | + | n | | i | + | g +---------------+ n | + | g | + | bottomPadding | + +------------------------------+ + |bottomMargin + | + V + + + 如果一个布局视图中的每个子视图都离自己有一定的距离就可以通过设置布局视图的内边距来实现,而不需要为每个子视图都设置外边距。 + + */ + + + //垂直线性布局直接添加子视图 + [self createSection1:contentLayout]; + + //垂直线性布局套水平线性布局 + [self createSection2:contentLayout]; + + //垂直线性布局套垂直线性布局 + [self createSection3:contentLayout]; + + //垂直线性布局套水平线性布局 + [self createSection4:contentLayout]; + + //垂直线性布局套水平线性布局,水平线性布局利用相对边距实现左右布局 + [self createSection5:contentLayout]; + + //水平线性布局中的基线对齐 + [self createSection6:contentLayout]; + + //对子视图的高度的缩放调整 + [self createSection7:contentLayout]; + + //子视图的显示和隐藏 + [self createSection8:contentLayout]; + +} - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. - - //创建一个视图。 - MyRelativeLayout *rootLayout = [MyRelativeLayout new]; - rootLayout.myMargin = 0; - [self.view addSubview:rootLayout]; - - UIView *v1 = [UIView new]; - v1.myCenter = CGPointMake(0, 0); - v1.backgroundColor = [UIColor redColor]; - v1.widthSize.equalTo(@[rootLayout.widthSize, rootLayout.heightSize].myMinSize).multiply(0.5); - v1.heightSize.equalTo(v1.widthSize); - [rootLayout addSubview:v1]; - - UILabel *label = [UILabel new]; - label.myCenterX = 0; - label.myBottom = MyLayoutPos.safeAreaMargin; - label.text = @"您好!!!"; - label.backgroundColor = [UIColor redColor]; - label.widthSize.equalTo(@[@(MyLayoutSize.wrap), v1.widthSize.detach(0, 0.5)].myMaxSize); - label.wrapContentHeight = YES; - [rootLayout addSubview:label]; - } - (void)didReceiveMemoryWarning { @@ -99,7 +157,7 @@ -(void)createSection2:(MyLinearLayout*)contentLayout UIImageView *headImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"head1"]]; headImageView.myCenterY = 0; [userInfoLayout addSubview:headImageView]; - + //nameLayout是垂直线性布局因此默认的wrapContentHeight确定了视图的高度;weight=1设置宽度比重值,表示占用父布局infoLayout的剩余宽度;y轴上默认和父布局上边对齐;x轴则根据其在父布局下的顺序自动算出。这个部分也是一个水平线性布局套垂直线性布局的场景。 MyLinearLayout *nameLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; nameLayout.weight = 1.0; @@ -112,7 +170,7 @@ -(void)createSection2:(MyLinearLayout*)contentLayout userNameLabel.font = [CFTool font:15]; [userNameLabel sizeToFit]; [nameLayout addSubview:userNameLabel]; - + //nickNameLabel的sizeToFit确定视图的尺寸;x轴位置和父布局左对齐;y轴位置由添加到父布局中的顺序决定。 UILabel *nickNameLabel = [UILabel new]; nickNameLabel.text = NSLocalizedString(@"Nickname:醉里挑灯看键", @""); @@ -125,41 +183,41 @@ -(void)createSection2:(MyLinearLayout*)contentLayout //使用线性布局实现这个功能的一个缺点就是必须使用线性布局嵌套线性布局来完成,这样嵌套层次就可能会比较多,因此您可以尝试改用流式布局局来实现这个功能,从而减少嵌套的问题 /* - MyFlowLayout *userInfoLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:2]; - userInfoLayout.layer.borderColor = [UIColor lightGrayColor].CGColor; - userInfoLayout.layer.borderWidth = 0.5; - userInfoLayout.layer.cornerRadius = 4; - userInfoLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); - userInfoLayout.myTop = 20; - userInfoLayout.myLeading = userInfoLayout.myTrailing = 0; - userInfoLayout.subviewHSpace = 10; //子视图的水平间距为10 - userInfoLayout.wrapContentHeight = YES; - userInfoLayout.gravity = MyGravity_Vert_Center; //里面的子视图整体垂直居中。 - [contentLayout addSubview:userInfoLayout]; - - //第一列: 一个头像视图,一个占位视图。 - UIImageView *headImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"head1"]]; - [userInfoLayout addSubview:headImageView]; - - //因为数量约束水平流式布局每列必须要2个所以这里建立一个占位视图填满第一列。 - UIView *placeHolderView = [UIView new]; - [userInfoLayout addSubview:placeHolderView]; - - - //第二列: 姓名视图,昵称视图。 - UILabel *userNameLabel = [UILabel new]; - userNameLabel.text = NSLocalizedString(@"Name:欧阳大哥", @""); - userNameLabel.font = [CFTool font:15]; - [userNameLabel sizeToFit]; - [userInfoLayout addSubview:userNameLabel]; - - UILabel *nickNameLabel = [UILabel new]; - nickNameLabel.text = NSLocalizedString(@"Nickname:醉里挑灯看键", @""); - nickNameLabel.textColor = [CFTool color:4]; - nickNameLabel.font = [CFTool font:14]; - [nickNameLabel sizeToFit]; - [userInfoLayout addSubview:nickNameLabel]; - */ + MyFlowLayout *userInfoLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:2]; + userInfoLayout.layer.borderColor = [UIColor lightGrayColor].CGColor; + userInfoLayout.layer.borderWidth = 0.5; + userInfoLayout.layer.cornerRadius = 4; + userInfoLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); + userInfoLayout.myTop = 20; + userInfoLayout.myLeading = userInfoLayout.myTrailing = 0; + userInfoLayout.subviewHSpace = 10; //子视图的水平间距为10 + userInfoLayout.wrapContentHeight = YES; + userInfoLayout.gravity = MyGravity_Vert_Center; //里面的子视图整体垂直居中。 + [contentLayout addSubview:userInfoLayout]; + + //第一列: 一个头像视图,一个占位视图。 + UIImageView *headImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"head1"]]; + [userInfoLayout addSubview:headImageView]; + + //因为数量约束水平流式布局每列必须要2个所以这里建立一个占位视图填满第一列。 + UIView *placeHolderView = [UIView new]; + [userInfoLayout addSubview:placeHolderView]; + + + //第二列: 姓名视图,昵称视图。 + UILabel *userNameLabel = [UILabel new]; + userNameLabel.text = NSLocalizedString(@"Name:欧阳大哥", @""); + userNameLabel.font = [CFTool font:15]; + [userNameLabel sizeToFit]; + [userInfoLayout addSubview:userNameLabel]; + + UILabel *nickNameLabel = [UILabel new]; + nickNameLabel.text = NSLocalizedString(@"Nickname:醉里挑灯看键", @""); + nickNameLabel.textColor = [CFTool color:4]; + nickNameLabel.font = [CFTool font:14]; + [nickNameLabel sizeToFit]; + [userInfoLayout addSubview:nickNameLabel]; + */ } @@ -210,43 +268,43 @@ -(void)createSection3:(MyLinearLayout*)contentLayout //为实现这个功能,线性布局需要2层嵌套来完成,这无疑增加了代码量,因此您可以改为用一个垂直浮动布局来实现相同的能力。 - /* MyFloatLayout *ageLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; - ageLayout.layer.borderColor = [UIColor lightGrayColor].CGColor; - ageLayout.layer.borderWidth = 0.5; - ageLayout.layer.cornerRadius = 4; - ageLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); - ageLayout.myTop = 20; - ageLayout.myLeading = ageLayout.myTrailing = 0; // 宽度和父布局相等 - ageLayout.wrapContentHeight = YES; //高度由子视图包裹。 - ageLayout.subviewVSpace = 5; //所有子视图垂直间距为5 - ageLayout.subviewHSpace = 10; //所有子视图水平间距为10 - [contentLayout addSubview:ageLayout]; - - UILabel *ageTitleLabel = [UILabel new]; - ageTitleLabel.text = NSLocalizedString(@"Age:", @""); - ageTitleLabel.font = [CFTool font:15]; - [ageTitleLabel sizeToFit]; - ageTitleLabel.widthSize.equalTo(ageLayout.widthSize); - [ageLayout addSubview:ageTitleLabel]; - - - for (int i = 0; i < 3; i++) - { - UILabel *ageLabel = [UILabel new]; - ageLabel.text = [NSString stringWithFormat:@"%d", (i+2)*10]; - ageLabel.textAlignment = NSTextAlignmentCenter; - ageLabel.layer.cornerRadius = 15; - ageLabel.layer.borderColor = [CFTool color:3].CGColor; - ageLabel.layer.borderWidth = 0.5; - ageLabel.font = [CFTool font:13]; - ageLabel.heightSize.equalTo(@30); - //宽度这样设置的原因是:3个子视图要平分布局视图的宽度,这里每个子视图的间距是10。 - //因此每个子视图的宽度 = (布局视图宽度 - 2 * 子视图间距)/3 = 布局视图宽度 * 1/3 - 2*子视图间距/3 - //MyLayoutSize中的equalTo方法设置布局宽度,multiply方法用来设置1/3,add方法用来设置2*子视图间距/3. 因此可以进行如下设置: - ageLabel.widthSize.equalTo(ageLayout.widthSize).multiply(1.0/3).add(-1 * 2 * ageLayout.subviewHSpace / 3); - [ageLayout addSubview:ageLabel]; - } - */ + /* MyFloatLayout *ageLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; + ageLayout.layer.borderColor = [UIColor lightGrayColor].CGColor; + ageLayout.layer.borderWidth = 0.5; + ageLayout.layer.cornerRadius = 4; + ageLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); + ageLayout.myTop = 20; + ageLayout.myLeading = ageLayout.myTrailing = 0; // 宽度和父布局相等 + ageLayout.wrapContentHeight = YES; //高度由子视图包裹。 + ageLayout.subviewVSpace = 5; //所有子视图垂直间距为5 + ageLayout.subviewHSpace = 10; //所有子视图水平间距为10 + [contentLayout addSubview:ageLayout]; + + UILabel *ageTitleLabel = [UILabel new]; + ageTitleLabel.text = NSLocalizedString(@"Age:", @""); + ageTitleLabel.font = [CFTool font:15]; + [ageTitleLabel sizeToFit]; + ageTitleLabel.widthSize.equalTo(ageLayout.widthSize); + [ageLayout addSubview:ageTitleLabel]; + + + for (int i = 0; i < 3; i++) + { + UILabel *ageLabel = [UILabel new]; + ageLabel.text = [NSString stringWithFormat:@"%d", (i+2)*10]; + ageLabel.textAlignment = NSTextAlignmentCenter; + ageLabel.layer.cornerRadius = 15; + ageLabel.layer.borderColor = [CFTool color:3].CGColor; + ageLabel.layer.borderWidth = 0.5; + ageLabel.font = [CFTool font:13]; + ageLabel.heightSize.equalTo(@30); + //宽度这样设置的原因是:3个子视图要平分布局视图的宽度,这里每个子视图的间距是10。 + //因此每个子视图的宽度 = (布局视图宽度 - 2 * 子视图间距)/3 = 布局视图宽度 * 1/3 - 2*子视图间距/3 + //MyLayoutSize中的equalTo方法设置布局宽度,multiply方法用来设置1/3,add方法用来设置2*子视图间距/3. 因此可以进行如下设置: + ageLabel.widthSize.equalTo(ageLayout.widthSize).multiply(1.0/3).add(-1 * 2 * ageLayout.subviewHSpace / 3); + [ageLayout addSubview:ageLabel]; + } + */ } @@ -309,7 +367,7 @@ -(void)createSection5:(MyLinearLayout*)contentLayout UISwitch *sexSwitch = [UISwitch new]; sexSwitch.myLeading = 0.5; //线性布局中的子视图的边距如果设置为大于0小于1的值表示的是相对间距,0.5的左边距表示左边是父布局剩余空间的50% [sexLayout addSubview:sexSwitch]; - + } @@ -399,7 +457,7 @@ -(void)createSection8:(MyLinearLayout*)contentLayout hiddenView.myHeight = 800; [contentLayout addSubview:hiddenView]; self.hiddenView = hiddenView; - + } @@ -443,13 +501,13 @@ -(void)handleHideAndShowMore:(UIButton*)sender /* -#pragma mark - Navigation - -// In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. -} -*/ + #pragma mark - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. + } + */ @end diff --git a/MyLayoutDemo/LLTest4ViewController.m b/MyLayoutDemo/LLTest4ViewController.m index 5e9c5dc..9ab7916 100644 --- a/MyLayoutDemo/LLTest4ViewController.m +++ b/MyLayoutDemo/LLTest4ViewController.m @@ -18,53 +18,46 @@ @interface LLTest4ViewController () @implementation LLTest4ViewController - - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view. - - - - MyRelativeLayout *rootLayout = [MyRelativeLayout new]; - rootLayout.wrapContentWidth = YES; - rootLayout.myVertMargin = 0; - rootLayout.backgroundColor = [UIColor redColor]; - [self.view addSubview:rootLayout]; - rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); - rootLayout.topPadding = MyLayoutPos.safeAreaMargin + 100; - - - UILabel *l1 = [UILabel new]; - l1.text = @"您好"; - l1.backgroundColor = [UIColor blueColor]; - l1.wrapContentSize = YES; - [rootLayout addSubview:l1]; - - UILabel *l3 = [UILabel new]; - l3.text = @"ak"; - l3.wrapContentSize = YES; - l3.topPos.equalTo(l1.bottomPos).offset(10); - l3.leftPos.equalTo(l1.leftPos); - l3.backgroundColor = [UIColor greenColor]; - [rootLayout addSubview:l3]; +-(void)loadView +{ + /* + 这个例子详细说明wrapContentHeight和wrapContentWidth的包裹属性的设置、以及边界线性的设定、以及布局中可局部缩放背景图片的设定方法。 + */ - UILabel *l2 = [UILabel new]; - l2.text = @"2019-04-03"; - [l2 sizeToFit]; - [rootLayout addSubview:l2]; - l2.topPos.equalTo(l1.topPos); - l2.rightPos.equalTo(l3.rightPos); - l2.rightPos.min(-1 *(l2.frame.size.width + 30 + 50)); + self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + [super loadView]; + self.view.backgroundColor = [UIColor whiteColor]; + UIView *contentView = [UIView new]; + contentView.backgroundColor = [CFTool color:5]; + [self.view addSubview:contentView]; + contentView.wrapContentWidth = YES; + contentView.wrapContentHeight = YES; //如果一个非布局父视图里面有布局子视图,那么这个非布局父视图也是可以设置wrapContentHeight和wrapContentWidth的,他表示的意义是这个非布局父视图的尺寸由里面的布局子视图的尺寸来决定的。这个功能是在1.3.3版本支持的。 还有一个场景是非布局父视图是一个UIScrollView。他是左右滚动的,但是滚动视图的高度是由里面的布局子视图确定的,而宽度则是和窗口保持一致。这样只需要将滚动视图的宽度设置为和屏幕保持一致,高度设置为wrapContentHeight,并且把一个水平线性布局添加到滚动视图即可。 + self.rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + self.rootLayout.layer.borderWidth = 1; + self.rootLayout.layer.borderColor = [UIColor lightGrayColor].CGColor; + self.rootLayout.wrapContentHeight = YES; + self.rootLayout.wrapContentWidth = YES; //布局的高度和宽度由子视图决定 + self.rootLayout.myTop = 10; + self.rootLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); + self.rootLayout.zeroPadding = NO; //这个属性设置为NO时表示当布局视图的尺寸是wrap也就是由子视图决定时并且在没有任何子视图是不会参与布局视图高度的计算的。您可以在这个DEMO的测试中将所有子视图都删除掉,看看效果,然后注释掉这句代码看看效果。 + self.rootLayout.subviewVSpace = 5; + [contentView addSubview:self.rootLayout]; + [self.rootLayout addSubview:[self addWrapContentLayout]]; } + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index 14050c4..1f6258b 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -1003,6 +1003,30 @@ -(void)testMaxHeightAndWidth } +-(void)test123 +{ + //创建一个视图。 + MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + rootLayout.myMargin = 0; + // [self.view addSubview:rootLayout]; + + UIView *v1 = [UIView new]; + v1.myCenter = CGPointMake(0, 0); + v1.backgroundColor = [UIColor redColor]; + v1.widthSize.equalTo(@[rootLayout.widthSize, rootLayout.heightSize].myMinSize).multiply(0.5); + v1.heightSize.equalTo(v1.widthSize); + [rootLayout addSubview:v1]; + + UILabel *label = [UILabel new]; + label.myCenterX = 0; + label.myBottom = MyLayoutPos.safeAreaMargin; + label.text = @"您好!!!"; + label.backgroundColor = [UIColor redColor]; + label.widthSize.equalTo(@[@(MyLayoutSize.wrap), v1.widthSize.detach(0, 0.5)].myMaxSize); + label.wrapContentHeight = YES; + [rootLayout addSubview:label]; +} + -(void)testMaxAndMin { From df060295cd83cc1ec4bd464d54e61f6b2c74b764 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Thu, 19 Sep 2019 00:08:49 +0800 Subject: [PATCH 037/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96,?= =?UTF-8?q?=20BUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcschemes/MyLayoutDemo.xcscheme | 112 +++++++ MyLayout/Lib/MyBaseLayout.h | 2 +- MyLayout/Lib/MyBaseLayout.m | 8 +- MyLayout/Lib/MyFlexLayout.m | 4 +- MyLayout/Lib/MyFloatLayout.m | 12 +- MyLayout/Lib/MyFlowLayout.m | 20 +- MyLayout/Lib/MyFrameLayout.m | 4 +- MyLayout/Lib/MyGridLayout.m | 4 +- MyLayout/Lib/MyLayoutInner.h | 2 +- MyLayout/Lib/MyLinearLayout.m | 26 +- MyLayout/Lib/MyPathLayout.m | 4 +- MyLayout/Lib/MyRelativeLayout.m | 4 +- MyLayoutTests/MyFloatLayoutTestCase.m | 40 ++- MyLayoutTests/MyFrameLayoutTestCase.m | 46 ++- MyLayoutTests/MyLinearLayoutTestCase.m | 294 ++++++++++++++++-- MyLayoutTests/MyNoLayoutSuperviewTestCase.m | 11 +- 17 files changed, 518 insertions(+), 83 deletions(-) create mode 100644 MyLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 MyLayout.xcodeproj/xcshareddata/xcschemes/MyLayoutDemo.xcscheme diff --git a/MyLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/MyLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/MyLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/MyLayout.xcodeproj/xcshareddata/xcschemes/MyLayoutDemo.xcscheme b/MyLayout.xcodeproj/xcshareddata/xcschemes/MyLayoutDemo.xcscheme new file mode 100644 index 0000000..2ac539f --- /dev/null +++ b/MyLayout.xcodeproj/xcshareddata/xcschemes/MyLayoutDemo.xcscheme @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index 310e506..b296312 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -619,7 +619,7 @@ /** 布局视图基类,基类不支持实例化对象。在编程时我们经常会用到一些视图,这种视图只是负责将里面的子视图按照某种规则进行排列和布局,而别无其他的作用。因此我们称这种视图为容器视图或者称为布局视图。 布局视图通过重载layoutSubviews方法来完成子视图的布局和排列的工作。对于每个加入到布局视图中的子视图,都会在加入时通过KVO机制监控子视图的center和bounds以及frame值的变化,每当子视图的这些属性一变化时就又会重新引发布局视图的布局动作。同时对每个视图的布局扩展属性的设置以及对布局视图的布局属性的设置都会引发布局视图的布局动作。布局视图在添加到非布局父视图时也会通过KVO机制来监控非布局父视图的frame值和bounds值,这样每当非布局父视图的尺寸变更时也会引发布局视图的布局动作。前面说的引起变动的方法就是会在KVO处理逻辑以及布局扩展属性和布局属性设置完毕后通过调用setNeedLayout来实现的,当布局视图收到setNeedLayout的请求后,会在下一个runloop中对布局视图进行重新布局而这就是通过调用layoutSubviews方法来实现的。布局视图基类只提供了更新所有子视图的位置和尺寸以及一些基础的设置,而至于如何排列和布局这些子视图则要根据应用的场景和需求来确定,因此布局基类视图提供了一个: - -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs + -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs 的方法,要求派生类去重载这个方法,这样不同的派生类就可以实现不同的应用场景,这就是布局视图的核心实现机制。 MyLayout布局库根据实际中常见的场景实现了8种不同的布局视图派生类他们分别是:线性布局、表格布局、相对布局、框架布局、流式布局、浮动布局、路径布局、栅格布局。 diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 5d24216..b1dbc41 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -1230,14 +1230,14 @@ -(CGSize)myEstimateLayoutRect:(CGSize)size inSizeClass:(MySizeClass)sizeClass sb } BOOL hasSubLayout = NO; - CGSize selfSize= [self calcLayoutRect:size isEstimate:NO pHasSubLayout:&hasSubLayout sizeClass:sizeClass sbs:sbs]; + CGSize selfSize= [self calcLayoutSize:size isEstimate:NO pHasSubLayout:&hasSubLayout sizeClass:sizeClass sbs:sbs]; if (hasSubLayout) { selfMyFrame.width = selfSize.width; selfMyFrame.height = selfSize.height; - selfSize = [self calcLayoutRect:CGSizeZero isEstimate:YES pHasSubLayout:&hasSubLayout sizeClass:sizeClass sbs:sbs]; + selfSize = [self calcLayoutSize:CGSizeZero isEstimate:YES pHasSubLayout:&hasSubLayout sizeClass:sizeClass sbs:sbs]; } selfMyFrame.width = selfSize.width; @@ -1498,7 +1498,7 @@ -(void)setWrapContentSize:(BOOL)wrapContentSize --(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs +-(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { CGSize selfSize; if (isEstimate) @@ -2030,7 +2030,7 @@ -(void)layoutSubviews } else { - newSelfSize = [self calcLayoutRect:[self myCalcSizeInNoLayoutSuperview:self.superview currentSize:oldSelfSize] isEstimate:NO pHasSubLayout:nil sizeClass:sizeClass sbs:nil]; + newSelfSize = [self calcLayoutSize:[self myCalcSizeInNoLayoutSuperview:self.superview currentSize:oldSelfSize] isEstimate:NO pHasSubLayout:nil sizeClass:sizeClass sbs:nil]; } newSelfSize = _myCGSizeRound(newSelfSize); _useCacheRects = NO; diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index c1395c6..9a78868 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -445,7 +445,7 @@ -(instancetype)init } --(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs +-(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { MyFlexLayout *lsc = self.myCurrentSizeClass; @@ -701,7 +701,7 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( } } - return [super calcLayoutRect:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; + return [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; } diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 95585f5..36eed2c 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -121,9 +121,9 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace: #pragma mark -- Override Methods --(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs +-(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { - CGSize selfSize = [super calcLayoutRect:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; + CGSize selfSize = [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; if (sbs == nil) sbs = [self myGetLayoutSubviews]; @@ -152,9 +152,9 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( }]; if (orientation == MyOrientation_Vert) - selfSize = [self myLayoutSubviewsForVert:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; + selfSize = [self myCalcLayoutSizeForVertOrientation:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; else - selfSize = [self myLayoutSubviewsForHorz:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; + selfSize = [self myCalcLayoutSizeForHorzOrientation:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; @@ -442,7 +442,7 @@ -(void)myCalcFloatLayoutSubviewsSize:(NSArray*)sbs } --(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFloatLayout*)lsc +-(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFloatLayout*)lsc { //对于垂直浮动布局来说,默认是左浮动,当设置为RTL时则默认是右浮动,因此我们只需要改变一下sbv.reverseFloat的定义就好了。 @@ -933,7 +933,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:( return selfSize; } --(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFloatLayout*)lsc +-(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFloatLayout*)lsc { //对于水平浮动布局来说,最终是从左到右排列,而对于RTL则是从右到左排列,因此这里先抽象定义头尾的概念,然后最后再计算时统一将抽象位置转化为CGRect的左边值。 diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 451cc34..ae34682 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -138,9 +138,9 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace: #pragma mark -- Override Methods --(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs +-(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { - CGSize selfSize = [super calcLayoutRect:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; + CGSize selfSize = [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; if (sbs == nil) sbs = [self myGetLayoutSubviews]; @@ -179,16 +179,16 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (orientation == MyOrientation_Vert) { if (lsc.arrangedCount == 0) - selfSize = [self myLayoutSubviewsForVertContent:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; + selfSize = [self myCalcLayoutSizeForVertOrientationContent:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; else - selfSize = [self myLayoutSubviewsForVert:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; + selfSize = [self myCalcLayoutSizeForVertOrientation:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; } else { if (lsc.arrangedCount == 0) - selfSize = [self myLayoutSubviewsForHorzContent:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; + selfSize = [self myCalcLayoutSizeForHorzOrientationContent:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; else - selfSize = [self myLayoutSubviewsForHorz:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; + selfSize = [self myCalcLayoutSizeForHorzOrientation:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; } //调整布局视图自己的尺寸。 @@ -887,7 +887,7 @@ -(CGFloat)myCalcMaxMinSubviewSize:(CGFloat)selfSize lsc:(MyFlowLayoutViewSizeCla } --(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +-(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc { CGFloat paddingTop = lsc.myLayoutTopPadding; @@ -1169,7 +1169,7 @@ -(CGSize)myLayoutSubviewsForVertContent:(CGSize)selfSize sbs:(NSMutableArray*)sb } --(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +-(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc { CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; @@ -1640,7 +1640,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEst return selfSize; } --(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +-(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc { CGFloat paddingTop = lsc.myLayoutTopPadding; @@ -1905,7 +1905,7 @@ -(CGSize)myLayoutSubviewsForHorzContent:(CGSize)selfSize sbs:(NSMutableArray*)sb --(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +-(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc { CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; diff --git a/MyLayout/Lib/MyFrameLayout.m b/MyLayout/Lib/MyFrameLayout.m index a55d5e5..b81076f 100644 --- a/MyLayout/Lib/MyFrameLayout.m +++ b/MyLayout/Lib/MyFrameLayout.m @@ -25,9 +25,9 @@ - (void)drawRect:(CGRect)rect { #pragma mark -- Override Methods --(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray *)sbs +-(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray *)sbs { - CGSize selfSize = [super calcLayoutRect:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; + CGSize selfSize = [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; if (sbs == nil) sbs = [self myGetLayoutSubviews]; diff --git a/MyLayout/Lib/MyGridLayout.m b/MyLayout/Lib/MyGridLayout.m index a7a13ce..6512ef3 100644 --- a/MyLayout/Lib/MyGridLayout.m +++ b/MyLayout/Lib/MyGridLayout.m @@ -831,9 +831,9 @@ -(void)willRemoveSubview:(UIView *)subview } --(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs +-(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { - CGSize selfSize = [super calcLayoutRect:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; + CGSize selfSize = [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; if (sbs == nil) sbs = [self myGetLayoutSubviews]; diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index 4586a4f..67c04d0 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -46,7 +46,7 @@ //派生类重载这个函数进行布局 --(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs; +-(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs; -(id)createSizeClassInstance; diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 3cc1742..1904dab 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -179,9 +179,9 @@ - (void)willRemoveSubview:(UIView *)subview --(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray *)sbs +-(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray *)sbs { - CGSize selfSize = [super calcLayoutRect:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; + CGSize selfSize = [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; if (sbs == nil) sbs = [self myGetLayoutSubviews]; @@ -191,18 +191,18 @@ -(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = lsc.gravity & MyGravity_Vert_Mask; - MyOrientation oreintation = lsc.orientation; + MyOrientation orientation = lsc.orientation; [self myCalcSubviewsWrapContentSize:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs withCustomSetting:^(UIView *sbv, UIView *sbvsc) { - [self myAdjustSubviewWrapContent:sbv sbvsc:sbvsc orientation:oreintation gravity:(oreintation == MyOrientation_Vert)? horzGravity : vertGravity]; + [self myAdjustSubviewWrapContent:sbv sbvsc:sbvsc orientation:orientation gravity:(orientation == MyOrientation_Vert)? horzGravity : vertGravity]; }]; - if (oreintation == MyOrientation_Vert) - selfSize = [self myLayoutSubviewsForVert:selfSize sbs:sbs lsc:lsc]; + if (orientation == MyOrientation_Vert) + selfSize = [self myCalcLayoutSizeForVertOrientation:selfSize sbs:sbs lsc:lsc]; else - selfSize = [self myLayoutSubviewsForHorz:selfSize sbs:sbs lsc:lsc]; + selfSize = [self myCalcLayoutSizeForHorzOrientation:selfSize sbs:sbs lsc:lsc]; //绘制智能线。 if (!isEstimate) @@ -354,7 +354,7 @@ -(void)mySetLayoutIntelligentBorderline:(NSArray*)sbs lsc:(MyLinearLayout*)lsc } } --(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinearLayout*)lsc +-(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinearLayout*)lsc { CGFloat subviewSpace = lsc.subviewVSpace; CGFloat paddingTop = lsc.myLayoutTopPadding; @@ -419,7 +419,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea if ((tempSelfWidth > maxSelfWidth) && - ((sbvsc.widthSizeInner.dimeVal != nil && sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) || sbvsc.wrapContentWidth)) + ((sbvsc.widthSizeInner.dimeVal != nil && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) || sbvsc.wrapContentWidth)) { maxSelfWidth = tempSelfWidth; } @@ -779,7 +779,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea lsc:lsc]; if ((tempSelfWidth > maxSelfWidth) && - ((sbvsc.widthSizeInner.dimeVal != nil && sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) || sbvsc.wrapContentWidth)) + ((sbvsc.widthSizeInner.dimeVal != nil && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) || sbvsc.wrapContentWidth)) { maxSelfWidth = tempSelfWidth; } @@ -849,7 +849,7 @@ -(CGSize)myLayoutSubviewsForVert:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea return selfSize; } --(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinearLayout*)lsc +-(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinearLayout*)lsc { CGFloat subviewSpace = lsc.subviewHSpace; CGFloat paddingTop = lsc.myLayoutTopPadding; @@ -914,7 +914,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea lsc:lsc]; if ((tempSelfHeight > maxSelfHeight) && - ((sbvsc.heightSizeInner.dimeVal != nil && sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) || sbvsc.wrapContentHeight)) + ((sbvsc.heightSizeInner.dimeVal != nil && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) || sbvsc.wrapContentHeight)) { maxSelfHeight = tempSelfHeight; } @@ -1328,7 +1328,7 @@ -(CGSize)myLayoutSubviewsForHorz:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinea lsc:lsc]; if ((tempSelfHeight > maxSelfHeight) && - ((sbvsc.heightSizeInner.dimeVal != nil && sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) || sbvsc.wrapContentHeight)) + ((sbvsc.heightSizeInner.dimeVal != nil && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) || sbvsc.wrapContentHeight)) { maxSelfHeight = tempSelfHeight; } diff --git a/MyLayout/Lib/MyPathLayout.m b/MyLayout/Lib/MyPathLayout.m index cd6f3fd..1a43f4b 100644 --- a/MyLayout/Lib/MyPathLayout.m +++ b/MyLayout/Lib/MyPathLayout.m @@ -548,9 +548,9 @@ - (void)drawRect:(CGRect)rect { --(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs +-(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { - CGSize selfSize = [super calcLayoutRect:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; + CGSize selfSize = [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; if (sbs == nil) sbs = [self myGetLayoutSubviews]; diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 6eeff0a..3ba86aa 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -15,9 +15,9 @@ @implementation MyRelativeLayout #pragma mark -- Override Methods --(CGSize)calcLayoutRect:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs +-(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { - CGSize selfSize = [super calcLayoutRect:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; + CGSize selfSize = [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; MyRelativeLayout *lsc = self.myCurrentSizeClass; diff --git a/MyLayoutTests/MyFloatLayoutTestCase.m b/MyLayoutTests/MyFloatLayoutTestCase.m index a0ee233..4e2d50c 100644 --- a/MyLayoutTests/MyFloatLayoutTestCase.m +++ b/MyLayoutTests/MyFloatLayoutTestCase.m @@ -7,7 +7,13 @@ // #import "MyLayoutTestCaseBase.h" +#import "FOLTest1ViewController.h" #import "FOLTest2ViewController.h" +#import "FOLTest3ViewController.h" +#import "FOLTest4ViewController.h" +#import "FOLTest5ViewController.h" +#import "FOLTest6ViewController.h" +#import "FOLTest7ViewController.h" @interface MyFloatLayoutTestCase : MyLayoutTestCaseBase @@ -28,18 +34,30 @@ - (void)tearDown { - (void)testExample { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. - FOLTest2ViewController *vc = [FOLTest2ViewController new]; - - [self startClock]; - UIView *v1 = vc.view; - [self endClock:@"load view:"]; //>60ms - - [self startClock]; - + FOLTest1ViewController *vc1 = [FOLTest1ViewController new]; + FOLTest2ViewController *vc2 = [FOLTest2ViewController new]; + FOLTest3ViewController *vc3 = [FOLTest3ViewController new]; + FOLTest4ViewController *vc4 = [FOLTest4ViewController new]; + FOLTest5ViewController *vc5 = [FOLTest5ViewController new]; + FOLTest6ViewController *vc6 = [FOLTest6ViewController new]; + FOLTest7ViewController *vc7 = [FOLTest7ViewController new]; + + UIView *v1 = vc1.view; + UIView *v2= vc2.view; + UIView *v3 = vc3.view; + UIView *v4 = vc4.view; + UIView *v5 = vc5.view; + UIView *v6 = vc6.view; + UIView *v7 = vc7.view; + + [v1 layoutIfNeeded]; - - [self endClock:@"layout:"]; - + [v2 layoutIfNeeded]; + [v3 layoutIfNeeded]; + [v4 layoutIfNeeded]; + [v5 layoutIfNeeded]; + [v6 layoutIfNeeded]; + [v7 layoutIfNeeded]; } diff --git a/MyLayoutTests/MyFrameLayoutTestCase.m b/MyLayoutTests/MyFrameLayoutTestCase.m index d010351..9c05c00 100644 --- a/MyLayoutTests/MyFrameLayoutTestCase.m +++ b/MyLayoutTests/MyFrameLayoutTestCase.m @@ -7,6 +7,8 @@ // #import "MyLayoutTestCaseBase.h" +#import "FLTest1ViewController.h" +#import "FLTest2ViewController.h" @interface MyFrameLayoutTestCase : MyLayoutTestCaseBase @@ -24,6 +26,22 @@ - (void)tearDown { [super tearDown]; } +-(void)testExample +{ + FLTest1ViewController *vc1 = [FLTest1ViewController new]; + FLTest2ViewController *vc2 = [FLTest2ViewController new]; + + + [self startClock]; + UIView *v1 = vc1.view; + UIView *v2= vc2.view; + + [v1 layoutIfNeeded]; + [v2 layoutIfNeeded]; + + +} + -(void)testblurred { //测试位置偏移不正确或者尺寸不正确将会产生模糊显示的效果。 @@ -277,10 +295,36 @@ -(void)testWrapContent3 XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(30,40,140,160)), @"v1 rect is:%@", NSStringFromCGRect(v1.frame)); XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(60,30,100,200)), @"v2 rect is:%@", NSStringFromCGRect(v2.frame)); + [v1 removeFromSuperview]; + [v2 removeFromSuperview]; + + UILabel *label = [UILabel new]; + label.wrapContentSize = YES; + label.text = @"您好!"; + label.myMargin = 20; + CGSize lablesz = [label sizeThatFits:CGSizeZero]; + [rootLayout addSubview:label]; + + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,60+40+lablesz.width,40+40+lablesz.height)), @"rootLayout rect is:%@", NSStringFromCGRect(rootLayout.frame)); + XCTAssertTrue(CGRectEqualToRect(label.frame, CGRectMake(20+20,10+20,lablesz.width,lablesz.height)), @"label rect is:%@", NSStringFromCGRect(label.frame)); + + + UIView *v3 = [UIView new]; + v3.myRight = 30; + v3.myBottom = 30; + v3.mySize = CGSizeMake(100, 100); + [rootLayout addSubview:v3]; + + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,20+40+30+100,10+30+30+100)), @"rootLayout rect is:%@", NSStringFromCGRect(rootLayout.frame)); + XCTAssertTrue(CGRectEqualToRect(label.frame, CGRectMake(20+20,10+20,lablesz.width,lablesz.height)), @"label rect is:%@", NSStringFromCGRect(label.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(rootLayout.frame.size.width - 40 - 30 - 100 ,rootLayout.frame.size.height - 30 - 30 - 100, 100,100)), @"v3 rect is:%@", NSStringFromCGRect(v3.frame)); - //测试一个布局视图的尺寸是非包裹的,同时里面的子视图设置了宽高。 } diff --git a/MyLayoutTests/MyLinearLayoutTestCase.m b/MyLayoutTests/MyLinearLayoutTestCase.m index 24ee661..4437fec 100644 --- a/MyLayoutTests/MyLinearLayoutTestCase.m +++ b/MyLayoutTests/MyLinearLayoutTestCase.m @@ -7,7 +7,19 @@ // #import "MyLayoutTestCaseBase.h" +#import "LLTest1ViewController.h" +#import "LLTest2ViewController.h" +#import "LLTest3ViewController.h" +#import "LLTest4ViewController.h" +#import "LLTest5ViewController.h" +#import "LLTest6ViewController.h" +#import "LLTest7ViewController.h" + +#import "TLTest1ViewController.h" +#import "TLTest2ViewController.h" #import "TLTest3ViewController.h" +#import "TLTest4ViewController.h" + @interface MyLinearLayoutTestCase : MyLayoutTestCaseBase @@ -28,34 +40,60 @@ - (void)tearDown { - (void)testExample { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. -} + + LLTest1ViewController *vc1 = [LLTest1ViewController new]; + LLTest2ViewController *vc2 = [LLTest2ViewController new]; + LLTest3ViewController *vc3 = [LLTest3ViewController new]; + LLTest4ViewController *vc4 = [LLTest4ViewController new]; + LLTest5ViewController *vc5 = [LLTest5ViewController new]; + LLTest6ViewController *vc6 = [LLTest6ViewController new]; + LLTest7ViewController *vc7 = [LLTest7ViewController new]; + + + TLTest1ViewController *vc10 = [TLTest1ViewController new]; + TLTest2ViewController *vc11 = [TLTest2ViewController new]; + TLTest3ViewController *vc12 = [TLTest3ViewController new]; + TLTest4ViewController *vc13 = [TLTest4ViewController new]; + + + UIView *v1 = vc1.view; + UIView *v2= vc2.view; + UIView *v3 = vc3.view; + UIView *v4 = vc4.view; + UIView *v5 = vc5.view; + UIView *v6 = vc6.view; + UIView *v7 = vc7.view; + + UIView *v10 = vc10.view; + UIView *v11 = vc11.view; + UIView *v12 = vc12.view; + UIView *v13 = vc13.view; --(void)testWrapContentHeight -{ + + [v1 layoutIfNeeded]; + [v2 layoutIfNeeded]; + [v3 layoutIfNeeded]; + [v4 layoutIfNeeded]; + [v5 layoutIfNeeded]; + [v6 layoutIfNeeded]; + [v7 layoutIfNeeded]; + + [v10 layoutIfNeeded]; + [v11 layoutIfNeeded]; + [v12 layoutIfNeeded]; + [v13 layoutIfNeeded]; + } -- (void)testTable1 { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - - TLTest3ViewController *vc = [TLTest3ViewController new]; - - [self startClock]; - - UIView *view = vc.view; - - [self endClock:@"vc loadview"]; //>=20ms - - [self startClock]; - - [view layoutIfNeeded]; +-(void)testWrapContentHeight +{ - [self endClock:@"view layout"]; } + -(void)testSubviewSizeDependent {//测试子视图尺寸依赖 @@ -255,9 +293,9 @@ -(void)testWeight [rootLayout1 layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(rootLayout1.subviews[0].frame, CGRectMake(0,0,94,667)), @"the button0.frame = %@",NSStringFromCGRect(rootLayout1.subviews[0].frame)); - XCTAssertTrue(CGRectEqualToRect(rootLayout1.subviews[1].frame, CGRectMake(94,0,93.5,667)), @"the button0.frame = %@",NSStringFromCGRect(rootLayout1.subviews[1].frame)); - XCTAssertTrue(CGRectEqualToRect(rootLayout1.subviews[2].frame, CGRectMake(187.5,0,94,667)), @"the button0.frame = %@",NSStringFromCGRect(rootLayout1.subviews[2].frame)); - XCTAssertTrue(CGRectEqualToRect(rootLayout1.subviews[3].frame, CGRectMake(281.5,0,93.5,667)), @"the button0.frame = %@",NSStringFromCGRect(rootLayout1.subviews[3].frame)); + XCTAssertTrue(CGRectEqualToRect(rootLayout1.subviews[1].frame, CGRectMake(94,0,94,667)), @"the button0.frame = %@",NSStringFromCGRect(rootLayout1.subviews[1].frame)); + XCTAssertTrue(CGRectEqualToRect(rootLayout1.subviews[2].frame, CGRectMake(188,0,94,667)), @"the button0.frame = %@",NSStringFromCGRect(rootLayout1.subviews[2].frame)); + XCTAssertTrue(CGRectEqualToRect(rootLayout1.subviews[3].frame, CGRectMake(282,0,94,667)), @"the button0.frame = %@",NSStringFromCGRect(rootLayout1.subviews[3].frame)); @@ -328,7 +366,7 @@ -(void)testWrapGravityMinMaxShrink UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; [button setTitle:@"点我" forState:UIControlStateNormal]; - [button sizeToFit]; + button.wrapContentSize = YES; [testLayout addSubview:button]; @@ -342,7 +380,6 @@ -(void)testWrapGravityMinMaxShrink label2.text = @"文本2"; label2.wrapContentSize = YES; label2.backgroundColor = [UIColor cyanColor]; - [label2 sizeToFit]; [testLayout addSubview:label2]; [testLayout layoutIfNeeded]; @@ -354,7 +391,7 @@ -(void)testWrapGravityMinMaxShrink //字体高度扩高。文字超长。 button.titleLabel.font = [UIFont systemFontOfSize:30]; label1.text = @"文本111111111111"; - [button sizeToFit]; + [testLayout setNeedsLayout]; [testLayout layoutIfNeeded]; @@ -365,6 +402,8 @@ -(void)testWrapGravityMinMaxShrink // label1.text = @"文本111111111111111111111111111"; // label1.mySize = CGSizeMake(400, 20.5); +// +// [testLayout setNeedsLayout]; // [testLayout layoutIfNeeded]; // // XCTAssertTrue(CGRectEqualToRect(testLayout.frame, CGRectMake(0,0,330,48)), @"the testLayout.frame = %@",NSStringFromCGRect(testLayout.frame)); @@ -443,8 +482,213 @@ -(void)testBetweenAndAround [layout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(60,0,30,30)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); +} + +-(void)testFillAndStretch +{ + //子视图有几个设置了约束,有几个没有设置约束。分别展现Fill 和Stretch的差异。 + { + MyLinearLayout *rootLayout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 0, 400) orientation:MyOrientation_Vert]; + rootLayout.padding = UIEdgeInsetsMake(10, 10, 20, 20); + rootLayout.wrapContentWidth = YES; + rootLayout.wrapContentHeight = NO; + + //视图1宽度依赖父视图,高度设置。 + UILabel *v1 = [UILabel new]; + v1.text = @"你好"; //iPhone8模拟器 + v1.myHorzMargin = 10; + v1.wrapContentHeight = YES; + [rootLayout addSubview:v1]; + + //视图2宽度定值,右边对齐,高度不设置。 + UIView *v2 = [UIView new]; + v2.myRight = 20; + v2.myWidth = 50; + [rootLayout addSubview:v2]; + + //视图3宽度定值,居中对齐,高度设置。 + UIView *v3 = [UIView new]; + v3.widthSize.equalTo(v2.widthSize).add(20); + v3.myCenterX = 0; + v3.myHeight = 40; + [rootLayout addSubview:v3]; + + //视图4设置左右边距,并且宽度定值,高度不设置。 + UIView *v4 = [UIView new]; + v4.myHorzMargin = 30; + v4.myWidth = 100; + [rootLayout addSubview:v4]; + + //视图5设置宽度依赖父视图,高度设置。 + UIView *v5 = [UIView new]; + v5.widthSize.equalTo(rootLayout.widthSize).multiply(0.5); + v5.myHeight = 40; + [rootLayout addSubview:v5]; + + rootLayout.gravity = MyGravity_Vert_Fill; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,190,400)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(20,10,140,20.5)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(100,30.5,50,67.5)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(55,98,70,107.5)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(40,205.5,100,67.5)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(10,272.5,80,107.5)), @"the v5 .frame = %@",NSStringFromCGRect(v5.frame)); + } + + { + MyLinearLayout *rootLayout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 0, 400) orientation:MyOrientation_Vert]; + rootLayout.padding = UIEdgeInsetsMake(10, 10, 20, 20); + rootLayout.wrapContentWidth = YES; + rootLayout.wrapContentHeight = NO; + + //视图1宽度依赖父视图,高度设置。 + UILabel *v1 = [UILabel new]; + v1.text = @"你好"; //iPhone8模拟器 + v1.myHorzMargin = 10; + v1.wrapContentHeight = YES; + [rootLayout addSubview:v1]; + + //视图2宽度定值,右边对齐,高度不设置。 + UIView *v2 = [UIView new]; + v2.myRight = 20; + v2.myWidth = 50; + [rootLayout addSubview:v2]; + + //视图3宽度定值,居中对齐,高度设置。 + UIView *v3 = [UIView new]; + v3.widthSize.equalTo(v2.widthSize).add(20); + v3.myCenterX = 0; + v3.myHeight = 40; + [rootLayout addSubview:v3]; + + //视图4设置左右边距,并且宽度定值,高度不设置。 + UIView *v4 = [UIView new]; + v4.myHorzMargin = 30; + v4.myWidth = 100; + [rootLayout addSubview:v4]; + + //视图5设置宽度依赖父视图,高度设置。 + UIView *v5 = [UIView new]; + v5.widthSize.equalTo(rootLayout.widthSize).multiply(0.5); + v5.myHeight = 40; + [rootLayout addSubview:v5]; + + rootLayout.gravity = MyGravity_Vert_Stretch; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,190,400)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(20,10,140,20.5)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(100,30.5,50,135)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(55,165.5,70,40)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(40,205.5,100,135)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(10,340,80,40)), @"the v5 .frame = %@",NSStringFromCGRect(v5.frame)); + } + + { + MyLinearLayout *rootLayout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 400, 0) orientation:MyOrientation_Horz]; + rootLayout.padding = UIEdgeInsetsMake(10, 10, 20, 20); + rootLayout.wrapContentWidth = NO; + rootLayout.wrapContentHeight = YES; + + //视图1高度依赖父视图,宽度设置。 + UILabel *v1 = [UILabel new]; + v1.text = @"你好"; //iPhone8模拟器 + v1.myVertMargin = 10; + v1.wrapContentWidth = YES; + [rootLayout addSubview:v1]; + + //视图2高度定值,下边对齐,宽度不设置。 + UIView *v2 = [UIView new]; + v2.myBottom = 20; + v2.myHeight = 50; + [rootLayout addSubview:v2]; + + //视图3高度定值,居中对齐,宽度设置。 + UIView *v3 = [UIView new]; + v3.heightSize.equalTo(v2.heightSize).add(20); + v3.myCenterY = 0; + v3.myWidth = 40; + [rootLayout addSubview:v3]; + + //视图4设置上下边距,并且高度定值,宽度不设置。 + UIView *v4 = [UIView new]; + v4.myVertMargin = 30; + v4.myHeight = 100; + [rootLayout addSubview:v4]; + + //视图5设置高度依赖父视图,宽度设置。 + UIView *v5 = [UIView new]; + v5.heightSize.equalTo(rootLayout.heightSize).multiply(0.5); + v5.myWidth = 40; + [rootLayout addSubview:v5]; + + rootLayout.gravity = MyGravity_Horz_Fill; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,400,190)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(10,20,35,140)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(45,100,96,50)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(141,55,72,70)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(212.5,40,96,100)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(308.5,10,72,80)), @"the v5 .frame = %@",NSStringFromCGRect(v5.frame)); + } + { + MyLinearLayout *rootLayout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 400, 0) orientation:MyOrientation_Horz]; + rootLayout.padding = UIEdgeInsetsMake(10, 10, 20, 20); + rootLayout.wrapContentWidth = NO; + rootLayout.wrapContentHeight = YES; + + //视图1高度依赖父视图,宽度设置。 + UILabel *v1 = [UILabel new]; + v1.text = @"你好"; //iPhone8模拟器 + v1.myVertMargin = 10; + v1.wrapContentWidth = YES; + [rootLayout addSubview:v1]; + + //视图2高度定值,下边对齐,宽度不设置。 + UIView *v2 = [UIView new]; + v2.myBottom = 20; + v2.myHeight = 50; + [rootLayout addSubview:v2]; + + //视图3高度定值,居中对齐,宽度设置。 + UIView *v3 = [UIView new]; + v3.heightSize.equalTo(v2.heightSize).add(20); + v3.myCenterY = 0; + v3.myWidth = 40; + [rootLayout addSubview:v3]; + + //视图4设置上下边距,并且高度定值,宽度不设置。 + UIView *v4 = [UIView new]; + v4.myVertMargin = 30; + v4.myHeight = 100; + [rootLayout addSubview:v4]; + + //视图5设置高度依赖父视图,宽度设置。 + UIView *v5 = [UIView new]; + v5.heightSize.equalTo(rootLayout.heightSize).multiply(0.5); + v5.myWidth = 40; + [rootLayout addSubview:v5]; + + rootLayout.gravity = MyGravity_Horz_Stretch; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,400,190)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(10,20,35,140)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(45,100,127.5,50)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(172.5,55,40,70)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(212.5,40,127.5,100)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(340,10,40,80)), @"the v5 .frame = %@",NSStringFromCGRect(v5.frame)); + } + + } diff --git a/MyLayoutTests/MyNoLayoutSuperviewTestCase.m b/MyLayoutTests/MyNoLayoutSuperviewTestCase.m index 97e2ddf..0cdcd70 100644 --- a/MyLayoutTests/MyNoLayoutSuperviewTestCase.m +++ b/MyLayoutTests/MyNoLayoutSuperviewTestCase.m @@ -28,7 +28,7 @@ - (void)testExample1 { //测试停靠到非布局父视图上的布局。 - [MyBaseLayout setIsRTL:YES]; + [MyBaseLayout setIsRTL:NO]; UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 400)]; @@ -76,6 +76,12 @@ - (void)testExample1 { v1.mySize = CGSizeMake(60, 60); [layout6 addSubview:v1]; [layout6 layoutIfNeeded]; + + MyFrameLayout *layout7 = [MyFrameLayout new]; + layout7.mySize = CGSizeMake(40, 40); + layout7.myMargin = 20; + [containerView addSubview:layout7]; + if ([MyBaseLayout isRTL]) @@ -86,6 +92,7 @@ - (void)testExample1 { XCTAssertTrue(CGRectEqualToRect(layout4.frame, CGRectMake(70, 60, 40, 300)), @"layout4 frame=%@", NSStringFromCGRect(layout4.frame)); XCTAssertTrue(CGRectEqualToRect(layout5.frame, CGRectMake(100, 200, 40, 80)), @"layout5 frame=%@", NSStringFromCGRect(layout5.frame)); XCTAssertTrue(CGRectEqualToRect(layout6.frame, CGRectMake(45, 310, 70, 70)), @"layout6 frame=%@", NSStringFromCGRect(layout6.frame)); + XCTAssertTrue(CGRectEqualToRect(layout7.frame, CGRectMake(140, 20, 40, 40)), @"layout7 frame=%@", NSStringFromCGRect(layout7.frame)); } else @@ -97,6 +104,8 @@ - (void)testExample1 { XCTAssertTrue(CGRectEqualToRect(layout4.frame, CGRectMake(90, 60, 40, 300)), @"layout4 frame=%@", NSStringFromCGRect(layout4.frame)); XCTAssertTrue(CGRectEqualToRect(layout5.frame, CGRectMake(100, 200, 40, 80)), @"layout5 frame=%@", NSStringFromCGRect(layout5.frame)); XCTAssertTrue(CGRectEqualToRect(layout6.frame, CGRectMake(85, 310, 70, 70)), @"layout6 frame=%@", NSStringFromCGRect(layout6.frame)); + XCTAssertTrue(CGRectEqualToRect(layout7.frame, CGRectMake(20, 20, 40, 40)), @"layout7 frame=%@", NSStringFromCGRect(layout7.frame)); + } From b927499432b2cd0ea86fe35530dbcf2ec311875a Mon Sep 17 00:00:00 2001 From: youngsoft Date: Thu, 19 Sep 2019 09:42:05 +0800 Subject: [PATCH 038/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyLinearLayout.m | 114 +++++++++++++------------ MyLayoutTests/MyLinearLayoutTestCase.m | 23 +++-- 2 files changed, 76 insertions(+), 61 deletions(-) diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 1904dab..f828d95 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -385,6 +385,37 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGRect rect = sbvmyFrame.frame; + + if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) + { + BOOL canAddToNoWrapSbs = YES; + + if (sbvsc.weight != 0) + canAddToNoWrapSbs = NO; + + //判断是否是添加到参与布局视图包裹计算的子视图。 + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) + canAddToNoWrapSbs = NO; + + //如果子视图高度是包裹的也不进行扩展 + if (sbvsc.wrapContentHeight) + canAddToNoWrapSbs = NO; + + //如果子视图的最小高度就是自身则也不进行扩展。 + if (sbvsc.heightSizeInner.lBoundValInner.dimeSelfVal != nil) + canAddToNoWrapSbs = NO; + + //对于尺寸拉升来说,只要设置了高度约束就都不拉升。 + if (vertGravity == MyGravity_Vert_Stretch && sbvsc.heightSizeInner.dimeVal != nil) + canAddToNoWrapSbs = NO; + + if (canAddToNoWrapSbs) + [noWrapsbsSet addObject:sbv]; + + //在计算拉伸时,如果没有设置宽度约束则将宽度设置为0 + if (!sbvsc.wrapContentHeight && sbvsc.heightSizeInner.dimeVal == nil && sbvsc.heightSizeInner.lBoundValInner.dimeSelfVal == nil) + rect.size.height = 0; + } //计算子视图的高度 rect.size.height = [self myGetSubviewHeightSizeValue:sbv @@ -513,33 +544,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } } - if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) - { - BOOL canAddToNoWrapSbs = YES; - - if (sbvsc.weight != 0) - canAddToNoWrapSbs = NO; - - //判断是否是添加到参与布局视图包裹计算的子视图。 - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) - canAddToNoWrapSbs = NO; - - //如果子视图高度是包裹的也不进行扩展 - if (sbvsc.wrapContentHeight) - canAddToNoWrapSbs = NO; - - //如果子视图的最小高度就是自身则也不进行扩展。 - if (sbvsc.heightSizeInner.lBoundValInner.dimeSelfVal != nil) - canAddToNoWrapSbs = NO; - - //对于尺寸拉升来说,只要设置了高度约束就都不拉升。 - if (vertGravity == MyGravity_Vert_Stretch && sbvsc.heightSizeInner.dimeVal != nil) - canAddToNoWrapSbs = NO; - - if (canAddToNoWrapSbs) - [noWrapsbsSet addObject:sbv]; - } - sbvmyFrame.frame = rect; } @@ -885,6 +889,36 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGRect rect = sbvmyFrame.frame; + if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) + { + BOOL canAddToNoWrapSbs = YES; + + if (sbvsc.weight != 0) + canAddToNoWrapSbs = NO; + + //判断是否是添加到参与布局视图包裹计算的子视图。 + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner) + canAddToNoWrapSbs = NO; + + //如果子视图宽度是包裹的也不进行扩展 + if (sbvsc.wrapContentWidth) + canAddToNoWrapSbs = NO; + + //如果子视图的最小宽度就是自身则也不进行扩展。 + if (sbvsc.widthSizeInner.lBoundValInner.dimeSelfVal != nil) + canAddToNoWrapSbs = NO; + + if (horzGravity == MyGravity_Horz_Stretch && sbvsc.widthSizeInner.dimeVal != nil) + canAddToNoWrapSbs = NO; + + if (canAddToNoWrapSbs) + [noWrapsbsSet addObject:sbv]; + + //在计算拉伸时,如果没有设置宽度约束则将宽度设置为0 + if (!sbvsc.wrapContentWidth && sbvsc.widthSizeInner.dimeVal == nil && sbvsc.widthSizeInner.lBoundValInner.dimeSelfVal == nil) + rect.size.width = 0; + } + //计算子视图的宽度,这里不管是否设置约束以及是否宽度是weight的都是进行计算。 rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc @@ -1018,32 +1052,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } } - if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) - { - BOOL canAddToNoWrapSbs = YES; - - if (sbvsc.weight != 0) - canAddToNoWrapSbs = NO; - - //判断是否是添加到参与布局视图包裹计算的子视图。 - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner) - canAddToNoWrapSbs = NO; - - //如果子视图宽度是包裹的也不进行扩展 - if (sbvsc.wrapContentWidth) - canAddToNoWrapSbs = NO; - - //如果子视图的最小宽度就是自身则也不进行扩展。 - if (sbvsc.widthSizeInner.lBoundValInner.dimeSelfVal != nil) - canAddToNoWrapSbs = NO; - - if (horzGravity == MyGravity_Horz_Stretch && sbvsc.widthSizeInner.dimeVal != nil) - canAddToNoWrapSbs = NO; - - if (canAddToNoWrapSbs) - [noWrapsbsSet addObject:sbv]; - } - sbvmyFrame.frame = rect; } diff --git a/MyLayoutTests/MyLinearLayoutTestCase.m b/MyLayoutTests/MyLinearLayoutTestCase.m index 4437fec..6e4c76a 100644 --- a/MyLayoutTests/MyLinearLayoutTestCase.m +++ b/MyLayoutTests/MyLinearLayoutTestCase.m @@ -84,6 +84,13 @@ - (void)testExample { [v12 layoutIfNeeded]; [v13 layoutIfNeeded]; + for (int i = 1; i <=12; i++) + { + Class cls = NSClassFromString([NSString stringWithFormat:@"AllTest%dViewController", i]); + UIViewController *vc = [cls new]; + UIView *v = vc.view; + [v layoutIfNeeded]; + } } @@ -487,7 +494,7 @@ -(void)testBetweenAndAround -(void)testFillAndStretch { //子视图有几个设置了约束,有几个没有设置约束。分别展现Fill 和Stretch的差异。 - { + if (1){ MyLinearLayout *rootLayout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 0, 400) orientation:MyOrientation_Vert]; rootLayout.padding = UIEdgeInsetsMake(10, 10, 20, 20); rootLayout.wrapContentWidth = YES; @@ -537,7 +544,7 @@ -(void)testFillAndStretch XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(10,272.5,80,107.5)), @"the v5 .frame = %@",NSStringFromCGRect(v5.frame)); } - { + if (1){ MyLinearLayout *rootLayout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 0, 400) orientation:MyOrientation_Vert]; rootLayout.padding = UIEdgeInsetsMake(10, 10, 20, 20); rootLayout.wrapContentWidth = YES; @@ -588,7 +595,7 @@ -(void)testFillAndStretch } - { + if (1){ MyLinearLayout *rootLayout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 400, 0) orientation:MyOrientation_Horz]; rootLayout.padding = UIEdgeInsetsMake(10, 10, 20, 20); rootLayout.wrapContentWidth = NO; @@ -632,13 +639,13 @@ -(void)testFillAndStretch XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,400,190)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(10,20,35,140)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); - XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(45,100,96,50)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); - XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(141,55,72,70)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); - XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(212.5,40,96,100)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); - XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(308.5,10,72,80)), @"the v5 .frame = %@",NSStringFromCGRect(v5.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(45,100,64,50)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(109,55,104,70)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(212.5,40,64,100)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(276.5,10,104,80)), @"the v5 .frame = %@",NSStringFromCGRect(v5.frame)); } - { + if (1){ MyLinearLayout *rootLayout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 400, 0) orientation:MyOrientation_Horz]; rootLayout.padding = UIEdgeInsetsMake(10, 10, 20, 20); rootLayout.wrapContentWidth = NO; From 1471e8d2198eaac29234f2bec857de2258726be8 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Thu, 19 Sep 2019 20:22:30 +0800 Subject: [PATCH 039/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.h | 214 ++++++++++++++++--------------- MyLayout/Lib/MyBaseLayout.m | 170 +++++++++--------------- MyLayout/Lib/MyFlexLayout.m | 38 +++--- MyLayout/Lib/MyFloatLayout.h | 10 +- MyLayout/Lib/MyFloatLayout.m | 51 ++++---- MyLayout/Lib/MyFlowLayout.h | 18 +-- MyLayout/Lib/MyFlowLayout.m | 50 ++++---- MyLayout/Lib/MyFrameLayout.m | 8 +- MyLayout/Lib/MyGridLayout.m | 4 +- MyLayout/Lib/MyLayoutDef.h | 2 + MyLayout/Lib/MyLayoutPos.m | 67 ++++------ MyLayout/Lib/MyLayoutSize.h | 12 +- MyLayout/Lib/MyLayoutSize.m | 193 ++++++++++++++-------------- MyLayout/Lib/MyLayoutSizeClass.m | 76 +++-------- MyLayout/Lib/MyLayoutSizeInner.h | 6 +- MyLayout/Lib/MyLinearLayout.h | 12 +- MyLayout/Lib/MyLinearLayout.m | 132 ++++++++----------- MyLayout/Lib/MyPathLayout.m | 4 +- MyLayout/Lib/MyRelativeLayout.m | 53 +++----- MyLayout/Lib/MyTableLayout.m | 26 ++-- 20 files changed, 503 insertions(+), 643 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index b296312..0e264ea 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -351,107 +351,6 @@ @property(nonatomic,assign) IBInspectable CGSize mySize; - -/** - *视图的宽度包裹属性,表示视图的宽度由所有子视图的整体宽度来确定或者根据视图内容来宽度自适应。默认值是NO(水平线性布局默认这个属性是YES),表示必须要明确指定视图的宽度,而当设置为YES时则不需要明确的指定视图的宽度了。这个属性不能和widthSize(或者设置了左右边距)同时设置否则可能会产生约束冲突,因为前者表明宽度由子视图或者内容来决定而后者则表示宽度是一个明确的值。如果同时设置了宽度包裹属性又同时设置了明确的宽度则系统会出现约束冲突告警,虽然如此,系统在布局时做了一些优化,如果同时设置了明确的宽度和宽度包裹则会在布局前将宽度包裹属性置为NO。 - */ -@property(nonatomic,assign) IBInspectable BOOL wrapContentWidth; - -/** - *视图的高度包裹属性,表示视图的高度由所有子视图的整体高度来确定或者根据视图内容来高度自适应。默认值是NO(垂直线性布局默认这个属性是YES),表示必须要明确指定布局的高度,而当设置为YES时则不需要明确的指定视图的高度了。这个属性不能和heightSize(或者设置了上下边距)同时设置否则可能会产生约束冲突,因为前者表明高度由子视图或者内容来决定而后者则表示高度是一个明确的值。如果同时设置了高度包裹属性又同时设置了明确的高度则系统会出现约束冲突告警,虽然如此,系统在布局时做了一些优化,如果同时设置了明确的高度和高度包裹则会在布局前将高度包裹属性置为NO。如果某个非布局视图指定了明确的宽度,而又将这个属性设置为了YES的话就能实现在固定宽度的情况下视图的高度根据内容自适应的效果,这个特性主要用于UILabel,UITextView以及实现了sizeThatFits方法的视图来实现高度根据内容自适应的场景。UILabel在使用这个属性时会自动设置numberOfLines为0,因此如果您要修改numberOfLines则需要在设置这个属性后进行;UITextView可以用这个属性以及heightSize中的max方法来实现到达指定的高度后若继续输入则产生滚动的效果;UIImageView可以用这个属性来在实现在确定宽度的情况下高度根据宽度的缩放情况进行等比例的缩放。 - */ -@property(nonatomic,assign) IBInspectable BOOL wrapContentHeight; - - -/** - *视图的尺寸根据内容来决定,也就是视图的尺寸由内容包裹。这个属性是: A.wrapContentWidth = YES; A.wrapContentHeight = YES;的简化版本。 - *在历史版本中对UILabel进行text赋值后总要手动调用sizeToFit来重新更新布局,在1.3.6以后的新版本中,如果你希望视图的尺寸根据内容而确定则请将这个属性 - *设置为YES。这样就可以在设置完毕text后系统会自动激发布局处理。 - */ -@property(nonatomic, assign) IBInspectable BOOL wrapContentSize; - - -/** - 设置子视图的相对比重尺寸。也就是子视图的尺寸并不是一个绝对值而是一个相对值,在最终布局时系统会根据布局视图的剩余尺寸来将这个相对的值转化为绝对的值。通过对子视图设置相对的尺寸可以很方便的适配各种屏幕尺寸的设备,以便达到完美的布局效果。这个属性默认值是0表示不使用相对尺寸。weight属性的引入是参考android中的weight的概念而来的。 - - 目前只有在线性布局、表格布局、流式布局、浮动布局下的子视图设置weight才有效,相对布局、框架布局、路径布局里面的子视图不支持weight属性的设置。 - 在不同的布局下的子视图的weight属性所表达的意义也有所差异: - - @note - 1.在线性布局和表格布局下: - - 1.1. 当线性布局是垂直线性布局时这个属性用来设置子视图高度占用父线性布局剩余高度的比重,这样子视图就不需要明确的设定高度值。 - - 1.2. 当线性布局是水平线性布局时这个属性用来设置子视图宽度占用父线性布局剩余宽度的比重,这样子视图就不需要明确的设定宽度值。 - - @code - 视图的真实尺寸值 = 布局视图剩余尺寸 * 当前视图的weight比重/(布局视图内所有设置了weight比重值的子视图比重之和)。 - @endcode - - 对一个垂直线性布局举例来说:假设布局视图的高度是100,A子视图占据了20的固定高度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: - @code - A子视图的高度 = 20 - B子视图的高度 = (100-20)*0.4/(0.4+0.6) = 32 - C子视图的高度 = (100-20)*0.6/(0.4+0.6) = 48 - @endcode - - 子视图设置weight属性时要注意如下几点: - - - 垂直线性布局必须指定明确的高度,而不能使用wrapContentHeight属性;水平线性布局必须指定明确的宽度,而不能使用wrapContentWidth属性。 - - - 如果比重属性设置为0的话则表示视图的尺寸必须要明确的被指定,这也是默认值。 - - - 线性布局里面的所有子视图的比重值的和不一定要求是1,比如线性布局里面两个视图的比重都设置为1和都设置为0.5以及都设置为0.1的意义是一样的,都是占用50%。 - - @note - 2.在流式布局下: - - 2.1. 当流式布局是垂直流式布局时这个属性用来设置子视图宽度占用父流式布局当前行的剩余宽度的比重,这样子视图就不需要明确的设定宽度值。 - - 2.2. 当流式布局是水平流式布局时这个属性用来设置子视图高度占用父流式布局当前列的剩余高度的比重,这样子视图就不需要明确的设定高度值。 - - 同时在数量约束和内容约束两种布局中视图设置的比重值在最终计算出真实尺寸时也是有差异的: - - @code - 数量约束流式布局内的视图的真实尺寸值 = 布局视图剩余尺寸 * 当前视图的weight比重/(视图所在行的所有设置了weight比重值的视图比重之和)。 - - 内容约束流式布局内的视图的真实尺寸值 = 布局视图剩余尺寸 * 当前视图的weight比重。 - - 对一个垂直数量约束流式布局举例来说:假设布局视图的宽度是100,A子视图占据了20的固定宽度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: - A子视图的宽度 = 20 - B子视图的宽度 = (100-20)*0.4/(0.4+0.6) = 32 - C子视图的宽度 = (100-20)*0.6/(0.4+0.6) = 48 - - 对一个垂直内容约束流式布局举例来说:假设布局视图的宽度是100,A子视图占据了20的固定宽度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: - A子视图的宽度 = 20 - B子视图的宽度 = (100-20)*0.4 = 32 - C子视图的宽度 = (100-20-32)*0.6 = 28.8 - @endcode - - - @note - 3. 在浮动布局下: - - 3.1. 当浮动布局的方向是垂直布局时,这个属性用来设置视图宽度占用当前浮动布局父视图剩余宽度的比重,这样视图就不需要明确的设定宽度值。 - - 3.2. 当浮动布局的方向是水平布局时,这个属性用来设置视图高度占用当前浮动布局父视图剩余高度的比重,这样子视图就不需要明确的设定高度值。 - - @code - 视图的真实尺寸 = 布局父视图的剩余尺寸 * 视图的weight比重值。 - @endcode - - 举例来说:假设一个垂直浮动布局视图的宽度是100,A子视图占据了20的固定宽度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: - - @code - A子视图的宽度 = 20 - B子视图的宽度 = (100-20)*0.4 = 32 - C子视图的宽度 = (100-20-32)*0.6 = 28.8 - @endcode - - */ -@property(nonatomic, assign) IBInspectable CGFloat weight; - - /** 设置视图不受布局父视图的布局约束控制和不再参与视图的布局,所有设置的其他扩展属性都将失效而必须用frame来设置视图的位置和尺寸,默认值是NO。这个属性主要用于某些视图希望在布局视图中进行特殊处理和进行自定义的设置的场景。比如一个垂直线性布局下有A,B,C三个子视图设置如下: @@ -710,7 +609,7 @@ /** * 设置当布局的尺寸由子视图决定并且在没有子视图加入的情况下padding的设置值是否会加入到布局的尺寸值里面。默认是YES,表示当布局视图没有子视图时padding值也会加入到尺寸里面。 - * 举例来说假设某个布局视图的高度是wrapContentHeight,并且设置了topPadding为10,bottomPadding为20。那么默认情况下当没有任何子视图时布局视图的高度是30;而当我们将这个属性设置为NO时,那么在没有任何子视图时布局视图的高度就是0,也就是说topPadding和bottomPadding不会参与高度的计算了。 + * 举例来说假设某个布局视图的高度是自适应,并且设置了topPadding为10,bottomPadding为20。那么默认情况下当没有任何子视图时布局视图的高度是30;而当我们将这个属性设置为NO时,那么在没有任何子视图时布局视图的高度就是0,也就是说topPadding和bottomPadding不会参与高度的计算了。 */ @property(nonatomic, assign) BOOL zeroPadding; @@ -958,7 +857,7 @@ MyXXXLayout *rootLayout= [MyXXXLayout new]; rootLayout.cacheEstimatedRect = YES; //设置缓存评估的rect,如果您的cell是高度自适应的话,强烈建立打开这个属性,这会大大的增强您的tableview的性能!! rootLayout.myHorzMargin = 0; //宽度和父视图相等 - rootLayout.wrapContentHeight = YES; //高度动态包裹。 + rootLayout.myHeight = MyLayoutSize.wrap; //高度动态包裹。 [self.contentView addSubview:rootLayout]; self.rootLayout = rootLayout; @@ -1071,3 +970,112 @@ +#pragma mark -- Deprecated + + +@interface UIView(MyDeprecated) + + +/** + *不建议使用这个属性了,而是直接设置视图的宽度为MyLayoutSize.wrap 比如:myWidth = MyLayoutSize.wrap 或者widthSize.equalTo(@(MyLayoutSize.wrap)) + *视图的宽度包裹属性,表示视图的宽度由所有子视图的整体宽度来确定或者根据视图内容来宽度自适应。默认值是NO(水平线性布局默认这个属性是YES),表示必须要明确指定视图的宽度,而当设置为YES时则不需要明确的指定视图的宽度了。这个属性不能和widthSize(或者设置了左右边距)同时设置否则可能会产生约束冲突,因为前者表明宽度由子视图或者内容来决定而后者则表示宽度是一个明确的值。如果同时设置了宽度包裹属性又同时设置了明确的宽度则系统会出现约束冲突告警,虽然如此,系统在布局时做了一些优化,如果同时设置了明确的宽度和宽度包裹则会在布局前将宽度包裹属性置为NO。 + */ +@property(nonatomic,assign) BOOL wrapContentWidth; + +/** + *!!!!不建议使用这个属性了,而是直接设置视图的高度为MyLayoutSize.wrap 比如:myHeight = MyLayoutSize.wrap 或者heightSize.equalTo(@(MyLayoutSize.wrap)) + + *视图的高度包裹属性,表示视图的高度由所有子视图的整体高度来确定或者根据视图内容来高度自适应。默认值是NO(垂直线性布局默认这个属性是YES),表示必须要明确指定布局的高度,而当设置为YES时则不需要明确的指定视图的高度了。这个属性不能和heightSize(或者设置了上下边距)同时设置否则可能会产生约束冲突,因为前者表明高度由子视图或者内容来决定而后者则表示高度是一个明确的值。如果同时设置了高度包裹属性又同时设置了明确的高度则系统会出现约束冲突告警,虽然如此,系统在布局时做了一些优化,如果同时设置了明确的高度和高度包裹则会在布局前将高度包裹属性置为NO。如果某个非布局视图指定了明确的宽度,而又将这个属性设置为了YES的话就能实现在固定宽度的情况下视图的高度根据内容自适应的效果,这个特性主要用于UILabel,UITextView以及实现了sizeThatFits方法的视图来实现高度根据内容自适应的场景。UILabel在使用这个属性时会自动设置numberOfLines为0,因此如果您要修改numberOfLines则需要在设置这个属性后进行;UITextView可以用这个属性以及heightSize中的max方法来实现到达指定的高度后若继续输入则产生滚动的效果;UIImageView可以用这个属性来在实现在确定宽度的情况下高度根据宽度的缩放情况进行等比例的缩放。 + */ +@property(nonatomic,assign) BOOL wrapContentHeight; + + +/** + *不建议使用这个属性了!直接设置尺寸为MyLayoutSize.wrap即可。 + *视图的尺寸根据内容来决定,也就是视图的尺寸由内容包裹。这个属性是: A.wrapContentWidth = YES; A.wrapContentHeight = YES;的简化版本。 + *在历史版本中对UILabel进行text赋值后总要手动调用sizeToFit来重新更新布局,在1.3.6以后的新版本中,如果你希望视图的尺寸根据内容而确定则请将这个属性 + *设置为YES。这样就可以在设置完毕text后系统会自动激发布局处理。 + */ +@property(nonatomic, assign) BOOL wrapContentSize; + +/** + 设置子视图的相对比重尺寸。也就是子视图的尺寸并不是一个绝对值而是一个相对值,在最终布局时系统会根据布局视图的剩余尺寸来将这个相对的值转化为绝对的值。通过对子视图设置相对的尺寸可以很方便的适配各种屏幕尺寸的设备,以便达到完美的布局效果。这个属性默认值是0表示不使用相对尺寸。weight属性的引入是参考android中的weight的概念而来的。 + + 目前只有在线性布局、表格布局、流式布局、浮动布局下的子视图设置weight才有效,相对布局、框架布局、路径布局里面的子视图不支持weight属性的设置。 + 在不同的布局下的子视图的weight属性所表达的意义也有所差异: + + @note + 1.在线性布局和表格布局下: + + 1.1. 当线性布局是垂直线性布局时这个属性用来设置子视图高度占用父线性布局剩余高度的比重,这样子视图就不需要明确的设定高度值。 + + 1.2. 当线性布局是水平线性布局时这个属性用来设置子视图宽度占用父线性布局剩余宽度的比重,这样子视图就不需要明确的设定宽度值。 + + @code + 视图的真实尺寸值 = 布局视图剩余尺寸 * 当前视图的weight比重/(布局视图内所有设置了weight比重值的子视图比重之和)。 + @endcode + + 对一个垂直线性布局举例来说:假设布局视图的高度是100,A子视图占据了20的固定高度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: + @code + A子视图的高度 = 20 + B子视图的高度 = (100-20)*0.4/(0.4+0.6) = 32 + C子视图的高度 = (100-20)*0.6/(0.4+0.6) = 48 + @endcode + + 子视图设置weight属性时要注意如下几点: + + - 垂直线性布局必须指定明确的高度,而高度不能设置为自适应;水平线性布局必须指定明确的宽度,而不能使用wrapContentWidth属性。 + + - 如果比重属性设置为0的话则表示视图的尺寸必须要明确的被指定,这也是默认值。 + + - 线性布局里面的所有子视图的比重值的和不一定要求是1,比如线性布局里面两个视图的比重都设置为1和都设置为0.5以及都设置为0.1的意义是一样的,都是占用50%。 + + @note + 2.在流式布局下: + + 2.1. 当流式布局是垂直流式布局时这个属性用来设置子视图宽度占用父流式布局当前行的剩余宽度的比重,这样子视图就不需要明确的设定宽度值。 + + 2.2. 当流式布局是水平流式布局时这个属性用来设置子视图高度占用父流式布局当前列的剩余高度的比重,这样子视图就不需要明确的设定高度值。 + + 同时在数量约束和内容约束两种布局中视图设置的比重值在最终计算出真实尺寸时也是有差异的: + + @code + 数量约束流式布局内的视图的真实尺寸值 = 布局视图剩余尺寸 * 当前视图的weight比重/(视图所在行的所有设置了weight比重值的视图比重之和)。 + + 内容约束流式布局内的视图的真实尺寸值 = 布局视图剩余尺寸 * 当前视图的weight比重。 + + 对一个垂直数量约束流式布局举例来说:假设布局视图的宽度是100,A子视图占据了20的固定宽度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: + A子视图的宽度 = 20 + B子视图的宽度 = (100-20)*0.4/(0.4+0.6) = 32 + C子视图的宽度 = (100-20)*0.6/(0.4+0.6) = 48 + + 对一个垂直内容约束流式布局举例来说:假设布局视图的宽度是100,A子视图占据了20的固定宽度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: + A子视图的宽度 = 20 + B子视图的宽度 = (100-20)*0.4 = 32 + C子视图的宽度 = (100-20-32)*0.6 = 28.8 + @endcode + + + @note + 3. 在浮动布局下: + + 3.1. 当浮动布局的方向是垂直布局时,这个属性用来设置视图宽度占用当前浮动布局父视图剩余宽度的比重,这样视图就不需要明确的设定宽度值。 + + 3.2. 当浮动布局的方向是水平布局时,这个属性用来设置视图高度占用当前浮动布局父视图剩余高度的比重,这样子视图就不需要明确的设定高度值。 + + @code + 视图的真实尺寸 = 布局父视图的剩余尺寸 * 视图的weight比重值。 + @endcode + + 举例来说:假设一个垂直浮动布局视图的宽度是100,A子视图占据了20的固定宽度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: + + @code + A子视图的宽度 = 20 + B子视图的宽度 = (100-20)*0.4 = 32 + C子视图的宽度 = (100-20-32)*0.6 = 28.8 + @endcode + + */ +@property(nonatomic, assign) IBInspectable CGFloat weight; + +@end diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index b1dbc41..f4bea1a 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -1447,14 +1447,12 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIView*)object chan UIView *sbvsc = object.myCurrentSizeClass; - if (sbvsc.widthSizeInner.dimeSelfVal != nil && sbvsc.heightSizeInner.dimeSelfVal != nil) + //这是什么意思? 这就是不注释的悲剧!!! + if (sbvsc.widthSizeInner.dimeWrapVal && sbvsc.heightSizeInner.dimeWrapVal) { [self setNeedsLayout]; } - else if (sbvsc.wrapContentWidth || - sbvsc.wrapContentHeight || - sbvsc.widthSizeInner.dimeSelfVal != nil || - sbvsc.heightSizeInner.dimeSelfVal != nil) + else if (sbvsc.widthSizeInner.dimeWrapVal || sbvsc.heightSizeInner.dimeWrapVal) { [object sizeToFit]; } @@ -1597,7 +1595,7 @@ - (void)willMoveToSuperview:(UIView*)newSuperview MyBaseLayout *lsc = self.myCurrentSizeClass; - //特殊处理如果视图是控制器根视图则取消wrapContentWidth, wrapContentHeight,以及adjustScrollViewContentSizeMode的设置。 + //特殊处理如果视图是控制器根视图则取消高度或者宽度包裹,以及adjustScrollViewContentSizeMode的设置。 @try { if (newSuperview != nil) @@ -1606,8 +1604,11 @@ - (void)willMoveToSuperview:(UIView*)newSuperview id vc = [self valueForKey:@"viewDelegate"]; if (vc != nil) { - lsc.wrapContentWidth = NO; - lsc.wrapContentHeight = NO; + if (lsc.widthSizeInner.dimeWrapVal) + [lsc.widthSizeInner __equalTo:nil]; + if (lsc.heightSizeInner.dimeWrapVal) + [lsc.heightSizeInner __equalTo:nil]; + if (lsc.insetsPaddingFromSafeArea == defRectEdge) lsc.insetsPaddingFromSafeArea = ~UIRectEdgeTop; self.adjustScrollViewContentSizeMode = MyAdjustScrollViewContentSizeModeNo; @@ -1625,26 +1626,6 @@ - (void)willMoveToSuperview:(UIView*)newSuperview } - -#ifdef DEBUG - - if (lsc.wrapContentHeight && lsc.heightSizeInner.dimeVal != nil) - { - //约束警告:wrapContentHeight和设置的heightSize可能有约束冲突 - NSLog(@"Constraint warning!%@'s wrapContentHeight and heightSize setting may be constraint.",self); - } - - if (lsc.wrapContentWidth && lsc.widthSizeInner.dimeVal != nil) - { - //约束警告:wrapContentWidth和设置的widthSize可能有约束冲突 - NSLog(@"Constraint warning!%@'s wrapContentWidth and widthSize setting may be constraint.",self); - } - -#endif - - - - //将要添加到父视图时,如果不是MyLayout派生则则跟需要根据父视图的frame的变化而调整自身的位置和尺寸 if (newSuperview != nil && ![newSuperview isKindOfClass:[MyBaseLayout class]]) { @@ -1850,13 +1831,13 @@ -(CGSize)intrinsicContentSize { CGSize sz = [super intrinsicContentSize]; - if (self.translatesAutoresizingMaskIntoConstraints == NO && (self.wrapContentWidth || self.wrapContentHeight)) + if (self.translatesAutoresizingMaskIntoConstraints == NO && (self.widthSizeInner.dimeWrapVal || self.heightSizeInner.dimeWrapVal)) { - if (self.wrapContentWidth && self.wrapContentHeight) + if (self.widthSizeInner.dimeWrapVal && self.heightSizeInner.dimeWrapVal) { sz = [self sizeThatFits:CGSizeZero]; } - else if (self.wrapContentWidth) + else if (self.widthSizeInner.dimeWrapVal) { //动态宽度 NSLayoutConstraint *heightConstraint = nil; @@ -2131,7 +2112,7 @@ -(void)layoutSubviews } - if (newSelfSize.width != CGFLOAT_MAX && (lsc.wrapContentWidth || lsc.wrapContentHeight)) + if (newSelfSize.width != CGFLOAT_MAX && (lsc.widthSizeInner.dimeWrapVal || lsc.heightSizeInner.dimeWrapVal)) { //因为布局子视图的新老尺寸计算在上面有两种不同的方法,因此这里需要考虑两种计算的误差值,而这两种计算的误差值是不超过1/屏幕精度的。 @@ -2163,10 +2144,10 @@ -(void)layoutSubviews if (CGAffineTransformIsIdentity(self.transform)) { CGRect currentFrame = self.frame; - if (isWidthAlter && lsc.wrapContentWidth) + if (isWidthAlter && lsc.widthSizeInner.dimeWrapVal) currentFrame.size.width = newSelfSize.width; - if (isHeightAlter && lsc.wrapContentHeight) + if (isHeightAlter && lsc.heightSizeInner.dimeWrapVal) currentFrame.size.height = newSelfSize.height; self.frame = currentFrame; @@ -2181,13 +2162,13 @@ -(void)layoutSubviews if ([self.superview isKindOfClass:[UIScrollView class]]) superViewZoomScale = ((UIScrollView*)self.superview).zoomScale; - if (isWidthAlter && lsc.wrapContentWidth) + if (isWidthAlter && lsc.widthSizeInner.dimeWrapVal) { currentBounds.size.width = newSelfSize.width; currentCenter.x += (newSelfSize.width - oldSelfSize.width) * self.layer.anchorPoint.x * superViewZoomScale; } - if (isHeightAlter && lsc.wrapContentHeight) + if (isHeightAlter && lsc.heightSizeInner.dimeWrapVal) { currentBounds.size.height = newSelfSize.height; currentCenter.y += (newSelfSize.height - oldSelfSize.height) * self.layer.anchorPoint.y * superViewZoomScale; @@ -2222,7 +2203,7 @@ -(void)layoutSubviews } - //如果自己的父视图是非UIScrollView以及非布局视图。以及自己是wrapContentWidth或者wrapContentHeight时,并且如果设置了在父视图居中或者居下或者居右时要在父视图中更新自己的位置。 + //如果自己的父视图是非UIScrollView以及非布局视图。以及自己的宽度或者高度是包裹的,并且如果设置了在父视图居中或者居下或者居右时要在父视图中更新自己的位置。 if (supv != nil && ![supv isKindOfClass:[MyBaseLayout class]]) { CGPoint centerPonintSelf = self.center; @@ -2242,14 +2223,14 @@ -(void)layoutSubviews } } - //如果自己的父视图是非UIScrollView以及非布局视图。以及自己是wrapContentWidth或者wrapContentHeight时,并且如果设置了在父视图居中或者居下或者居右时要在父视图中更新自己的位置。 - if (![supv isKindOfClass:[UIScrollView class]] && (lsc.wrapContentWidth || lsc.wrapContentHeight)) + //如果自己的父视图是非UIScrollView以及非布局视图。以及自己的宽度或者高度是包裹的时,并且如果设置了在父视图居中或者居下或者居右时要在父视图中更新自己的位置。 + if (![supv isKindOfClass:[UIScrollView class]] && (lsc.widthSizeInner.dimeWrapVal || lsc.heightSizeInner.dimeWrapVal)) { if ([MyBaseLayout isRTL]) centerPonintSelf.x = rectSuper.size.width - centerPonintSelf.x; - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) { //如果只设置了右边,或者只设置了居中则更新位置。。 if (lsc.centerXPosInner.posVal != nil) @@ -2265,7 +2246,7 @@ -(void)layoutSubviews } - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) { if (lsc.centerYPosInner.posVal != nil) { @@ -2295,19 +2276,19 @@ -(void)layoutSubviews //这里处理当布局视图的父视图是非布局父视图,且父视图具有wrap属性时需要调整父视图的尺寸。 if (supv != nil && ![supv isKindOfClass:[MyBaseLayout class]]) { - if (supv.wrapContentHeight || supv.wrapContentWidth) + if (supv.heightSizeInner.dimeWrapVal || supv.widthSizeInner.dimeWrapVal) { //调整父视图的高度和宽度。frame值。 CGRect superBounds = supv.bounds; CGPoint superCenter = supv.center; - if (supv.wrapContentHeight) + if (supv.heightSizeInner.dimeWrapVal) { superBounds.size.height = [self myValidMeasure:supv.heightSizeInner sbv:supv calcSize:lsc.myTop + newSelfSize.height + lsc.myBottom sbvSize:superBounds.size selfLayoutSize:newSelfSize]; superCenter.y += (superBounds.size.height - supv.bounds.size.height) * supv.layer.anchorPoint.y; } - if (supv.wrapContentWidth) + if (supv.widthSizeInner.dimeWrapVal) { superBounds.size.width = [self myValidMeasure:supv.widthSizeInner sbv:supv calcSize:lsc.myLeading + newSelfSize.width + lsc.myTrailing sbvSize:superBounds.size selfLayoutSize:newSelfSize]; superCenter.x += (superBounds.size.width - supv.bounds.size.width) * supv.layer.anchorPoint.x; @@ -2394,7 +2375,7 @@ -(MyGravity)myGetSubviewVertGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc vertGravit if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { - if (sbvsc.heightSizeInner.dimeVal == nil && !sbvsc.wrapContentHeight) + if (sbvsc.heightSizeInner.dimeVal == nil) sbvVertGravity = MyGravity_Vert_Fill; } else if (sbvsc.centerYPosInner.posVal != nil) @@ -2451,7 +2432,7 @@ -(CGFloat)myCalcVertGravity:(MyGravity)vertGravity //如果是设置垂直拉伸则,如果子视图有约束则不受影响,否则就变为和填充一个意思。 if (vertGravity == MyGravity_Vert_Stretch) { - if (sbvsc.wrapContentHeight || sbvsc.heightSizeInner.dimeVal != nil) + if (sbvsc.heightSizeInner.dimeVal != nil) vertGravity = MyGravity_Vert_Top; else vertGravity = MyGravity_Vert_Fill; @@ -2536,7 +2517,7 @@ -(MyGravity)myGetSubviewHorzGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc horzGravit if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { - if (sbvsc.widthSizeInner.dimeVal == nil && !sbvsc.wrapContentWidth) + if (sbvsc.widthSizeInner.dimeVal == nil) sbvHorzGravity = MyGravity_Horz_Fill; } else if (sbvsc.centerXPosInner.posVal != nil) @@ -2591,10 +2572,10 @@ -(CGFloat)myCalcHorzGravity:(MyGravity)horzGravity //如果是设置水平拉伸则,如果子视图有约束则不受影响,否则就变为和填充一个意思。 if (horzGravity == MyGravity_Horz_Stretch) { - if (sbvsc.wrapContentWidth || sbvsc.widthSizeInner.dimeVal != nil) - horzGravity = MyGravity_Horz_Fill; - else + if (sbvsc.widthSizeInner.dimeVal != nil) horzGravity = MyGravity_Horz_Leading; + else + horzGravity = MyGravity_Horz_Fill; } @@ -2651,8 +2632,8 @@ -(void)myCalcSizeOfWrapContentSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc sbvmyFra } BOOL isLayoutView = [sbv isKindOfClass:[MyBaseLayout class]]; - BOOL isWrapWidth = (sbvsc.widthSizeInner.dimeSelfVal != nil) || (!isLayoutView && sbvsc.wrapContentWidth); //宽度包裹特殊处理 - BOOL isWrapHeight = (sbvsc.heightSizeInner.dimeSelfVal != nil) || (!isLayoutView && sbvsc.wrapContentSize);//高度包裹也特殊处理 + BOOL isWrapWidth = (!isLayoutView && sbvsc.widthSizeInner.dimeWrapVal); //宽度包裹特殊处理 + BOOL isWrapHeight = (!isLayoutView && sbvsc.heightSizeInner.dimeWrapVal);//高度包裹也特殊处理 if (isWrapWidth || isWrapHeight) @@ -2665,20 +2646,10 @@ -(void)myCalcSizeOfWrapContentSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc sbvmyFra CGSize fitSize = [sbv sizeThatFits:thatFits]; if (isWrapWidth) - { - if (sbvsc.wrapContentWidth) - sbvmyFrame.width = fitSize.width; - else - sbvmyFrame.width = [sbvsc.widthSizeInner measureWith:fitSize.width]; - } + sbvmyFrame.width = [sbvsc.widthSizeInner measureWith:fitSize.width]; if (isWrapHeight) - { - if (sbvsc.wrapContentHeight) - sbvmyFrame.height = fitSize.height; - else - sbvmyFrame.height = [sbvsc.heightSizeInner measureWith:fitSize.height]; - } + sbvmyFrame.height = [sbvsc.heightSizeInner measureWith:fitSize.height]; } } @@ -2692,7 +2663,7 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize UIView *ssc = newSuperview.myCurrentSizeClassInner; UIView *lsc = self.myCurrentSizeClass; - if (!ssc.wrapContentWidth) + if (!ssc.widthSizeInner.dimeWrapVal) { if (lsc.widthSizeInner.dimeRelaVal.view == newSuperview) { @@ -2706,7 +2677,7 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize if (lsc.leadingPosInner.posVal != nil && lsc.trailingPosInner.posVal != nil) { - if (!lsc.wrapContentWidth && lsc.widthSizeInner.dimeVal == nil) + if (lsc.widthSizeInner.dimeVal == nil) { CGFloat leadingMargin = [lsc.leadingPosInner realPosIn:rectSuper.size.width]; CGFloat trailingMargin = [lsc.trailingPosInner realPosIn:rectSuper.size.width]; @@ -2722,7 +2693,7 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize } } - if (!ssc.wrapContentHeight) + if (!ssc.heightSizeInner.dimeWrapVal) { if (lsc.heightSizeInner.dimeRelaVal.view == newSuperview) { @@ -2737,7 +2708,7 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize if (lsc.topPosInner.posVal != nil && lsc.bottomPosInner.posVal != nil) { - if (!lsc.wrapContentHeight && lsc.heightSizeInner.dimeVal == nil) + if (lsc.heightSizeInner.dimeVal == nil) { CGFloat topMargin = [lsc.topPosInner realPosIn:rectSuper.size.height]; CGFloat bottomMargin = [lsc.bottomPosInner realPosIn:rectSuper.size.height]; @@ -2785,8 +2756,6 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview //确定左右边距和宽度。 if (lsc.widthSizeInner.dimeVal != nil) { - lsc.wrapContentWidth = NO; - if (lsc.widthSizeInner.dimeRelaVal != nil) { if (lsc.widthSizeInner.dimeRelaVal.view == newSuperview) @@ -2823,7 +2792,7 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview if (lsc.leadingPosInner.posVal != nil && lsc.trailingPosInner.posVal != nil) { isAdjust = YES; - if (!lsc.wrapContentWidth && lsc.widthSizeInner.dimeVal == nil) + if (lsc.widthSizeInner.dimeVal == nil) { rectSelf.size.width = rectSuper.size.width - leadingMargin - trailingMargin; rectSelf.size.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:rectSelf.size.width sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; @@ -2881,8 +2850,6 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview if (lsc.heightSizeInner.dimeVal != nil) { - lsc.wrapContentHeight = NO; - if (lsc.heightSizeInner.dimeRelaVal != nil) { if (lsc.heightSizeInner.dimeRelaVal.view == newSuperview) @@ -2913,7 +2880,7 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview if (lsc.topPosInner.posVal != nil && lsc.bottomPosInner.posVal != nil) { isAdjust = YES; - if (!lsc.wrapContentHeight && lsc.heightSizeInner.dimeVal == nil) + if (lsc.heightSizeInner.dimeVal == nil) { rectSelf.size.height = rectSuper.size.height - topMargin - bottomMargin; rectSelf.size.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:rectSelf.size.height sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; @@ -2993,9 +2960,9 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview self.center = CGPointMake(rectSelf.origin.x + self.layer.anchorPoint.x * rectSelf.size.width * superViewZoomScale, rectSelf.origin.y + self.layer.anchorPoint.y * rectSelf.size.height * superViewZoomScale); } } - else if (lsc.wrapContentWidth || lsc.wrapContentHeight) + else if (lsc.widthSizeInner.dimeWrapVal || lsc.heightSizeInner.dimeWrapVal) { - [self setNeedsLayout]; + [self setNeedsLayout]; } @@ -3010,7 +2977,7 @@ -(CGFloat)myHeightFromFlexedHeightView:(UIView*)sbv sbvsc:(UIView*)sbvsc inWidth if ([sbv isKindOfClass:[UIImageView class]]) { //根据图片的尺寸进行等比缩放得到合适的高度。 - if (!sbvsc.wrapContentWidth) + if (!sbvsc.widthSizeInner.dimeWrapVal) { UIImage *img = ((UIImageView*)sbv).image; if (img != nil && img.size.width != 0) @@ -3078,13 +3045,6 @@ -(CGFloat)myGetBoundLimitMeasure:(MyLayoutSize*)boundDime sbv:(UIView*)sbv dimeT value = sbvSize.height; } } - else if (boundDime.dimeSelfVal != nil) - { - if (dimeType == MyGravity_Horz_Fill) - value = sbvSize.width; - else - value = sbvSize.height; - } else { if (boundDime.dimeRelaVal.dime == MyGravity_Horz_Fill) @@ -3098,6 +3058,13 @@ -(CGFloat)myGetBoundLimitMeasure:(MyLayoutSize*)boundDime sbv:(UIView*)sbv dimeT } } + else if (lValueType == MyLayoutValueType_Wrap) + { + if (dimeType == MyGravity_Horz_Fill) + value = sbvSize.width; + else + value = sbvSize.height; + } else { //约束冲突:无效的边界设置方法 @@ -3254,9 +3221,9 @@ -(CGSize)myAdjustSizeWhenNoSubviews:(CGSize)size sbs:(NSArray *)sbs lsc:(MyBaseL //如果没有子视图,并且padding不参与空子视图尺寸计算则尺寸应该扣除padding的值。 if (sbs.count == 0 && !lsc.zeroPadding) { - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) size.width -= (lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding); - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) size.height -= (lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding); } @@ -3543,21 +3510,10 @@ -(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sb if ([sbv isKindOfClass:[MyBaseLayout class]]) { - if (sbvsc.wrapContentHeight && sbvsc.heightSizeInner.dimeVal != nil) - { - sbvsc.wrapContentHeight = NO; - } - - if (sbvsc.wrapContentWidth && sbvsc.widthSizeInner.dimeVal != nil) - { - sbvsc.wrapContentWidth = NO; - } - - - if (pHasSubLayout != nil && (sbvsc.wrapContentHeight || sbvsc.wrapContentWidth)) + if (pHasSubLayout != nil && (sbvsc.heightSizeInner.dimeWrapVal || sbvsc.widthSizeInner.dimeWrapVal)) *pHasSubLayout = YES; - if (isEstimate && (sbvsc.wrapContentHeight || sbvsc.wrapContentWidth)) + if (isEstimate && (sbvsc.heightSizeInner.dimeWrapVal || sbvsc.widthSizeInner.dimeWrapVal)) { [(MyBaseLayout*)sbv sizeThatFits:sbvmyFrame.frame.size inSizeClass:sizeClass]; if (sbvmyFrame.multiple) @@ -3643,7 +3599,7 @@ -(CGFloat)myGetSubviewHeightSizeValue:(UIView *)sbv } //高度等于内容的高度,特殊处理。 - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) + if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) retVal = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:sbvSize.width]; return retVal; @@ -3693,7 +3649,7 @@ -(void)myCalcSubViewRect:(UIView*)sbv { rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) + if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; @@ -3706,7 +3662,7 @@ -(void)myCalcSubViewRect:(UIView*)sbv if (pMaxWrapSize != NULL) { - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) { //如果同时设置左右边界则左右边界为最小的宽度 if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) @@ -3716,7 +3672,7 @@ -(void)myCalcSubViewRect:(UIView*)sbv } //宽度不依赖布局并且没有同时设置左右边距则参与最大宽度计算。 - if ((sbvsc.widthSizeInner.dimeVal != nil && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) || sbvsc.wrapContentWidth) + if (sbvsc.widthSizeInner.dimeVal != nil && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) { if (_myCGFloatLess(pMaxWrapSize->width, sbvmyFrame.width + sbvsc.leadingPosInner.absVal + sbvsc.centerXPosInner.absVal + sbvsc.trailingPosInner.absVal + paddingLeading + paddingTrailing)) @@ -3733,7 +3689,7 @@ -(void)myCalcSubViewRect:(UIView*)sbv } } - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) { //如果同时设置上下边界则上下边界为最小的高度 if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) @@ -3743,7 +3699,7 @@ -(void)myCalcSubViewRect:(UIView*)sbv } //高度不依赖布局并且没有同时设置上下边距则参与最大高度计算。 - if ((sbvsc.heightSizeInner.dimeVal != nil && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) || sbvsc.wrapContentHeight) + if (sbvsc.heightSizeInner.dimeVal != nil && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) { if (_myCGFloatLess(pMaxWrapSize->height, sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.centerYPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom)) pMaxWrapSize->height = sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.centerYPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom; @@ -3771,7 +3727,7 @@ -(void)myInvalidateIntrinsicContentSize { if (!self.translatesAutoresizingMaskIntoConstraints) { - if (self.wrapContentWidth || self.wrapContentHeight) + if (self.widthSizeInner.dimeWrapVal || self.heightSizeInner.dimeWrapVal) [self invalidateIntrinsicContentSize]; } } @@ -3795,7 +3751,7 @@ -(void)myCalcSubviewsWrapContentSize:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasS if (customSetting != nil) customSetting(sbv, sbvsc); - BOOL isSbvWrap = sbvsc.wrapContentHeight || sbvsc.wrapContentWidth; + BOOL isSbvWrap = sbvsc.widthSizeInner.dimeWrapVal || sbvsc.heightSizeInner.dimeWrapVal; if (pHasSubLayout != nil && isSbvWrap) *pHasSubLayout = YES; diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index 9a78868..a5002ca 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -117,19 +117,19 @@ -(instancetype)initWithView:(UIView*)view; if (_width != CGFLOAT_MAX) { if (_width == MyLayoutSize.fill) - self->_view.widthSize.equalTo(val); + [self->_view.widthSize __equalTo:val]; else if (_width < 1 && _width > 0) - self->_view.widthSize.equalTo(val.widthSize).multiply(_width); + [[self->_view.widthSize __equalTo:val.widthSize] __multiply:_width]; else; } if (_height != CGFLOAT_MAX) { - if (_height == MyLayoutSize.fill) - self->_view.heightSize.equalTo(val); - else if (_height < 1 && _height > 0) - self->_view.heightSize.equalTo(val.heightSize).multiply(_height); - else; + if (_height == MyLayoutSize.fill) + [self->_view.heightSize __equalTo:val]; + else if (_height < 1 && _height > 0) + [[self->_view.heightSize __equalTo:val.heightSize] __multiply:_height]; + else; } [val addSubview:self->_view]; @@ -144,18 +144,14 @@ -(instancetype)initWithView:(UIView*)view; if (_width == MyLayoutSize.fill) { if (self->_view.superview) - self->_view.widthSize.equalTo(self->_view.superview); - } - else if (_width == MyLayoutSize.wrap) - { - self->_view.wrapContentWidth = YES; + [self->_view.widthSize __equalTo:self->_view.superview]; } else { if (_width < 1 && _width > 0) { if (self->_view.superview) - self->_view.widthSize.equalTo(self->_view.superview).multiply(_width); + [[self->_view.widthSize __equalTo:self->_view.superview] __multiply:_width]; } else self->_view.myWidth = _width; @@ -171,18 +167,14 @@ -(instancetype)initWithView:(UIView*)view; if (_height == MyLayoutSize.fill) { if (self->_view.superview) - self->_view.heightSize.equalTo(self->_view.superview); - } - else if (_height == MyLayoutSize.wrap) - { - self->_view.wrapContentHeight = YES; + [self->_view.heightSize __equalTo:self->_view.superview]; } else { if (_height < 1 && _height > 0) { if (self->_view.superview) - self->_view.heightSize.equalTo(self->_view.superview).multiply(_height); + [[self->_view.heightSize __equalTo:self->_view.superview] __multiply:_height]; } else self->_view.myHeight = _height; @@ -510,16 +502,16 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (lsc.orientation == MyOrientation_Vert) { if (flexItem->_flex_basis < 1) - sbvsc.widthSize.equalTo(lsc.widthSize).multiply(flexItem->_flex_basis); + [[sbvsc.widthSize __equalTo:lsc.widthSize] __multiply:flexItem->_flex_basis]; else - sbvsc.widthSize.equalTo(@(flexItem->_flex_basis)); + [sbvsc.widthSize __equalTo:@(flexItem->_flex_basis)]; } else { if (flexItem->_flex_basis < 1) - sbvsc.heightSize.equalTo(lsc.heightSize).multiply(flexItem->_flex_basis); + [[sbvsc.heightSize __equalTo:lsc.heightSize] __multiply:flexItem->_flex_basis]; else - sbvsc.heightSize.equalTo(@(flexItem->_flex_basis)); + [sbvsc.heightSize __equalTo:@(flexItem->_flex_basis)]; } } diff --git a/MyLayout/Lib/MyFloatLayout.h b/MyLayout/Lib/MyFloatLayout.h index fa9e9e4..5a97104 100644 --- a/MyLayout/Lib/MyFloatLayout.h +++ b/MyLayout/Lib/MyFloatLayout.h @@ -131,14 +131,14 @@ /** 不做布局边界尺寸的限制,子视图不会自动换行。因此当设置为YES时,子视图需要明确设置clearFloat来实现主动换行的处理。默认为NO。这个属性设置的意义使得我们可以自定义子视图的换行,而不是让子视图根据布局视图的尺寸限制自动换行。 - 1. 当布局的orientation为MyOrientation_Vert并且wrapContentWidth为YES时,这个属性设置为YES才生效。 + 1. 当布局的orientation为MyOrientation_Vert并且宽度自适应时,这个属性设置为YES才生效。 - 2. 当布局的orientation为MyOrientation_Horz并且wrapContentHeight为YES时,这个属性设置为YES才生效。 + 2. 当布局的orientation为MyOrientation_Horz并且高度自适应时,这个属性设置为YES才生效。 @note 当属性设置为YES时,子视图不能将扩展属性reverseFloat设置为YES,同时不能设置weight属性,否则将导致结果异常。 - @note 这个属性设置为YES时,在左右浮动布局中,子视图只能向左浮动,并且没有右边界的限制,因此如果子视图没有clearFloat时则总是排列在前一个子视图的右边,并不会自动换行,因此为了让这个属性生效,布局视图必须要同时设置wrapContentWidth为YES。 - @note 这个属性设置为YES时,在上下浮动布局中,子视图只能向上浮动,并且没有下边界的限制,因此如果子视图没有设置clearFloat时则总是排列在前一个子视图的下边,并不会自动换行,因此为了让这个属性生效,布局视图必须要同时设置wrapContentHeight为YES. + @note 这个属性设置为YES时,在左右浮动布局中,子视图只能向左浮动,并且没有右边界的限制,因此如果子视图没有clearFloat时则总是排列在前一个子视图的右边,并不会自动换行,因此为了让这个属性生效,布局视图必须要同时设置宽度为自适应。 + @note 这个属性设置为YES时,在上下浮动布局中,子视图只能向上浮动,并且没有下边界的限制,因此如果子视图没有设置clearFloat时则总是排列在前一个子视图的下边,并不会自动换行,因此为了让这个属性生效,布局视图必须要同时设置高度为自适应。 */ -@property(nonatomic,assign) IBInspectable BOOL noBoundaryLimit MYDEPRECATED("此属性已经过期,请直接设置布局视图的wrapContentWidth或者wrapContentHeight为YES即可"); +@property(nonatomic,assign) IBInspectable BOOL noBoundaryLimit MYDEPRECATED("此属性已经过期,请直接设置布局视图的高度或者宽度值为MyLayoutSize.wrap即可"); @end diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 36eed2c..372240d 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -95,7 +95,7 @@ -(MyOrientation)orientation -(void)setNoBoundaryLimit:(BOOL)noBoundaryLimit { - NSLog(@"属性已经过期!请直接设置wrapContentWidth或者wrapContentHeight即可"); + NSLog(@"属性已经过期!请直接设置宽度或者高度值为MyLayoutSize.wrap"); } -(BOOL)noBoundaryLimit @@ -133,22 +133,21 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( [self myCalcSubviewsWrapContentSize:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs withCustomSetting:^(UIView *sbv, UIView *sbvsc) { - if (sbvsc.wrapContentWidth) + if (sbvsc.widthSizeInner.dimeWrapVal) { - if (sbvsc.widthSizeInner.dimeVal != nil || (orientation == MyOrientation_Vert && sbvsc.weight != 0)) + if (orientation == MyOrientation_Vert && sbvsc.weight != 0) { - sbvsc.wrapContentWidth = NO; + [sbvsc.widthSizeInner __equalTo:nil]; } } - if (sbvsc.wrapContentHeight) + if (sbvsc.heightSizeInner.dimeWrapVal) { - if (sbvsc.heightSizeInner.dimeVal != nil || (orientation == MyOrientation_Horz && sbvsc.weight != 0)) + if (orientation == MyOrientation_Horz && sbvsc.weight != 0) { - sbvsc.wrapContentHeight = NO; + [sbvsc.heightSizeInner __equalTo:nil]; } } - }]; if (orientation == MyOrientation_Vert) @@ -454,7 +453,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i // CGFloat paddingVert = paddingTop + paddingBottom; //如果没有边界限制我们将高度设置为最大。。 - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) selfSize.width = CGFLOAT_MAX; @@ -509,8 +508,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i if (sbvsc.isReverseFloat) { #ifdef DEBUG - //异常崩溃:当布局视图设置了wrapContentWidth为YES时子视图不能设置逆向浮动 - NSCAssert(!lsc.wrapContentWidth, @"Constraint exception!!, vertical float layout:%@ can not set wrapContentWidth to YES when the subview:%@ set reverseFloat to YES.",self, sbv); + //异常崩溃:当布局视图设置了宽度值为MyLayoutSize.wrap时,子视图不能逆向浮动 + NSCAssert(!lsc.widthSizeInner.dimeWrapVal, @"Constraint exception!!, vertical float layout:%@ can not set width to MyLayoutSize.wrap when the subview:%@ set reverseFloat to YES.",self, sbv); #endif CGPoint nextPoint = {selfSize.width - paddingTrailing, leadingLastYOffset}; @@ -558,7 +557,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i } //特殊处理高度包裹的场景 - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) + if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) { rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; @@ -699,8 +698,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i if (sbvsc.weight != 0) { #ifdef DEBUG - //异常崩溃:当布局视图设置了wrapContentWidth为YES时子视图不能设置weight大于0 - NSCAssert(!lsc.wrapContentWidth, @"Constraint exception!!, vertical float layout:%@ can not set wrapContentWidth to YES when the subview:%@ set weight big than zero.",self, sbv); + //异常崩溃:当布局视图设置了宽度值为MyLayoutSize.wrap 子视图不能设置weight大于0 + NSCAssert(!lsc.widthSizeInner.dimeWrapVal, @"Constraint exception!!, vertical float layout:%@ can not set width to MyLayoutSize.wrap when the subview:%@ set weight big than zero.",self, sbv); #endif rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:(trailingCandidateXBoundary - nextPoint.x + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace sbvSize:rect.size selfLayoutSize:selfSize]; @@ -712,7 +711,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i } //特殊处理高度包裹的场景 - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) + if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) { rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; @@ -818,11 +817,11 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i } maxWidth += paddingTrailing; - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) selfSize.width = maxWidth; maxHeight += paddingBottom; - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) selfSize.height = maxHeight; else { @@ -907,7 +906,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i break; case MyGravity_Vert_Stretch: { - if (!sbvsc.wrapContentHeight && sbvsc.heightSizeInner.dimeVal == nil) + if (sbvsc.heightSizeInner.dimeVal == nil) sbvmyFrame.height = lineMaxHeight; } break; @@ -945,7 +944,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i CGFloat paddingVert = paddingTop + paddingBottom; //如果没有边界限制我们将高度设置为最大。。 - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) selfSize.height = CGFLOAT_MAX; //支持浮动垂直间距。 @@ -998,8 +997,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i if (sbvsc.reverseFloat) { #ifdef DEBUG - //异常崩溃:当布局视图设置了wrapContentHeight为YES时子视图不能设置逆向浮动 - NSCAssert(!lsc.wrapContentHeight, @"Constraint exception!!, horizontal float layout:%@ can not set wrapContentHeight to YES when the subview:%@ set reverseFloat to YES.",self, sbv); + //异常崩溃:当布局视图设置了高度为MyLayoutSize.wrap时子视图不能设置逆向浮动 + NSCAssert(!lsc.heightSizeInner.dimeWrapVal, @"Constraint exception!!, horizontal float layout:%@ can not set height to wrap when the subview:%@ set reverseFloat to YES.",self, sbv); #endif CGPoint nextPoint = {topLastXOffset, selfSize.height - paddingBottom}; @@ -1170,8 +1169,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i { #ifdef DEBUG - //异常崩溃:当布局视图设置了wrapContentHeight为YES时子视图不能设置weight大于0 - NSCAssert(!lsc.wrapContentHeight, @"Constraint exception!!, horizontal float layout:%@ can not set wrapContentHeight to YES when the subview:%@ set weight big than zero.",self, sbv); + //异常崩溃:当布局视图设置了高度为wrap时子视图不能设置weight大于0 + NSCAssert(!lsc.heightSizeInner.dimeWrapVal, @"Constraint exception!!, horizontal float layout:%@ can not set height to wrap when the subview:%@ set weight big than zero.",self, sbv); #endif rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:(bottomCandidateYBoundary - nextPoint.y + sbvsc.heightSizeInner.addVal) * sbvsc.weight - topSpace - bottomSpace sbvSize:rect.size selfLayoutSize:selfSize]; @@ -1278,11 +1277,11 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i } maxHeight += paddingBottom; - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) selfSize.height = maxHeight; maxWidth += paddingTrailing; - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) selfSize.width = maxWidth; else { @@ -1358,7 +1357,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i break; case MyGravity_Horz_Stretch: { - if (!sbvsc.wrapContentWidth && sbvsc.widthSizeInner == nil) + if (sbvsc.widthSizeInner.dimeVal == nil) sbvmyFrame.width = lineMaxWidth; } break; diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index f573e57..684e6e1 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -14,7 +14,7 @@ 流式布局是一种里面的子视图按照添加的顺序依次排列,当遇到某种约束限制后会另起一排再重新排列的多行多列展示的布局视图。这里的约束限制主要有数量约束限制和内容尺寸约束限制两种,排列的方向又分为垂直和水平方向,因此流式布局一共有垂直数量约束流式布局、垂直内容约束流式布局、水平数量约束流式布局、水平内容约束流式布局。流式布局主要应用于那些有规律排列的场景,在某种程度上可以作为UICollectionView的替代品,同时流式布局实现了CSS3的flexbox的几乎全部功能。 1.垂直数量约束流式布局 - orientation为MyOrientation_Vert,arrangedCount不为0,支持wrapContentHeight,支持wrapContentWidth,不支持autoArrange。 + orientation为MyOrientation_Vert,arrangedCount不为0 @code 每排数量为3的垂直数量约束流式布局 @@ -30,7 +30,7 @@ @endcode 2.垂直内容约束流式布局. - orientation为MyOrientation_Vert,arrangedCount为0,支持wrapContentHeight,支持wrapContentWidth,支持autoArrange。 + orientation为MyOrientation_Vert,arrangedCount为0 @code 垂直内容约束流式布局 => @@ -45,7 +45,7 @@ @endcode 3.水平数量约束流式布局。 - orientation为MyOrientation_Horz,arrangedCount不为0,支持wrapContentHeight,支持wrapContentWidth,不支持autoArrange。 + orientation为MyOrientation_Horz,arrangedCount不为0 @code 每排数量为3的水平数量约束流式布局 @@ -64,7 +64,7 @@ @endcode 4.水平内容约束流式布局 - orientation为MyOrientation_Horz,arrangedCount为0,支持wrapContentHeight,支持wrapContentWidth,支持autoArrange。 + orientation为MyOrientation_Horz,arrangedCount为0 @code 水平内容约束流式布局 @@ -137,9 +137,9 @@ /** - 为流式布局提供分页展示的能力,默认是0表不支持分页展示。当设置为非0时则要求必须是arrangedCount的整数倍数,表示每页的子视图的数量。而arrangedCount则表示每排内的子视图的数量。当启用pagedCount时要求将流式布局加入到UIScrollView或者其派生类中才能生效。只有数量约束流式布局才支持分页展示的功能,通过pagedCount和wrapContentHeight以及wrapContentWidth配合使用能实现不同的分页展示能力: + 为流式布局提供分页展示的能力,默认是0表不支持分页展示。当设置为非0时则要求必须是arrangedCount的整数倍数,表示每页的子视图的数量。而arrangedCount则表示每排内的子视图的数量。当启用pagedCount时要求将流式布局加入到UIScrollView或者其派生类中才能生效。只有数量约束流式布局才支持分页展示的功能,通过pagedCount和设置尺寸的高度或者宽度自适应配合使用能实现不同的分页展示能力: @note - 1. 垂直数量约束流式布局的wrapContentHeight设置为YES时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一排的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的宽度你也可以自定义),整体的分页滚动是从上到下滚动。(每页布局时从左到右再从上到下排列,新页往下滚动继续排列): + 1. 垂直数量约束流式布局的高度设置为自适应时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一排的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的宽度你也可以自定义),整体的分页滚动是从上到下滚动。(每页布局时从左到右再从上到下排列,新页往下滚动继续排列): @code 1 2 3 4 5 6 @@ -148,21 +148,21 @@ 10 11 12 @endcode - 2. 垂直数量约束流式布局的wrapContentWidth设置为YES时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一排的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的高度你也可以自定义),整体的分页滚动是从左到右滚动。(每页布局时从左到右再从上到下排列,新页往右滚动继续排列) + 2. 垂直数量约束流式布局的宽度设置为自适应时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一排的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的高度你也可以自定义),整体的分页滚动是从左到右滚动。(每页布局时从左到右再从上到下排列,新页往右滚动继续排列) @code 1 2 3 | 7 8 9 4 5 6 | 10 11 12 → @endcode - 3. 水平数量约束流式布局的wrapContentWidth设置为YES时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一排的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的高度你也可以自定义),整体的分页滚动是从左到右滚动。(每页布局时从上到下再从左到右排列,新页往右滚动继续排列) + 3. 水平数量约束流式布局的宽度设置为自适应时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一排的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的高度你也可以自定义),整体的分页滚动是从左到右滚动。(每页布局时从上到下再从左到右排列,新页往右滚动继续排列) @code 1 3 5 | 7 9 11 2 4 6 | 8 10 12 → @endcode - 4. 水平数量约束流式布局的wrapContentHeight设置为YES时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一排的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的宽度你也可以自定义),整体的分页滚动是从上到下滚动。(每页布局时从上到下再从左到右排列,新页往下滚动继续排列) + 4. 水平数量约束流式布局的高度设置为自适应时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一排的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的宽度你也可以自定义),整体的分页滚动是从上到下滚动。(每页布局时从上到下再从左到右排列,新页往下滚动继续排列) @code 1 3 5 2 4 6 diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index ae34682..8b15009 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -153,23 +153,23 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( [self myCalcSubviewsWrapContentSize:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs withCustomSetting:^(UIView *sbv, UIView *sbvsc) { - if (sbvsc.wrapContentWidth) + if (sbvsc.widthSizeInner.dimeWrapVal) { if (lsc.pagedCount > 0 || sbvsc.widthSizeInner.dimeVal != nil || (orientation == MyOrientation_Horz && (arrangedGravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill) || (orientation == MyOrientation_Vert && ((gravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill || sbvsc.weight != 0))) { - sbvsc.wrapContentWidth = NO; + [sbvsc.widthSizeInner __equalTo:nil]; } } - if (sbvsc.wrapContentHeight) + if (sbvsc.heightSizeInner.dimeWrapVal) { if (lsc.pagedCount > 0 || sbvsc.heightSizeInner.dimeVal != nil || (orientation == MyOrientation_Vert && (arrangedGravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill) || (orientation == MyOrientation_Horz && ((gravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill || sbvsc.weight != 0))) { - sbvsc.wrapContentHeight = NO; + [sbvsc.heightSizeInner __equalTo:nil]; } } @@ -473,7 +473,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo //只拉伸宽度不拉伸间距 if (horzGravity == MyGravity_Horz_Stretch) { - if (!sbvsc.wrapContentWidth && sbvsc.widthSizeInner.dimeVal == nil) + if (sbvsc.widthSizeInner.dimeVal == nil) sbvmyFrame.width += addXFill; } else @@ -510,7 +510,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo break; case MyGravity_Vert_Stretch: { - if (!sbvsc.wrapContentHeight && sbvsc.heightSizeInner.dimeVal == nil) + if (sbvsc.heightSizeInner.dimeVal == nil) { sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rowMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } @@ -686,7 +686,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa if (vertGravity == MyGravity_Vert_Stretch) { - if (!sbvsc.wrapContentHeight && sbvsc.heightSizeInner.dimeVal == nil) + if (sbvsc.heightSizeInner.dimeVal == nil) sbvmyFrame.height += addYFill; } else @@ -723,7 +723,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa break; case MyGravity_Horz_Stretch: { - if (!sbvsc.wrapContentWidth && sbvsc.widthSizeInner.dimeVal == nil) + if (sbvsc.widthSizeInner.dimeVal == nil) { sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:colMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } @@ -1016,7 +1016,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab maxWidth = place; //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的宽度和布局视图保持一致。 - if (!lsc.wrapContentWidth && (place - selfSize.width > 0.0001)) + if (!lsc.widthSizeInner.dimeWrapVal && (place - selfSize.width > 0.0001)) { xPos = paddingLeading; yPos += vertSpace; @@ -1034,7 +1034,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:selfSize.width - paddingHorz - leadingSpace - trailingSpace sbvSize:rect.size selfLayoutSize:selfSize]; //特殊处理高度包裹。 - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) + if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) { rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; @@ -1077,7 +1077,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab } //内容填充约束布局的宽度包裹计算。 - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) { selfSize.width = maxWidth; } @@ -1088,7 +1088,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) selfSize.height = yPos + paddingBottom + rowMaxHeight; else { @@ -1143,7 +1143,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab if (vertGravity == MyGravity_Vert_Stretch) { UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (!sbvsc.wrapContentHeight && sbvsc.heightSizeInner == nil) + if (sbvsc.heightSizeInner == nil) sbvmyFrame.height += fill; } else @@ -1213,7 +1213,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray NSInteger rows = lsc.pagedCount / arrangedCount; //每页的行数。 //对于垂直流式布局来说,要求要有明确的宽度。因此如果我们启用了分页又设置了宽度包裹时则我们的分页是从左到右的排列。否则分页是从上到下的排列。 - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) { isHorzPaging = YES; if (isPagingScroll) @@ -1543,7 +1543,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray maxHeight += paddingBottom; - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) { selfSize.height = maxHeight; @@ -1600,7 +1600,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (vertGravity == MyGravity_Vert_Stretch) { UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (!sbvsc.wrapContentHeight && sbvsc.heightSizeInner == nil) + if (sbvsc.heightSizeInner.dimeVal == nil) sbvmyFrame.height += fill; } else @@ -1622,7 +1622,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray } } - if (lsc.wrapContentWidth && !averageArrange) + if (lsc.widthSizeInner.dimeWrapVal && !averageArrange) { selfSize.width = maxWidth + paddingTrailing; @@ -1768,7 +1768,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab maxHeight = place; //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的宽度和布局视图保持一致。 - if (!lsc.wrapContentHeight && (place - selfSize.height > 0.0001)) + if (!lsc.heightSizeInner.dimeWrapVal && (place - selfSize.height > 0.0001)) { yPos = paddingTop; xPos += horzSpace; @@ -1817,7 +1817,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab } - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) { selfSize.height = maxHeight; } @@ -1826,7 +1826,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab [arrangeIndexSet addIndex:i - arrangedIndex]; [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) selfSize.width = xPos + paddingTrailing + colMaxWidth; else { @@ -1880,7 +1880,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab if (horzGravity == MyGravity_Horz_Stretch) { UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (!sbvsc.wrapContentWidth && sbvsc.widthSizeInner == nil) + if (sbvsc.widthSizeInner.dimeVal == nil) sbvmyFrame.width += fill; } else @@ -1950,7 +1950,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray NSInteger cols = lsc.pagedCount / arrangedCount; //每页的列数。 //对于水平流式布局来说,要求要有明确的高度。因此如果我们启用了分页又设置了高度包裹时则我们的分页是从上到下的排列。否则分页是从左到右的排列。 - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) { isVertPaging = YES; if (isPagingScroll) @@ -2260,7 +2260,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray //最后一列 [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - if (lsc.wrapContentHeight && !averageArrange) + if (lsc.heightSizeInner.dimeWrapVal && !averageArrange) { selfSize.height = maxHeight + paddingBottom; @@ -2277,7 +2277,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray maxWidth += paddingTrailing; - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) { selfSize.width = maxWidth; @@ -2335,7 +2335,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray if (horzGravity == MyGravity_Horz_Stretch) { UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (!sbvsc.wrapContentWidth && sbvsc.widthSizeInner == nil) + if (sbvsc.widthSizeInner.dimeVal == nil) sbvmyFrame.width += fill; } else diff --git a/MyLayout/Lib/MyFrameLayout.m b/MyLayout/Lib/MyFrameLayout.m index b81076f..e2581cb 100644 --- a/MyLayout/Lib/MyFrameLayout.m +++ b/MyLayout/Lib/MyFrameLayout.m @@ -44,7 +44,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( CGSize maxWrapSize = CGSizeMake(paddingLeading + paddingTrailing, paddingTop + paddingBottom); CGSize *pMaxWrapSize = &maxWrapSize; - if (!lsc.wrapContentHeight && !lsc.wrapContentWidth) + if (!lsc.heightSizeInner.dimeWrapVal && !lsc.widthSizeInner.dimeWrapVal) pMaxWrapSize = NULL; for (UIView *sbv in sbs) @@ -60,12 +60,12 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( } - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) { selfSize.width = maxWrapSize.width; } - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) { selfSize.height = maxWrapSize.height; } @@ -74,7 +74,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; //如果布局视图具有包裹属性这里要调整那些依赖父视图宽度和高度的子视图的位置和尺寸。 - if ((lsc.wrapContentWidth && horzGravity != MyGravity_Horz_Fill) || (lsc.wrapContentHeight && vertGravity != MyGravity_Vert_Fill)) + if ((lsc.widthSizeInner.dimeWrapVal && horzGravity != MyGravity_Horz_Fill) || (lsc.heightSizeInner.dimeWrapVal && vertGravity != MyGravity_Vert_Fill)) { for (UIView *sbv in sbs) { diff --git a/MyLayout/Lib/MyGridLayout.m b/MyLayout/Lib/MyGridLayout.m index 6512ef3..9768dc5 100644 --- a/MyLayout/Lib/MyGridLayout.m +++ b/MyLayout/Lib/MyGridLayout.m @@ -867,12 +867,12 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //遍历尺寸 NSInteger index = 0; CGFloat selfMeasure = [self myTraversalGridSize:lsc gridSize:selfSize lsc:lsc sbs:sbs pIndex:&index tagViewGroupIndexDict:tagKeyIndexDict tagViewGroup:nil pTagIndex:nil]; - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) { selfSize.height = selfMeasure; } - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) { selfSize.width = selfMeasure; } diff --git a/MyLayout/Lib/MyLayoutDef.h b/MyLayout/Lib/MyLayoutDef.h index c1bccce..378ea71 100644 --- a/MyLayout/Lib/MyLayoutDef.h +++ b/MyLayout/Lib/MyLayoutDef.h @@ -261,4 +261,6 @@ typedef enum : unsigned char MyLayoutValueType_Extreme, MyLayoutValueType_LayoutDimeDetach, MyLayoutValueType_Weight, + MyLayoutValueType_Wrap, + MyLayoutValueType_Fill, }MyLayoutValueType; diff --git a/MyLayout/Lib/MyLayoutPos.m b/MyLayout/Lib/MyLayoutPos.m index 666016c..ea7422a 100644 --- a/MyLayout/Lib/MyLayoutPos.m +++ b/MyLayout/Lib/MyLayoutPos.m @@ -52,7 +52,9 @@ -(id)init { return ^id(id val){ - return [self __equalTo:val]; + [self __equalTo:val]; + [self setNeedsLayout]; + return self; }; } @@ -61,7 +63,9 @@ -(id)init { return ^id(CGFloat val){ - return [self __offset:val]; + [self __offset:val]; + [self setNeedsLayout]; + return self; }; } @@ -70,7 +74,9 @@ -(id)init { return ^id(CGFloat val){ - return [self __min:val]; + [self __min:val]; + [self setNeedsLayout]; + return self; }; } @@ -79,7 +85,9 @@ -(id)init { return ^id(CGFloat val){ - return [self __max:val]; + [self __max:val]; + [self setNeedsLayout]; + return self; }; } @@ -87,7 +95,9 @@ -(id)init { return ^id(id posVal, CGFloat offset){ - return [self __lBound:posVal offsetVal:offset]; + [self __lBound:posVal offsetVal:offset]; + [self setNeedsLayout]; + return self; }; } @@ -95,7 +105,9 @@ -(id)init { return ^id(id posVal, CGFloat offset){ - return [self __uBound:posVal offsetVal:offset]; + [self __uBound:posVal offsetVal:offset]; + [self setNeedsLayout]; + return self; }; } @@ -106,58 +118,41 @@ -(id)init -(void)myClear { [self __clear]; + [self setNeedsLayout]; } -(MyLayoutPos* (^)(id val))equalTo { - return ^id(id val){ - - return [self __equalTo:val]; - }; + return self.myEqualTo; } -(MyLayoutPos* (^)(CGFloat val))offset { - return ^id(CGFloat val){ - - return [self __offset:val]; - }; + return self.myOffset; } -(MyLayoutPos* (^)(CGFloat val))min { - return ^id(CGFloat val){ - - return [self __min:val]; - }; + return self.myMin; } -(MyLayoutPos* (^)(id posVal, CGFloat offsetVal))lBound { - return ^id(id posVal, CGFloat offsetVal){ - - return [self __lBound:posVal offsetVal:offsetVal]; - }; + return self.myLBound; } -(MyLayoutPos* (^)(CGFloat val))max { - return ^id(CGFloat val){ - - return [self __max:val]; - }; + return self.myMax; } -(MyLayoutPos* (^)(id posVal, CGFloat offsetVal))uBound { - return ^id(id posVal, CGFloat offsetVal){ - - return [self __uBound:posVal offsetVal:offsetVal]; - }; + return self.myUBound; } @@ -165,7 +160,7 @@ -(void)myClear -(void)clear { - [self __clear]; + [self myClear]; } @@ -473,7 +468,6 @@ -(MyLayoutPos*)__equalTo:(id)val _posValType = MyLayoutValueType_Nil; _posVal = val; - [self setNeedsLayout]; } return self; @@ -485,7 +479,6 @@ -(MyLayoutPos*)__offset:(CGFloat)val if (_offsetVal != val) { _offsetVal = val; - [self setNeedsLayout]; } return self; @@ -497,8 +490,6 @@ -(MyLayoutPos*)__min:(CGFloat)val if (self.lBoundVal.posNumVal.doubleValue != val) { [self.lBoundVal __equalTo:@(val)]; - - [self setNeedsLayout]; } return self; @@ -509,8 +500,6 @@ -(MyLayoutPos*)__lBound:(id)posVal offsetVal:(CGFloat)offsetVal [[self.lBoundVal __equalTo:posVal] __offset:offsetVal]; - [self setNeedsLayout]; - return self; } @@ -521,7 +510,6 @@ -(MyLayoutPos*)__max:(CGFloat)val if (self.uBoundVal.posNumVal.doubleValue != val) { [self.uBoundVal __equalTo:@(val)]; - [self setNeedsLayout]; } return self; @@ -532,8 +520,6 @@ -(MyLayoutPos*)__uBound:(id)posVal offsetVal:(CGFloat)offsetVal [[self.uBoundVal __equalTo:posVal] __offset:offsetVal]; - [self setNeedsLayout]; - return self; } @@ -548,7 +534,6 @@ -(void)__clear _lBoundVal = nil; _uBoundVal = nil; _shrink = 0; - [self setNeedsLayout]; } diff --git a/MyLayout/Lib/MyLayoutSize.h b/MyLayout/Lib/MyLayoutSize.h index e4f61cb..b440008 100644 --- a/MyLayout/Lib/MyLayoutSize.h +++ b/MyLayout/Lib/MyLayoutSize.h @@ -27,23 +27,23 @@ #if UIKIT_DEFINE_AS_PROPERTIES /**特殊的尺寸,表示尺寸由子视图决定或者由内容决定。目前只用在表格布局MyTableLayout和栅格布局MyGridLayout中。*/ -@property(class, nonatomic, assign,readonly) CGFloat wrap; +@property(class, nonatomic, assign,readonly) NSInteger wrap; #else -+(CGFloat)wrap; ++(NSInteger)wrap; #endif #if UIKIT_DEFINE_AS_PROPERTIES /**特殊的尺寸,表示尺寸会填充满父视图的剩余空间。目前只用在表格布局MyTableLayout和栅格布局MyGridLayout中。*/ -@property(class, nonatomic, assign,readonly) CGFloat fill; +@property(class, nonatomic, assign,readonly) NSInteger fill; #else -+(CGFloat)fill; ++(NSInteger)fill; #endif #if UIKIT_DEFINE_AS_PROPERTIES /**特殊的尺寸,表示尺寸会均分父视图的剩余空间。目前只用在表格布局MyTableLayout */ -@property(class, nonatomic, assign,readonly) CGFloat average; +@property(class, nonatomic, assign,readonly) NSInteger average; #else -+(CGFloat)average; ++(NSInteger)average; #endif //because masonry defined macro MAS_SHORTHAND_GLOBALS. the equalTo, offset may conflict with below method. so diff --git a/MyLayout/Lib/MyLayoutSize.m b/MyLayout/Lib/MyLayoutSize.m index cd2750a..e59edf3 100644 --- a/MyLayout/Lib/MyLayoutSize.m +++ b/MyLayout/Lib/MyLayoutSize.m @@ -23,19 +23,19 @@ @implementation MyLayoutSize } -+(CGFloat)wrap ++(NSInteger)wrap { - return -1; + return -99999; //这么定义纯粹是一个数字没有其他意义 } -+(CGFloat)fill ++(NSInteger)fill { - return -2; + return -99998; //这么定义纯粹是一个数字没有其他意义 } -+(CGFloat)average ++(NSInteger)average { - return -3; + return -99997; //这么定义纯粹是一个数字没有其他意义 } @@ -54,6 +54,7 @@ -(id)init _lBoundVal = nil; _uBoundVal = nil; _shrink = 0.0; + _priority = 500; } return self; @@ -64,7 +65,9 @@ -(id)init { return ^id(id val){ - return [self __equalTo:val]; + [self __equalTo:val]; + [self setNeedsLayout]; + return self; }; } @@ -72,7 +75,9 @@ -(id)init { return ^id(CGFloat val){ - return [self __add:val]; + [self __add:val]; + [self setNeedsLayout]; + return self; }; } @@ -80,7 +85,9 @@ -(id)init { return ^id(CGFloat val){ - return [self __multiply:val]; + [self __multiply:val]; + [self setNeedsLayout]; + return self; }; } @@ -89,7 +96,9 @@ -(id)init { return ^id(CGFloat val){ - return [self __min:val]; + [self __min:val]; + [self setNeedsLayout]; + return self; }; } @@ -99,8 +108,9 @@ -(id)init return ^id(id sizeVal, CGFloat addVal, CGFloat multiVal){ - return [self __lBound:sizeVal addVal:addVal multiVal:multiVal]; - + [self __lBound:sizeVal addVal:addVal multiVal:multiVal]; + [self setNeedsLayout]; + return self; }; } @@ -108,7 +118,9 @@ -(id)init { return ^id(CGFloat val){ - return [self __max:val]; + [self __max:val]; + [self setNeedsLayout]; + return self; }; } @@ -116,81 +128,57 @@ -(id)init { return ^id(id sizeVal, CGFloat addVal, CGFloat multiVal){ - return [self __uBound:sizeVal addVal:addVal multiVal:multiVal]; + [self __uBound:sizeVal addVal:addVal multiVal:multiVal]; + [self setNeedsLayout]; + return self; }; - } -(void)myClear { [self __clear]; + [self setNeedsLayout]; } -(MyLayoutSize* (^)(id val))equalTo { - return ^id(id val){ - - return [self __equalTo:val]; - }; + return self.myEqualTo; } -(MyLayoutSize* (^)(CGFloat val))add { - return ^id(CGFloat val){ - - return [self __add:val]; - }; + return self.myAdd; } -(MyLayoutSize* (^)(CGFloat val))multiply { - return ^id(CGFloat val){ - - return [self __multiply:val]; - }; - + return self.myMultiply; } -(MyLayoutSize* (^)(CGFloat val))min { - return ^id(CGFloat val){ - - return [self __min:val]; - }; - + return self.myMin; } -(MyLayoutSize* (^)(id sizeVal, CGFloat addVal, CGFloat multiVal))lBound { - - return ^id(id sizeVal, CGFloat addVal, CGFloat multiVal){ - - return [self __lBound:sizeVal addVal:addVal multiVal:multiVal]; - - }; + return self.myLBound; } -(MyLayoutSize* (^)(CGFloat val))max { - return ^id(CGFloat val){ - - return [self __max:val]; - }; + return self.myMax; } -(MyLayoutSize* (^)(id sizeVal, CGFloat addVal, CGFloat multiVal))uBound { - return ^id(id sizeVal, CGFloat addVal, CGFloat multiVal){ - - return [self __uBound:sizeVal addVal:addVal multiVal:multiVal]; - }; - + return self.myUBound; } -(void)clear { - [self __clear]; + [self myClear]; } -(void)setActive:(BOOL)active @@ -212,16 +200,7 @@ -(CGFloat)shrink -(id)dimeVal { - if (self.isActive) - { - if (_dimeValType == MyLayoutValueType_LayoutDime && _dimeVal == nil) - return self; - - return _dimeVal; - } - else - return nil; - + return self.isActive ? _dimeVal : nil; } -(CGFloat)minVal @@ -248,12 +227,12 @@ -(id)copyWithZone:(NSZone *)zone ld->_multiVal = _multiVal; ld->_dimeVal = _dimeVal; ld->_dimeValType = _dimeValType; + ld->_priority = _priority; if (_lBoundVal != nil) { ld->_lBoundVal = [[[self class] allocWithZone:zone] init]; ld->_lBoundVal->_active = _active; [[[ld->_lBoundVal __equalTo:_lBoundVal.dimeVal] __add:_lBoundVal.addVal] __multiply:_lBoundVal.multiVal]; - } if (_uBoundVal != nil) @@ -261,7 +240,6 @@ -(id)copyWithZone:(NSZone *)zone ld->_uBoundVal = [[[self class] allocWithZone:zone] init]; ld->_uBoundVal->_active = _active; [[[ld->_uBoundVal __equalTo:_uBoundVal.dimeVal] __add:_uBoundVal.addVal] __multiply:_uBoundVal.multiVal]; - } @@ -291,8 +269,8 @@ -(MyLayoutSize*)dimeRelaVal return nil; if (_dimeValType == MyLayoutValueType_LayoutDime) return _dimeVal; - return nil; + return nil; } @@ -302,17 +280,14 @@ -(NSArray*)dimeArrVal return nil; if (_dimeValType == MyLayoutValueType_Array) return _dimeVal; - return nil; + return nil; } --(MyLayoutSize*)dimeSelfVal +-(BOOL)dimeWrapVal { - if (_dimeValType == MyLayoutValueType_LayoutDime && _dimeVal == nil && self.isActive) - return self; - - return nil; + return self.isActive && _dimeValType == MyLayoutValueType_Wrap; } @@ -353,22 +328,47 @@ -(MyLayoutSize*)uBoundValInner -(MyLayoutSize*)__equalTo:(id)val { + return [self __equalTo:val priority:500]; +} + +-(MyLayoutSize*)__equalTo:(id)val priority:(NSInteger)priority +{ + + _priority = priority; if (![_dimeVal isEqual:val]) { if ([val isKindOfClass:[NSNumber class]]) { - _dimeValType = MyLayoutValueType_NSNumber; + //特殊处理。 + if ([val integerValue] == MyLayoutSize.wrap) + { + _dimeValType = MyLayoutValueType_Wrap; + } + else if ([val integerValue] == MyLayoutSize.fill) + { + NSAssert(0, @"oops! 暂时不支持"); + } + else + { + _dimeValType = MyLayoutValueType_NSNumber; + } } else if ([val isMemberOfClass:[MyLayoutSize class]]) { - _dimeValType = MyLayoutValueType_LayoutDime; - //我们支持尺寸等于自己的情况,用来支持那些尺寸包裹内容但又想扩展尺寸的场景,为了不造成循环引用这里做特殊处理 //当尺寸等于自己时,我们只记录_dimeValType,而把值设置为nil if (val == self) { - val = nil; +#if DEBUG + NSLog(@"不建议这样设置,请使用MyLayoutSize.wrap代替!"); +#endif + _dimeValType = MyLayoutValueType_Wrap; + val = @(MyLayoutSize.wrap); + } + else + { + _dimeValType = MyLayoutValueType_LayoutDime; } } else if ([val isKindOfClass:[UIView class]]) @@ -388,7 +388,7 @@ -(MyLayoutSize*)__equalTo:(id)val NSAssert(0, @"oops!"); break; } - + } else if ([val isKindOfClass:[NSArray class]]) { @@ -403,22 +403,23 @@ -(MyLayoutSize*)__equalTo:(id)val _dimeValType = MyLayoutValueType_Nil; } - _dimeVal = val; - [self setNeedsLayout]; - } - else - { - //参考上面自己等于自己的特殊情况需要特殊处理。 - if (val == nil && _dimeVal == nil && _dimeValType == MyLayoutValueType_LayoutDime) + //特殊处理UILabel的高度是wrap的情况。 + if (_dimeValType == MyLayoutValueType_Wrap && _view != nil && _dime == MyGravity_Vert_Fill) { - _dimeValType = MyLayoutValueType_Nil; - [self setNeedsLayout]; + if([_view isKindOfClass:[UILabel class]]) + { + if (((UILabel*)_view).numberOfLines == 1) + ((UILabel*)_view).numberOfLines = 0; + } } + + _dimeVal = val; } return self; } + //加 -(MyLayoutSize*)__add:(CGFloat)val { @@ -426,7 +427,6 @@ -(MyLayoutSize*)__add:(CGFloat)val if (_addVal != val) { _addVal = val; - [self setNeedsLayout]; } return self; @@ -440,7 +440,6 @@ -(MyLayoutSize*)__multiply:(CGFloat)val if (_multiVal != val) { _multiVal = val; - [self setNeedsLayout]; } return self; @@ -453,7 +452,6 @@ -(MyLayoutSize*)__min:(CGFloat)val if (self.lBoundVal.dimeNumVal.doubleValue != val) { [self.lBoundVal __equalTo:@(val)]; - [self setNeedsLayout]; } return self; @@ -463,11 +461,14 @@ -(MyLayoutSize*)__min:(CGFloat)val -(MyLayoutSize*)__lBound:(id)sizeVal addVal:(CGFloat)addVal multiVal:(CGFloat)multiVal { if (sizeVal == self) - sizeVal = self.lBoundVal; + { +#if DEBUG + NSLog(@"不建议这样设置,请使用MyLayoutSize.wrap代替!"); +#endif + sizeVal = @(MyLayoutSize.wrap); + } [[[self.lBoundVal __equalTo:sizeVal] __add:addVal] __multiply:multiVal]; - [self setNeedsLayout]; - return self; } @@ -477,7 +478,6 @@ -(MyLayoutSize*)__max:(CGFloat)val if (self.uBoundVal.dimeNumVal.doubleValue != val) { [self.uBoundVal __equalTo:@(val)]; - [self setNeedsLayout]; } return self; @@ -486,10 +486,14 @@ -(MyLayoutSize*)__max:(CGFloat)val -(MyLayoutSize*)__uBound:(id)sizeVal addVal:(CGFloat)addVal multiVal:(CGFloat)multiVal { if (sizeVal == self) - sizeVal = self.uBoundVal; + { +#if DEBUG + NSLog(@"不建议这样设置,请使用MyLayoutSize.wrap代替!"); +#endif + sizeVal = @(MyLayoutSize.wrap); + } [[[self.uBoundVal __equalTo:sizeVal] __add:addVal] __multiply:multiVal]; - [self setNeedsLayout]; return self; } @@ -505,9 +509,8 @@ -(void)__clear _uBoundVal = nil; _dimeVal = nil; _shrink = 0; + _priority = 500; _dimeValType = MyLayoutValueType_Nil; - - [self setNeedsLayout]; } @@ -574,6 +577,9 @@ -(NSString*)description case MyLayoutValueType_NSNumber: dimeValStr = [_dimeVal description]; break; + case MyLayoutValueType_Wrap: + dimeValStr = @"wrap"; + break; case MyLayoutValueType_LayoutDime: dimeValStr = [MyLayoutSize dimestrFromDime:_dimeVal showView:YES]; break; @@ -626,7 +632,6 @@ @implementation MyLayoutSize(Detach) }; } - @end diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index 68f8ca1..5bbe571 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -14,9 +14,6 @@ @interface MyViewSizeClass() -@property(nonatomic, assign) BOOL wrapWidth; -@property(nonatomic, assign) BOOL wrapHeight; - @end @implementation MyViewSizeClass @@ -343,9 +340,6 @@ -(void)setMyVertMargin:(CGFloat)myVertMargin [self.bottomPos __equalTo:@(myVertMargin)]; } - - - -(MyLayoutSize*)widthSize { if (_widthSize == nil) @@ -353,7 +347,6 @@ -(MyLayoutSize*)widthSize _widthSize = [MyLayoutSize new]; _widthSize.view = self.view; _widthSize.dime = MyGravity_Horz_Fill; - } return _widthSize; @@ -367,7 +360,6 @@ -(MyLayoutSize*)heightSize _heightSize = [MyLayoutSize new]; _heightSize.view = self.view; _heightSize.dime = MyGravity_Vert_Fill; - } return _heightSize; @@ -418,49 +410,36 @@ -(void)setWeight:(CGFloat)weight -(BOOL)wrapContentWidth { - return self.wrapWidth; + return self.widthSizeInner.dimeWrapVal; } -(BOOL)wrapContentHeight { - return self.wrapHeight; + return self.heightSizeInner.dimeWrapVal; } -(void)setWrapContentWidth:(BOOL)wrapContentWidth { - if (self.wrapWidth != wrapContentWidth) + if (wrapContentWidth) { - self.wrapWidth = wrapContentWidth; - - if (wrapContentWidth) - { - [self.widthSize __equalTo:self.widthSize]; - } - else - { - if (self.widthSizeInner.dimeSelfVal != nil) - { - [self.widthSizeInner __equalTo:nil]; - } - } + [self.widthSize __equalTo:@(MyLayoutSize.wrap)]; + } + else + { + [self.widthSize __equalTo:nil]; } } -(void)setWrapContentHeight:(BOOL)wrapContentHeight { - if (self.wrapHeight != wrapContentHeight) + if (wrapContentHeight) { - self.wrapHeight = wrapContentHeight; - - if (wrapContentHeight) - { - if([_view isKindOfClass:[UILabel class]]) - { - if (((UILabel*)_view).numberOfLines == 1) - ((UILabel*)_view).numberOfLines = 0; - } - } + [self.heightSize __equalTo:@(MyLayoutSize.wrap)]; + } + else + { + [self.heightSize __equalTo:nil]; } } @@ -481,7 +460,7 @@ -(void)setWrapContentSize:(BOOL)wrapContentSize -(NSString*)debugDescription { - NSString*dbgDesc = [NSString stringWithFormat:@"\nView:\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\nweight=%f\nuseFrame=%@\nnoLayout=%@\nvisibility=%c\nalignment=%hu\nwrapContentWidth=%@\nwrapContentHeight=%@\nreverseFloat=%@\nclearFloat=%@", + NSString*dbgDesc = [NSString stringWithFormat:@"\nView:\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\nweight=%f\nuseFrame=%@\nnoLayout=%@\nvisibility=%c\nalignment=%hu\nreverseFloat=%@\nclearFloat=%@", self.topPosInner, self.leadingPosInner, self.bottomPosInner, @@ -495,8 +474,6 @@ -(NSString*)debugDescription self.noLayout? @"YES":@"NO", self.visibility, self.alignment, - self.wrapContentWidth ? @"YES":@"NO", - self.wrapContentHeight ? @"YES":@"NO", self.reverseFloat ? @"YES":@"NO", self.clearFloat ? @"YES":@"NO"]; @@ -511,7 +488,6 @@ - (id)copyWithZone:(NSZone *)zone { MyViewSizeClass *lsc = [[[self class] allocWithZone:zone] init]; - //这里不会复制hidden属性 lsc->_view = _view; lsc->_topPos = [self.topPosInner copy]; @@ -523,8 +499,6 @@ - (id)copyWithZone:(NSZone *)zone lsc->_baselinePos = [self.baselinePos copy]; lsc->_widthSize = [self.widthSizeInner copy]; lsc->_heightSize = [self.heightSizeInner copy]; - lsc->_wrapWidth = self.wrapWidth; - lsc->_wrapHeight = self.wrapHeight; lsc.useFrame = self.useFrame; lsc.noLayout = self.noLayout; lsc.visibility = self.visibility; @@ -533,7 +507,6 @@ - (id)copyWithZone:(NSZone *)zone lsc.reverseFloat = self.isReverseFloat; lsc.clearFloat = self.clearFloat; - return lsc; } @@ -556,25 +529,6 @@ -(id)init return self; } --(void)setWrapContentWidth:(BOOL)wrapContentWidth -{ - if (self.wrapWidth != wrapContentWidth) - { - self.wrapWidth = wrapContentWidth; - } - -} - --(void)setWrapContentHeight:(BOOL)wrapContentHeight -{ - if (self.wrapHeight != wrapContentHeight) - { - self.wrapHeight = wrapContentHeight; - } - -} - - -(UIEdgeInsets)padding { diff --git a/MyLayout/Lib/MyLayoutSizeInner.h b/MyLayout/Lib/MyLayoutSizeInner.h index 75e1a7c..12c5789 100644 --- a/MyLayout/Lib/MyLayoutSizeInner.h +++ b/MyLayout/Lib/MyLayoutSizeInner.h @@ -19,7 +19,8 @@ @property(nonatomic, readonly, strong) NSNumber *dimeNumVal; @property(nonatomic, readonly, strong) MyLayoutSize *dimeRelaVal; @property(nonatomic, readonly, strong) NSArray *dimeArrVal; -@property(nonatomic, readonly, strong) MyLayoutSize *dimeSelfVal; + +@property(nonatomic, readonly, assign) BOOL dimeWrapVal; @property(nonatomic, readonly, strong) MyLayoutSize *lBoundVal; @property(nonatomic, readonly, strong) MyLayoutSize *uBoundVal; @@ -27,9 +28,12 @@ @property(nonatomic, readonly, strong) MyLayoutSize *lBoundValInner; @property(nonatomic, readonly, strong) MyLayoutSize *uBoundValInner; +//优先级,内部使用,值是0,500, 1000 分别代表低、中、高,默认是500,这个属性先内部生效。 +@property(nonatomic, assign) NSInteger priority; -(MyLayoutSize*)__equalTo:(id)val; +-(MyLayoutSize*)__equalTo:(id)val priority:(NSInteger)priority; -(MyLayoutSize*)__add:(CGFloat)val; -(MyLayoutSize*)__multiply:(CGFloat)val; -(MyLayoutSize*)__min:(CGFloat)val; diff --git a/MyLayout/Lib/MyLinearLayout.h b/MyLayout/Lib/MyLinearLayout.h index 61ae207..61c25b9 100644 --- a/MyLayout/Lib/MyLinearLayout.h +++ b/MyLayout/Lib/MyLinearLayout.h @@ -39,7 +39,7 @@ /** 初始化一个线性布局,并指定子视图排列的方向。如果不明确指定方向则默认是建立一个垂直线性布局。 - @note 建立一个垂直线性布局时默认的wrapContentHeight设置为YES,表示高度默认由所有子视图的高度决定;而建立一个水平线性布局时默认的wrapContentWidth设置为YES,表示宽度默认由所有子视图的宽度决定。 + @note 建立一个垂直线性布局时默认的高度是自适应,表示高度默认由所有子视图的高度决定;而建立一个水平线性布局时默认的宽度是自适应,表示宽度默认由所有子视图的宽度决定。 @param orientation 布局视图内子视图的排列方向。 @return 返回线性布局对象实例。 @@ -110,22 +110,22 @@ @code MyLinearLayout *horzLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; horzLayout.myHorzMargin = 0; - horzLayout.wrapContentHeight = YES; + horzLayout.myHeight = MyLayoutSize.wrap; horzLayout.subviewSpace = 10; //二者的最小间距不能小于20 horzLayout.shrinkType = MySubviewsShrink_Auto; UILabel *A = [UILabel new]; A.text = @"xxxxxxx"; - A.widthSize.equalTo(A.widthSize); //宽度等于自身内容的宽度,必须要这么设置和 MySubviewsShrink_Auto 结合使用。 - A.wrapContentHeight = YES; //自动换行 + A.myWidth = MyLayoutSize.wrap; //宽度自适应,必须要这么设置和 MySubviewsShrink_Auto 结合使用。 + A.myHeight = MyLayoutSize.wrap; //高度自适应 A.rightPos.equalTo(@0.5); //右边间距是剩余的50% [horzLayout addSubview:A]; UILabel *B = [UILabel new]; B.text = @"XXXXXXXX"; - B.widthSize.equalTo(B.widthSize); //宽度等于自身内容的宽度,必须要这么设置和 MySubviewsShrink_Auto 结合使用。 - B.wrapContentHeight = YES; //自动换行 + B.myWidth = MyLayoutSize.wrap; //宽度自适应,必须要这么设置和 MySubviewsShrink_Auto 结合使用。 + B.myHeight = MyLayoutSize.wrap; //高度自适应 B.leftPos.equalTo(@0.5); //左边间距是剩余的50% [horzLayout addSubview:B]; @endcode diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index f828d95..a1e2b0e 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -20,9 +20,9 @@ -(instancetype)initWithFrame:(CGRect)frame orientation:(MyOrientation)orientatio { MyLinearLayout *lsc = self.myCurrentSizeClass; if (orientation == MyOrientation_Vert) - lsc.wrapContentHeight = YES; + [lsc.heightSize __equalTo:@(MyLayoutSize.wrap) priority:0]; //这是暂时先设置为低优先级。 else - lsc.wrapContentWidth = YES; + [lsc.widthSize __equalTo:@(MyLayoutSize.wrap) priority:0]; lsc.orientation = orientation; } @@ -114,7 +114,6 @@ -(void)equalizeSubviewsSpace:(BOOL)centered { [self equalizeSubviewsSpace:centered inSizeClass:MySizeClass_hAny | MySizeClass_wAny]; [self setNeedsLayout]; - } -(void)equalizeSubviewsSpace:(BOOL)centered inSizeClass:(MySizeClass)sizeClass @@ -142,31 +141,6 @@ -(void)equalizeSubviewsSpace:(BOOL)centered inSizeClass:(MySizeClass)sizeClass #pragma mark -- Override Methods -- (void)willMoveToSuperview:(UIView*)newSuperview -{ - //减少约束冲突的提示。。 - MyLinearLayout *lsc = self.myCurrentSizeClass; - - if (lsc.orientation == MyOrientation_Vert) - { - if (lsc.heightSizeInner.dimeVal != nil && lsc.wrapContentHeight) - { - lsc.wrapContentHeight = NO; - } - - } - else - { - if (lsc.widthSizeInner.dimeVal != nil && lsc.wrapContentWidth) - { - lsc.wrapContentWidth = NO; - } - - } - - [super willMoveToSuperview:newSuperview]; -} - - (void)willRemoveSubview:(UIView *)subview { [super willRemoveSubview:subview]; @@ -236,48 +210,54 @@ - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation { if (orientation == MyOrientation_Vert) { - if (sbvsc.wrapContentWidth) + if (sbvsc.widthSizeInner.dimeWrapVal) { - //只要同时设置了左右边距或者设置了宽度或者设置了子视图宽度填充则应该把wrapContentWidth置为NO - if ((sbvsc.widthSizeInner.dimeVal != nil) || - (gravity == MyGravity_Horz_Fill) - ) + //如果是拉伸处理则需要把包裹宽度取消。 + if (gravity == MyGravity_Horz_Fill) + { + [sbvsc.widthSizeInner __equalTo:nil]; + } + + //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 + if (sbvsc.widthSizeInner.priority == 0 && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) { - sbvsc.wrapContentWidth = NO; + [sbvsc.widthSizeInner __equalTo:nil]; } } - if (sbvsc.wrapContentHeight) + if (sbvsc.heightSizeInner.dimeWrapVal) { - //只要同时设置了高度或者比重属性则应该把wrapContentHeight置为NO - if ((sbvsc.heightSizeInner.dimeVal != nil) || - (sbvsc.weight != 0)) + //只要同时设置了高度或者比重属性则应该把尺寸设置为空 + if (sbvsc.weight != 0) { - sbvsc.wrapContentHeight = NO; + [sbvsc.heightSizeInner __equalTo:nil]; } } - } else { - if (sbvsc.wrapContentHeight) + if (sbvsc.heightSizeInner.dimeWrapVal) { - //只要同时设置了高度或者上下边距或者父视图的填充属性则应该把wrapContentHeight置为NO - if ((sbvsc.heightSizeInner.dimeVal != nil) || - (gravity == MyGravity_Vert_Fill) - ) + //如果是拉伸处理则需要把包裹高度 + if (gravity == MyGravity_Vert_Fill) + { + [sbvsc.heightSizeInner __equalTo:nil]; + } + + //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 + if (sbvsc.heightSizeInner.priority == 0 && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) { - sbvsc.wrapContentHeight = NO; + [sbvsc.heightSizeInner __equalTo:nil]; } } - if (sbvsc.wrapContentWidth) + if (sbvsc.widthSizeInner.dimeWrapVal) { - //只要同时设置了宽度或者比重属性则应该把wrapContentWidth置为NO - if (sbvsc.widthSizeInner.dimeVal != nil || sbvsc.weight != 0) + //只要同时设置了宽度或者比重属性则应该把宽度置空 + if (sbvsc.weight != 0) { - sbvsc.wrapContentWidth = NO; + [sbvsc.widthSizeInner __equalTo:nil]; } } } @@ -398,11 +378,11 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l canAddToNoWrapSbs = NO; //如果子视图高度是包裹的也不进行扩展 - if (sbvsc.wrapContentHeight) + if (sbvsc.heightSizeInner.dimeWrapVal) canAddToNoWrapSbs = NO; //如果子视图的最小高度就是自身则也不进行扩展。 - if (sbvsc.heightSizeInner.lBoundValInner.dimeSelfVal != nil) + if (sbvsc.heightSizeInner.lBoundValInner.dimeWrapVal) canAddToNoWrapSbs = NO; //对于尺寸拉升来说,只要设置了高度约束就都不拉升。 @@ -413,7 +393,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l [noWrapsbsSet addObject:sbv]; //在计算拉伸时,如果没有设置宽度约束则将宽度设置为0 - if (!sbvsc.wrapContentHeight && sbvsc.heightSizeInner.dimeVal == nil && sbvsc.heightSizeInner.lBoundValInner.dimeSelfVal == nil) + if (sbvsc.heightSizeInner.dimeVal == nil && !sbvsc.heightSizeInner.lBoundValInner.dimeWrapVal) rect.size.height = 0; } @@ -450,7 +430,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l if ((tempSelfWidth > maxSelfWidth) && - ((sbvsc.widthSizeInner.dimeVal != nil && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) || sbvsc.wrapContentWidth)) + (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) { maxSelfWidth = tempSelfWidth; } @@ -463,7 +443,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } //再次特殊处理高度包裹的场景 - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]) + if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) { rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; @@ -503,7 +483,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l totalShrink += sbvsc.heightSizeInner.shrink; //如果最小高度不为自身并且高度不是包裹的则可以进行缩小。 - if (sbvsc.heightSizeInner.lBoundValInner.dimeSelfVal == nil) + if (!sbvsc.heightSizeInner.lBoundValInner.dimeWrapVal) { fixedSizeHeight += rect.size.height; [fixedSizeSbs addObject:sbv]; @@ -547,7 +527,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l sbvmyFrame.frame = rect; } - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) { if (totalWeight != 0) { //在包裹高度且总体比重不为0时则,则需要还原最小的高度,这样就不会使得高度在横竖屏或者多次计算后越来高。 @@ -567,7 +547,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) { selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:maxSelfWidth + paddingLeading + paddingTrailing sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; } @@ -651,7 +631,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } //如果有浮动尺寸或者有压缩模式 - if (totalWeight != 0.0 || totalShrink != 0.0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingHeight, 0)) || vertGravity != MyGravity_None || lsc.wrapContentWidth) + if (totalWeight != 0.0 || totalShrink != 0.0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingHeight, 0)) || vertGravity != MyGravity_None || lsc.widthSizeInner.dimeWrapVal) { maxSelfWidth = 0; CGFloat between = 0; //间距扩充 @@ -783,7 +763,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l lsc:lsc]; if ((tempSelfWidth > maxSelfWidth) && - ((sbvsc.widthSizeInner.dimeVal != nil && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) || sbvsc.wrapContentWidth)) + (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) { maxSelfWidth = tempSelfWidth; } @@ -844,10 +824,10 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l pos += paddingBottom; - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) selfSize.height = pos; - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) selfSize.width = maxSelfWidth + paddingLeading + paddingTrailing; return selfSize; @@ -901,11 +881,11 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l canAddToNoWrapSbs = NO; //如果子视图宽度是包裹的也不进行扩展 - if (sbvsc.wrapContentWidth) + if (sbvsc.widthSizeInner.dimeWrapVal) canAddToNoWrapSbs = NO; //如果子视图的最小宽度就是自身则也不进行扩展。 - if (sbvsc.widthSizeInner.lBoundValInner.dimeSelfVal != nil) + if (sbvsc.widthSizeInner.lBoundValInner.dimeWrapVal) canAddToNoWrapSbs = NO; if (horzGravity == MyGravity_Horz_Stretch && sbvsc.widthSizeInner.dimeVal != nil) @@ -915,7 +895,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l [noWrapsbsSet addObject:sbv]; //在计算拉伸时,如果没有设置宽度约束则将宽度设置为0 - if (!sbvsc.wrapContentWidth && sbvsc.widthSizeInner.dimeVal == nil && sbvsc.widthSizeInner.lBoundValInner.dimeSelfVal == nil) + if (sbvsc.widthSizeInner.dimeVal == nil && !sbvsc.widthSizeInner.lBoundValInner.dimeWrapVal) rect.size.width = 0; } @@ -948,7 +928,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l lsc:lsc]; if ((tempSelfHeight > maxSelfHeight) && - ((sbvsc.heightSizeInner.dimeVal != nil && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) || sbvsc.wrapContentHeight)) + (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) { maxSelfHeight = tempSelfHeight; } @@ -1006,13 +986,13 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l totalShrink += sbvsc.widthSizeInner.shrink; //如果最小宽度不为自身并且宽度不是包裹的则可以进行缩小。 - if (sbvsc.widthSizeInner.lBoundValInner.dimeSelfVal == nil) + if (!sbvsc.widthSizeInner.lBoundValInner.dimeWrapVal) { fixedSizeWidth += rect.size.width; [fixedSizeSbs addObject:sbv]; } - if (sbvsc.widthSizeInner.dimeSelfVal != nil) + if (sbvsc.widthSizeInner.dimeWrapVal) { [flexedSizeSbs addObject:sbv]; } @@ -1056,7 +1036,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } //在包裹宽度且总体比重不为0时则,则需要还原最小的宽度,这样就不会使得宽度在横竖屏或者多次计算后越来越宽。 - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) { if (totalWeight != 0) { @@ -1076,7 +1056,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) { selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:maxSelfHeight + paddingTop + paddingBottom sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; } @@ -1203,7 +1183,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } //如果有浮动尺寸或者有压缩模式 - if (totalWeight != 0.0 || totalShrink != 0.0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingWidth, 0)) || horzGravity != MyGravity_None || lsc.wrapContentHeight) + if (totalWeight != 0.0 || totalShrink != 0.0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingWidth, 0)) || horzGravity != MyGravity_None || lsc.heightSizeInner.dimeWrapVal) { maxSelfHeight = 0; CGFloat between = 0; //间距扩充 @@ -1336,7 +1316,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l lsc:lsc]; if ((tempSelfHeight > maxSelfHeight) && - ((sbvsc.heightSizeInner.dimeVal != nil && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) || sbvsc.wrapContentHeight)) + (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) { maxSelfHeight = tempSelfHeight; } @@ -1396,10 +1376,10 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l pos += paddingTrailing; - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) selfSize.width = pos; - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) selfSize.height = maxSelfHeight + paddingTop + paddingBottom; return selfSize; @@ -1412,7 +1392,7 @@ - (CGFloat)myCalcSubviewLeadingTrailingRect:(MyGravity)horzGravity selfSize:(CGS if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { - if (sbvsc.widthSizeInner.dimeVal == nil && !sbvsc.wrapContentWidth) + if (sbvsc.widthSizeInner.dimeVal == nil) { pRect->size.width = selfSize.width - paddingLeading - paddingTrailing - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal; } @@ -1429,7 +1409,7 @@ - (CGFloat)myCalcSubviewTopBottomRect:(MyGravity)vertGravity selfSize:(CGSize)se if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { - if (sbvsc.heightSizeInner.dimeVal == nil && !sbvsc.wrapContentHeight) + if (sbvsc.heightSizeInner.dimeVal == nil) { pRect->size.height = selfSize.height - paddingTop - paddingBottom - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal; } diff --git a/MyLayout/Lib/MyPathLayout.m b/MyLayout/Lib/MyPathLayout.m index 1a43f4b..3e66ee9 100644 --- a/MyLayout/Lib/MyPathLayout.m +++ b/MyLayout/Lib/MyPathLayout.m @@ -734,12 +734,12 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( } - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) { selfSize.width = maxXPos - minXPos; } - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) { selfSize.height = maxYPos - minYPos; } diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 3ba86aa..e2b5fc7 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -37,23 +37,10 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if ([sbv isKindOfClass:[MyBaseLayout class]]) { - if (sbvsc.wrapContentWidth) - { - //只要设置了宽度则应该把wrapContentWidth置为NO - if (sbvsc.widthSizeInner.dimeVal != nil) - sbvsc.wrapContentWidth = NO; - } - - if (sbvsc.wrapContentHeight) - { - if (sbvsc.heightSizeInner.dimeVal != nil) - sbvsc.wrapContentHeight = NO; - } - - if (pHasSubLayout != nil && (sbvsc.wrapContentHeight || sbvsc.wrapContentWidth)) + if (pHasSubLayout != nil && (sbvsc.heightSizeInner.dimeWrapVal || sbvsc.widthSizeInner.dimeWrapVal)) *pHasSubLayout = YES; - if (isEstimate && (sbvsc.wrapContentWidth || sbvsc.wrapContentHeight)) + if (isEstimate && (sbvsc.widthSizeInner.dimeWrapVal || sbvsc.heightSizeInner.dimeWrapVal)) { CGSize sbvSize = sbvmyFrame.frame.size; if (sbvSize.width == CGFLOAT_MAX) @@ -76,17 +63,17 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( BOOL reCalc = NO; CGSize maxSize = [self myCalcLayout:&reCalc lsc:lsc selfSize:selfSize]; - if (lsc.wrapContentWidth || lsc.wrapContentHeight) + if (lsc.widthSizeInner.dimeWrapVal || lsc.heightSizeInner.dimeWrapVal) { if (_myCGFloatNotEqual(selfSize.height, maxSize.height) || _myCGFloatNotEqual(selfSize.width, maxSize.width)) { - if (lsc.wrapContentWidth) + if (lsc.widthSizeInner.dimeWrapVal) { selfSize.width = maxSize.width; } - if (lsc.wrapContentHeight) + if (lsc.heightSizeInner.dimeWrapVal) { selfSize.height = maxSize.height; } @@ -186,7 +173,7 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv sbvmyFrame.leading -= sbvsc.centerXPosInner.absVal; } - if (sbvmyFrame.leading < 0 && relaView == self && lsc.wrapContentWidth) + if (sbvmyFrame.leading < 0 && relaView == self && lsc.widthSizeInner.dimeWrapVal) sbvmyFrame.leading = 0; sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; @@ -195,7 +182,7 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv { sbvmyFrame.leading = (selfSize.width - lsc.myLayoutLeadingPadding - lsc.myLayoutTrailingPadding - sbvmyFrame.width) / 2 + lsc.myLayoutLeadingPadding + sbvsc.centerXPosInner.absVal; - if (sbvmyFrame.leading < 0 && lsc.wrapContentWidth) + if (sbvmyFrame.leading < 0 && lsc.widthSizeInner.dimeWrapVal) sbvmyFrame.leading = 0; sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; @@ -378,7 +365,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL sbvmyFrame.top -= sbvsc.centerYPosInner.absVal; } - if (sbvmyFrame.top < 0 && relaView == self && lsc.wrapContentHeight) + if (sbvmyFrame.top < 0 && relaView == self && lsc.heightSizeInner.dimeWrapVal) sbvmyFrame.top = 0; sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; @@ -387,7 +374,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL { sbvmyFrame.top = (selfSize.height - lsc.myLayoutTopPadding - lsc.myLayoutBottomPadding - sbvmyFrame.height) / 2 + lsc.myLayoutTopPadding + sbvsc.centerYPosInner.absVal; - if (sbvmyFrame.top < 0 && lsc.wrapContentHeight) + if (sbvmyFrame.top < 0 && lsc.heightSizeInner.dimeWrapVal) sbvmyFrame.top = 0; sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; @@ -428,7 +415,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL } else if (sbvsc.bottomPosInner.posNumVal != nil) { - if (selfSize.height == 0 && lsc.wrapContentHeight) + if (selfSize.height == 0 && lsc.heightSizeInner.dimeWrapVal) { sbvmyFrame.top = lsc.myLayoutTopPadding; sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; @@ -733,7 +720,7 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc } //只有在没有设置宽度时才计算宽度。 - if (sbvsc.widthSizeInner.dimeVal == nil && !sbvsc.wrapContentWidth) + if (sbvsc.widthSizeInner.dimeVal == nil) { sbvmyFrame.width = sbvmyFrame.trailing - sbvmyFrame.leading; sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; @@ -836,7 +823,7 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc } //只有在没有设置高度时才计算高度。 - if (sbvsc.heightSizeInner.dimeVal == nil && !sbvsc.wrapContentHeight) + if (sbvsc.heightSizeInner.dimeVal == nil) { sbvmyFrame.height = sbvmyFrame.bottom - sbvmyFrame.top; sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; @@ -858,7 +845,7 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc { sbvmyFrame.height = CGRectGetHeight(sbv.bounds); - if (sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]] && ![self myIsNoLayoutSubview:sbv]) + if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]] && ![self myIsNoLayoutSubview:sbv]) { if (sbvmyFrame.width == CGFLOAT_MAX) [self myCalcWidth:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; @@ -1237,7 +1224,7 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - BOOL sbvWrapContentHeight = sbvsc.wrapContentHeight && ![sbv isKindOfClass:[MyBaseLayout class]]; + BOOL sbvWrapContentHeight = sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]; [self myCalcSubViewLeadingTrailing:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; @@ -1254,7 +1241,7 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize continue; - if (lsc.wrapContentWidth && pRecalc != NULL) + if (lsc.widthSizeInner.dimeWrapVal && pRecalc != NULL) { //当有子视图依赖于父视图的一些设置时,需要重新进行布局(设置了右边或者中间的值,或者宽度依赖父视图) if(sbvsc.trailingPosInner.posNumVal != nil || @@ -1283,7 +1270,7 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize else if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { //如果设置有宽度则宽度参与最大!!!!!! - if (sbvsc.wrapContentWidth || sbvsc.widthSizeInner.dimeVal != nil) + if (sbvsc.widthSizeInner.dimeVal != nil) { if (_myCGFloatLess(maxWidth, sbvmyFrame.leading + sbvmyFrame.width + sbvmyFrame.trailing + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding)) { @@ -1315,7 +1302,7 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize } } - if (lsc.wrapContentHeight && pRecalc != NULL) + if (lsc.heightSizeInner.dimeWrapVal && pRecalc != NULL) { //当有子视图依赖于父视图的一些设置时,需要重新进行布局(设置了下边或者中间的值,或者高度依赖父视图) if(sbvsc.bottomPosInner.posNumVal != nil || @@ -1333,11 +1320,9 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize maxHeight = sbvsc.topPosInner.absVal + sbvsc.bottomPosInner.absVal + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding; } - - //这里加入特殊的条件sbvWrapContentHeight,因为有可能有同时设置顶部和底部位置又同时设置wrapContentHeight的情况,这种情况我们也让其加入最大高度计算行列。 + if (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != self.heightSizeInner) { - if (sbvsc.centerYPosInner.posVal != nil) { if (_myCGFloatLess(maxHeight, sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.bottomPosInner.absVal + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding)) @@ -1346,7 +1331,7 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize else if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { //如果设置有高度则高度参与最大!!!!!! - if (sbvsc.wrapContentHeight || sbvsc.heightSizeInner.dimeVal != nil) + if (sbvsc.heightSizeInner.dimeVal != nil) { if (_myCGFloatLess(maxHeight, sbvmyFrame.top + sbvmyFrame.height + sbvmyFrame.bottom + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding)) { diff --git a/MyLayout/Lib/MyTableLayout.m b/MyLayout/Lib/MyTableLayout.m index a1e4ec1..7aa88f9 100644 --- a/MyLayout/Lib/MyTableLayout.m +++ b/MyLayout/Lib/MyTableLayout.m @@ -50,9 +50,9 @@ -(instancetype)initWith:(CGFloat)rowSize colSize:(CGFloat)colSize orientation:(M else if (rowSize == MyLayoutSize.wrap) { if (orientation == MyOrientation_Horz) - lsc.wrapContentHeight = YES; + [lsc.heightSize __equalTo:@(MyLayoutSize.wrap)]; else - lsc.wrapContentWidth = YES; + [lsc.widthSize __equalTo:@(MyLayoutSize.wrap)]; } else { @@ -63,12 +63,12 @@ -(instancetype)initWith:(CGFloat)rowSize colSize:(CGFloat)colSize orientation:(M { if (orientation == MyOrientation_Horz) { - lsc.wrapContentWidth = NO; + [lsc.widthSize __equalTo:nil]; lsc.myHorzMargin = 0; } else { - lsc.wrapContentHeight = NO; + [lsc.heightSize __equalTo:nil]; lsc.myVertMargin = 0; } @@ -223,19 +223,11 @@ -(void)insertCol:(UIView*)colView atIndexPath:(NSIndexPath*)indexPath NSUInteger colCount = sColCountTag - rowView.colSize; if (rowsc.orientation == MyOrientation_Horz) { -#ifdef MY_USEPREFIXMETHOD - colsc.widthSize.myEqualTo(rowView.widthSize).myMultiply(1.0 / colCount).myAdd(-1 * rowView.subviewHSpace * (colCount - 1.0)/ colCount); -#else - colsc.widthSize.equalTo(rowView.widthSize).multiply(1.0 / colCount).add(-1 * rowView.subviewHSpace * (colCount - 1.0)/ colCount); -#endif + [[[colsc.widthSize __equalTo:rowView.widthSize] __multiply:(1.0 / colCount)] __add:-1 * rowView.subviewHSpace * (colCount - 1.0)/ colCount]; } else { -#ifdef MY_USEPREFIXMETHOD - colsc.heightSize.myEqualTo(rowView.heightSize).myMultiply(1.0 / colCount).myAdd(-1 * rowView.subviewVSpace * (colCount - 1.0)/ colCount); -#else - colsc.heightSize.equalTo(rowView.heightSize).multiply(1.0 / colCount).add(-1 * rowView.subviewVSpace * (colCount - 1.0)/ colCount); -#endif + [[[colsc.heightSize __equalTo:rowView.heightSize] __multiply:(1.0 / colCount)] __add:-1 * rowView.subviewVSpace * (colCount - 1.0)/ colCount]; } } @@ -253,7 +245,7 @@ -(void)insertCol:(UIView*)colView atIndexPath:(NSIndexPath*)indexPath { if ([colView isKindOfClass:[MyBaseLayout class]]) { - if (!colsc.wrapContentHeight) + if (!colsc.heightSizeInner.dimeWrapVal) [colsc.heightSize __equalTo:rowsc.heightSize]; } else @@ -267,16 +259,14 @@ -(void)insertCol:(UIView*)colView atIndexPath:(NSIndexPath*)indexPath if ([colView isKindOfClass:[MyBaseLayout class]]) { - if (!colsc.wrapContentWidth) + if (!colsc.widthSizeInner.dimeWrapVal) [colsc.widthSize __equalTo:rowsc.widthSize]; } else [colsc.widthSize __equalTo:rowsc.widthSize]; } - } - [rowView insertSubview:colView atIndex:indexPath.col]; } From 6e8d5aaad4b6a08b3a0fa5387301ce613adcdab4 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Fri, 20 Sep 2019 09:11:03 +0800 Subject: [PATCH 040/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 73 +++++++++++++--------------- MyLayout/Lib/MyFrameLayout.m | 4 -- MyLayout/Lib/MyLayout.h | 2 +- MyLayout/Lib/MyLayoutDef.h | 18 ------- MyLayout/Lib/MyLayoutInner.h | 2 - MyLayout/Lib/MyLayoutMath.h | 28 +++++++++++ MyLayout/Lib/MyLayoutPos.m | 2 +- MyLayout/Lib/MyLayoutPosInner.h | 8 +++ MyLayout/Lib/MyLayoutSize.h | 4 +- MyLayout/Lib/MyLayoutSize.m | 15 +++--- MyLayout/Lib/MyLayoutSizeClass.m | 70 +++++++++++--------------- MyLayout/Lib/MyLayoutSizeInner.h | 14 +++++- MyLayout/Lib/MyLinearLayout.m | 38 ++++++--------- MyLayout/Lib/MyMaker.m | 14 +++--- MyLayoutDemo/LLTest2ViewController.m | 14 ++---- 15 files changed, 152 insertions(+), 154 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index f4bea1a..4f2f671 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -280,9 +280,6 @@ -(MyLayoutSize*)heightSize -(CGFloat)myWidth { -#if DEBUG - NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); -#endif return self.myCurrentSizeClass.myWidth; } @@ -294,9 +291,6 @@ -(void)setMyWidth:(CGFloat)myWidth -(CGFloat)myHeight { -#if DEBUG - NSLog(@"%s 一般只用于设置,而不能用于获取!!", sel_getName(_cmd)); -#endif return self.myCurrentSizeClass.myHeight; } @@ -2089,7 +2083,6 @@ -(void)layoutSubviews sbv.center = CGPointMake(rc.origin.x + sbv.layer.anchorPoint.x * rc.size.width, rc.origin.y + sbv.layer.anchorPoint.y * rc.size.height); sbv.bounds = CGRectMake(sbvOldBounds.origin.x, sbvOldBounds.origin.y, rc.size.width, rc.size.height); - } } @@ -2132,14 +2125,10 @@ -(void)layoutSubviews { if (newSelfSize.width < 0) - { newSelfSize.width = 0; - } if (newSelfSize.height < 0) - { newSelfSize.height = 0; - } if (CGAffineTransformIsIdentity(self.transform)) { @@ -2261,7 +2250,6 @@ -(void)layoutSubviews if ([MyBaseLayout isRTL]) centerPonintSelf.x = rectSuper.size.width - centerPonintSelf.x; - } //如果有变化则只调整自己的center。而不变化 @@ -2269,7 +2257,6 @@ -(void)layoutSubviews { self.center = centerPonintSelf; } - } @@ -2299,7 +2286,6 @@ -(void)layoutSubviews supv.center = superCenter; supv.bounds = superBounds; } - } } @@ -2337,8 +2323,6 @@ -(void)layoutSubviews _lastScreenOrientation = currentScreenOrientation; } - - } @@ -2677,14 +2661,13 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize if (lsc.leadingPosInner.posVal != nil && lsc.trailingPosInner.posVal != nil) { - if (lsc.widthSizeInner.dimeVal == nil) + if (lsc.widthSizeInner.priority == MyPriority_Low) { CGFloat leadingMargin = [lsc.leadingPosInner realPosIn:rectSuper.size.width]; CGFloat trailingMargin = [lsc.trailingPosInner realPosIn:rectSuper.size.width]; size.width = rectSuper.size.width - leadingMargin - trailingMargin; size.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:size.width sbvSize:size selfLayoutSize:rectSuper.size]; } - } if (size.width < 0) @@ -2703,12 +2686,11 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize size.height = [lsc.heightSizeInner measureWith:rectSuper.size.width]; size.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:size.height sbvSize:size selfLayoutSize:rectSuper.size]; - } if (lsc.topPosInner.posVal != nil && lsc.bottomPosInner.posVal != nil) { - if (lsc.heightSizeInner.dimeVal == nil) + if (lsc.heightSizeInner.priority == MyPriority_Low) { CGFloat topMargin = [lsc.topPosInner realPosIn:rectSuper.size.height]; CGFloat bottomMargin = [lsc.bottomPosInner realPosIn:rectSuper.size.height]; @@ -2731,7 +2713,7 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview { - BOOL isAdjust = NO; + BOOL isAdjust = NO; //这个变量表明是否后续父视图尺寸变化后需要调整更新布局视图的尺寸。 CGRect rectSuper = newSuperview.bounds; @@ -2760,21 +2742,26 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview { if (lsc.widthSizeInner.dimeRelaVal.view == newSuperview) { + isAdjust = YES; + if (lsc.widthSizeInner.dimeRelaVal.dime == MyGravity_Horz_Fill) rectSelf.size.width = [lsc.widthSizeInner measureWith:rectSuper.size.width]; else rectSelf.size.width = [lsc.widthSizeInner measureWith:rectSuper.size.height]; - } else { rectSelf.size.width = [lsc.widthSizeInner measureWith:lsc.widthSizeInner.dimeRelaVal.view.myEstimatedWidth]; } - isAdjust = YES; } - else + else if (lsc.widthSizeInner.dimeNumVal != nil) + { rectSelf.size.width = lsc.widthSizeInner.measure; - + } + else + { + //do nothing... + } } //这里要判断自己的宽度设置了最小和最大宽度依赖于父视图的情况。如果有这种情况,则父视图在变化时也需要调整自身。 @@ -2792,8 +2779,10 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview if (lsc.leadingPosInner.posVal != nil && lsc.trailingPosInner.posVal != nil) { isAdjust = YES; - if (lsc.widthSizeInner.dimeVal == nil) + //如果是没有设置宽度约束,或者宽度约束的优先级很低都按左右边距来决定布局视图的宽度。 + if (lsc.widthSizeInner.priority == MyPriority_Low) { + [lsc.widthSizeInner __equalTo:nil]; rectSelf.size.width = rectSuper.size.width - leadingMargin - trailingMargin; rectSelf.size.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:rectSelf.size.width sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; } @@ -2854,6 +2843,7 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview { if (lsc.heightSizeInner.dimeRelaVal.view == newSuperview) { + isAdjust = YES; if (lsc.heightSizeInner.dimeRelaVal.dime == MyGravity_Vert_Fill) rectSelf.size.height = [lsc.heightSizeInner measureWith:rectSuper.size.height]; else @@ -2863,10 +2853,15 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview { rectSelf.size.height = [lsc.heightSizeInner measureWith:lsc.heightSizeInner.dimeRelaVal.view.myEstimatedHeight]; } - isAdjust = YES; } - else + else if (lsc.heightSizeInner.dimeNumVal != nil) + { rectSelf.size.height = lsc.heightSizeInner.measure; + } + else + { + // do nothing... + } } //这里要判断自己的高度设置了最小和最大高度依赖于父视图的情况。如果有这种情况,则父视图在变化时也需要调整自身。 @@ -2880,8 +2875,10 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview if (lsc.topPosInner.posVal != nil && lsc.bottomPosInner.posVal != nil) { isAdjust = YES; - if (lsc.heightSizeInner.dimeVal == nil) + //如果没有设置高度约束,或者高度约束优先级很低则按上下边距来决定布局视图高度。 + if (lsc.heightSizeInner.priority == MyPriority_Low) { + [lsc.heightSizeInner __equalTo:nil]; rectSelf.size.height = rectSuper.size.height - topMargin - bottomMargin; rectSelf.size.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:rectSelf.size.height sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; } @@ -2965,10 +2962,8 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview [self setNeedsLayout]; } - - - return isAdjust; + return isAdjust; } -(CGFloat)myHeightFromFlexedHeightView:(UIView*)sbv sbvsc:(UIView*)sbvsc inWidth:(CGFloat)width @@ -3001,7 +2996,9 @@ -(CGFloat)myHeightFromFlexedHeightView:(UIView*)sbv sbvsc:(UIView*)sbvsc inWidth } } else - ; + { + // do nothing... + } if (sbvsc.heightSizeInner == nil) return h; @@ -3509,6 +3506,11 @@ -(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sb if ([sbv isKindOfClass:[MyBaseLayout class]]) { + if (sbvsc.widthSizeInner.priority == MyPriority_Low && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) + [sbvsc.widthSizeInner __equalTo:nil]; + + if (sbvsc.heightSizeInner.priority == MyPriority_Low && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) + [sbvsc.heightSizeInner __equalTo:nil]; if (pHasSubLayout != nil && (sbvsc.heightSizeInner.dimeWrapVal || sbvsc.widthSizeInner.dimeWrapVal)) *pHasSubLayout = YES; @@ -3541,7 +3543,6 @@ -(CGFloat)myGetSubviewWidthSizeValue:(UIView *)sbv if (sbvWidthSizeInner.dimeNumVal != nil) {//宽度等于固定的值。 - retVal = sbvWidthSizeInner.measure; } else if (sbvWidthSizeInner.dimeRelaVal != nil && sbvWidthSizeInner.dimeRelaVal.view != sbv) @@ -3574,11 +3575,8 @@ -(CGFloat)myGetSubviewHeightSizeValue:(UIView *)sbv sbvSize:(CGSize)sbvSize { CGFloat retVal = sbvSize.height; - - MyLayoutSize *sbvHeightSizeInner = sbvsc.heightSizeInner; - if (sbvHeightSizeInner.dimeNumVal != nil) {//高度等于固定的值。 retVal = sbvHeightSizeInner.measure; @@ -3655,7 +3653,6 @@ -(void)myCalcSubViewRect:(UIView*)sbv rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; [self myCalcVertGravity:[self myGetSubviewVertGravity:sbv sbvsc:sbvsc vertGravity:vertGravity] sbv:sbv sbvsc:sbvsc paddingTop:paddingTop paddingBottom:paddingBottom baselinePos:CGFLOAT_MAX selfSize:selfSize pRect:&rect]; - } sbvmyFrame.frame = rect; diff --git a/MyLayout/Lib/MyFrameLayout.m b/MyLayout/Lib/MyFrameLayout.m index e2581cb..d87ca0a 100644 --- a/MyLayout/Lib/MyFrameLayout.m +++ b/MyLayout/Lib/MyFrameLayout.m @@ -52,12 +52,10 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - [self myAdjustSubviewWrapContentSet:sbv isEstimate:isEstimate sbvmyFrame:sbvmyFrame sbvsc:sbvsc selfSize:selfSize sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; //计算自己的位置和高宽 [self myCalcSubViewRect:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame lsc:lsc vertGravity:vertGravity horzGravity:horzGravity inSelfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:pMaxWrapSize]; - } if (lsc.widthSizeInner.dimeWrapVal) @@ -93,7 +91,6 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( { [self myCalcSubViewRect:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame lsc:lsc vertGravity:vertGravity horzGravity:horzGravity inSelfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:NULL]; } - } } @@ -104,7 +101,6 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( [self myAdjustSubviewsRTLPos:sbs selfWidth:selfSize.width]; return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs lsc:lsc]; - } -(id)createSizeClassInstance diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index d405f8c..dc0ed55 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -37,7 +37,7 @@ */ -//Current version is 1.8.0, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.9.0, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. #ifndef MyLayout_MyLayout_h diff --git a/MyLayout/Lib/MyLayoutDef.h b/MyLayout/Lib/MyLayoutDef.h index 378ea71..7a2535b 100644 --- a/MyLayout/Lib/MyLayoutDef.h +++ b/MyLayout/Lib/MyLayoutDef.h @@ -246,21 +246,3 @@ typedef enum : unsigned char{ MySizeClass_Portrait = 0x40, //竖屏 MySizeClass_Landscape = 0x80, //横屏,注意横屏和竖屏不支持 | 运算操作,只能指定一个。 }MySizeClass; - - -//内部使用 -typedef enum : unsigned char -{ - MyLayoutValueType_Nil, - MyLayoutValueType_NSNumber, - MyLayoutValueType_LayoutDime, - MyLayoutValueType_LayoutPos, - MyLayoutValueType_Array, - MyLayoutValueType_UILayoutSupport, - MyLayoutValueType_SafeArea, - MyLayoutValueType_Extreme, - MyLayoutValueType_LayoutDimeDetach, - MyLayoutValueType_Weight, - MyLayoutValueType_Wrap, - MyLayoutValueType_Fill, -}MyLayoutValueType; diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index 67c04d0..25dab99 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -223,6 +223,4 @@ @property(nonatomic, readonly) CGFloat myEstimatedWidth; @property(nonatomic, readonly) CGFloat myEstimatedHeight; - - @end diff --git a/MyLayout/Lib/MyLayoutMath.h b/MyLayout/Lib/MyLayoutMath.h index 89c9279..5c498b6 100644 --- a/MyLayout/Lib/MyLayoutMath.h +++ b/MyLayout/Lib/MyLayoutMath.h @@ -35,3 +35,31 @@ extern CGFloat _myCGFloatMin(CGFloat a, CGFloat b); //a*b + c extern CGFloat _myCGFloatFma(CGFloat a, CGFloat b, CGFloat c); + + +/** + * 定义优先级 + */ +typedef enum : short { + MyPriority_Low = 0, + MyPriority_Normal = 500, //默认值。 + MyPriority_High = 1000, +}MyPriority; + + +//内部使用先放在这里。后续再移到合适位置。 +typedef enum : unsigned char +{ + MyLayoutValueType_Nil, + MyLayoutValueType_NSNumber, + MyLayoutValueType_LayoutDime, + MyLayoutValueType_LayoutPos, + MyLayoutValueType_Array, + MyLayoutValueType_UILayoutSupport, + MyLayoutValueType_SafeArea, + MyLayoutValueType_Extreme, + MyLayoutValueType_LayoutDimeDetach, + MyLayoutValueType_Weight, + MyLayoutValueType_Wrap, + MyLayoutValueType_Fill, +}MyLayoutValueType; diff --git a/MyLayout/Lib/MyLayoutPos.m b/MyLayout/Lib/MyLayoutPos.m index ea7422a..b05a7b7 100644 --- a/MyLayout/Lib/MyLayoutPos.m +++ b/MyLayout/Lib/MyLayoutPos.m @@ -9,7 +9,7 @@ #import "MyLayoutPos.h" #import "MyLayoutPosInner.h" #import "MyBaseLayout.h" -#import "MyLayoutMath.h" +#import "MyLayoutInner.h" diff --git a/MyLayout/Lib/MyLayoutPosInner.h b/MyLayout/Lib/MyLayoutPosInner.h index a25b432..a483495 100644 --- a/MyLayout/Lib/MyLayoutPosInner.h +++ b/MyLayout/Lib/MyLayoutPosInner.h @@ -7,6 +7,7 @@ // #import "MyLayoutPos.h" +#import "MyLayoutMath.h" //布局位置内部定义 @@ -27,6 +28,13 @@ @property(nonatomic, readonly, strong) MyLayoutPos *uBoundValInner; +-(MyLayoutPos* (^)(id val))myEqualTo; +-(MyLayoutPos* (^)(CGFloat val))myOffset; +-(MyLayoutPos* (^)(CGFloat val))myMin; +-(MyLayoutPos* (^)(id posVal, CGFloat offset))myLBound; +-(MyLayoutPos* (^)(CGFloat val))myMax; +-(MyLayoutPos* (^)(id posVal, CGFloat offset))myUBound; +-(void)myClear; -(MyLayoutPos*)__equalTo:(id)val; -(MyLayoutPos*)__offset:(CGFloat)val; diff --git a/MyLayout/Lib/MyLayoutSize.h b/MyLayout/Lib/MyLayoutSize.h index b440008..6dcd67f 100644 --- a/MyLayout/Lib/MyLayoutSize.h +++ b/MyLayout/Lib/MyLayoutSize.h @@ -59,7 +59,6 @@ -(MyLayoutSize* (^)(id sizeVal, CGFloat addVal, CGFloat multiVal))myUBound; -(void)myClear; - #else @@ -216,6 +215,9 @@ @property(nonatomic, assign, readonly) CGFloat minVal; @property(nonatomic, assign, readonly) CGFloat maxVal; +//判断尺寸值是否是包裹自适应 +@property(nonatomic, assign, readonly) BOOL isWrap; + @end diff --git a/MyLayout/Lib/MyLayoutSize.m b/MyLayout/Lib/MyLayoutSize.m index e59edf3..6527374 100644 --- a/MyLayout/Lib/MyLayoutSize.m +++ b/MyLayout/Lib/MyLayoutSize.m @@ -10,7 +10,6 @@ #import "MyLayoutSizeInner.h" #import "MyBaseLayout.h" #import "MyLayoutInner.h" -#import "MyLayoutMath.h" @implementation MyLayoutSize @@ -54,7 +53,7 @@ -(id)init _lBoundVal = nil; _uBoundVal = nil; _shrink = 0.0; - _priority = 500; + _priority = MyPriority_Normal; } return self; @@ -213,6 +212,11 @@ -(CGFloat)maxVal return (self.isActive && _uBoundVal != nil) ? _uBoundVal.dimeNumVal.doubleValue : CGFLOAT_MAX; } +-(BOOL)isWrap +{ + return [self dimeWrapVal]; +} + #pragma mark -- NSCopying @@ -325,10 +329,9 @@ -(MyLayoutSize*)uBoundValInner return _uBoundVal; } - -(MyLayoutSize*)__equalTo:(id)val { - return [self __equalTo:val priority:500]; + return [self __equalTo:val priority:MyPriority_Normal]; } -(MyLayoutSize*)__equalTo:(id)val priority:(NSInteger)priority @@ -509,7 +512,7 @@ -(void)__clear _uBoundVal = nil; _dimeVal = nil; _shrink = 0; - _priority = 500; + _priority = MyPriority_Normal; _dimeValType = MyLayoutValueType_Nil; } @@ -535,7 +538,6 @@ -(void)setNeedsLayout if (!lb.isMyLayouting) [_view.superview setNeedsLayout]; } - } @@ -717,5 +719,4 @@ -(MyLayoutExtremeSize *)myMaxSize return [[MyLayoutExtremeSize alloc] initWith:self isMax:YES]; } - @end diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index 5bbe571..8962ccd 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -209,7 +209,7 @@ -(CGFloat)myTop -(void)setMyTop:(CGFloat)myTop { - [self.topPos __equalTo:@(myTop)]; + self.topPos.myEqualTo(@(myTop)); } @@ -220,7 +220,7 @@ -(CGFloat)myLeading -(void)setMyLeading:(CGFloat)myLeading { - [self.leadingPos __equalTo:@(myLeading)]; + self.leadingPos.myEqualTo(@(myLeading)); } @@ -231,7 +231,7 @@ -(CGFloat)myBottom -(void)setMyBottom:(CGFloat)myBottom { - [self.bottomPos __equalTo:@(myBottom)]; + self.bottomPos.myEqualTo(@(myBottom)); } @@ -242,7 +242,7 @@ -(CGFloat)myTrailing -(void)setMyTrailing:(CGFloat)myTrailing { - [self.trailingPos __equalTo:@(myTrailing)]; + self.trailingPos.myEqualTo(@(myTrailing)); } @@ -253,7 +253,7 @@ -(CGFloat)myCenterX -(void)setMyCenterX:(CGFloat)myCenterX { - [self.centerXPos __equalTo:@(myCenterX)]; + self.centerXPos.myEqualTo(@(myCenterX)); } -(CGFloat)myCenterY @@ -263,7 +263,7 @@ -(CGFloat)myCenterY -(void)setMyCenterY:(CGFloat)myCenterY { - [self.centerYPos __equalTo:@(myCenterY)]; + self.centerYPos.myEqualTo(@(myCenterY)); } @@ -287,8 +287,7 @@ -(CGFloat)myLeft -(void)setMyLeft:(CGFloat)myLeft { - [self.leftPos __equalTo:@(myLeft)]; - + self.leftPos.myEqualTo(@(myLeft)); } -(CGFloat)myRight @@ -298,7 +297,7 @@ -(CGFloat)myRight -(void)setMyRight:(CGFloat)myRight { - [self.rightPos __equalTo:@(myRight)]; + self.rightPos.myEqualTo(@(myRight)); } @@ -311,10 +310,10 @@ -(CGFloat)myMargin -(void)setMyMargin:(CGFloat)myMargin { - [self.topPos __equalTo:@(myMargin)]; - [self.leftPos __equalTo:@(myMargin)]; - [self.rightPos __equalTo:@(myMargin)]; - [self.bottomPos __equalTo:@(myMargin)]; + self.topPos.myEqualTo(@(myMargin)); + self.leftPos.myEqualTo(@(myMargin)); + self.rightPos.myEqualTo(@(myMargin)); + self.bottomPos.myEqualTo(@(myMargin)); } @@ -325,8 +324,8 @@ -(CGFloat)myHorzMargin -(void)setMyHorzMargin:(CGFloat)myHorzMargin { - [self.leftPos __equalTo:@(myHorzMargin)]; - [self.rightPos __equalTo:@(myHorzMargin)]; + self.leftPos.myEqualTo(@(myHorzMargin)); + self.rightPos.myEqualTo(@(myHorzMargin)); } -(CGFloat)myVertMargin @@ -336,8 +335,8 @@ -(CGFloat)myVertMargin -(void)setMyVertMargin:(CGFloat)myVertMargin { - [self.topPos __equalTo:@(myVertMargin)]; - [self.bottomPos __equalTo:@(myVertMargin)]; + self.topPos.myEqualTo(@(myVertMargin)); + self.bottomPos.myEqualTo(@(myVertMargin)); } -(MyLayoutSize*)widthSize @@ -368,22 +367,29 @@ -(MyLayoutSize*)heightSize -(CGFloat)myWidth { - return self.widthSizeInner.measure; + //特殊处理设置为MyLayoutSize.wrap的返回 + if (self.widthSizeInner.dimeValType == MyLayoutValueType_Wrap) + return MyLayoutSize.wrap; + else + return self.widthSizeInner.measure; } -(void)setMyWidth:(CGFloat)width { - [self.widthSize __equalTo:@(width)]; + self.widthSize.myEqualTo(@(width)); } -(CGFloat)myHeight { - return self.heightSizeInner.measure; + if (self.heightSizeInner.dimeValType == MyLayoutValueType_Wrap) + return MyLayoutSize.wrap; + else + return self.heightSizeInner.measure; } -(void)setMyHeight:(CGFloat)height { - [self.heightSize __equalTo:@(height)]; + self.heightSize.myEqualTo(@(height)); } -(CGSize)mySize @@ -398,7 +404,6 @@ -(void)setMySize:(CGSize)mySize } - -(void)setWeight:(CGFloat)weight { if (weight < 0) @@ -420,27 +425,13 @@ -(BOOL)wrapContentHeight -(void)setWrapContentWidth:(BOOL)wrapContentWidth { - if (wrapContentWidth) - { - [self.widthSize __equalTo:@(MyLayoutSize.wrap)]; - } - else - { - [self.widthSize __equalTo:nil]; - } + self.widthSize.myEqualTo(wrapContentWidth?@(MyLayoutSize.wrap):nil); } -(void)setWrapContentHeight:(BOOL)wrapContentHeight { - if (wrapContentHeight) - { - [self.heightSize __equalTo:@(MyLayoutSize.wrap)]; - } - else - { - [self.heightSize __equalTo:nil]; - } + self.heightSize.myEqualTo(wrapContentHeight?@(MyLayoutSize.wrap):nil); } -(BOOL)wrapContentSize @@ -454,9 +445,6 @@ -(void)setWrapContentSize:(BOOL)wrapContentSize self.wrapContentWidth = self.wrapContentHeight = wrapContentSize; } - - - -(NSString*)debugDescription { diff --git a/MyLayout/Lib/MyLayoutSizeInner.h b/MyLayout/Lib/MyLayoutSizeInner.h index 12c5789..d1b5e50 100644 --- a/MyLayout/Lib/MyLayoutSizeInner.h +++ b/MyLayout/Lib/MyLayoutSizeInner.h @@ -7,6 +7,8 @@ // #import "MyLayoutSize.h" +#import "MyLayoutMath.h" + //尺寸对象内部定义 @@ -29,7 +31,17 @@ @property(nonatomic, readonly, strong) MyLayoutSize *uBoundValInner; //优先级,内部使用,值是0,500, 1000 分别代表低、中、高,默认是500,这个属性先内部生效。 -@property(nonatomic, assign) NSInteger priority; +@property(nonatomic, assign) MyPriority priority; + + +-(MyLayoutSize* (^)(id val))myEqualTo; +-(MyLayoutSize* (^)(CGFloat val))myAdd; +-(MyLayoutSize* (^)(CGFloat val))myMultiply; +-(MyLayoutSize* (^)(CGFloat val))myMin; +-(MyLayoutSize* (^)(id sizeVal, CGFloat addVal, CGFloat multiVal))myLBound; +-(MyLayoutSize* (^)(CGFloat val))myMax; +-(MyLayoutSize* (^)(id sizeVal, CGFloat addVal, CGFloat multiVal))myUBound; +-(void)myClear; -(MyLayoutSize*)__equalTo:(id)val; diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index a1e2b0e..a5495f4 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -20,9 +20,9 @@ -(instancetype)initWithFrame:(CGRect)frame orientation:(MyOrientation)orientatio { MyLinearLayout *lsc = self.myCurrentSizeClass; if (orientation == MyOrientation_Vert) - [lsc.heightSize __equalTo:@(MyLayoutSize.wrap) priority:0]; //这是暂时先设置为低优先级。 + [lsc.heightSize __equalTo:@(MyLayoutSize.wrap) priority:MyPriority_Low]; //这是暂时先设置为低优先级,为了兼容老版本。 else - [lsc.widthSize __equalTo:@(MyLayoutSize.wrap) priority:0]; + [lsc.widthSize __equalTo:@(MyLayoutSize.wrap) priority:MyPriority_Low]; lsc.orientation = orientation; } @@ -214,24 +214,18 @@ - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation { //如果是拉伸处理则需要把包裹宽度取消。 if (gravity == MyGravity_Horz_Fill) - { [sbvsc.widthSizeInner __equalTo:nil]; - } //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 - if (sbvsc.widthSizeInner.priority == 0 && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) - { + if (sbvsc.widthSizeInner.priority == MyPriority_Low && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) [sbvsc.widthSizeInner __equalTo:nil]; - } } if (sbvsc.heightSizeInner.dimeWrapVal) { //只要同时设置了高度或者比重属性则应该把尺寸设置为空 if (sbvsc.weight != 0) - { [sbvsc.heightSizeInner __equalTo:nil]; - } } } else @@ -241,24 +235,18 @@ - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation { //如果是拉伸处理则需要把包裹高度 if (gravity == MyGravity_Vert_Fill) - { [sbvsc.heightSizeInner __equalTo:nil]; - } //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 - if (sbvsc.heightSizeInner.priority == 0 && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) - { + if (sbvsc.heightSizeInner.priority == MyPriority_Low && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) [sbvsc.heightSizeInner __equalTo:nil]; - } } if (sbvsc.widthSizeInner.dimeWrapVal) { //只要同时设置了宽度或者比重属性则应该把宽度置空 if (sbvsc.weight != 0) - { [sbvsc.widthSizeInner __equalTo:nil]; - } } } } @@ -425,12 +413,11 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l lsc:lsc]; - - - - + + //左右依赖的,或者依赖父视图宽度的不参数最宽计算!! if ((tempSelfWidth > maxSelfWidth) && - (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) + (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) && + (sbvsc.leadingPosInner == nil || sbvsc.trailingPosInner == nil || sbvsc.widthSizeInner.dimeVal != nil)) { maxSelfWidth = tempSelfWidth; } @@ -763,7 +750,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l lsc:lsc]; if ((tempSelfWidth > maxSelfWidth) && - (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) + (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) && + (sbvsc.leadingPosInner == nil || sbvsc.trailingPosInner == nil || sbvsc.widthSizeInner.dimeVal != nil)) { maxSelfWidth = tempSelfWidth; } @@ -928,7 +916,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l lsc:lsc]; if ((tempSelfHeight > maxSelfHeight) && - (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) + (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) && + (sbvsc.topPosInner == nil || sbvsc.bottomPosInner == nil || sbvsc.heightSizeInner.dimeVal != nil)) { maxSelfHeight = tempSelfHeight; } @@ -1316,7 +1305,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l lsc:lsc]; if ((tempSelfHeight > maxSelfHeight) && - (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) + (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) && + (sbvsc.topPosInner == nil || sbvsc.bottomPosInner == nil || sbvsc.heightSizeInner.dimeVal != nil)) { maxSelfHeight = tempSelfHeight; } diff --git a/MyLayout/Lib/MyMaker.m b/MyLayout/Lib/MyMaker.m index 631b795..8eb7d69 100644 --- a/MyLayout/Lib/MyMaker.m +++ b/MyLayout/Lib/MyMaker.m @@ -319,37 +319,37 @@ -(MyMaker*)pagedCount id oldVal = [myView valueForKey:key]; if ([oldVal isKindOfClass:[MyLayoutPos class]]) { - [((MyLayoutPos*)oldVal) __equalTo:val]; + ((MyLayoutPos*)oldVal).myEqualTo(val); } else if ([oldVal isKindOfClass:[MyLayoutSize class]]) { - [((MyLayoutSize*)oldVal) __equalTo:val]; + ((MyLayoutSize*)oldVal).myEqualTo(val); } else [myView setValue:val forKey:key]; } else if ([val isKindOfClass:[MyLayoutPos class]]) { - [((MyLayoutPos*)[myView valueForKey:key]) __equalTo:val]; + ((MyLayoutPos*)[myView valueForKey:key]).myEqualTo(val); } else if ([val isKindOfClass:[MyLayoutSize class]]) { - [((MyLayoutSize*)[myView valueForKey:key]) __equalTo:val]; + ((MyLayoutSize*)[myView valueForKey:key]).myEqualTo(val); } else if ([val isKindOfClass:[NSArray class]]) { - [((MyLayoutSize*)[myView valueForKey:key]) __equalTo:val]; + ((MyLayoutSize*)[myView valueForKey:key]).myEqualTo(val); } else if ([val isKindOfClass:[UIView class]]) { id oldVal = [val valueForKey:key]; if ([oldVal isKindOfClass:[MyLayoutPos class]]) { - [((MyLayoutPos*)[myView valueForKey:key]) __equalTo:oldVal]; + ((MyLayoutPos*)[myView valueForKey:key]).myEqualTo(oldVal); } else if ([oldVal isKindOfClass:[MyLayoutSize class]]) { - [((MyLayoutSize*)[myView valueForKey:key]) __equalTo:oldVal]; + ((MyLayoutSize*)[myView valueForKey:key]).myEqualTo(oldVal); } else diff --git a/MyLayoutDemo/LLTest2ViewController.m b/MyLayoutDemo/LLTest2ViewController.m index 49ac203..eec64c3 100644 --- a/MyLayoutDemo/LLTest2ViewController.m +++ b/MyLayoutDemo/LLTest2ViewController.m @@ -421,8 +421,7 @@ -(void)createSection7:(MyLinearLayout*)contentLayout //下面四个属性配合一起简单的实现文本的收起和展开。 shrinkLabel.clipsToBounds = YES; //为了实现文本可缩放,需要将这个标志设置为YES,否则效果无法实现。但要慎重使用这个标志,因为如果设置YES的话会影响性能。 - shrinkLabel.myHeight = 0; //这里设置高度为0,而下面设置wrapContentHeight为YES的优先级比较高。所以当wrapContentHeight = NO时这个高度才起作用。这两个属性搭配使用非常容易实现UILabel的收起和展开 - shrinkLabel.wrapContentHeight = YES; //这个属性会控制在固定宽度下自动调整视图的高度。 + shrinkLabel.myHeight = MyLayoutSize.wrap; [contentLayout addSubview:shrinkLabel]; self.shrinkLabel = shrinkLabel; @@ -460,25 +459,22 @@ -(void)createSection8:(MyLinearLayout*)contentLayout } - - #pragma mark -- Handle Method -(void)handleLabelShrink:(UIButton*)sender { - //因为self.shrinkLabel设置了wrapContentHeight来实现动态的文本高度。因此这里可以通过这个标志来实现文本伸缩功能。 - if (self.shrinkLabel.wrapContentHeight) + //通过设置文本的高度在自适应和0之间切换来实现文本的伸缩显示功能。 + if (self.shrinkLabel.myHeight == MyLayoutSize.wrap) { - self.shrinkLabel.wrapContentHeight = NO; //当设置为NO时,视图的myHeight将起作用,这边高度就变为了0 + self.shrinkLabel.myHeight = 0; //当设置为NO时,视图的myHeight将起作用,这边高度就变为了0 } else { - self.shrinkLabel.wrapContentHeight = YES; //当设置为YES时,视图的myHeight将不起作用,这样高度就由内容包裹。 + self.shrinkLabel.myHeight = MyLayoutSize.wrap; //当设置为YES时,视图的myHeight将不起作用,这样高度就由内容包裹。 } [self.contentLayout layoutAnimationWithDuration:0.3]; - } -(void)handleHideAndShowMore:(UIButton*)sender From acb4b7068fe050cb9e652b07be9324f4a5b4bded Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Mon, 23 Sep 2019 20:13:09 +0800 Subject: [PATCH 041/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 12 +++++----- MyLayout/Lib/MyRelativeLayout.m | 28 ++++++++++++++---------- MyLayout/Lib/MyTableLayout.m | 26 ++-------------------- MyLayoutTests/MyRelativeLayoutTestCase.m | 2 +- 4 files changed, 26 insertions(+), 42 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 4f2f671..9a30bf2 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -3504,14 +3504,14 @@ -(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sb [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; } + if (sbvsc.widthSizeInner.priority == MyPriority_Low && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) + [sbvsc.widthSizeInner __equalTo:nil]; + + if (sbvsc.heightSizeInner.priority == MyPriority_Low && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) + [sbvsc.heightSizeInner __equalTo:nil]; + if ([sbv isKindOfClass:[MyBaseLayout class]]) { - if (sbvsc.widthSizeInner.priority == MyPriority_Low && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) - [sbvsc.widthSizeInner __equalTo:nil]; - - if (sbvsc.heightSizeInner.priority == MyPriority_Low && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) - [sbvsc.heightSizeInner __equalTo:nil]; - if (pHasSubLayout != nil && (sbvsc.heightSizeInner.dimeWrapVal || sbvsc.widthSizeInner.dimeWrapVal)) *pHasSubLayout = YES; diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index e2b5fc7..213302d 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -33,6 +33,20 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (!isEstimate || (pHasSubLayout != nil && (*pHasSubLayout) == YES)) [sbvmyFrame reset]; + + //只要同时设置了左右边距则把宽度值置空 + if (sbvsc.widthSizeInner.priority == MyPriority_Low && + sbvsc.leadingPosInner.posVal != nil && + sbvsc.trailingPosInner.posVal != nil) + [sbvsc.widthSizeInner __equalTo:nil]; + + + //只要同时设置了上下边距则把高度值置空 + if (sbvsc.heightSizeInner.priority == MyPriority_Low && + sbvsc.topPosInner.posVal != nil && + sbvsc.bottomPosInner.posVal != nil) + [sbvsc.heightSizeInner __equalTo:nil]; + if ([sbv isKindOfClass:[MyBaseLayout class]]) { @@ -42,12 +56,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (isEstimate && (sbvsc.widthSizeInner.dimeWrapVal || sbvsc.heightSizeInner.dimeWrapVal)) { - CGSize sbvSize = sbvmyFrame.frame.size; - if (sbvSize.width == CGFLOAT_MAX) - sbvSize.width = 0; - if (sbvSize.height == CGFLOAT_MAX) - sbvSize.height = 0; - [(MyBaseLayout*)sbv sizeThatFits:sbvSize inSizeClass:sizeClass]; + [(MyBaseLayout*)sbv sizeThatFits:sbvmyFrame.frame.size inSizeClass:sizeClass]; sbvmyFrame.leading = sbvmyFrame.trailing = sbvmyFrame.top = sbvmyFrame.bottom = CGFLOAT_MAX; @@ -1209,10 +1218,7 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize [[pos.view.topPos __equalTo:prev] __offset:pos.view.centerYPos.absVal]; prev = pos.view.bottomPos; } - } - - } //计算最大的宽度和高度 @@ -1260,7 +1266,7 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize maxWidth = sbvsc.leadingPosInner.absVal + sbvsc.trailingPosInner.absVal + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding; } - if (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != self.widthSizeInner) + if (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) { if (sbvsc.centerXPosInner.posVal != nil) { @@ -1321,7 +1327,7 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize } - if (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != self.heightSizeInner) + if (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) { if (sbvsc.centerYPosInner.posVal != nil) { diff --git a/MyLayout/Lib/MyTableLayout.m b/MyLayout/Lib/MyTableLayout.m index 7aa88f9..bea9a00 100644 --- a/MyLayout/Lib/MyTableLayout.m +++ b/MyLayout/Lib/MyTableLayout.m @@ -168,13 +168,9 @@ -(MyLinearLayout*)insertRow:(CGFloat)rowSize colSize:(CGFloat)colSize atIndex:(N MyTableRowLayout *rowView = [MyTableRowLayout rowSize:rowSize colSize:colSize orientation:ori]; if (ori == MyOrientation_Horz) - { rowView.subviewHSpace = lsc.subviewHSpace; - } else - { rowView.subviewVSpace = lsc.subviewVSpace; - } rowView.intelligentBorderline = self.intelligentBorderline; [super insertSubview:rowView atIndex:rowIndex]; return rowView; @@ -213,7 +209,6 @@ -(void)insertCol:(UIView*)colView atIndexPath:(NSIndexPath*)indexPath MyLinearLayout *rowsc = rowView.myCurrentSizeClass; UIView *colsc = colView.myCurrentSizeClass; - //colSize为0表示均分尺寸,为-1表示由子视图决定尺寸,大于0表示固定尺寸。 if (rowView.colSize == MyLayoutSize.average) { colsc.weight = 1; @@ -242,29 +237,12 @@ -(void)insertCol:(UIView*)colView atIndexPath:(NSIndexPath*)indexPath if (rowsc.orientation == MyOrientation_Horz) { if (CGRectGetHeight(colView.bounds) == 0 && colsc.heightSizeInner.dimeVal == nil) - { - if ([colView isKindOfClass:[MyBaseLayout class]]) - { - if (!colsc.heightSizeInner.dimeWrapVal) - [colsc.heightSize __equalTo:rowsc.heightSize]; - } - else - [colsc.heightSize __equalTo:rowsc.heightSize]; - } + [colsc.heightSize __equalTo:rowsc.heightSize]; } else { if (CGRectGetWidth(colView.bounds) == 0 && colsc.widthSizeInner.dimeVal == nil) - { - - if ([colView isKindOfClass:[MyBaseLayout class]]) - { - if (!colsc.widthSizeInner.dimeWrapVal) - [colsc.widthSize __equalTo:rowsc.widthSize]; - } - else - [colsc.widthSize __equalTo:rowsc.widthSize]; - } + [colsc.widthSize __equalTo:rowsc.widthSize]; } [rowView insertSubview:colView atIndex:indexPath.col]; diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index 1f6258b..54278b2 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -307,7 +307,7 @@ -(void)testWrapContentHeight2 [rootRelativeView addSubview:dateLabel]; UILabel *newsTitleLabel = [UILabel new]; - newsTitleLabel.wrapContentHeight = YES; + // newsTitleLabel.wrapContentHeight = YES; newsTitleLabel.topPos.equalTo(dateLabel.bottomPos).offset(5); newsTitleLabel.leftPos.equalTo(dateLabel.leftPos); newsTitleLabel.rightPos.equalTo(dateLabel.rightPos); From 91a014e2a6a4ebbc3ce0d5964b332f60bd8c1eb2 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Wed, 25 Sep 2019 09:47:12 +0800 Subject: [PATCH 042/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 20 +-- MyLayout/Lib/MyFloatLayout.m | 4 +- MyLayout/Lib/MyFlowLayout.m | 8 +- MyLayout/Lib/MyLayoutSize.m | 2 +- MyLayout/Lib/MyLayoutSizeClass.m | 10 +- MyLayout/Lib/MyLinearLayout.m | 13 +- MyLayout/Lib/MyRelativeLayout.m | 48 +++---- MyLayoutDemo/LLTest3ViewController.m | 26 +++- .../zh-Hans.lproj/Localizable.strings | 2 + MyLayoutTests/MyLinearLayoutTestCase.m | 121 ++++++++++++++++++ MyLayoutTests/MyRelativeLayoutTestCase.m | 2 +- 11 files changed, 203 insertions(+), 53 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 9a30bf2..fd01df2 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -2661,7 +2661,7 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize if (lsc.leadingPosInner.posVal != nil && lsc.trailingPosInner.posVal != nil) { - if (lsc.widthSizeInner.priority == MyPriority_Low) + if (lsc.widthSizeInner.priority == MyPriority_Low || lsc.widthSizeInner.dimeVal == nil) { CGFloat leadingMargin = [lsc.leadingPosInner realPosIn:rectSuper.size.width]; CGFloat trailingMargin = [lsc.trailingPosInner realPosIn:rectSuper.size.width]; @@ -2690,7 +2690,7 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize if (lsc.topPosInner.posVal != nil && lsc.bottomPosInner.posVal != nil) { - if (lsc.heightSizeInner.priority == MyPriority_Low) + if (lsc.heightSizeInner.priority == MyPriority_Low || lsc.heightSizeInner.dimeVal == nil) { CGFloat topMargin = [lsc.topPosInner realPosIn:rectSuper.size.height]; CGFloat bottomMargin = [lsc.bottomPosInner realPosIn:rectSuper.size.height]; @@ -2780,9 +2780,9 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview { isAdjust = YES; //如果是没有设置宽度约束,或者宽度约束的优先级很低都按左右边距来决定布局视图的宽度。 - if (lsc.widthSizeInner.priority == MyPriority_Low) + if (lsc.widthSizeInner.priority == MyPriority_Low || lsc.widthSizeInner.dimeVal == nil) { - [lsc.widthSizeInner __equalTo:nil]; + [lsc.widthSizeInner __clear]; rectSelf.size.width = rectSuper.size.width - leadingMargin - trailingMargin; rectSelf.size.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:rectSelf.size.width sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; } @@ -2876,9 +2876,9 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview { isAdjust = YES; //如果没有设置高度约束,或者高度约束优先级很低则按上下边距来决定布局视图高度。 - if (lsc.heightSizeInner.priority == MyPriority_Low) + if (lsc.heightSizeInner.priority == MyPriority_Low || lsc.heightSizeInner.dimeVal == nil) { - [lsc.heightSizeInner __equalTo:nil]; + [lsc.heightSizeInner __clear]; rectSelf.size.height = rectSuper.size.height - topMargin - bottomMargin; rectSelf.size.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:rectSelf.size.height sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; } @@ -3504,11 +3504,11 @@ -(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sb [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; } - if (sbvsc.widthSizeInner.priority == MyPriority_Low && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) - [sbvsc.widthSizeInner __equalTo:nil]; + if ((sbvsc.widthSizeInner.priority == MyPriority_Low || sbvsc.widthSizeInner.dimeVal == nil) && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) + [sbvsc.widthSizeInner __clear]; - if (sbvsc.heightSizeInner.priority == MyPriority_Low && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) - [sbvsc.heightSizeInner __equalTo:nil]; + if ((sbvsc.heightSizeInner.priority == MyPriority_Low || sbvsc.heightSizeInner.dimeVal == nil) && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) + [sbvsc.heightSizeInner __clear]; if ([sbv isKindOfClass:[MyBaseLayout class]]) { diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 372240d..3ba7ae9 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -137,7 +137,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( { if (orientation == MyOrientation_Vert && sbvsc.weight != 0) { - [sbvsc.widthSizeInner __equalTo:nil]; + [sbvsc.widthSizeInner __clear]; } } @@ -145,7 +145,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( { if (orientation == MyOrientation_Horz && sbvsc.weight != 0) { - [sbvsc.heightSizeInner __equalTo:nil]; + [sbvsc.heightSizeInner __clear]; } } }]; diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 8b15009..30af73c 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -155,21 +155,21 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbvsc.widthSizeInner.dimeWrapVal) { - if (lsc.pagedCount > 0 || sbvsc.widthSizeInner.dimeVal != nil || + if (lsc.pagedCount > 0 || (orientation == MyOrientation_Horz && (arrangedGravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill) || (orientation == MyOrientation_Vert && ((gravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill || sbvsc.weight != 0))) { - [sbvsc.widthSizeInner __equalTo:nil]; + [sbvsc.widthSizeInner __clear]; } } if (sbvsc.heightSizeInner.dimeWrapVal) { - if (lsc.pagedCount > 0 || sbvsc.heightSizeInner.dimeVal != nil || + if (lsc.pagedCount > 0 || (orientation == MyOrientation_Vert && (arrangedGravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill) || (orientation == MyOrientation_Horz && ((gravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill || sbvsc.weight != 0))) { - [sbvsc.heightSizeInner __equalTo:nil]; + [sbvsc.heightSizeInner __clear]; } } diff --git a/MyLayout/Lib/MyLayoutSize.m b/MyLayout/Lib/MyLayoutSize.m index 6527374..85369a0 100644 --- a/MyLayout/Lib/MyLayoutSize.m +++ b/MyLayout/Lib/MyLayoutSize.m @@ -512,7 +512,7 @@ -(void)__clear _uBoundVal = nil; _dimeVal = nil; _shrink = 0; - _priority = MyPriority_Normal; + _priority = MyPriority_Low; _dimeValType = MyLayoutValueType_Nil; } diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index 8962ccd..ba27481 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -425,13 +425,19 @@ -(BOOL)wrapContentHeight -(void)setWrapContentWidth:(BOOL)wrapContentWidth { - self.widthSize.myEqualTo(wrapContentWidth?@(MyLayoutSize.wrap):nil); + if (wrapContentWidth) + self.widthSize.myEqualTo(@(MyLayoutSize.wrap)); + else + _widthSize = nil; } -(void)setWrapContentHeight:(BOOL)wrapContentHeight { - self.heightSize.myEqualTo(wrapContentHeight?@(MyLayoutSize.wrap):nil); + if (wrapContentHeight) + self.heightSize.myEqualTo(@(MyLayoutSize.wrap)); + else + _heightSize = nil; } -(BOOL)wrapContentSize diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index a5495f4..18e73f3 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -214,18 +214,18 @@ - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation { //如果是拉伸处理则需要把包裹宽度取消。 if (gravity == MyGravity_Horz_Fill) - [sbvsc.widthSizeInner __equalTo:nil]; + [sbvsc.widthSizeInner __clear]; //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 if (sbvsc.widthSizeInner.priority == MyPriority_Low && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) - [sbvsc.widthSizeInner __equalTo:nil]; + [sbvsc.widthSizeInner __clear]; } if (sbvsc.heightSizeInner.dimeWrapVal) { //只要同时设置了高度或者比重属性则应该把尺寸设置为空 if (sbvsc.weight != 0) - [sbvsc.heightSizeInner __equalTo:nil]; + [sbvsc.heightSizeInner __clear]; } } else @@ -235,18 +235,18 @@ - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation { //如果是拉伸处理则需要把包裹高度 if (gravity == MyGravity_Vert_Fill) - [sbvsc.heightSizeInner __equalTo:nil]; + [sbvsc.heightSizeInner __clear]; //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 if (sbvsc.heightSizeInner.priority == MyPriority_Low && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) - [sbvsc.heightSizeInner __equalTo:nil]; + [sbvsc.heightSizeInner __clear]; } if (sbvsc.widthSizeInner.dimeWrapVal) { //只要同时设置了宽度或者比重属性则应该把宽度置空 if (sbvsc.weight != 0) - [sbvsc.widthSizeInner __equalTo:nil]; + [sbvsc.widthSizeInner __clear]; } } } @@ -1447,7 +1447,6 @@ -(void)myEqualizeSubviewsForVert:(BOOL)centered withSpace:(CGFloat)margin if (sbv == sbs.lastObject && centered) [sbvsc.bottomPos __equalTo:@(scale2)]; } - } -(void)myEqualizeSubviewsForHorz:(BOOL)centered withSpace:(CGFloat)space diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 213302d..983d62b 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -35,17 +35,17 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //只要同时设置了左右边距则把宽度值置空 - if (sbvsc.widthSizeInner.priority == MyPriority_Low && + if ((sbvsc.widthSizeInner.priority == MyPriority_Low || sbvsc.widthSizeInner.dimeVal == nil)&& sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) - [sbvsc.widthSizeInner __equalTo:nil]; + [sbvsc.widthSizeInner __clear]; //只要同时设置了上下边距则把高度值置空 - if (sbvsc.heightSizeInner.priority == MyPriority_Low && + if ((sbvsc.heightSizeInner.priority == MyPriority_Low || sbvsc.heightSizeInner.dimeVal == nil) && sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) - [sbvsc.heightSizeInner __equalTo:nil]; + [sbvsc.heightSizeInner __clear]; if ([sbv isKindOfClass:[MyBaseLayout class]]) @@ -1276,20 +1276,20 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize else if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { //如果设置有宽度则宽度参与最大!!!!!! - if (sbvsc.widthSizeInner.dimeVal != nil) - { - if (_myCGFloatLess(maxWidth, sbvmyFrame.leading + sbvmyFrame.width + sbvmyFrame.trailing + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding)) - { - maxWidth = sbvmyFrame.leading + sbvmyFrame.width + sbvmyFrame.trailing + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding; - } - } - else - { +// if (sbvsc.widthSizeInner.dimeVal != nil) +// { +// if (_myCGFloatLess(maxWidth, sbvmyFrame.leading + sbvmyFrame.width + sbvmyFrame.trailing + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding)) +// { +// maxWidth = sbvmyFrame.leading + sbvmyFrame.width + sbvmyFrame.trailing + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding; +// } +// } +// else +// { if (_myCGFloatLess(maxWidth, fabs(sbvmyFrame.trailing) + sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding)) { maxWidth = fabs(sbvmyFrame.trailing) + sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; } - } + //} } else if (sbvsc.trailingPosInner.posVal != nil) { @@ -1337,20 +1337,20 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize else if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { //如果设置有高度则高度参与最大!!!!!! - if (sbvsc.heightSizeInner.dimeVal != nil) - { - if (_myCGFloatLess(maxHeight, sbvmyFrame.top + sbvmyFrame.height + sbvmyFrame.bottom + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding)) - { - maxHeight = sbvmyFrame.top + sbvmyFrame.height + sbvmyFrame.bottom + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding; - } - } - else - { +// if (sbvsc.heightSizeInner.dimeVal != nil) +// { +// if (_myCGFloatLess(maxHeight, sbvmyFrame.top + sbvmyFrame.height + sbvmyFrame.bottom + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding)) +// { +// maxHeight = sbvmyFrame.top + sbvmyFrame.height + sbvmyFrame.bottom + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding; +// } +// } +// else +// { if (_myCGFloatLess(maxHeight, fabs(sbvmyFrame.bottom) + sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding)) { maxHeight = fabs(sbvmyFrame.bottom) + sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding; } - } + //} } else if (sbvsc.bottomPosInner.posVal != nil) { diff --git a/MyLayoutDemo/LLTest3ViewController.m b/MyLayoutDemo/LLTest3ViewController.m index fb89d20..bb05251 100644 --- a/MyLayoutDemo/LLTest3ViewController.m +++ b/MyLayoutDemo/LLTest3ViewController.m @@ -134,7 +134,9 @@ -(void)createVertLayoutGravityActionLayout:(MyLinearLayout*)contentLayout NSLocalizedString(@"between",@""), NSLocalizedString(@"around",@""), NSLocalizedString(@"horz fill",@""), - NSLocalizedString(@"vert fill", @"")]; + NSLocalizedString(@"vert fill", @""), + NSLocalizedString(@"horz stretch", @""), + NSLocalizedString(@"vert stretch", @"")]; for (NSInteger i = 0; i < actions.count; i++) { @@ -223,7 +225,9 @@ -(void)createHorzLayoutGravityActionLayout:(MyLinearLayout*)contentLayout NSLocalizedString(@"between",@""), NSLocalizedString(@"around",@""), NSLocalizedString(@"horz fill",@""), - NSLocalizedString(@"vert fill", @"")]; + NSLocalizedString(@"vert fill", @""), + NSLocalizedString(@"horz stretch",@""), + NSLocalizedString(@"vert stretch", @"")]; for (NSInteger i = 0; i < actions.count; i++) { @@ -343,6 +347,12 @@ -(void)handleVertLayoutGravity:(UIButton*)button case 12: //垂直填充 vertGravity = MyGravity_Vert_Fill; //这里模拟器顶部出现黑线,真机是不会出现的。。 break; + case 13: //水平拉伸 + horzGravity = MyGravity_Horz_Stretch; + break; + case 14: //垂直拉伸 + vertGravity = MyGravity_Vert_Stretch; //这里模拟器顶部出现黑线,真机是不会出现的。。 + break; default: break; } @@ -399,6 +409,12 @@ -(void)handleHorzLayoutGravity:(UIButton*)button case 12: vertGravity = MyGravity_Vert_Fill; break; + case 13: //水平拉伸 + horzGravity = MyGravity_Horz_Stretch; + break; + case 14: //垂直拉伸 + vertGravity = MyGravity_Vert_Stretch; + break; default: break; } @@ -478,6 +494,9 @@ -(NSString*)gravityText:(MyGravity)gravity prefixText:(NSString*)prefixText case MyGravity_Vert_Fill: vertGravityStr = @"MyGravity_Vert_Fill"; break; + case MyGravity_Vert_Stretch: + vertGravityStr = @"MyGravity_Vert_Stretch"; + break; case MyGravity_Vert_Between: vertGravityStr = @"MyGravity_Vert_Between"; break; @@ -506,6 +525,9 @@ -(NSString*)gravityText:(MyGravity)gravity prefixText:(NSString*)prefixText case MyGravity_Horz_Fill: horzGravityStr = @"MyGravity_Horz_Fill"; break; + case MyGravity_Horz_Stretch: + horzGravityStr = @"MyGravity_Horz_Stretch"; + break; case MyGravity_Horz_Between: horzGravityStr = @"MyGravity_Horz_Between"; break; diff --git a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings index 26788f5..fd53e74 100644 --- a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings +++ b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings @@ -103,6 +103,8 @@ "right" = "右停靠"; "horz fill"="水平填充"; "vert fill"="垂直填充"; +"horz stretch"="水平拉伸"; +"vert stretch"="垂直拉伸"; "screen vert center" = "屏幕垂直居中"; "screen horz center" ="屏幕水平居中"; "space" = "间距调整"; diff --git a/MyLayoutTests/MyLinearLayoutTestCase.m b/MyLayoutTests/MyLinearLayoutTestCase.m index 6e4c76a..6cca28e 100644 --- a/MyLayoutTests/MyLinearLayoutTestCase.m +++ b/MyLayoutTests/MyLinearLayoutTestCase.m @@ -698,6 +698,127 @@ -(void)testFillAndStretch +} + +-(void)testequalizeSubviews +{ + //测试均分视图的能力。 + { + MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + rootLayout.heightSize.equalTo(@300); + rootLayout.frame = CGRectMake(0, 0, 100, 300); + rootLayout.gravity = MyGravity_Horz_Fill; + + UIView *v1 = [UIView new]; + v1.myHeight = 10; + UIView *v2 = [UIView new]; + v2.myHeight = 10; + UIView *v3 = [UIView new]; + v3.myHeight = 10; + + [rootLayout addSubview:v1]; + [rootLayout addSubview:v2]; + [rootLayout addSubview:v3]; + + [rootLayout equalizeSubviews:YES]; + [rootLayout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,43,100,43)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,129,100,43)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(0,215,100,43)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + + [rootLayout equalizeSubviews:NO]; + [rootLayout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,0,100,60)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,120,100,60)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(0,240,100,60)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + + [rootLayout equalizeSubviewsSpace:YES]; + [rootLayout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,67.5,100,10)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,67.5+10+67.5,100,10)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(0,67.5*3+10*2,100,10)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + [rootLayout equalizeSubviewsSpace:NO]; + [rootLayout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,0,100,10)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,90+10,100,10)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(0,90+10+90,100,10)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + [rootLayout equalizeSubviews:YES withSpace:10]; + [rootLayout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,10,100,86.5)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,106.5,100,86.5)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(0,203,100,86.5)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + [rootLayout equalizeSubviews:NO withSpace:10]; + [rootLayout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,0,100,93.5)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,103.5,100,93.5)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(0,207,100,93.5)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + } + + + { + MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + rootLayout.widthSize.equalTo(@300); + rootLayout.frame = CGRectMake(0, 0, 300, 100); + rootLayout.gravity = MyGravity_Vert_Fill; + + UIView *v1 = [UIView new]; + v1.myWidth = 10; + UIView *v2 = [UIView new]; + v2.myWidth = 10; + UIView *v3 = [UIView new]; + v3.myWidth = 10; + + [rootLayout addSubview:v1]; + [rootLayout addSubview:v2]; + [rootLayout addSubview:v3]; + + [rootLayout equalizeSubviews:YES]; + [rootLayout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(43,0,43,100)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(129,0,43,100)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(215,0,43,100)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + + + [rootLayout equalizeSubviews:NO]; + [rootLayout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,0,60,100)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(120,0,60,100)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(240,0,60,100)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + + [rootLayout equalizeSubviewsSpace:YES]; + [rootLayout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(67.5,0,10,100)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(67.5+10+67.5,0,10,100)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(67.5*3+10*2,0,10,100)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + [rootLayout equalizeSubviewsSpace:NO]; + [rootLayout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,0,10,100)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(90+10,0,10,100)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(90+10+90,0,10,100)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + [rootLayout equalizeSubviews:YES withSpace:10]; + [rootLayout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(10,0,86.5,100)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(106.5,0,86.5,100)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(203,0,86.5,100)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + [rootLayout equalizeSubviews:NO withSpace:10]; + [rootLayout layoutIfNeeded]; + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,0,93.5,100)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(103.5,0,93.5,100)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(207,0,93.5,100)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + } + + + } - (void)testPerformanceExample { diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index 54278b2..1f6258b 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -307,7 +307,7 @@ -(void)testWrapContentHeight2 [rootRelativeView addSubview:dateLabel]; UILabel *newsTitleLabel = [UILabel new]; - // newsTitleLabel.wrapContentHeight = YES; + newsTitleLabel.wrapContentHeight = YES; newsTitleLabel.topPos.equalTo(dateLabel.bottomPos).offset(5); newsTitleLabel.leftPos.equalTo(dateLabel.leftPos); newsTitleLabel.rightPos.equalTo(dateLabel.rightPos); From db18a5a957de48143aac996c33f556f8741abb80 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Wed, 25 Sep 2019 20:40:10 +0800 Subject: [PATCH 043/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 6 +-- MyLayout/Lib/MyFlexLayout.m | 1 + MyLayout/Lib/MyFlowLayout.h | 17 +++++++ MyLayout/Lib/MyFlowLayout.m | 70 +++++++++++++++++--------- MyLayout/Lib/MyLinearLayout.m | 16 +++--- MyLayout/Lib/MyTableLayout.m | 4 +- MyLayoutTests/MyLinearLayoutTestCase.m | 55 +++++++++++++++++--- 7 files changed, 126 insertions(+), 43 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index fd01df2..d44d5ab 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -3742,12 +3742,12 @@ -(void)myCalcSubviewsWrapContentSize:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasS [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; } + if (customSetting != nil) + customSetting(sbv, sbvsc); + if ([sbv isKindOfClass:[MyBaseLayout class]]) { - if (customSetting != nil) - customSetting(sbv, sbvsc); - BOOL isSbvWrap = sbvsc.widthSizeInner.dimeWrapVal || sbvsc.heightSizeInner.dimeWrapVal; if (pHasSubLayout != nil && isSbvWrap) diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index a5002ca..c05362d 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -432,6 +432,7 @@ -(instancetype)init _flex = [[MyFlex alloc] initWithView:self]; self.orientation = MyOrientation_Vert; self.arrangedCount = NSIntegerMax; //单行 + self.gravityAlways = YES; //flexbox对所有行都让停靠生效。 } return self; } diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index 684e6e1..158710a 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -217,6 +217,22 @@ +/** + 是否停靠属性gravity在所有行中都有效。默认是NO,表示停靠属性不会在最后一行生效。当设置为YES时则所有行的子视图都会受到gravity属性设置的影响。 + 在一些场景中,往往最后一行的子视图个数并没有填充满布局视图,如果这时候设置了gravity时产生的效果并不美观。所以默认情况下最后一行的子视图 + 并不会受到gravity设置的影响,但是特殊情况除外:1.只有一行时,2.最后一行的数量和其他行的数量一样时 这两种情况gravity会影响所有子视图。 + */ +@property(nonatomic, assign) BOOL gravityAlways; + + +/** + 单独为某一行或者一列定制gravity停靠对齐属性,默认情况下布局视图的gravity作用于所有行或者列的停靠对齐。如果你想单独定制某一行或者某一列的停靠对齐方式时 + 可以通过设置这个block属性。lineGravity的入参是布局对象和当前行列的索引值,索引值以0开始,返回的是此行的停靠对齐方式,如果返回MyGravity_None则表示使用 + 布局默认的gravity停靠对齐属性。 + */ +@property(nonatomic, copy) MyGravity (^lineGravity)(MyFlowLayout *layout, NSInteger lineIndex); + + /** 在流式布局的一些应用场景中我们希望子视图的宽度或者高度是固定的但间距是浮动的,这样就尽可能在一排中容纳更多的子视图。比如设置每个子视图的宽度固定为80,那么在小屏幕下每排只能放3个,而大屏幕则每排能放4个或者5个子视图。 因此您可以通过如下方法来设置子视图的固定尺寸和最小最大浮动间距。这个方法会根据您当前布局的方向不同而具有不同的意义: @@ -237,5 +253,6 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace inSizeClass:(MySizeClass)sizeClass; + @end diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 30af73c..ea051a9 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -309,7 +309,7 @@ - (void)myCalcHorzLayoutSinglelineHeightShrink:(CGSize)selfSize totalFloatHeight } -- (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFloat)rowMaxHeight rowMaxWidth:(CGFloat)rowMaxWidth rowTotalShrink:(CGFloat)rowTotalShrink horzGravity:(MyGravity)horzGravity vertAlignment:(MyGravity)vertAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +- (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger)rowIndex rowMaxHeight:(CGFloat)rowMaxHeight rowMaxWidth:(CGFloat)rowMaxWidth rowTotalShrink:(CGFloat)rowTotalShrink horzGravity:(MyGravity)horzGravity vertAlignment:(MyGravity)vertAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc { CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; @@ -322,14 +322,25 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo if (rowTotalShrink != 0.0) rowMaxWidth = selfSize.width - paddingHorz; + //计算每行的gravity情况。 + MyGravity lineHorzGravity = horzGravity; + if (self.lineGravity != nil) + { + lineHorzGravity = self.lineGravity(self, rowIndex); + if (lineHorzGravity == MyGravity_None) + lineHorzGravity = horzGravity; + else + lineHorzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lineHorzGravity]; + } + CGFloat addXPos = 0; //多出来的空隙区域,用于停靠处理。 CGFloat addXFill = 0; //多出来的平均区域,用于拉伸间距或者尺寸 - BOOL averageArrange = (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch); + BOOL averageArrange = (lineHorzGravity == MyGravity_Horz_Fill || lineHorzGravity == MyGravity_Horz_Stretch); if (!averageArrange || lsc.arrangedCount == 0) { - switch (horzGravity) { + switch (lineHorzGravity) { case MyGravity_Horz_Center: { addXPos = (selfSize.width - paddingHorz - rowMaxWidth) / 2; @@ -343,7 +354,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo case MyGravity_Horz_Between: { //总宽度减去最大的宽度。再除以数量表示每个应该扩展的空间。最后一行无效(如果最后一行的数量和其他行的数量一样以及总共就只有一行除外)。 - if ((startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) + if ((self.gravityAlways || startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) { addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / (count - 1); } @@ -371,7 +382,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo if (lsc.arrangedCount == 0 && averageArrange) { //不是最后一行。。 - if (startIndex != sbs.count) + if (self.gravityAlways || startIndex != sbs.count) { addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / count; } @@ -471,7 +482,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo if (lsc.arrangedCount == 0 && averageArrange) { //只拉伸宽度不拉伸间距 - if (horzGravity == MyGravity_Horz_Stretch) + if (lineHorzGravity == MyGravity_Horz_Stretch) { if (sbvsc.widthSizeInner.dimeVal == nil) sbvmyFrame.width += addXFill; @@ -531,7 +542,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowMaxHeight:(CGFlo } } -- (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloat)colMaxWidth colMaxHeight:(CGFloat)colMaxHeight colTotalShrink:(CGFloat)colTotalShrink vertGravity:(MyGravity)vertGravity horzAlignment:(MyGravity)horzAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +- (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger)colIndex colMaxWidth:(CGFloat)colMaxWidth colMaxHeight:(CGFloat)colMaxHeight colTotalShrink:(CGFloat)colTotalShrink vertGravity:(MyGravity)vertGravity horzAlignment:(MyGravity)horzAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc { CGFloat paddingTop = lsc.myLayoutTopPadding; @@ -545,14 +556,22 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa if (colTotalShrink != 0.0) colMaxHeight = selfSize.height - paddingVert; + //计算每行的gravity情况。 + MyGravity lineVertGravity = vertGravity; + if (self.lineGravity != nil) + { + lineVertGravity = self.lineGravity(self, colIndex); + if (lineVertGravity == MyGravity_None) + lineVertGravity = vertGravity; + } CGFloat addYPos = 0; CGFloat addYFill = 0; - BOOL averageArrange = (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch); + BOOL averageArrange = (lineVertGravity == MyGravity_Vert_Fill || lineVertGravity == MyGravity_Vert_Stretch); if (!averageArrange || lsc.arrangedCount == 0) { - switch (vertGravity) { + switch (lineVertGravity) { case MyGravity_Vert_Center: { addYPos = (selfSize.height - paddingVert - colMaxHeight) / 2; @@ -566,7 +585,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa case MyGravity_Vert_Between: { //总高度减去最大的高度。再除以数量表示每个应该扩展的空间。最后一列无效(如果最后一列的数量和其他列的数量一样以及总共就只有一列除外)。 - if ((startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) + if ((self.gravityAlways || startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) { addYFill = (selfSize.height - paddingVert - colMaxHeight) / (count - 1); } @@ -592,7 +611,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa //处理内容拉伸的情况。 if (lsc.arrangedCount == 0 && averageArrange) { - if (startIndex != sbs.count) + if (self.gravityAlways || startIndex != sbs.count) { addYFill = (selfSize.height - paddingVert - colMaxHeight) / count; } @@ -684,7 +703,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colMaxWidth:(CGFloa { //只拉伸宽度不拉伸间距 - if (vertGravity == MyGravity_Vert_Stretch) + if (lineVertGravity == MyGravity_Vert_Stretch) { if (sbvsc.heightSizeInner.dimeVal == nil) sbvmyFrame.height += addYFill; @@ -942,6 +961,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab NSMutableIndexSet *arrangeIndexSet = [NSMutableIndexSet new]; + NSInteger rowIndex = 0; //行的索引。 NSInteger arrangedIndex = 0; NSInteger i = 0; for (; i < sbs.count; i++) @@ -981,7 +1001,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab else { rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; - } rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; @@ -1025,7 +1044,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab [arrangeIndexSet addIndex:i - arrangedIndex]; //计算前面每行的gravity情况。 - [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; //计算单独的sbv的宽度是否大于整体的宽度。如果大于则缩小宽度。 if (_myCGFloatGreat(leadingSpace + trailingSpace + rect.size.width, selfSize.width - paddingHorz)) @@ -1051,6 +1070,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab rowMaxHeight = 0; rowMaxWidth = 0; arrangedIndex = 0; + rowIndex++; } @@ -1085,7 +1105,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab //最后一行 [arrangeIndexSet addIndex:i - arrangedIndex]; - [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; if (lsc.heightSizeInner.dimeWrapVal) @@ -1355,6 +1375,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray } } + NSInteger rowIndex = 0; //行索引 CGFloat pageWidth = 0; //页宽。 CGFloat averageWidth = (selfSize.width - paddingHorz - (arrangedCount - 1) * horzSpace) / arrangedCount; arrangedIndex = 0; @@ -1405,12 +1426,12 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray xPos = paddingLeading + pageWidth; - //计算每行的gravity情况。 - [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; rowMaxHeight = 0; rowMaxWidth = 0; rowTotalShrink = 0; + rowIndex++; } @@ -1539,7 +1560,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray } //最后一行 - [self myCalcVertLayoutSinglelineAlignment:selfSize rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; maxHeight += paddingBottom; @@ -1699,6 +1720,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab } NSMutableIndexSet *arrangeIndexSet = [NSMutableIndexSet new]; + NSInteger colIndex = 0; NSInteger arrangedIndex = 0; NSInteger i = 0; for (; i < sbs.count; i++) @@ -1777,7 +1799,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab //计算每行的gravity情况。 [arrangeIndexSet addIndex:i - arrangedIndex]; - [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; //计算单独的sbv的高度是否大于整体的高度。如果大于则缩小高度。 if (_myCGFloatGreat(topSpace + bottomSpace + rect.size.height, selfSize.height - paddingVert)) @@ -1794,7 +1816,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab colMaxWidth = 0; colMaxHeight = 0; arrangedIndex = 0; - + colIndex++; } if (arrangedIndex != 0) @@ -1824,7 +1846,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab //最后一行 [arrangeIndexSet addIndex:i - arrangedIndex]; - [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; if (lsc.widthSizeInner.dimeWrapVal) selfSize.width = xPos + paddingTrailing + colMaxWidth; @@ -2095,6 +2117,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray } } + NSInteger colIndex = 0; CGFloat pageHeight = 0; //页高 CGFloat averageHeight = (selfSize.height - paddingVert - (arrangedCount - 1) * vertSpace) / arrangedCount; arrangedIndex = 0; @@ -2146,11 +2169,12 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray yPos = paddingTop + pageHeight; //计算每行的gravity情况。 - [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; colMaxWidth = 0; colMaxHeight = 0; colTotalShrink = 0; + colIndex++; } CGFloat topSpace = sbvsc.topPosInner.absVal; @@ -2258,7 +2282,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray } //最后一列 - [self myCalcHorzLayoutSinglelineAlignment:selfSize colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; if (lsc.heightSizeInner.dimeWrapVal && !averageArrange) { diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 18e73f3..88d38e3 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -215,12 +215,12 @@ - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation //如果是拉伸处理则需要把包裹宽度取消。 if (gravity == MyGravity_Horz_Fill) [sbvsc.widthSizeInner __clear]; - - //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 - if (sbvsc.widthSizeInner.priority == MyPriority_Low && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) - [sbvsc.widthSizeInner __clear]; } + //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 + if (sbvsc.widthSizeInner.priority == MyPriority_Low && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) + [sbvsc.widthSizeInner __clear]; + if (sbvsc.heightSizeInner.dimeWrapVal) { //只要同时设置了高度或者比重属性则应该把尺寸设置为空 @@ -236,12 +236,12 @@ - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation //如果是拉伸处理则需要把包裹高度 if (gravity == MyGravity_Vert_Fill) [sbvsc.heightSizeInner __clear]; - - //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 - if (sbvsc.heightSizeInner.priority == MyPriority_Low && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) - [sbvsc.heightSizeInner __clear]; } + //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 + if (sbvsc.heightSizeInner.priority == MyPriority_Low && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) + [sbvsc.heightSizeInner __clear]; + if (sbvsc.widthSizeInner.dimeWrapVal) { //只要同时设置了宽度或者比重属性则应该把宽度置空 diff --git a/MyLayout/Lib/MyTableLayout.m b/MyLayout/Lib/MyTableLayout.m index bea9a00..b11482f 100644 --- a/MyLayout/Lib/MyTableLayout.m +++ b/MyLayout/Lib/MyTableLayout.m @@ -237,12 +237,12 @@ -(void)insertCol:(UIView*)colView atIndexPath:(NSIndexPath*)indexPath if (rowsc.orientation == MyOrientation_Horz) { if (CGRectGetHeight(colView.bounds) == 0 && colsc.heightSizeInner.dimeVal == nil) - [colsc.heightSize __equalTo:rowsc.heightSize]; + [colsc.heightSize __equalTo:rowsc.heightSize priority:MyPriority_Low]; } else { if (CGRectGetWidth(colView.bounds) == 0 && colsc.widthSizeInner.dimeVal == nil) - [colsc.widthSize __equalTo:rowsc.widthSize]; + [colsc.widthSize __equalTo:rowsc.widthSize priority:MyPriority_Low]; } [rowView insertSubview:colView atIndex:indexPath.col]; diff --git a/MyLayoutTests/MyLinearLayoutTestCase.m b/MyLayoutTests/MyLinearLayoutTestCase.m index 6cca28e..7dbfd2f 100644 --- a/MyLayoutTests/MyLinearLayoutTestCase.m +++ b/MyLayoutTests/MyLinearLayoutTestCase.m @@ -734,24 +734,45 @@ -(void)testequalizeSubviews XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(0,240,100,60)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + v1.weight = 0; + v2.weight = 0; + v3.weight = 0; [rootLayout equalizeSubviewsSpace:YES]; [rootLayout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,67.5,100,10)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,67.5+10+67.5,100,10)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(0,67.5*3+10*2,100,10)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + v1.myTop = 0; + v1.myBottom = 0; + v2.myTop = 0; + v2.myBottom = 0; + v3.myTop = 0; + v3.myBottom = 0; [rootLayout equalizeSubviewsSpace:NO]; [rootLayout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,0,100,10)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); - XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,90+10,100,10)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); - XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(0,90+10+90,100,10)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); - + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,135+10,100,10)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(0,135+10+135+10,100,10)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + v1.weight = 0; + v2.weight = 0; + v3.weight = 0; + v1.myTop = 0; + v1.myBottom = 0; + v2.myTop = 0; + v2.myBottom = 0; + v3.myTop = 0; + v3.myBottom = 0; [rootLayout equalizeSubviews:YES withSpace:10]; [rootLayout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,10,100,86.5)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,106.5,100,86.5)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(0,203,100,86.5)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + v1.weight = 0; + v2.weight = 0; + v3.weight = 0; [rootLayout equalizeSubviews:NO withSpace:10]; [rootLayout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,0,100,93.5)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); @@ -791,25 +812,45 @@ -(void)testequalizeSubviews XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(120,0,60,100)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(240,0,60,100)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); - + v1.weight = 0; + v2.weight = 0; + v3.weight = 0; [rootLayout equalizeSubviewsSpace:YES]; [rootLayout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(67.5,0,10,100)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(67.5+10+67.5,0,10,100)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(67.5*3+10*2,0,10,100)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + v1.myLeading = 0; + v1.myTrailing = 0; + v2.myLeading = 0; + v2.myTrailing = 0; + v3.myLeading = 0; + v3.myTrailing = 0; [rootLayout equalizeSubviewsSpace:NO]; [rootLayout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,0,10,100)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); - XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(90+10,0,10,100)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); - XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(90+10+90,0,10,100)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); - + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(135+10,0,10,100)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(135+10+135+10,0,10,100)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + v1.weight = 0; + v2.weight = 0; + v3.weight = 0; + v1.myLeading = 0; + v1.myTrailing = 0; + v2.myLeading = 0; + v2.myTrailing = 0; + v3.myLeading = 0; + v3.myTrailing = 0; [rootLayout equalizeSubviews:YES withSpace:10]; [rootLayout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(10,0,86.5,100)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(106.5,0,86.5,100)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(203,0,86.5,100)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + v1.weight = 0; + v2.weight = 0; + v3.weight = 0; [rootLayout equalizeSubviews:NO withSpace:10]; [rootLayout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,0,93.5,100)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); From 9aff22f4b4e8a03c0f59e2447e92ca873867e779 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Thu, 26 Sep 2019 09:44:23 +0800 Subject: [PATCH 044/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 23 ++++++++++++++++++----- MyLayout/Lib/MyLayoutDelegate.h | 2 ++ MyLayout/Lib/MyLayoutDelegate.m | 22 ++++++++++++++++++++++ MyLayoutDemo/FLLTest2ViewController.m | 8 ++++++++ 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index d44d5ab..f229fb8 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -2325,6 +2325,19 @@ -(void)layoutSubviews } } +-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection +{ + [super traitCollectionDidChange:previousTraitCollection]; + if (@available(iOS 12.0, *)) { + if (self.traitCollection.userInterfaceStyle != previousTraitCollection.userInterfaceStyle) + { + [_borderlineLayerDelegate updateAllBorderlineColor]; + } + } else { + // Fallback on earlier versions + } +} + #pragma mark -- Private Methods @@ -2359,7 +2372,7 @@ -(MyGravity)myGetSubviewVertGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc vertGravit if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { - if (sbvsc.heightSizeInner.dimeVal == nil) + if (sbvsc.heightSizeInner.dimeVal == nil || sbvsc.heightSizeInner.priority == MyPriority_Low) sbvVertGravity = MyGravity_Vert_Fill; } else if (sbvsc.centerYPosInner.posVal != nil) @@ -2501,7 +2514,7 @@ -(MyGravity)myGetSubviewHorzGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc horzGravit if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { - if (sbvsc.widthSizeInner.dimeVal == nil) + if (sbvsc.widthSizeInner.dimeVal == nil || sbvsc.widthSizeInner.priority == MyPriority_Low) sbvHorzGravity = MyGravity_Horz_Fill; } else if (sbvsc.centerXPosInner.posVal != nil) @@ -3742,12 +3755,12 @@ -(void)myCalcSubviewsWrapContentSize:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasS [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; } - if (customSetting != nil) - customSetting(sbv, sbvsc); - if ([sbv isKindOfClass:[MyBaseLayout class]]) { + if (customSetting != nil) + customSetting(sbv, sbvsc); + BOOL isSbvWrap = sbvsc.widthSizeInner.dimeWrapVal || sbvsc.heightSizeInner.dimeWrapVal; if (pHasSubLayout != nil && isSbvWrap) diff --git a/MyLayout/Lib/MyLayoutDelegate.h b/MyLayout/Lib/MyLayoutDelegate.h index 0823384..b0dd55a 100644 --- a/MyLayout/Lib/MyLayoutDelegate.h +++ b/MyLayout/Lib/MyLayoutDelegate.h @@ -36,6 +36,8 @@ -(void)setNeedsLayoutIn:(CGRect)rect withLayer:(CALayer*)layer; +-(void)updateAllBorderlineColor; + @end diff --git a/MyLayout/Lib/MyLayoutDelegate.m b/MyLayout/Lib/MyLayoutDelegate.m index 19e0156..48b9b52 100644 --- a/MyLayout/Lib/MyLayoutDelegate.m +++ b/MyLayout/Lib/MyLayoutDelegate.m @@ -347,6 +347,28 @@ -(void)setNeedsLayoutIn:(CGRect)rect withLayer:(CALayer*)layer } +-(void)updateAllBorderlineColor +{ + [self updateBorderlineColorHelper:_topBorderlineLayer borderline:_topBorderline]; + [self updateBorderlineColorHelper:_bottomBorderlineLayer borderline:_bottomBorderline]; + [self updateBorderlineColorHelper:_leadingBorderlineLayer borderline:_leadingBorderline]; + [self updateBorderlineColorHelper:_trailingBorderlineLayer borderline:_trailingBorderline]; +} + +-(void)updateBorderlineColorHelper:(CAShapeLayer*)layer borderline:(MyBorderline*)borderline +{ + if (layer != nil && borderline != nil) + { + if (borderline.dash != 0.0) + { + layer.strokeColor = borderline.color.CGColor; + } + else + { + layer.backgroundColor = borderline.color.CGColor; + } + } +} @end diff --git a/MyLayoutDemo/FLLTest2ViewController.m b/MyLayoutDemo/FLLTest2ViewController.m index fa7d51a..32684f3 100644 --- a/MyLayoutDemo/FLLTest2ViewController.m +++ b/MyLayoutDemo/FLLTest2ViewController.m @@ -34,6 +34,9 @@ - (void)viewDidLoad { [self createTagButton:NSLocalizedString(@"click to remove tag", @"")]; [self createTagButton:NSLocalizedString(@"tag2", @"")]; [self createTagButton:NSLocalizedString(@"MyLayout can used in XIB&SB", @"")]; + + UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"gravity\nalways" style:UIBarButtonItemStylePlain target:self action:@selector(handleChangeGravityAlways:)]; + self.navigationItem.rightBarButtonItem = item; } - (void)didReceiveMemoryWarning { @@ -72,6 +75,11 @@ -(void)createTagButton:(NSString*)text #pragma mark -- Handle Method +-(IBAction)handleChangeGravityAlways:(id)sender +{ + self.flowLayout.gravityAlways = !self.flowLayout.gravityAlways; +} + - (IBAction)handleShrinkMargin:(UISwitch *)sender { //间距拉伸 From fcf0c4b27cec418c566e707bff760d59d9c6e387 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Mon, 30 Sep 2019 09:21:59 +0800 Subject: [PATCH 045/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 32 ++++++++++++---------- MyLayout/Lib/MyFloatLayout.m | 1 - MyLayout/Lib/MyFrameLayout.m | 2 +- MyLayout/Lib/MyGridLayout.m | 2 +- MyLayout/Lib/MyLayoutInner.h | 2 +- MyLayout/Lib/MyLinearLayout.m | 41 ++++++++++------------------ MyLayout/Lib/MyRelativeLayout.m | 47 +++++++++------------------------ 7 files changed, 47 insertions(+), 80 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index f229fb8..c0326b7 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -2074,8 +2074,6 @@ -(void)layoutSubviews { sbv.center = sbvTempCenter; } - - } else { @@ -2084,7 +2082,6 @@ -(void)layoutSubviews sbv.center = CGPointMake(rc.origin.x + sbv.layer.anchorPoint.x * rc.size.width, rc.origin.y + sbv.layer.anchorPoint.y * rc.size.height); sbv.bounds = CGRectMake(sbvOldBounds.origin.x, sbvOldBounds.origin.y, rc.size.width, rc.size.height); } - } if (sbvsc.visibility == MyVisibility_Gone && !sbv.isHidden) @@ -2123,7 +2120,6 @@ -(void)layoutSubviews } if (isAdjustSelf && (isWidthAlter || isHeightAlter)) { - if (newSelfSize.width < 0) newSelfSize.width = 0; @@ -2372,6 +2368,7 @@ -(MyGravity)myGetSubviewVertGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc vertGravit if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { + //只有在没有设置高度约束,或者高度约束优先级很低的情况下同时设置上下才转化为填充。 if (sbvsc.heightSizeInner.dimeVal == nil || sbvsc.heightSizeInner.priority == MyPriority_Low) sbvVertGravity = MyGravity_Vert_Fill; } @@ -2429,7 +2426,7 @@ -(CGFloat)myCalcVertGravity:(MyGravity)vertGravity //如果是设置垂直拉伸则,如果子视图有约束则不受影响,否则就变为和填充一个意思。 if (vertGravity == MyGravity_Vert_Stretch) { - if (sbvsc.heightSizeInner.dimeVal != nil) + if (sbvsc.heightSizeInner.dimeVal != nil && sbvsc.heightSizeInner.priority != MyPriority_Low) vertGravity = MyGravity_Vert_Top; else vertGravity = MyGravity_Vert_Fill; @@ -2514,6 +2511,7 @@ -(MyGravity)myGetSubviewHorzGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc horzGravit if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { + //只有在没有设置宽度约束,或者宽度约束优先级很低的情况下同时设置左右才转化为填充。 if (sbvsc.widthSizeInner.dimeVal == nil || sbvsc.widthSizeInner.priority == MyPriority_Low) sbvHorzGravity = MyGravity_Horz_Fill; } @@ -2569,7 +2567,7 @@ -(CGFloat)myCalcHorzGravity:(MyGravity)horzGravity //如果是设置水平拉伸则,如果子视图有约束则不受影响,否则就变为和填充一个意思。 if (horzGravity == MyGravity_Horz_Stretch) { - if (sbvsc.widthSizeInner.dimeVal != nil) + if (sbvsc.widthSizeInner.dimeVal != nil && sbvsc.widthSizeInner.priority != MyPriority_Low) horzGravity = MyGravity_Horz_Leading; else horzGravity = MyGravity_Horz_Fill; @@ -2586,7 +2584,6 @@ -(CGFloat)myCalcHorzGravity:(MyGravity)horzGravity } if (horzGravity == MyGravity_Horz_Fill) { - pRect->origin.x = paddingLeading + leadingMargin; pRect->size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:selfSize.width - paddingHorz - leadingMargin - trailingMargin sbvSize:pRect->size selfLayoutSize:selfSize]; @@ -2674,7 +2671,7 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize if (lsc.leadingPosInner.posVal != nil && lsc.trailingPosInner.posVal != nil) { - if (lsc.widthSizeInner.priority == MyPriority_Low || lsc.widthSizeInner.dimeVal == nil) + if (lsc.widthSizeInner.priority == MyPriority_Low) { CGFloat leadingMargin = [lsc.leadingPosInner realPosIn:rectSuper.size.width]; CGFloat trailingMargin = [lsc.trailingPosInner realPosIn:rectSuper.size.width]; @@ -2703,7 +2700,7 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize if (lsc.topPosInner.posVal != nil && lsc.bottomPosInner.posVal != nil) { - if (lsc.heightSizeInner.priority == MyPriority_Low || lsc.heightSizeInner.dimeVal == nil) + if (lsc.heightSizeInner.priority == MyPriority_Low) { CGFloat topMargin = [lsc.topPosInner realPosIn:rectSuper.size.height]; CGFloat bottomMargin = [lsc.bottomPosInner realPosIn:rectSuper.size.height]; @@ -2793,7 +2790,7 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview { isAdjust = YES; //如果是没有设置宽度约束,或者宽度约束的优先级很低都按左右边距来决定布局视图的宽度。 - if (lsc.widthSizeInner.priority == MyPriority_Low || lsc.widthSizeInner.dimeVal == nil) + if (lsc.widthSizeInner.priority == MyPriority_Low) { [lsc.widthSizeInner __clear]; rectSelf.size.width = rectSuper.size.width - leadingMargin - trailingMargin; @@ -3509,7 +3506,7 @@ -(void)myAddSubviewObserver:(UIView*)subview sbvmyFrame:(MyFrame*)sbvmyFrame } --(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame sbvsc:(UIView*)sbvsc selfSize:(CGSize)selfSize sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout +-(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame sbvsc:(UIView*)sbvsc selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout { if (!isEstimate) { @@ -3517,14 +3514,21 @@ -(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sb [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; } - if ((sbvsc.widthSizeInner.priority == MyPriority_Low || sbvsc.widthSizeInner.dimeVal == nil) && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) + //只要子视图是包裹并且布局视图是fill填充,都应该清除子视图的包裹设置。 + if (sbvsc.widthSizeInner.dimeWrapVal && horzGravity == MyGravity_Horz_Fill) [sbvsc.widthSizeInner __clear]; - - if ((sbvsc.heightSizeInner.priority == MyPriority_Low || sbvsc.heightSizeInner.dimeVal == nil) && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) + if (sbvsc.heightSizeInner.dimeWrapVal && vertGravity == MyGravity_Vert_Fill) [sbvsc.heightSizeInner __clear]; + if ([sbv isKindOfClass:[MyBaseLayout class]]) { + if ((sbvsc.widthSizeInner.priority == MyPriority_Low) && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) + [sbvsc.widthSizeInner __clear]; + + if ((sbvsc.heightSizeInner.priority == MyPriority_Low) && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) + [sbvsc.heightSizeInner __clear]; + if (pHasSubLayout != nil && (sbvsc.heightSizeInner.dimeWrapVal || sbvsc.widthSizeInner.dimeWrapVal)) *pHasSubLayout = YES; diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 3ba7ae9..3663c5f 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -26,7 +26,6 @@ -(void)setReverseFloat:(BOOL)reverseFloat -(BOOL)isReverseFloat { return self.myCurrentSizeClass.isReverseFloat; - } -(void)setClearFloat:(BOOL)clearFloat diff --git a/MyLayout/Lib/MyFrameLayout.m b/MyLayout/Lib/MyFrameLayout.m index d87ca0a..e7d7bda 100644 --- a/MyLayout/Lib/MyFrameLayout.m +++ b/MyLayout/Lib/MyFrameLayout.m @@ -52,7 +52,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - [self myAdjustSubviewWrapContentSet:sbv isEstimate:isEstimate sbvmyFrame:sbvmyFrame sbvsc:sbvsc selfSize:selfSize sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; + [self myAdjustSubviewWrapContentSet:sbv isEstimate:isEstimate sbvmyFrame:sbvmyFrame sbvsc:sbvsc selfSize:selfSize vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; //计算自己的位置和高宽 [self myCalcSubViewRect:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame lsc:lsc vertGravity:vertGravity horzGravity:horzGravity inSelfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:pMaxWrapSize]; diff --git a/MyLayout/Lib/MyGridLayout.m b/MyLayout/Lib/MyGridLayout.m index 9768dc5..d90edba 100644 --- a/MyLayout/Lib/MyGridLayout.m +++ b/MyLayout/Lib/MyGridLayout.m @@ -1051,7 +1051,7 @@ -(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigi //如果尺寸是0则因为前面有算出尺寸,所以这里就不进行调整了。 if (grid.measure != 0 && [sbv isKindOfClass:[MyBaseLayout class]]) { - [self myAdjustSubviewWrapContentSet:sbv isEstimate:isEstimate sbvmyFrame:sbvmyFrame sbvsc:sbvsc selfSize:grid.gridRect.size sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; + [self myAdjustSubviewWrapContentSet:sbv isEstimate:isEstimate sbvmyFrame:sbvmyFrame sbvsc:sbvsc selfSize:grid.gridRect.size vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; } else { diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index 25dab99..e02628e 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -108,7 +108,7 @@ -(CGFloat)myLayoutLeadingPadding; -(CGFloat)myLayoutTrailingPadding; --(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame sbvsc:(UIView*)sbvsc selfSize:(CGSize)selfSize sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout; +-(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame sbvsc:(UIView*)sbvsc selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout; //根据子视图的宽度约束得到宽度值 diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 88d38e3..b41615d 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -75,7 +75,7 @@ -(MySubviewsShrinkType)shrinkType -(void)equalizeSubviews:(BOOL)centered { - [self equalizeSubviews:centered withSpace:CGFLOAT_MAX]; + [self equalizeSubviews:centered inSizeClass:MySizeClass_hAny | MySizeClass_wAny]; } -(void)equalizeSubviews:(BOOL)centered inSizeClass:(MySizeClass)sizeClass @@ -86,7 +86,6 @@ -(void)equalizeSubviews:(BOOL)centered inSizeClass:(MySizeClass)sizeClass -(void)equalizeSubviews:(BOOL)centered withSpace:(CGFloat)space { [self equalizeSubviews:centered withSpace:space inSizeClass:MySizeClass_hAny | MySizeClass_wAny]; - [self setNeedsLayout]; } -(void)equalizeSubviews:(BOOL)centered withSpace:(CGFloat)space inSizeClass:(MySizeClass)sizeClass @@ -108,6 +107,7 @@ -(void)equalizeSubviews:(BOOL)centered withSpace:(CGFloat)space inSizeClass:(MyS for (UIView *sbv in self.subviews) sbv.myFrame.sizeClass = sbv.myDefaultSizeClass; + [self setNeedsLayout]; } -(void)equalizeSubviewsSpace:(BOOL)centered @@ -210,44 +210,31 @@ - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation { if (orientation == MyOrientation_Vert) { - if (sbvsc.widthSizeInner.dimeWrapVal) - { - //如果是拉伸处理则需要把包裹宽度取消。 - if (gravity == MyGravity_Horz_Fill) - [sbvsc.widthSizeInner __clear]; - } + //如果是拉伸处理则需要把包裹宽度取消。 + if (sbvsc.widthSizeInner.dimeWrapVal && gravity == MyGravity_Horz_Fill) + [sbvsc.widthSizeInner __clear]; //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 if (sbvsc.widthSizeInner.priority == MyPriority_Low && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) [sbvsc.widthSizeInner __clear]; - if (sbvsc.heightSizeInner.dimeWrapVal) - { - //只要同时设置了高度或者比重属性则应该把尺寸设置为空 - if (sbvsc.weight != 0) - [sbvsc.heightSizeInner __clear]; - } + //只要同时设置了高度或者比重属性则应该把尺寸设置为空 + if (sbvsc.heightSizeInner.dimeWrapVal && sbvsc.weight != 0) + [sbvsc.heightSizeInner __clear]; } else { - - if (sbvsc.heightSizeInner.dimeWrapVal) - { - //如果是拉伸处理则需要把包裹高度 - if (gravity == MyGravity_Vert_Fill) - [sbvsc.heightSizeInner __clear]; - } + //如果是拉伸处理则需要把包裹高度 + if (sbvsc.heightSizeInner.dimeWrapVal && gravity == MyGravity_Vert_Fill) + [sbvsc.heightSizeInner __clear]; //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 if (sbvsc.heightSizeInner.priority == MyPriority_Low && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) [sbvsc.heightSizeInner __clear]; - if (sbvsc.widthSizeInner.dimeWrapVal) - { - //只要同时设置了宽度或者比重属性则应该把宽度置空 - if (sbvsc.weight != 0) - [sbvsc.widthSizeInner __clear]; - } + //只要同时设置了宽度或者比重属性则应该把宽度置空 + if (sbvsc.widthSizeInner.dimeWrapVal && sbvsc.weight != 0) + [sbvsc.widthSizeInner __clear]; } } diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 983d62b..a109b1e 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -34,15 +34,15 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( [sbvmyFrame reset]; - //只要同时设置了左右边距则把宽度值置空 - if ((sbvsc.widthSizeInner.priority == MyPriority_Low || sbvsc.widthSizeInner.dimeVal == nil)&& + //只要同时设置了左右边距且宽度优先级很低则把宽度值置空 + if ((sbvsc.widthSizeInner.priority == MyPriority_Low)&& sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) [sbvsc.widthSizeInner __clear]; - //只要同时设置了上下边距则把高度值置空 - if ((sbvsc.heightSizeInner.priority == MyPriority_Low || sbvsc.heightSizeInner.dimeVal == nil) && + //只要同时设置了上下边距且高度优先级很低则把高度值置空 + if ((sbvsc.heightSizeInner.priority == MyPriority_Low) && sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) [sbvsc.heightSizeInner __clear]; @@ -846,7 +846,6 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc return YES; - } @@ -1275,21 +1274,10 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize } else if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { - //如果设置有宽度则宽度参与最大!!!!!! -// if (sbvsc.widthSizeInner.dimeVal != nil) -// { -// if (_myCGFloatLess(maxWidth, sbvmyFrame.leading + sbvmyFrame.width + sbvmyFrame.trailing + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding)) -// { -// maxWidth = sbvmyFrame.leading + sbvmyFrame.width + sbvmyFrame.trailing + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding; -// } -// } -// else -// { - if (_myCGFloatLess(maxWidth, fabs(sbvmyFrame.trailing) + sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding)) - { - maxWidth = fabs(sbvmyFrame.trailing) + sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; - } - //} + if (_myCGFloatLess(maxWidth, fabs(sbvmyFrame.trailing) + sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding)) + { + maxWidth = fabs(sbvmyFrame.trailing) + sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; + } } else if (sbvsc.trailingPosInner.posVal != nil) { @@ -1336,21 +1324,10 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize } else if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { - //如果设置有高度则高度参与最大!!!!!! -// if (sbvsc.heightSizeInner.dimeVal != nil) -// { -// if (_myCGFloatLess(maxHeight, sbvmyFrame.top + sbvmyFrame.height + sbvmyFrame.bottom + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding)) -// { -// maxHeight = sbvmyFrame.top + sbvmyFrame.height + sbvmyFrame.bottom + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding; -// } -// } -// else -// { - if (_myCGFloatLess(maxHeight, fabs(sbvmyFrame.bottom) + sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding)) - { - maxHeight = fabs(sbvmyFrame.bottom) + sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding; - } - //} + if (_myCGFloatLess(maxHeight, fabs(sbvmyFrame.bottom) + sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding)) + { + maxHeight = fabs(sbvmyFrame.bottom) + sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding; + } } else if (sbvsc.bottomPosInner.posVal != nil) { From 7cf6e91820b55a76f01953424d9581ea05227c1d Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Mon, 30 Sep 2019 17:44:36 +0800 Subject: [PATCH 046/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout.xcodeproj/project.pbxproj | 6 ++ MyLayoutDemo/AllTestExampleViewController.h | 14 +++ MyLayoutDemo/AllTestExampleViewController.m | 100 ++++++++++++++++++++ MyLayoutDemo/ViewController.m | 4 + MyLayoutTests/MyRelativeLayoutTestCase.m | 21 ++-- 5 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 MyLayoutDemo/AllTestExampleViewController.h create mode 100644 MyLayoutDemo/AllTestExampleViewController.m diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index bbcf709..2939e82 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -162,6 +162,7 @@ 208157BD1F586AA700E945B6 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157BC1F586AA700E945B6 /* DetailViewController.m */; }; 208157C31F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; 208157C41F5A886400E945B6 /* MyLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */; }; + 2094619E2341FD6F005F5C8E /* AllTestExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2094619D2341FD6F005F5C8E /* AllTestExampleViewController.m */; }; 20A45EC52318FCA50026A18C /* MyFlexLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DF42402318F4EA0078CAA0 /* MyFlexLayout.m */; }; 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */ = {isa = PBXBuildFile; fileRef = 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */; }; 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */; }; @@ -408,6 +409,8 @@ 208157BC1F586AA700E945B6 /* DetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; 208157C01F5A886300E945B6 /* MyLayoutDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutDelegate.h; sourceTree = ""; }; 208157C11F5A886300E945B6 /* MyLayoutDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLayoutDelegate.m; sourceTree = ""; }; + 2094619C2341FD5E005F5C8E /* AllTestExampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTestExampleViewController.h; sourceTree = ""; }; + 2094619D2341FD6F005F5C8E /* AllTestExampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTestExampleViewController.m; sourceTree = ""; }; 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo8.gif; sourceTree = ""; }; 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest7ViewController.h; sourceTree = ""; }; 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest7ViewController.m; sourceTree = ""; }; @@ -690,6 +693,8 @@ 20F0DFFC2111749A00CFCE8C /* AllTest11ViewController.m */, 467E63CA228C4D630065D080 /* AllTest12ViewController.h */, 467E63CB228C4D6F0065D080 /* AllTest12ViewController.m */, + 2094619C2341FD5E005F5C8E /* AllTestExampleViewController.h */, + 2094619D2341FD6F005F5C8E /* AllTestExampleViewController.m */, 18D3C9021EDF068200D3DE43 /* AllTestModel&View */, ); name = IntegratedDemo; @@ -1158,6 +1163,7 @@ 467E63CF228CDA660065D080 /* AllTest1TableViewCellForAutoLayout.m in Sources */, 18D3C95A1EDF07F800D3DE43 /* FOLTest1ViewController.m in Sources */, 182225D01E77E5930081AA4B /* MyLayoutPos.m in Sources */, + 2094619E2341FD6F005F5C8E /* AllTestExampleViewController.m in Sources */, 18D3C98B1EDF084000D3DE43 /* AllTest7ViewController.m in Sources */, 20F0E00021120A8D00CFCE8C /* FLLTest8ViewController.m in Sources */, 200A26DC1FA96B2400B06E7B /* AllTest9CollectionViewCell.m in Sources */, diff --git a/MyLayoutDemo/AllTestExampleViewController.h b/MyLayoutDemo/AllTestExampleViewController.h new file mode 100644 index 0000000..fcc1809 --- /dev/null +++ b/MyLayoutDemo/AllTestExampleViewController.h @@ -0,0 +1,14 @@ +// +// AllTest11ViewController.h +// MyLayoutDemo +// +// Created by oubaiquan on 2018/8/1. +// Copyright © 2018年 YoungSoft. All rights reserved. +// + +#import + + +@interface AllTestExampleViewController : UIViewController + +@end diff --git a/MyLayoutDemo/AllTestExampleViewController.m b/MyLayoutDemo/AllTestExampleViewController.m new file mode 100644 index 0000000..8693239 --- /dev/null +++ b/MyLayoutDemo/AllTestExampleViewController.m @@ -0,0 +1,100 @@ +// +// AllTestExampleViewController.m +// MyLayoutDemo +// +// Created by oubaiquan on 2018/8/1. +// Copyright © 2018年 YoungSoft. All rights reserved. +// + +#import "AllTestExampleViewController.h" +#import "MyLayout.h" +#import "CFTool.h" + +@interface AllTestExampleViewController () + + +@end + +@implementation AllTestExampleViewController + +- (void)viewDidLoad { + self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + + [self example1]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +-(void)example1 +{ + //验证相对布局的其他分支覆盖。 + + MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + rootLayout.myMargin = 0; + [self.view addSubview:rootLayout]; + + + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(100, 100); + v1.myTop = 100; + v1.myLeft = 100; + v1.visibility = MyVisibility_Gone; + [rootLayout addSubview:v1]; + + //某个视图的水平居中依赖另外一个视图,另外一个视图隐藏。 + UIView *v2 = [UIView new]; + v2.mySize = CGSizeMake(100, 100); + v2.centerXPos.equalTo(v1.centerXPos).offset(20); + v2.centerYPos.equalTo(v1.centerYPos).offset(20); + [rootLayout addSubview:v2]; + + //某个视图的左边依赖另外一个视图,另外一个视图隐藏。 + UIView *v3 = [UIView new]; + v3.mySize = CGSizeMake(100, 100); + v3.leadingPos.equalTo(v1.leadingPos).offset(20); + v3.bottomPos.equalTo(v1.bottomPos).offset(20); + [rootLayout addSubview:v3]; + + UIView *v4 = [UIView new]; + v4.mySize = CGSizeMake(100, 100); + v4.leadingPos.lBound(v3.leadingPos, 0); + v4.trailingPos.uBound(rootLayout.trailingPos,0); + v4.bottomPos.equalTo(@(10)); + [rootLayout addSubview:v4]; + + UIView *v5 = [UIView new]; + v5.mySize = CGSizeMake(100, 100); + v5.baselinePos.equalTo(v4.baselinePos).offset(20); + [rootLayout addSubview:v5]; + + UILabel *v6 = [UILabel new]; + v6.mySize = CGSizeMake(100, 100); + v6.baselinePos.equalTo(v1.baselinePos).offset(20); + [rootLayout addSubview:v6]; + + UILabel *v7 = [UILabel new]; + v7.mySize = CGSizeMake(100, 100); + v7.baselinePos.equalTo(@(40)); + [rootLayout addSubview:v7]; + +} + + + +@end diff --git a/MyLayoutDemo/ViewController.m b/MyLayoutDemo/ViewController.m index e6f15ef..75a5478 100644 --- a/MyLayoutDemo/ViewController.m +++ b/MyLayoutDemo/ViewController.m @@ -58,6 +58,7 @@ #import "AllTest10ViewController.h" #import "AllTest11ViewController.h" #import "AllTest12ViewController.h" +#import "AllTestExampleViewController.h" #import "FOLTest1ViewController.h" @@ -304,6 +305,9 @@ -(NSArray*)demoTypeList }, @{@"title":NSLocalizedString(@"❁6.MyLayout & AutoLayout", @""), @"class":[AllTest12ViewController class] + }, + @{@"title":NSLocalizedString(@"❁7.example", @""), + @"class":[AllTestExampleViewController class] } ] } diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index 1f6258b..e6ea6d1 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -8,6 +8,10 @@ #import "MyLayoutTestCaseBase.h" #import "RLTest1ViewController.h" +#import "RLTest2ViewController.h" +#import "RLTest3ViewController.h" +#import "RLTest4ViewController.h" +#import "RLTest5ViewController.h" @interface MyRelativeLayoutTestCase : MyLayoutTestCaseBase @@ -21,22 +25,25 @@ @implementation MyRelativeLayoutTestCase - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. - self.vc = [RLTest1ViewController new]; } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. - self.vc = nil; [super tearDown]; } -(void)testRLTest1VC { - - UIView *v = self.vc.view; - [self startClock]; - [v layoutIfNeeded]; - [self endClock:@"RLTest1"]; + + for (int i = 0; i <= 5; i++) + { + Class cls = NSClassFromString([NSString stringWithFormat:@"RLTest%dViewController", i]); + UIViewController *vc = [[cls alloc] init]; + UIView *v = vc.view; + [v setNeedsLayout]; + [v layoutIfNeeded]; + } + } From 42012c3b25a25c4439fbacf7f5d2084b8abd5b71 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Mon, 7 Oct 2019 10:27:58 +0800 Subject: [PATCH 047/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout.xcodeproj/project.pbxproj | 14 ++ MyLayout/Lib/MyBaseLayout.m | 17 +-- MyLayout/Lib/MyLayoutPos.h | 31 +++- MyLayout/Lib/MyLayoutPos.m | 176 ++++++++++++++++++++--- MyLayout/Lib/MyLayoutPosInner.h | 8 ++ MyLayout/Lib/MyLayoutSize.h | 8 +- MyLayout/Lib/MyLayoutSize.m | 47 +++--- MyLayout/Lib/MyRelativeLayout.m | 78 +++++++++- MyLayoutDemo/AllTest1TableViewCell.m | 4 +- MyLayoutDemo/AllTest2TableViewCell.m | 2 +- MyLayoutDemo/AllTest3ViewController.m | 6 +- MyLayoutDemo/AllTest6ViewController.m | 31 ++-- MyLayoutDemo/AllTest7ViewController.m | 51 ++++++- MyLayoutDemo/RLTest1ViewController.m | 11 ++ MyLayoutDemo/RLTest6ViewController.h | 16 +++ MyLayoutDemo/RLTest6ViewController.m | 121 ++++++++++++++++ MyLayoutDemo/ViewController.m | 5 +- MyLayoutTests/MyFloatLayoutTestCase.m | 40 ++---- MyLayoutTests/MyFlowLayoutTestCase.m | 9 ++ MyLayoutTests/MyFrameLayoutTestCase.m | 17 +-- MyLayoutTests/MyGridLayoutTestCase.m | 57 ++++++++ MyLayoutTests/MyLinearLayoutTestCase.m | 55 ++----- MyLayoutTests/MyPathLayoutTestCase.m | 50 +++++++ MyLayoutTests/MyRelativeLayoutTestCase.m | 62 +++++++- 24 files changed, 748 insertions(+), 168 deletions(-) create mode 100644 MyLayoutDemo/RLTest6ViewController.h create mode 100644 MyLayoutDemo/RLTest6ViewController.m create mode 100644 MyLayoutTests/MyGridLayoutTestCase.m create mode 100644 MyLayoutTests/MyPathLayoutTestCase.m diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index 2939e82..87a1a25 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -178,6 +178,9 @@ 44EBDA8E1F619C9000B47CBD /* GridLayoutDemo4.json in Resources */ = {isa = PBXBuildFile; fileRef = 44EBDA8D1F619C9000B47CBD /* GridLayoutDemo4.json */; }; 467E63CC228C4D6F0065D080 /* AllTest12ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 467E63CB228C4D6F0065D080 /* AllTest12ViewController.m */; }; 467E63CF228CDA660065D080 /* AllTest1TableViewCellForAutoLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 467E63CE228CDA660065D080 /* AllTest1TableViewCellForAutoLayout.m */; }; + 4689881D23430A8400BFE829 /* MyPathLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 4689881C23430A8400BFE829 /* MyPathLayoutTestCase.m */; }; + 4689881F23430AA000BFE829 /* MyGridLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 4689881E23430AA000BFE829 /* MyGridLayoutTestCase.m */; }; + 4689882223449E8300BFE829 /* RLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4689882123449E8300BFE829 /* RLTest6ViewController.m */; }; 6740E1F820A52D9E00AFBC5A /* AllTest10ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */; }; 6740E1FB20A52DA900AFBC5A /* AllTest10Model.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */; }; 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */; }; @@ -434,6 +437,10 @@ 467E63CB228C4D6F0065D080 /* AllTest12ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest12ViewController.m; sourceTree = ""; }; 467E63CD228CDA550065D080 /* AllTest1TableViewCellForAutoLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest1TableViewCellForAutoLayout.h; sourceTree = ""; }; 467E63CE228CDA660065D080 /* AllTest1TableViewCellForAutoLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest1TableViewCellForAutoLayout.m; sourceTree = ""; }; + 4689881C23430A8400BFE829 /* MyPathLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyPathLayoutTestCase.m; sourceTree = ""; }; + 4689881E23430AA000BFE829 /* MyGridLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyGridLayoutTestCase.m; sourceTree = ""; }; + 4689882023449E7900BFE829 /* RLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest6ViewController.h; sourceTree = ""; }; + 4689882123449E8300BFE829 /* RLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest6ViewController.m; sourceTree = ""; }; 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10ViewController.h; sourceTree = ""; }; 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10ViewController.m; sourceTree = ""; }; 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10Model.m; sourceTree = ""; }; @@ -582,6 +589,8 @@ 18D3C9251EDF07A700D3DE43 /* RLTest4ViewController.m */, 18D3C9261EDF07A700D3DE43 /* RLTest5ViewController.h */, 18D3C9271EDF07A700D3DE43 /* RLTest5ViewController.m */, + 4689882023449E7900BFE829 /* RLTest6ViewController.h */, + 4689882123449E8300BFE829 /* RLTest6ViewController.m */, ); name = RelativeLayoutDemo; sourceTree = ""; @@ -858,6 +867,8 @@ 18B2CCE71EAF5066001AE0E1 /* MyLinearLayoutTestCase.m */, 18B2CCE91EB046AB001AE0E1 /* MyFlowLayoutTestCase.m */, 205AE95D22BC4C2900BE8E76 /* MyFloatLayoutTestCase.m */, + 4689881C23430A8400BFE829 /* MyPathLayoutTestCase.m */, + 4689881E23430AA000BFE829 /* MyGridLayoutTestCase.m */, 1810AC211EB966D30022CBFF /* MyLayoutPerformanceTestCase.m */, ); path = MyLayoutTests; @@ -1167,6 +1178,7 @@ 18D3C98B1EDF084000D3DE43 /* AllTest7ViewController.m in Sources */, 20F0E00021120A8D00CFCE8C /* FLLTest8ViewController.m in Sources */, 200A26DC1FA96B2400B06E7B /* AllTest9CollectionViewCell.m in Sources */, + 4689882223449E8300BFE829 /* RLTest6ViewController.m in Sources */, 18D3C9881EDF084000D3DE43 /* AllTest4ViewController.m in Sources */, 18D3C9131EDF074900D3DE43 /* LLTest3ViewController.m in Sources */, 18D3C95E1EDF07F800D3DE43 /* FOLTest5ViewController.m in Sources */, @@ -1241,10 +1253,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4689881D23430A8400BFE829 /* MyPathLayoutTestCase.m in Sources */, 18B2CCE81EAF5066001AE0E1 /* MyLinearLayoutTestCase.m in Sources */, 205AE95E22BC4C2900BE8E76 /* MyFloatLayoutTestCase.m in Sources */, 18D684591C4F423400A48BB4 /* MyLayoutTests.m in Sources */, 1810AC221EB966D30022CBFF /* MyLayoutPerformanceTestCase.m in Sources */, + 4689881F23430AA000BFE829 /* MyGridLayoutTestCase.m in Sources */, 181836951EAB1CB10031F337 /* MyNoLayoutSuperviewTestCase.m in Sources */, 180BD8A11EA9EF9A00C6980B /* MyFrameLayoutTestCase.m in Sources */, 1897384F1E1631E3004F80D6 /* MyRelativeLayoutTestCase.m in Sources */, diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index c0326b7..338a0ce 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -1281,9 +1281,7 @@ -(CGRect)subview:(UIView*)subview estimatedRectInLayoutSize:(CGSize)size -(void)setHighlightedOpacity:(CGFloat)highlightedOpacity { if (_touchEventDelegate == nil) - { _touchEventDelegate = [[MyLayoutTouchEventDelegate alloc] initWithLayout:self]; - } _touchEventDelegate.highlightedOpacity = highlightedOpacity; } @@ -1296,9 +1294,7 @@ -(CGFloat)highlightedOpacity -(void)setHighlightedBackgroundColor:(UIColor *)highlightedBackgroundColor { if (_touchEventDelegate == nil) - { _touchEventDelegate = [[MyLayoutTouchEventDelegate alloc] initWithLayout:self]; - } _touchEventDelegate.highlightedBackgroundColor = highlightedBackgroundColor; } @@ -1311,9 +1307,7 @@ -(UIColor*)highlightedBackgroundColor -(void)setHighlightedBackgroundImage:(UIImage *)highlightedBackgroundImage { if (_touchEventDelegate == nil) - { _touchEventDelegate = [[MyLayoutTouchEventDelegate alloc] initWithLayout:self]; - } _touchEventDelegate.highlightedBackgroundImage = highlightedBackgroundImage; } @@ -1327,9 +1321,7 @@ -(UIImage*)highlightedBackgroundImage -(void)setTarget:(id)target action:(SEL)action { if (_touchEventDelegate == nil) - { _touchEventDelegate = [[MyLayoutTouchEventDelegate alloc] initWithLayout:self]; - } [_touchEventDelegate setTarget:target action:action]; } @@ -1338,9 +1330,7 @@ -(void)setTarget:(id)target action:(SEL)action -(void)setTouchDownTarget:(id)target action:(SEL)action { if (_touchEventDelegate == nil) - { _touchEventDelegate = [[MyLayoutTouchEventDelegate alloc] initWithLayout:self]; - } [_touchEventDelegate setTouchDownTarget:target action:action]; } @@ -1348,9 +1338,7 @@ -(void)setTouchDownTarget:(id)target action:(SEL)action -(void)setTouchCancelTarget:(id)target action:(SEL)action { if (_touchEventDelegate == nil) - { _touchEventDelegate = [[MyLayoutTouchEventDelegate alloc] initWithLayout:self]; - } [_touchEventDelegate setTouchCancelTarget:target action:action]; @@ -1415,9 +1403,8 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIView*)object chan CGRect rcOld = [change[NSKeyValueChangeOldKey] CGRectValue]; CGRect rcNew = [change[NSKeyValueChangeNewKey] CGRectValue]; if (!_myCGSizeEqual(rcOld.size, rcNew.size)) - { [self myUpdateLayoutRectInNoLayoutSuperview:object]; - } + return; } @@ -1434,7 +1421,6 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIView*)object chan { [(UIView*)object setNeedsDisplay]; } - } else if (context == _myObserverContextB) {//针对UILabel特殊处理。。 @@ -2586,7 +2572,6 @@ -(CGFloat)myCalcHorzGravity:(MyGravity)horzGravity { pRect->origin.x = paddingLeading + leadingMargin; pRect->size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:selfSize.width - paddingHorz - leadingMargin - trailingMargin sbvSize:pRect->size selfLayoutSize:selfSize]; - } else if (horzGravity == MyGravity_Horz_Center) { diff --git a/MyLayout/Lib/MyLayoutPos.h b/MyLayout/Lib/MyLayoutPos.h index de934f1..315b5bb 100644 --- a/MyLayout/Lib/MyLayoutPos.h +++ b/MyLayout/Lib/MyLayoutPos.h @@ -8,6 +8,9 @@ #import "MyLayoutDef.h" +@class MyLayoutExtremePos; + + /** *视图的布局位置类,用于定位视图在布局视图中的位置。位置可分为水平方向的位置和垂直方向的位置,在视图定位时必要同时指定水平方向的位置和垂直方向的位置。水平方向的位置可以分为左,水平居中,右三种位置,垂直方向的位置可以分为上,垂直居中,下三种位置。 其中的offset方法可以用来设置布局位置的偏移值,一般只在equalTo设置为MyLayoutPos或者NSArray时配合使用。比如A.leftPos.equalTo(B.rightPos).offset(5)表示A在B的右边再偏移5个点 @@ -130,7 +133,7 @@ #else /** - 设置布局位置的值。参数val可以接收下面六种类型的值: + 设置布局位置的值。参数val可以接收下面七种类型的值: 1. NSNumber表示位置是一个具体的数值。 对于框架布局和线性布局中的子视图来说,如果数值是一个大于0而小于1的数值时表示的是相对的间距或者边距。如果是相对边距那么真实的位置 = 布局视图尺寸*相对边距值;如果是相对间距那么真实的位置 = 布局视图剩余尺寸 * 相对间距值 /(所有相对间距值的总和)。 @@ -143,7 +146,9 @@ 5. UIView表示位置依赖指定视图的对应位置。 - 6. nil表示位置的值被清除。 + 6.MyLayoutExtremePos表示位置是表示取数组中所有元素位置中的最大的一个或者最小的一个元素的位置值, 只有相对布局中的子视图的位置才能设置这种类型。 + + 7. nil表示位置的值被清除。 */ -(MyLayoutPos* (^)(id val))equalTo; @@ -272,3 +277,25 @@ @end + + +@interface MyLayoutPos(Detach) + +//从布局位置中分离出一个位置对象来。这个分离出来的位置值是源位置对象的值加上offsetVal。这个方法通常用于下面数组元素的构造 +-(MyLayoutPos* (^)(CGFloat offsetVal))detach; + +@end + + +/** + 我们可以从一个数组中获取众多位置的最大最小的位置值。 + 这里要求数组的元素只能是MyLayoutPos或者NSNumber两种对象类型的值。如果是NSNumber类型则是一个绝对位置值,也就是包括布局视图padding设置的偏移值。 + */ +@interface NSArray(MyLayoutExtremePos) + +//从数组中得到最小的尺寸值。要求数组的元素必须是MyLayoutPos或者NSNumber类型 +@property(nonatomic, readonly) MyLayoutExtremePos *myMinPos; +//从数组中得到最小的尺寸值。要求数组的元素必须是MyLayoutPos或者NSNumber类型 +@property(nonatomic, readonly) MyLayoutExtremePos *myMaxPos; + +@end diff --git a/MyLayout/Lib/MyLayoutPos.m b/MyLayout/Lib/MyLayoutPos.m index b05a7b7..07ffbf6 100644 --- a/MyLayout/Lib/MyLayoutPos.m +++ b/MyLayout/Lib/MyLayoutPos.m @@ -206,28 +206,28 @@ -(CGFloat)maxVal -(id)copyWithZone:(NSZone *)zone { - MyLayoutPos *lp = [[[self class] allocWithZone:zone] init]; - lp.view = self.view; - lp->_active = _active; - lp->_shrink = _shrink; - lp->_pos = _pos; - lp->_posValType = _posValType; - lp->_posVal = _posVal; - lp->_offsetVal = _offsetVal; + MyLayoutPos *layoutPos = [[[self class] allocWithZone:zone] init]; + layoutPos.view = self.view; + layoutPos->_active = _active; + layoutPos->_shrink = _shrink; + layoutPos->_pos = _pos; + layoutPos->_posValType = _posValType; + layoutPos->_posVal = _posVal; + layoutPos->_offsetVal = _offsetVal; if (_lBoundVal != nil) { - lp->_lBoundVal = [[[self class] allocWithZone:zone] init]; - lp->_lBoundVal->_active = _active; - [[lp->_lBoundVal __equalTo:_lBoundVal.posVal] __offset:_lBoundVal.offsetVal]; + layoutPos->_lBoundVal = [[[self class] allocWithZone:zone] init]; + layoutPos->_lBoundVal->_active = _active; + [[layoutPos->_lBoundVal __equalTo:_lBoundVal.posVal] __offset:_lBoundVal.offsetVal]; } if (_uBoundVal != nil) { - lp->_uBoundVal = [[[self class] allocWithZone:zone] init]; - lp->_uBoundVal->_active = _active; - [[lp->_uBoundVal __equalTo:_uBoundVal.posVal] __offset:_uBoundVal.offsetVal]; + layoutPos->_uBoundVal = [[[self class] allocWithZone:zone] init]; + layoutPos->_uBoundVal->_active = _active; + [[layoutPos->_uBoundVal __equalTo:_uBoundVal.posVal] __offset:_uBoundVal.offsetVal]; } - return lp; + return layoutPos; } @@ -307,10 +307,8 @@ -(NSNumber*)posNumVal } return @(0); - } - return nil; } @@ -364,6 +362,20 @@ -(NSArray*)posArrVal } +-(NSNumber*)posExtremeVal +{ + if (_posVal == nil || !self.isActive) + return nil; + + if (_posValType == MyLayoutValueType_Extreme) + { + return @([((MyLayoutExtremePos*)_posVal) getExtremePosFrom:self]); + } + + return nil; +} + + -(MyLayoutPos*)lBoundVal { if (_lBoundVal == nil) @@ -409,8 +421,7 @@ -(MyLayoutPos*)__equalTo:(id)val //特殊处理设置为safeAreaMargin边距的值。 if ([val doubleValue] == [MyLayoutPos safeAreaMargin]) { - - _posValType = MyLayoutValueType_SafeArea; + _posValType = MyLayoutValueType_SafeArea; } else { @@ -431,6 +442,10 @@ -(MyLayoutPos*)__equalTo:(id)val _posValType = MyLayoutValueType_UILayoutSupport; } + else if ([val isKindOfClass:[MyLayoutExtremePos class]]) + { + _posValType = MyLayoutValueType_Extreme; + } else if ([val isKindOfClass:[UIView class]]) { UIView *rview = (UIView*)val; @@ -704,7 +719,130 @@ -(NSString*)description } +@end + +@implementation MyLayoutPos(Detach) + +-(MyLayoutPos* (^)(CGFloat offsetVal))detach +{ + return ^id(CGFloat offsetVal){ + + MyLayoutPos *detachPos = [[[self class] allocWithZone:nil] init]; + detachPos->_offsetVal = offsetVal; + detachPos->_posVal = self; + detachPos->_posValType = MyLayoutValueType_LayoutDimeDetach; + return detachPos; + }; +} + +@end +@implementation MyLayoutExtremePos +{ + NSArray *_poss; + BOOL _isMax; +} + +-(instancetype)initWith:(NSArray *)poss isMax:(BOOL)isMax +{ + self = [self init]; + if (self != nil) + { + _poss = poss; + _isMax = isMax; + } + + return self; +} + + +-(CGFloat)getExtremePosFrom:(MyLayoutPos *)layoutPos +{ + CGFloat retVal = _isMax ? -CGFLOAT_MAX : CGFLOAT_MAX; + + for (id pos in _poss) + { + CGFloat val = 0; + if ([pos isKindOfClass:[NSNumber class]]) + { + val = [(NSNumber*)pos doubleValue]; + + retVal = _isMax ? _myCGFloatMax(val, retVal) : _myCGFloatMin(val, retVal); + } + else if ([pos isKindOfClass:[MyLayoutPos class]]) + { + MyLayoutPos *lpos = (MyLayoutPos *)pos; + CGFloat offsetVal = 0; + if (lpos.posValType == MyLayoutValueType_LayoutDimeDetach) + { + offsetVal = lpos.offsetVal; + lpos = (MyLayoutPos *)lpos.posVal; + } + + if (layoutPos.pos & MyGravity_Vert_Mask) + {//水平 + + MyFrame *myFrame = lpos.view.myFrame; + + if (lpos.pos == MyGravity_Horz_Leading) + { + val = myFrame.leading + offsetVal; + } + else if (lpos.pos == MyGravity_Horz_Center) + { + val = myFrame.leading + myFrame.width / 2.0 + offsetVal; + } + else + { + val = myFrame.trailing - offsetVal; + } + + } + else + {//垂直 + + MyFrame *myFrame = lpos.view.myFrame; + + if (lpos.pos == MyGravity_Vert_Top) + { + val = myFrame.top + offsetVal; + } + else if (lpos.pos == MyGravity_Vert_Center) + { + val = myFrame.top + myFrame.height / 2.0 + offsetVal; + } + else + { + val = myFrame.bottom - offsetVal; + } + } + + retVal = _isMax ? _myCGFloatMax(val, retVal) : _myCGFloatMin(val, retVal); + } + else + { + NSAssert(NO, @"oops!, invalid type, only support NSNumber or MyLayoutPos"); + } + } + + return retVal; +} + +@end + + +@implementation NSArray(MyLayoutExtremePos) + +-(MyLayoutExtremePos *)myMinPos +{ + return [[MyLayoutExtremePos alloc] initWith:self isMax:NO]; +} + +-(MyLayoutExtremePos *)myMaxPos +{ + return [[MyLayoutExtremePos alloc] initWith:self isMax:YES]; +} + @end diff --git a/MyLayout/Lib/MyLayoutPosInner.h b/MyLayout/Lib/MyLayoutPosInner.h index a483495..c0a850e 100644 --- a/MyLayout/Lib/MyLayoutPosInner.h +++ b/MyLayout/Lib/MyLayoutPosInner.h @@ -20,6 +20,7 @@ @property(nonatomic, readonly, strong) NSNumber *posNumVal; @property(nonatomic, readonly, strong) MyLayoutPos *posRelaVal; @property(nonatomic, readonly, strong) NSArray *posArrVal; +@property(nonatomic, readonly, strong) NSNumber *posExtremeVal; @property(nonatomic, readonly, strong) MyLayoutPos *lBoundVal; @property(nonatomic, readonly, strong) MyLayoutPos *uBoundVal; @@ -57,6 +58,13 @@ -(BOOL)isSafeAreaPos; +@end + +@interface MyLayoutExtremePos:NSObject + +-(instancetype)initWith:(NSArray *)poss isMax:(BOOL)isMax; +//获取极限值 +-(CGFloat)getExtremePosFrom:(MyLayoutPos *)layoutPos; @end diff --git a/MyLayout/Lib/MyLayoutSize.h b/MyLayout/Lib/MyLayoutSize.h index 6dcd67f..30194b1 100644 --- a/MyLayout/Lib/MyLayoutSize.h +++ b/MyLayout/Lib/MyLayoutSize.h @@ -215,7 +215,7 @@ @property(nonatomic, assign, readonly) CGFloat minVal; @property(nonatomic, assign, readonly) CGFloat maxVal; -//判断尺寸值是否是包裹自适应 +//判断尺寸值是否是自适应值。 @property(nonatomic, assign, readonly) BOOL isWrap; @end @@ -223,7 +223,7 @@ @interface MyLayoutSize(Detach) -//从布局尺寸中分离出一个尺寸对象来。这个分离出来的尺寸值是源尺寸对象的值乘以multival再加上addVal。这个方法用于下面数组元素的构造 +//从布局尺寸中分离出一个尺寸对象来。这个分离出来的尺寸值是源尺寸对象的值乘以multival再加上addVal。这个方法通常用于下面数组元素的构造 -(MyLayoutSize* (^)(CGFloat addVal, CGFloat multiVal))detach; @end @@ -235,9 +235,9 @@ */ @interface NSArray(MyLayoutExtremeSize) -//从数组中得到最小的尺寸值。 +//从数组中得到最小的尺寸值。要求数组的元素必须是MyLayoutSize类型 @property(nonatomic, readonly) MyLayoutExtremeSize *myMinSize; -//从数组中得到最小的尺寸值。 +//从数组中得到最小的尺寸值。要求数组的元素必须是MyLayoutSize类型 @property(nonatomic, readonly) MyLayoutExtremeSize *myMaxSize; @end diff --git a/MyLayout/Lib/MyLayoutSize.m b/MyLayout/Lib/MyLayoutSize.m index 85369a0..254d5eb 100644 --- a/MyLayout/Lib/MyLayoutSize.m +++ b/MyLayout/Lib/MyLayoutSize.m @@ -222,32 +222,31 @@ -(BOOL)isWrap -(id)copyWithZone:(NSZone *)zone { - MyLayoutSize *ld = [[[self class] allocWithZone:zone] init]; - ld.view = self.view; - ld->_active = _active; - ld->_shrink = _shrink; - ld->_dime = _dime; - ld->_addVal = _addVal; - ld->_multiVal = _multiVal; - ld->_dimeVal = _dimeVal; - ld->_dimeValType = _dimeValType; - ld->_priority = _priority; + MyLayoutSize *layoutSize = [[[self class] allocWithZone:zone] init]; + layoutSize.view = self.view; + layoutSize->_active = _active; + layoutSize->_shrink = _shrink; + layoutSize->_dime = _dime; + layoutSize->_addVal = _addVal; + layoutSize->_multiVal = _multiVal; + layoutSize->_dimeVal = _dimeVal; + layoutSize->_dimeValType = _dimeValType; + layoutSize->_priority = _priority; if (_lBoundVal != nil) { - ld->_lBoundVal = [[[self class] allocWithZone:zone] init]; - ld->_lBoundVal->_active = _active; - [[[ld->_lBoundVal __equalTo:_lBoundVal.dimeVal] __add:_lBoundVal.addVal] __multiply:_lBoundVal.multiVal]; + layoutSize->_lBoundVal = [[[self class] allocWithZone:zone] init]; + layoutSize->_lBoundVal->_active = _active; + [[[layoutSize->_lBoundVal __equalTo:_lBoundVal.dimeVal] __add:_lBoundVal.addVal] __multiply:_lBoundVal.multiVal]; } if (_uBoundVal != nil) { - ld->_uBoundVal = [[[self class] allocWithZone:zone] init]; - ld->_uBoundVal->_active = _active; - [[[ld->_uBoundVal __equalTo:_uBoundVal.dimeVal] __add:_uBoundVal.addVal] __multiply:_uBoundVal.multiVal]; + layoutSize->_uBoundVal = [[[self class] allocWithZone:zone] init]; + layoutSize->_uBoundVal->_active = _active; + [[[layoutSize->_uBoundVal __equalTo:_uBoundVal.dimeVal] __add:_uBoundVal.addVal] __multiply:_uBoundVal.multiVal]; } - - return self; + return layoutSize; } #pragma mark -- Private Methods @@ -625,12 +624,12 @@ @implementation MyLayoutSize(Detach) { return ^id(CGFloat addVal, CGFloat multiVal){ - MyLayoutSize *ld = [[[self class] allocWithZone:nil] init]; - ld->_addVal = addVal; - ld->_multiVal = multiVal; - ld->_dimeVal = self; - ld->_dimeValType = MyLayoutValueType_LayoutDimeDetach; - return ld; + MyLayoutSize *detachSize = [[[self class] allocWithZone:nil] init]; + detachSize->_addVal = addVal; + detachSize->_multiVal = multiVal; + detachSize->_dimeVal = self; + detachSize->_dimeValType = MyLayoutValueType_LayoutDimeDetach; + return detachSize; }; } diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index a109b1e..b777a03 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -187,6 +187,11 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; } + else if (sbvsc.centerXPosInner.posExtremeVal != nil) + { + sbvmyFrame.leading = sbvsc.centerXPosInner.posExtremeVal.doubleValue - sbvmyFrame.width / 2 + sbvsc.centerXPosInner.absVal; + sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; + } else if (sbvsc.centerXPosInner.posNumVal != nil) { sbvmyFrame.leading = (selfSize.width - lsc.myLayoutLeadingPadding - lsc.myLayoutTrailingPadding - sbvmyFrame.width) / 2 + lsc.myLayoutLeadingPadding + sbvsc.centerXPosInner.absVal; @@ -212,6 +217,11 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; } + else if (sbvsc.leadingPosInner.posExtremeVal != nil) + { + sbvmyFrame.leading = sbvsc.leadingPosInner.posExtremeVal.doubleValue + sbvsc.leadingPosInner.absVal; + sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; + } else if (sbvsc.leadingPosInner.posNumVal != nil) { sbvmyFrame.leading = sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; @@ -232,6 +242,11 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv sbvmyFrame.leading = sbvmyFrame.trailing - sbvmyFrame.width; } + else if (sbvsc.trailingPosInner.posExtremeVal != nil) + { + sbvmyFrame.trailing = sbvsc.trailingPosInner.posExtremeVal.doubleValue - sbvsc.trailingPosInner.absVal + sbvsc.leadingPosInner.absVal; + sbvmyFrame.leading = sbvmyFrame.trailing - sbvmyFrame.width; + } else if (sbvsc.trailingPosInner.posNumVal != nil) { sbvmyFrame.trailing = selfSize.width - lsc.myLayoutTrailingPadding - sbvsc.trailingPosInner.absVal + sbvsc.leadingPosInner.absVal; @@ -239,7 +254,6 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv } else { - sbvmyFrame.leading = sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; } @@ -343,7 +357,20 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL } sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; - + } + else if (sbvsc.baselinePosInner.posExtremeVal != nil) + { + UIFont *sbvFont = [self myGetSubviewFont:sbv]; + if (sbvFont != nil) + { + sbvmyFrame.top = sbvsc.baselinePosInner.posExtremeVal.doubleValue + sbvsc.baselinePosInner.absVal - sbvFont.ascender - (sbvmyFrame.height - sbvFont.lineHeight) / 2; + } + else + { + sbvmyFrame.top = sbvsc.baselinePosInner.posExtremeVal.doubleValue + sbvsc.baselinePosInner.absVal; + } + + sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; } else if (sbvsc.baselinePosInner.posNumVal != nil) { @@ -379,6 +406,15 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; } + else if (sbvsc.centerYPosInner.posExtremeVal != nil) + { + sbvmyFrame.top = sbvsc.centerYPosInner.posExtremeVal.doubleValue + sbvsc.centerYPosInner.absVal - sbvmyFrame.height / 2; + + if (sbvmyFrame.top < 0 && lsc.heightSizeInner.dimeWrapVal) + sbvmyFrame.top = 0; + + sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; + } else if (sbvsc.centerYPosInner.posNumVal != nil) { sbvmyFrame.top = (selfSize.height - lsc.myLayoutTopPadding - lsc.myLayoutBottomPadding - sbvmyFrame.height) / 2 + lsc.myLayoutTopPadding + sbvsc.centerYPosInner.absVal; @@ -403,6 +439,11 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; } + else if (sbvsc.topPosInner.posExtremeVal != nil) + { + sbvmyFrame.top = sbvsc.topPosInner.posExtremeVal.doubleValue + sbvsc.topPosInner.absVal; + sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; + } else if (sbvsc.topPosInner.posNumVal != nil) { sbvmyFrame.top = sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding; @@ -422,6 +463,11 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL sbvmyFrame.top = sbvmyFrame.bottom - sbvmyFrame.height; } + else if (sbvsc.bottomPosInner.posExtremeVal != nil) + { + sbvmyFrame.bottom = sbvsc.bottomPosInner.posExtremeVal.doubleValue - sbvsc.bottomPosInner.absVal + sbvsc.topPosInner.absVal; + sbvmyFrame.top = sbvmyFrame.bottom - sbvmyFrame.height; + } else if (sbvsc.bottomPosInner.posNumVal != nil) { if (selfSize.height == 0 && lsc.heightSizeInner.dimeWrapVal) @@ -703,6 +749,10 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame.leading -= sbvsc.leadingPosInner.absVal; } } + else if (sbvsc.leadingPosInner.posExtremeVal != nil) + { + sbvmyFrame.leading = sbvsc.leadingPosInner.posExtremeVal.doubleValue + sbvsc.leadingPosInner.absVal; + } else sbvmyFrame.leading = sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; @@ -715,6 +765,10 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame.trailing += sbvsc.trailingPosInner.absVal; } } + else if (sbvsc.trailingPosInner.posExtremeVal != nil) + { + sbvmyFrame.trailing = sbvsc.trailingPosInner.posExtremeVal.doubleValue - sbvsc.trailingPosInner.absVal; + } else { //如果设置了宽度则认为trailing是尾部间距。 @@ -741,9 +795,7 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; } - return YES; - } @@ -768,6 +820,16 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize { + BOOL sbvWrapContentHeight = sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]; + if (sbvWrapContentHeight && !sbvsc.widthSizeInner.dimeWrapVal) + { + [self myCalcSubViewLeadingTrailing:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + + //特殊处理高度包裹的情况,如果高度包裹时则同时设置顶部和底部将无效。 + sbvmyFrame.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:sbvmyFrame.width]; + sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + } + if (sbvmyFrame.height == CGFLOAT_MAX) { if (sbvsc.heightSizeInner.dimeRelaVal != nil) @@ -804,6 +866,10 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc } } + else if (sbvsc.topPosInner.posExtremeVal != nil) + { + sbvmyFrame.top = sbvsc.topPosInner.posExtremeVal.doubleValue + sbvsc.topPosInner.absVal; + } else sbvmyFrame.top = sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding; @@ -818,6 +884,10 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame.bottom += sbvsc.bottomPosInner.absVal; } } + else if (sbvsc.bottomPosInner.posExtremeVal != nil) + { + sbvmyFrame.bottom = sbvsc.bottomPosInner.posExtremeVal.doubleValue - sbvsc.bottomPosInner.absVal; + } else { //如果设置了高度则认为bottom是尾部间距。 diff --git a/MyLayoutDemo/AllTest1TableViewCell.m b/MyLayoutDemo/AllTest1TableViewCell.m index 2ca167a..90405f8 100644 --- a/MyLayoutDemo/AllTest1TableViewCell.m +++ b/MyLayoutDemo/AllTest1TableViewCell.m @@ -30,8 +30,8 @@ -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSStri /** * 您可以尝试用不同的布局来实现相同的功能。 */ - [self createLinearRootLayout]; - // [self createRelativeRootLayout]; + // [self createLinearRootLayout]; + [self createRelativeRootLayout]; // [self createFloatRootLayout]; diff --git a/MyLayoutDemo/AllTest2TableViewCell.m b/MyLayoutDemo/AllTest2TableViewCell.m index 876d970..76655af 100644 --- a/MyLayoutDemo/AllTest2TableViewCell.m +++ b/MyLayoutDemo/AllTest2TableViewCell.m @@ -31,7 +31,7 @@ -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSStri /** * 您可以尝试用不同的布局来实现相同的功能。 */ - //[self createLinearRootLayout]; + // [self createLinearRootLayout]; [self createRelativeRootLayout]; // [self createFloatRootLayout]; } diff --git a/MyLayoutDemo/AllTest3ViewController.m b/MyLayoutDemo/AllTest3ViewController.m index 890246d..1420c3b 100644 --- a/MyLayoutDemo/AllTest3ViewController.m +++ b/MyLayoutDemo/AllTest3ViewController.m @@ -348,7 +348,8 @@ -(void)addActiveLayout:(MyLinearLayout*)contentLayout [testButton setTitle:@"Click me" forState:UIControlStateNormal]; testButton.backgroundColor = [CFTool color:0]; testButton.heightSize.equalTo(@50); - testButton.widthSize.equalTo(testButton.widthSize).add(20); + // testButton.widthSize.equalTo(testButton.widthSize).add(20); + testButton.widthSize.equalTo(@(MyLayoutSize.wrap)).add(20); testButton.leadingPos.equalTo(@10).active = YES; //左边边距是10,设置active为YES表示左边位置对象的设置是生效的。 testButton.trailingPos.equalTo(@10).active = NO; //右边边距是10,设置active为NO表示右边位置对象的设置是不生效的。 @@ -716,16 +717,19 @@ -(void)handleActiveTest:(UIButton*)sender { sender.leadingPos.active = YES; sender.trailingPos.active = NO; //按钮将停靠在父布局的左边。 + sender.widthSize.active = YES; } else if (sender.leadingPos.isActive) { sender.leadingPos.active = NO; sender.trailingPos.active = YES; //按钮将停靠在父布局的右边 + sender.widthSize.active = YES; } else if (sender.trailingPos.isActive) { sender.leadingPos.active = YES; sender.trailingPos.active = YES; //按钮的左右边距都生效,并且会拉伸按钮的宽度。 + sender.widthSize.active = NO; } MyLinearLayout *superLayout = (MyLinearLayout*)sender.superview; diff --git a/MyLayoutDemo/AllTest6ViewController.m b/MyLayoutDemo/AllTest6ViewController.m index ca86537..4833452 100644 --- a/MyLayoutDemo/AllTest6ViewController.m +++ b/MyLayoutDemo/AllTest6ViewController.m @@ -34,7 +34,7 @@ -(void)loadView //创建顶部的菜单布局部分。 MyFlowLayout *menuLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; - menuLayout.gravity = MyGravity_Fill; //填充所有尺寸。 + menuLayout.gravity = MyGravity_Horz_Fill; //水平填充所有尺寸。 menuLayout.wrapContentHeight = YES; menuLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); menuLayout.subviewSpace = 10; @@ -46,7 +46,7 @@ -(void)loadView menu1Label.backgroundColor = [CFTool color:5]; menu1Label.font = [CFTool font:16]; menu1Label.heightSize.equalTo(menu1Label.widthSize); - menu1Label.widthSize.equalTo(menu1Label.heightSize); + // menu1Label.widthSize.equalTo(menu1Label.heightSize); [menuLayout addSubview:menu1Label]; UILabel *menu2Label = [UILabel new]; @@ -55,7 +55,7 @@ -(void)loadView menu2Label.backgroundColor = [CFTool color:6]; menu2Label.font = [CFTool font:16]; menu2Label.heightSize.equalTo(menu2Label.widthSize); - menu2Label.widthSize.equalTo(menu2Label.heightSize); + // menu2Label.widthSize.equalTo(menu2Label.heightSize); [menuLayout addSubview:menu2Label]; UILabel *menu3Label = [UILabel new]; @@ -64,7 +64,7 @@ -(void)loadView menu3Label.backgroundColor = [CFTool color:7]; menu3Label.font = [CFTool font:16]; menu3Label.heightSize.equalTo(menu3Label.widthSize); - menu3Label.widthSize.equalTo(menu3Label.heightSize); + // menu3Label.widthSize.equalTo(menu3Label.heightSize); [menuLayout addSubview:menu3Label]; MyRelativeLayout *contentLayout = [MyRelativeLayout new]; @@ -113,8 +113,19 @@ -(void)loadView MyFlowLayout *menuLayoutSC = [menuLayout fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact copyFrom:MySizeClass_hAny | MySizeClass_wAny]; menuLayoutSC.orientation = MyOrientation_Horz; + menuLayoutSC.gravity = MyGravity_Vert_Fill; menuLayoutSC.wrapContentWidth = YES; + UILabel *menu1LabelSC = [menu1Label fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact]; + UILabel *menu2LabelSC = [menu2Label fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact]; + UILabel *menu3LabelSC = [menu3Label fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact]; + + menu1LabelSC.widthSize.equalTo(menu1LabelSC.heightSize); + menu2LabelSC.widthSize.equalTo(menu2LabelSC.heightSize); + menu3LabelSC.widthSize.equalTo(menu3LabelSC.heightSize); + + + UILabel *func1LabelSC = [func1Label fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact]; UILabel *func2LabelSC = [func2Label fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact]; @@ -128,12 +139,12 @@ -(void)loadView func3LabelSC.heightSize.equalTo(contentLayout.heightSize); //下面是定义在iPad上设备的横屏的界面布局,因为iPad上的SizeClass都是regular,所以这里要区分横竖屏的方法是使用MySizeClass_Portrait和MySizeClass_Landscape - UILabel *menu1LabelSC = [menu1Label fetchLayoutSizeClass:MySizeClass_wRegular | MySizeClass_hRegular | MySizeClass_Landscape copyFrom:MySizeClass_wAny | MySizeClass_hAny]; - menu1LabelSC.heightSize.max(200); - UILabel *menu2LabelSC = [menu2Label fetchLayoutSizeClass:MySizeClass_wRegular | MySizeClass_hRegular | MySizeClass_Landscape copyFrom:MySizeClass_wAny | MySizeClass_hAny]; - menu2LabelSC.heightSize.max(200); - UILabel *menu3LabelSC = [menu3Label fetchLayoutSizeClass:MySizeClass_wRegular | MySizeClass_hRegular | MySizeClass_Landscape copyFrom:MySizeClass_wAny | MySizeClass_hAny]; - menu3LabelSC.heightSize.max(200); + UILabel *menu1LabelSCForiPad = [menu1Label fetchLayoutSizeClass:MySizeClass_wRegular | MySizeClass_hRegular | MySizeClass_Landscape copyFrom:MySizeClass_wAny | MySizeClass_hAny]; + menu1LabelSCForiPad.heightSize.max(200); + UILabel *menu2LabelSCForiPad = [menu2Label fetchLayoutSizeClass:MySizeClass_wRegular | MySizeClass_hRegular | MySizeClass_Landscape copyFrom:MySizeClass_wAny | MySizeClass_hAny]; + menu2LabelSCForiPad.heightSize.max(200); + UILabel *menu3LabelSCForiPad = [menu3Label fetchLayoutSizeClass:MySizeClass_wRegular | MySizeClass_hRegular | MySizeClass_Landscape copyFrom:MySizeClass_wAny | MySizeClass_hAny]; + menu3LabelSCForiPad.heightSize.max(200); } diff --git a/MyLayoutDemo/AllTest7ViewController.m b/MyLayoutDemo/AllTest7ViewController.m index 5d6b524..e9b4934 100644 --- a/MyLayoutDemo/AllTest7ViewController.m +++ b/MyLayoutDemo/AllTest7ViewController.m @@ -64,7 +64,8 @@ -(void) loadView [self createDemo11:rootLayout]; - + [self createDemo12:rootLayout]; + } @@ -747,6 +748,54 @@ -(void)createDemo11:(MyLinearLayout*)rootLayout } +-(void)createDemo12:(MyLinearLayout*)rootLayout +{ + //一行内的子视图的间距会根据屏幕尺寸自动缩小。 + UILabel *tipLabel = [UILabel new]; + tipLabel.text = @"12. 当布局视图下有多个子视图时有可能无法将这些子视图显示完全,而是需要将某些子视图的尺寸或者子视图之间的间距进行压缩处理。这里可以通过设置子视图尺寸中的shrink或者间距中的shrink值来进行处理。默认情况下这些值都是0表明不压缩,值越大压缩就越大"; + tipLabel.font = [CFTool font:14]; + tipLabel.adjustsFontSizeToFitWidth = YES; + tipLabel.wrapContentHeight = YES; + tipLabel.myTop = 10; + [tipLabel sizeToFit]; + [rootLayout addSubview:tipLabel]; + + MyLinearLayout *contentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + contentLayout.wrapContentWidth = NO; + contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); + contentLayout.heightSize.equalTo(@(MyLayoutSize.wrap)).min(60); + contentLayout.gravity = MyGravity_Vert_Center; //内容垂直居中。 + contentLayout.backgroundColor = [CFTool color:0]; + [rootLayout addSubview:contentLayout]; + + UILabel *A = [self createLabel:@"不压缩" color:5]; + A.widthSize.equalTo(@(MyLayoutSize.wrap)); + A.heightSize.equalTo(@(MyLayoutSize.wrap)); + A.widthSize.shrink = 0; + [contentLayout addSubview:A]; + + UILabel *B = [self createLabel:@"压缩1,间距不压缩" color:6]; + B.widthSize.equalTo(@(MyLayoutSize.wrap)); + B.heightSize.equalTo(@(MyLayoutSize.wrap)); + B.widthSize.shrink = 1; + B.leftPos.equalTo(@(20)).shrink = 0; + [contentLayout addSubview:B]; + + UILabel *C = [self createLabel:@"压缩2,间距压缩1" color:7]; + C.widthSize.equalTo(@(MyLayoutSize.wrap)); + C.heightSize.equalTo(@(MyLayoutSize.wrap)); + C.widthSize.shrink = 2; + C.leftPos.equalTo(@(20)).shrink = 1; + [contentLayout addSubview:C]; + + UILabel *D = [self createLabel:@"压缩3,间距压缩2" color:8]; + D.widthSize.equalTo(@(MyLayoutSize.wrap)); + D.heightSize.equalTo(@(MyLayoutSize.wrap)); + D.widthSize.shrink = 3; + D.leftPos.equalTo(@(20)).shrink = 2; + [contentLayout addSubview:D]; +} + - (void)viewDidLoad { diff --git a/MyLayoutDemo/RLTest1ViewController.m b/MyLayoutDemo/RLTest1ViewController.m index 28452a3..5a4dbf3 100644 --- a/MyLayoutDemo/RLTest1ViewController.m +++ b/MyLayoutDemo/RLTest1ViewController.m @@ -247,6 +247,17 @@ -(void)loadView }]; */ + UIView *squareView = [UIView new]; + squareView.backgroundColor = [CFTool color:9]; + //宽度是父布局宽度和高度二者之间的最小值的1/5, 高度等于宽度。 + //这里面用到了数组的一个扩展属性myMinSize。要求数组中的元素必须是MyLayoutSize类型,而且这些值也必须在本视图约束计算前已经有明确的值。 + squareView.widthSize.equalTo(@[rootLayout.widthSize, rootLayout.heightSize].myMinSize).multiply(0.2); + squareView.heightSize.equalTo(squareView.widthSize); + squareView.centerXPos.equalTo(rootLayout.centerXPos); + squareView.centerYPos.equalTo(rootLayout.centerYPos).offset(40); + [rootLayout addSubview:squareView]; + + /* 左下角区域部分。 */ diff --git a/MyLayoutDemo/RLTest6ViewController.h b/MyLayoutDemo/RLTest6ViewController.h new file mode 100644 index 0000000..56fea66 --- /dev/null +++ b/MyLayoutDemo/RLTest6ViewController.h @@ -0,0 +1,16 @@ +// +// RLTest6ViewController.h +// MyLayout +// +// Created by oybq on 16/12/19. +// Copyright (c) 2016年 YoungSoft. All rights reserved. +// + +#import + +/** + * 6.RelativeLayout - ExtremeSize + */ +@interface RLTest6ViewController : UIViewController + +@end diff --git a/MyLayoutDemo/RLTest6ViewController.m b/MyLayoutDemo/RLTest6ViewController.m new file mode 100644 index 0000000..327bb6d --- /dev/null +++ b/MyLayoutDemo/RLTest6ViewController.m @@ -0,0 +1,121 @@ +// +// RLTest6ViewController.m +// MyLayout +// +// Created by oybq on 16/12/19. +// Copyright (c) 2016年 YoungSoft. All rights reserved. +// + +#import "RLTest6ViewController.h" +#import "MyLayout.h" +#import "CFTool.h" + +@interface RLTest6ViewController () + + + + +@end + +@implementation RLTest6ViewController + + +-(void)loadView +{ + [super loadView]; + //宽度和高度。 + // +} + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + + + MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + rootLayout.myMargin = 0; + [self.view addSubview:rootLayout]; + + MyRelativeLayout *layout1 = [self createLayoutName:@"张三" date:@"2019-10-07" detail:@"short detail"]; + layout1.topPos.equalTo(rootLayout.topPos); + layout1.leftPos.equalTo(rootLayout.leftPos); + layout1.backgroundColor = [CFTool color:3]; + // [rootLayout addSubview:layout1]; + + MyRelativeLayout *layout2 = [self createLayoutName:@"欧阳大哥" date:@"2019-10-07" detail:@"this is a middle length detail"]; + layout2.topPos.equalTo(layout1.bottomPos).offset(20); + layout2.leftPos.equalTo(rootLayout.leftPos); + layout2.backgroundColor = [CFTool color:4]; + // [rootLayout addSubview:layout2]; + + + MyRelativeLayout *layout3 = [self createLayoutName:@"李四" date:@"2019-10-07" detail:@"this is a long long long long long long long long length detail"]; + // layout3.topPos.equalTo(layout2.bottomPos).offset(20); + // layout3.leftPos.equalTo(rootLayout.leftPos); + layout3.backgroundColor = [CFTool color:5]; + [rootLayout addSubview:layout3]; + + + //三个例子: 底下的文字太少,底下的文字中等,底下的文字太长。 + + + +} + +-(MyRelativeLayout*)createLayoutName:(NSString*)name date:(NSString*)date detail:(NSString*)detail +{ + MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + rootLayout.widthSize.equalTo(@(MyLayoutSize.wrap)); + rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); + rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); + + + //名字控件,尺寸是自适应的。 + UILabel *nameLabel = [UILabel new]; + nameLabel.text = name; + nameLabel.widthSize.equalTo(@(MyLayoutSize.wrap)); + nameLabel.heightSize.equalTo(@(MyLayoutSize.wrap)); + // [rootLayout addSubview:nameLabel]; + + //详情控件,尺寸是自适应的,但是最宽是屏幕宽度减20,这里减20的原因是因为布局视图设置了左右padding为10。 + UILabel *detailLabel = [UILabel new]; + detailLabel.text = detail; + //宽度自适应,最宽是屏幕的宽度减去20 + detailLabel.widthSize.equalTo(@(MyLayoutSize.wrap)).uBound(self.view.widthSize, -20, 1); + detailLabel.heightSize.equalTo(@(MyLayoutSize.wrap)); + detailLabel.topPos.equalTo(nameLabel.bottomPos).offset(10); + detailLabel.leftPos.equalTo(nameLabel.leftPos); + [rootLayout addSubview:detailLabel]; + + //日期控件,右边和详情控件对齐,但是当详情控件的内容太少时,起码要和名字控件最小的距离是40 + UILabel *dateLabel = [UILabel new]; + dateLabel.text = date; + [dateLabel sizeToFit]; //这里直接计算出date的size是自适应的 +// [rootLayout addSubview:dateLabel]; + dateLabel.topPos.equalTo(nameLabel.topPos); + //最新版本的相对布局可以让子视图的位置设置为某些视图位置中的最大或者最小值,也就是极限值,我们可以对一个数组调用扩展分类的方法myMaxPos或者myMinPos来获取 + //到数组中元素的最大或者最小位置值。使用最大最小值的前提是在计算当前位置的约束时,要求数组中的元素的约束都是已经计算好了的,否则得到的结果是未可知,就如本例中 + //在计算dateLabel的右边距时,detailLabel以及nameLabel的右边距都是已经计算好了的。 + dateLabel.rightPos.equalTo(@[detailLabel.rightPos, nameLabel.rightPos.detach(-1 *(40+dateLabel.frame.size.width))].myMaxPos); + + return rootLayout; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/MyLayoutDemo/ViewController.m b/MyLayoutDemo/ViewController.m index 75a5478..ef53b0c 100644 --- a/MyLayoutDemo/ViewController.m +++ b/MyLayoutDemo/ViewController.m @@ -27,7 +27,7 @@ #import "RLTest3ViewController.h" #import "RLTest4ViewController.h" #import "RLTest5ViewController.h" - +#import "RLTest6ViewController.h" #import "TLTest1ViewController.h" #import "TLTest2ViewController.h" @@ -149,6 +149,9 @@ -(NSArray*)demoTypeList }, @{@"title":NSLocalizedString(@"5.RelativeLayout - Boundary limit", @""), @"class":[RLTest5ViewController class] + }, + @{@"title":NSLocalizedString(@"6.RelativeLayout - ExtremeSize", @""), + @"class":[RLTest6ViewController class] } ] }, diff --git a/MyLayoutTests/MyFloatLayoutTestCase.m b/MyLayoutTests/MyFloatLayoutTestCase.m index 4e2d50c..2d68916 100644 --- a/MyLayoutTests/MyFloatLayoutTestCase.m +++ b/MyLayoutTests/MyFloatLayoutTestCase.m @@ -7,13 +7,7 @@ // #import "MyLayoutTestCaseBase.h" -#import "FOLTest1ViewController.h" -#import "FOLTest2ViewController.h" -#import "FOLTest3ViewController.h" -#import "FOLTest4ViewController.h" -#import "FOLTest5ViewController.h" -#import "FOLTest6ViewController.h" -#import "FOLTest7ViewController.h" + @interface MyFloatLayoutTestCase : MyLayoutTestCaseBase @@ -34,30 +28,14 @@ - (void)tearDown { - (void)testExample { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. - FOLTest1ViewController *vc1 = [FOLTest1ViewController new]; - FOLTest2ViewController *vc2 = [FOLTest2ViewController new]; - FOLTest3ViewController *vc3 = [FOLTest3ViewController new]; - FOLTest4ViewController *vc4 = [FOLTest4ViewController new]; - FOLTest5ViewController *vc5 = [FOLTest5ViewController new]; - FOLTest6ViewController *vc6 = [FOLTest6ViewController new]; - FOLTest7ViewController *vc7 = [FOLTest7ViewController new]; - - UIView *v1 = vc1.view; - UIView *v2= vc2.view; - UIView *v3 = vc3.view; - UIView *v4 = vc4.view; - UIView *v5 = vc5.view; - UIView *v6 = vc6.view; - UIView *v7 = vc7.view; - - - [v1 layoutIfNeeded]; - [v2 layoutIfNeeded]; - [v3 layoutIfNeeded]; - [v4 layoutIfNeeded]; - [v5 layoutIfNeeded]; - [v6 layoutIfNeeded]; - [v7 layoutIfNeeded]; + for (int i = 1; i <= 7; i++) + { + Class cls = NSClassFromString([NSString stringWithFormat:@"FOLTest%dViewController", i]); + UIViewController *vc = [[cls alloc] init]; + UIView *v = vc.view; + [v setNeedsLayout]; + [v layoutIfNeeded]; + } } diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index 77d9892..0c83748 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -27,6 +27,15 @@ - (void)tearDown { - (void)testExample { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. + + for (int i = 1; i <= 9; i++) + { + Class cls = NSClassFromString([NSString stringWithFormat:@"FLLTest%dViewController", i]); + UIViewController *vc = [[cls alloc] init]; + UIView *v = vc.view; + [v setNeedsLayout]; + [v layoutIfNeeded]; + } } diff --git a/MyLayoutTests/MyFrameLayoutTestCase.m b/MyLayoutTests/MyFrameLayoutTestCase.m index 9c05c00..ae5f58a 100644 --- a/MyLayoutTests/MyFrameLayoutTestCase.m +++ b/MyLayoutTests/MyFrameLayoutTestCase.m @@ -28,17 +28,14 @@ - (void)tearDown { -(void)testExample { - FLTest1ViewController *vc1 = [FLTest1ViewController new]; - FLTest2ViewController *vc2 = [FLTest2ViewController new]; - - - [self startClock]; - UIView *v1 = vc1.view; - UIView *v2= vc2.view; - - [v1 layoutIfNeeded]; - [v2 layoutIfNeeded]; + for (int i = 1; i <=2; i++) + { + Class cls = NSClassFromString([NSString stringWithFormat:@"FLTest%dViewController", i]); + UIViewController *vc = [cls new]; + UIView *v = vc.view; + [v layoutIfNeeded]; + } } diff --git a/MyLayoutTests/MyGridLayoutTestCase.m b/MyLayoutTests/MyGridLayoutTestCase.m new file mode 100644 index 0000000..7d32a48 --- /dev/null +++ b/MyLayoutTests/MyGridLayoutTestCase.m @@ -0,0 +1,57 @@ +// +// MyFloatLayoutTestCase.m +// MyLayout +// +// Created by apple on 17/4/26. +// Copyright © 2017年 YoungSoft. All rights reserved. +// + +#import "MyLayoutTestCaseBase.h" +#import "GLTest1ViewController.h" +#import "GLTest2ViewController.h" +#import "GLTest3ViewController.h" +#import "GLTest4ViewController.h" +#import "GLTest5ViewController.h" + + +@interface MyGridLayoutTestCase : MyLayoutTestCaseBase + +@end + +@implementation MyGridLayoutTestCase + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + for (int i = 1; i <= 5; i++) + { + Class cls = NSClassFromString([NSString stringWithFormat:@"GLTest%dViewController", i]); + UIViewController *vc = [[cls alloc] init]; + UIView *v = vc.view; + [v setNeedsLayout]; + [v layoutIfNeeded]; + } + +} + + +- (void)testPerformanceExample { + // This is an example of a performance test case. + + [self measureBlock:^{ + // Put the code you want to measure the time of here. + + }]; +} + +@end diff --git a/MyLayoutTests/MyLinearLayoutTestCase.m b/MyLayoutTests/MyLinearLayoutTestCase.m index 7dbfd2f..32e79f6 100644 --- a/MyLayoutTests/MyLinearLayoutTestCase.m +++ b/MyLayoutTests/MyLinearLayoutTestCase.m @@ -41,49 +41,22 @@ - (void)testExample { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. - LLTest1ViewController *vc1 = [LLTest1ViewController new]; - LLTest2ViewController *vc2 = [LLTest2ViewController new]; - LLTest3ViewController *vc3 = [LLTest3ViewController new]; - LLTest4ViewController *vc4 = [LLTest4ViewController new]; - LLTest5ViewController *vc5 = [LLTest5ViewController new]; - LLTest6ViewController *vc6 = [LLTest6ViewController new]; - LLTest7ViewController *vc7 = [LLTest7ViewController new]; - - - TLTest1ViewController *vc10 = [TLTest1ViewController new]; - TLTest2ViewController *vc11 = [TLTest2ViewController new]; - TLTest3ViewController *vc12 = [TLTest3ViewController new]; - TLTest4ViewController *vc13 = [TLTest4ViewController new]; - - - UIView *v1 = vc1.view; - UIView *v2= vc2.view; - UIView *v3 = vc3.view; - UIView *v4 = vc4.view; - UIView *v5 = vc5.view; - UIView *v6 = vc6.view; - UIView *v7 = vc7.view; - - UIView *v10 = vc10.view; - UIView *v11 = vc11.view; - UIView *v12 = vc12.view; - UIView *v13 = vc13.view; - - + for (int i = 1; i <=7; i++) + { + Class cls = NSClassFromString([NSString stringWithFormat:@"LLTest%dViewController", i]); + UIViewController *vc = [cls new]; + UIView *v = vc.view; + [v layoutIfNeeded]; + } - [v1 layoutIfNeeded]; - [v2 layoutIfNeeded]; - [v3 layoutIfNeeded]; - [v4 layoutIfNeeded]; - [v5 layoutIfNeeded]; - [v6 layoutIfNeeded]; - [v7 layoutIfNeeded]; + for (int i = 1; i <=3; i++) + { + Class cls = NSClassFromString([NSString stringWithFormat:@"TLTest%dViewController", i]); + UIViewController *vc = [cls new]; + UIView *v = vc.view; + [v layoutIfNeeded]; + } - [v10 layoutIfNeeded]; - [v11 layoutIfNeeded]; - [v12 layoutIfNeeded]; - [v13 layoutIfNeeded]; - for (int i = 1; i <=12; i++) { Class cls = NSClassFromString([NSString stringWithFormat:@"AllTest%dViewController", i]); diff --git a/MyLayoutTests/MyPathLayoutTestCase.m b/MyLayoutTests/MyPathLayoutTestCase.m new file mode 100644 index 0000000..287ce34 --- /dev/null +++ b/MyLayoutTests/MyPathLayoutTestCase.m @@ -0,0 +1,50 @@ +// +// MyFloatLayoutTestCase.m +// MyLayout +// +// Created by apple on 17/4/26. +// Copyright © 2017年 YoungSoft. All rights reserved. +// + +#import "MyLayoutTestCaseBase.h" + +@interface MyPathLayoutTestCase : MyLayoutTestCaseBase + +@end + +@implementation MyPathLayoutTestCase + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + for (int i = 1; i <= 5; i++) + { + Class cls = NSClassFromString([NSString stringWithFormat:@"PLTest%dViewController", i]); + UIViewController *vc = [[cls alloc] init]; + UIView *v = vc.view; + [v setNeedsLayout]; + [v layoutIfNeeded]; + } +} + + +- (void)testPerformanceExample { + // This is an example of a performance test case. + + [self measureBlock:^{ + // Put the code you want to measure the time of here. + + }]; +} + +@end diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index e6ea6d1..9e0d2b5 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -35,7 +35,7 @@ - (void)tearDown { -(void)testRLTest1VC { - for (int i = 0; i <= 5; i++) + for (int i = 1; i <= 5; i++) { Class cls = NSClassFromString([NSString stringWithFormat:@"RLTest%dViewController", i]); UIViewController *vc = [[cls alloc] init]; @@ -1072,6 +1072,66 @@ -(void)testMaxAndMin } +-(void)testExample1 +{ + MyRelativeLayout *rootLayout = [[MyRelativeLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 603)]; + + + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(100, 100); + v1.myTop = 100; + v1.myLeft = 100; + v1.visibility = MyVisibility_Gone; + [rootLayout addSubview:v1]; + + //某个视图的水平居中依赖另外一个视图,另外一个视图隐藏。 + UIView *v2 = [UIView new]; + v2.mySize = CGSizeMake(100, 100); + v2.centerXPos.equalTo(v1.centerXPos).offset(20); + v2.centerYPos.equalTo(v1.centerYPos).offset(20); + [rootLayout addSubview:v2]; + + //某个视图的左边依赖另外一个视图,另外一个视图隐藏。 + UIView *v3 = [UIView new]; + v3.mySize = CGSizeMake(100, 100); + v3.leadingPos.equalTo(v1.leadingPos).offset(20); + v3.bottomPos.equalTo(v1.bottomPos).offset(20); + [rootLayout addSubview:v3]; + + UIView *v4 = [UIView new]; + v4.mySize = CGSizeMake(100, 100); + v4.leadingPos.lBound(v3.leadingPos, 0); + v4.trailingPos.uBound(rootLayout.trailingPos,0); + v4.bottomPos.equalTo(@(10)); + [rootLayout addSubview:v4]; + + UIView *v5 = [UIView new]; + v5.mySize = CGSizeMake(100, 100); + v5.baselinePos.equalTo(v4.baselinePos).offset(20); + [rootLayout addSubview:v5]; + + UILabel *v6 = [UILabel new]; + v6.mySize = CGSizeMake(100, 100); + v6.baselinePos.equalTo(v1.baselinePos).offset(20); + [rootLayout addSubview:v6]; + + UILabel *v7 = [UILabel new]; + v7.mySize = CGSizeMake(100, 100); + v7.baselinePos.equalTo(@(40)); + [rootLayout addSubview:v7]; + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(100,100,0,0)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(50,50,100,100)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(100,0,100,100)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(187.5,493,100,100)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(0,20,100,100)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + XCTAssertTrue(CGRectEqualToRect(v6.frame, CGRectMake(0,44,100,100)), @"the v6.frame = %@",NSStringFromCGRect(v6.frame)); + XCTAssertTrue(CGRectEqualToRect(v7.frame, CGRectMake(0,-16,100,100)), @"the v7.frame = %@",NSStringFromCGRect(v7.frame)); +} + - (void)testPerformanceExample { // This is an example of a performance test case. [self measureBlock:^{ From ccc1c745e7d6548d59b01a40b89be138185fb2cf Mon Sep 17 00:00:00 2001 From: youngsoft Date: Tue, 8 Oct 2019 15:30:05 +0800 Subject: [PATCH 048/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.h | 169 +++++++++--------- MyLayout/Lib/MyBaseLayout.m | 106 +++++------ MyLayout/Lib/MyGridLayout.m | 2 +- MyLayout/Lib/MyLayoutInner.h | 2 +- MyLayout/Lib/MyLayoutMath.h | 4 +- MyLayout/Lib/MyLayoutPos.h | 38 +--- MyLayout/Lib/MyLayoutPos.m | 57 +++--- MyLayout/Lib/MyLayoutPosInner.h | 6 +- MyLayout/Lib/MyLayoutSize.h | 25 +-- MyLayout/Lib/MyLayoutSize.m | 66 +++---- MyLayout/Lib/MyLayoutSizeInner.h | 4 +- MyLayout/Lib/MyRelativeLayout.m | 51 +++--- MyLayoutDemo/RLTest6ViewController.h | 2 +- MyLayoutDemo/RLTest6ViewController.m | 154 ++++++++++++---- MyLayoutDemo/ViewController.m | 2 +- .../zh-Hans.lproj/Localizable.strings | 1 + MyLayoutTests/MyRelativeLayoutTestCase.m | 4 +- 17 files changed, 370 insertions(+), 323 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index 0e264ea..b2963ac 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -314,12 +314,12 @@ /** - *视图的宽度布局尺寸对象,可以通过其中的euqalTo方法来设置NSNumber,MyLayoutSize,NSArray,MyLayoutExtremeSize,UIView,nil这六种值 + *视图的宽度布局尺寸对象,可以通过其中的euqalTo方法来设置NSNumber,MyLayoutSize,NSArray,MyLayoutMostSize,UIView,nil这六种值 */ @property(nonatomic, readonly) MyLayoutSize *widthSize; /** - *视图的高度布局尺寸对象,可以通过其中的euqalTo方法来设置NSNumber,MyLayoutSize,NSArray,MyLayoutExtremeSize,UIView,nil这六种值 + *视图的高度布局尺寸对象,可以通过其中的euqalTo方法来设置NSNumber,MyLayoutSize,NSArray,MyLayoutMostSize,UIView,nil这六种值 */ @property(nonatomic, readonly) MyLayoutSize *heightSize; @@ -350,6 +350,85 @@ */ @property(nonatomic,assign) IBInspectable CGSize mySize; +/** + 设置子视图的相对比重尺寸。也就是子视图的尺寸并不是一个绝对值而是一个相对值,在最终布局时系统会根据布局视图的剩余尺寸来将这个相对的值转化为绝对的值。通过对子视图设置相对的尺寸可以很方便的适配各种屏幕尺寸的设备,以便达到完美的布局效果。这个属性默认值是0表示不使用相对尺寸。weight属性的引入是参考android中的weight的概念而来的。 + + 目前只有在线性布局、表格布局、流式布局、浮动布局下的子视图设置weight才有效,相对布局、框架布局、路径布局里面的子视图不支持weight属性的设置。 + 在不同的布局下的子视图的weight属性所表达的意义也有所差异: + + @note + 1.在线性布局和表格布局下: + + 1.1. 当线性布局是垂直线性布局时这个属性用来设置子视图高度占用父线性布局剩余高度的比重,这样子视图就不需要明确的设定高度值。 + + 1.2. 当线性布局是水平线性布局时这个属性用来设置子视图宽度占用父线性布局剩余宽度的比重,这样子视图就不需要明确的设定宽度值。 + + @code + 视图的真实尺寸值 = 布局视图剩余尺寸 * 当前视图的weight比重/(布局视图内所有设置了weight比重值的子视图比重之和)。 + @endcode + + 对一个垂直线性布局举例来说:假设布局视图的高度是100,A子视图占据了20的固定高度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: + @code + A子视图的高度 = 20 + B子视图的高度 = (100-20)*0.4/(0.4+0.6) = 32 + C子视图的高度 = (100-20)*0.6/(0.4+0.6) = 48 + @endcode + + 子视图设置weight属性时要注意如下几点: + + - 垂直线性布局必须指定明确的高度,而高度不能设置为自适应;水平线性布局必须指定明确的宽度,而不能使用wrapContentWidth属性。 + + - 如果比重属性设置为0的话则表示视图的尺寸必须要明确的被指定,这也是默认值。 + + - 线性布局里面的所有子视图的比重值的和不一定要求是1,比如线性布局里面两个视图的比重都设置为1和都设置为0.5以及都设置为0.1的意义是一样的,都是占用50%。 + + @note + 2.在流式布局下: + + 2.1. 当流式布局是垂直流式布局时这个属性用来设置子视图宽度占用父流式布局当前行的剩余宽度的比重,这样子视图就不需要明确的设定宽度值。 + + 2.2. 当流式布局是水平流式布局时这个属性用来设置子视图高度占用父流式布局当前列的剩余高度的比重,这样子视图就不需要明确的设定高度值。 + + 同时在数量约束和内容约束两种布局中视图设置的比重值在最终计算出真实尺寸时也是有差异的: + + @code + 数量约束流式布局内的视图的真实尺寸值 = 布局视图剩余尺寸 * 当前视图的weight比重/(视图所在行的所有设置了weight比重值的视图比重之和)。 + + 内容约束流式布局内的视图的真实尺寸值 = 布局视图剩余尺寸 * 当前视图的weight比重。 + + 对一个垂直数量约束流式布局举例来说:假设布局视图的宽度是100,A子视图占据了20的固定宽度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: + A子视图的宽度 = 20 + B子视图的宽度 = (100-20)*0.4/(0.4+0.6) = 32 + C子视图的宽度 = (100-20)*0.6/(0.4+0.6) = 48 + + 对一个垂直内容约束流式布局举例来说:假设布局视图的宽度是100,A子视图占据了20的固定宽度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: + A子视图的宽度 = 20 + B子视图的宽度 = (100-20)*0.4 = 32 + C子视图的宽度 = (100-20-32)*0.6 = 28.8 + @endcode + + + @note + 3. 在浮动布局下: + + 3.1. 当浮动布局的方向是垂直布局时,这个属性用来设置视图宽度占用当前浮动布局父视图剩余宽度的比重,这样视图就不需要明确的设定宽度值。 + + 3.2. 当浮动布局的方向是水平布局时,这个属性用来设置视图高度占用当前浮动布局父视图剩余高度的比重,这样子视图就不需要明确的设定高度值。 + + @code + 视图的真实尺寸 = 布局父视图的剩余尺寸 * 视图的weight比重值。 + @endcode + + 举例来说:假设一个垂直浮动布局视图的宽度是100,A子视图占据了20的固定宽度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: + + @code + A子视图的宽度 = 20 + B子视图的宽度 = (100-20)*0.4 = 32 + C子视图的宽度 = (100-20-32)*0.6 = 28.8 + @endcode + + */ +@property(nonatomic, assign) IBInspectable CGFloat weight; /** 设置视图不受布局父视图的布局约束控制和不再参与视图的布局,所有设置的其他扩展属性都将失效而必须用frame来设置视图的位置和尺寸,默认值是NO。这个属性主要用于某些视图希望在布局视图中进行特殊处理和进行自定义的设置的场景。比如一个垂直线性布局下有A,B,C三个子视图设置如下: @@ -924,6 +1003,7 @@ @end +#pragma mark -- MyLayoutDragger //布局视图拖动器类,用来实现布局内的视图的拖动封装。用于实现布局子视图的拖放处理。 //布局视图的拖动器类,只支持那些按顺序添加的布局视图,不支持相对布局、框架布局、栅格布局、路径布局。 @@ -951,6 +1031,11 @@ //当拖动的视图和现有视图重叠时是否支持悬停功能,默认为NO。当开启开关后,并且oldIndex和currentIndex相等时则处于悬停状态。开启悬停功能的目的是为了支持一些替换或者更新的能力。 @property(nonatomic, assign) BOOL canHover; +//当前是否正在悬停中。我们可以借助这个属性值判断来做一些操作处理。 +@property(nonatomic, assign, readonly) BOOL isHovering; + +//下列方法请在子视图的相应事件处理中调用。 + //开始拖动,请在子视图view的拖动开始事件处调用这个方法,其中view指定要开始拖动的视图。 -(void)dragView:(UIView *)view withEvent:(UIEvent *)event; //拖动中,请在子视图view的拖动过程事件中调用这个方法,其中的view指定拖动中的视图。 @@ -998,84 +1083,4 @@ */ @property(nonatomic, assign) BOOL wrapContentSize; -/** - 设置子视图的相对比重尺寸。也就是子视图的尺寸并不是一个绝对值而是一个相对值,在最终布局时系统会根据布局视图的剩余尺寸来将这个相对的值转化为绝对的值。通过对子视图设置相对的尺寸可以很方便的适配各种屏幕尺寸的设备,以便达到完美的布局效果。这个属性默认值是0表示不使用相对尺寸。weight属性的引入是参考android中的weight的概念而来的。 - - 目前只有在线性布局、表格布局、流式布局、浮动布局下的子视图设置weight才有效,相对布局、框架布局、路径布局里面的子视图不支持weight属性的设置。 - 在不同的布局下的子视图的weight属性所表达的意义也有所差异: - - @note - 1.在线性布局和表格布局下: - - 1.1. 当线性布局是垂直线性布局时这个属性用来设置子视图高度占用父线性布局剩余高度的比重,这样子视图就不需要明确的设定高度值。 - - 1.2. 当线性布局是水平线性布局时这个属性用来设置子视图宽度占用父线性布局剩余宽度的比重,这样子视图就不需要明确的设定宽度值。 - - @code - 视图的真实尺寸值 = 布局视图剩余尺寸 * 当前视图的weight比重/(布局视图内所有设置了weight比重值的子视图比重之和)。 - @endcode - - 对一个垂直线性布局举例来说:假设布局视图的高度是100,A子视图占据了20的固定高度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: - @code - A子视图的高度 = 20 - B子视图的高度 = (100-20)*0.4/(0.4+0.6) = 32 - C子视图的高度 = (100-20)*0.6/(0.4+0.6) = 48 - @endcode - - 子视图设置weight属性时要注意如下几点: - - - 垂直线性布局必须指定明确的高度,而高度不能设置为自适应;水平线性布局必须指定明确的宽度,而不能使用wrapContentWidth属性。 - - - 如果比重属性设置为0的话则表示视图的尺寸必须要明确的被指定,这也是默认值。 - - - 线性布局里面的所有子视图的比重值的和不一定要求是1,比如线性布局里面两个视图的比重都设置为1和都设置为0.5以及都设置为0.1的意义是一样的,都是占用50%。 - - @note - 2.在流式布局下: - - 2.1. 当流式布局是垂直流式布局时这个属性用来设置子视图宽度占用父流式布局当前行的剩余宽度的比重,这样子视图就不需要明确的设定宽度值。 - - 2.2. 当流式布局是水平流式布局时这个属性用来设置子视图高度占用父流式布局当前列的剩余高度的比重,这样子视图就不需要明确的设定高度值。 - - 同时在数量约束和内容约束两种布局中视图设置的比重值在最终计算出真实尺寸时也是有差异的: - - @code - 数量约束流式布局内的视图的真实尺寸值 = 布局视图剩余尺寸 * 当前视图的weight比重/(视图所在行的所有设置了weight比重值的视图比重之和)。 - - 内容约束流式布局内的视图的真实尺寸值 = 布局视图剩余尺寸 * 当前视图的weight比重。 - - 对一个垂直数量约束流式布局举例来说:假设布局视图的宽度是100,A子视图占据了20的固定宽度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: - A子视图的宽度 = 20 - B子视图的宽度 = (100-20)*0.4/(0.4+0.6) = 32 - C子视图的宽度 = (100-20)*0.6/(0.4+0.6) = 48 - - 对一个垂直内容约束流式布局举例来说:假设布局视图的宽度是100,A子视图占据了20的固定宽度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: - A子视图的宽度 = 20 - B子视图的宽度 = (100-20)*0.4 = 32 - C子视图的宽度 = (100-20-32)*0.6 = 28.8 - @endcode - - - @note - 3. 在浮动布局下: - - 3.1. 当浮动布局的方向是垂直布局时,这个属性用来设置视图宽度占用当前浮动布局父视图剩余宽度的比重,这样视图就不需要明确的设定宽度值。 - - 3.2. 当浮动布局的方向是水平布局时,这个属性用来设置视图高度占用当前浮动布局父视图剩余高度的比重,这样子视图就不需要明确的设定高度值。 - - @code - 视图的真实尺寸 = 布局父视图的剩余尺寸 * 视图的weight比重值。 - @endcode - - 举例来说:假设一个垂直浮动布局视图的宽度是100,A子视图占据了20的固定宽度,B子视图的weight设置为0.4,C子视图的weight设置为0.6 那么: - - @code - A子视图的宽度 = 20 - B子视图的宽度 = (100-20)*0.4 = 32 - C子视图的宽度 = (100-20-32)*0.6 = 28.8 - @endcode - - */ -@property(nonatomic, assign) IBInspectable CGFloat weight; - @end diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 338a0ce..f55e318 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -55,33 +55,26 @@ -(MyLayoutPos*)leadingPos return self.myCurrentSizeClass.leadingPos; } - - -(MyLayoutPos*)bottomPos { return self.myCurrentSizeClass.bottomPos; } - -(MyLayoutPos*)trailingPos { return self.myCurrentSizeClass.trailingPos; } - - -(MyLayoutPos*)centerXPos { return self.myCurrentSizeClass.centerXPos; } - -(MyLayoutPos*)centerYPos { return self.myCurrentSizeClass.centerYPos; } - -(MyLayoutPos*)leftPos { return self.myCurrentSizeClass.leftPos; @@ -98,7 +91,6 @@ -(MyLayoutPos*)baselinePos } - -(CGFloat)myTop { #if DEBUG @@ -223,7 +215,6 @@ -(void)setMyRight:(CGFloat)myRight } - -(CGFloat)myMargin { #if DEBUG @@ -271,7 +262,6 @@ -(MyLayoutSize*)widthSize } - -(MyLayoutSize*)heightSize { return self.myCurrentSizeClass.heightSize; @@ -313,7 +303,6 @@ -(void)setMySize:(CGSize)mySize self.myCurrentSizeClass.mySize = mySize; } - -(void)setWrapContentHeight:(BOOL)wrapContentHeight { UIView *sc = self.myCurrentSizeClass; @@ -340,7 +329,6 @@ -(void)setWrapContentWidth:(BOOL)wrapContentWidth if (self.superview != nil) [self.superview setNeedsLayout]; } - } -(BOOL)wrapContentWidth @@ -483,9 +471,6 @@ -(void)setViewLayoutCompleteBlock:(void (^)(MyBaseLayout *, UIView *))viewLayout } - - - -(CGRect)estimatedRect { CGRect rect = self.myFrame.frame; @@ -495,7 +480,6 @@ -(CGRect)estimatedRect } - -(void)resetMyLayoutSetting { [self resetMyLayoutSettingInSizeClass:MySizeClass_wAny | MySizeClass_hAny]; @@ -534,8 +518,6 @@ -(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass copyFrom:(MySizeClass } - - @end @@ -547,14 +529,10 @@ -(instancetype)myDefaultSizeClass return [self fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hAny]; } - -(instancetype)myCurrentSizeClass { MyFrame *myFrame = self.myFrame; //减少多次访问,增加性能。 - if (myFrame.sizeClass == nil) - myFrame.sizeClass = [self myDefaultSizeClass]; - - return myFrame.sizeClass; + return [self myCurrentSizeClassFrom:myFrame]; } -(instancetype)myCurrentSizeClassInner @@ -573,17 +551,13 @@ -(instancetype)myCurrentSizeClassFrom:(MyFrame*)myFrame } - - --(instancetype)myBestSizeClass:(MySizeClass)sizeClass +-(instancetype)myBestSizeClass:(MySizeClass)sizeClass myFrame:(MyFrame*)myFrame { MySizeClass wsc = sizeClass & 0x03; MySizeClass hsc = sizeClass & 0x0C; MySizeClass ori = sizeClass & 0xC0; - MyFrame *myFrame = self.myFrame; - if (myFrame.sizeClasses == nil) myFrame.sizeClasses = [NSMutableDictionary new]; @@ -707,13 +681,11 @@ -(MyLayoutPos*)trailingPosInner } - -(MyLayoutPos*)centerXPosInner { return self.myCurrentSizeClass.centerXPosInner; } - -(MyLayoutPos*)centerYPosInner { return self.myCurrentSizeClass.centerYPosInner; @@ -751,18 +723,33 @@ -(MyLayoutSize*)heightSizeInner -(CGFloat)myEstimatedWidth { - MyFrame *myFrame = self.myFrame; - if (myFrame.width == CGFLOAT_MAX) + //如果视图的父视图不是布局视图则直接返回宽度值。 + if (![self.superview isKindOfClass:[MyBaseLayout class]]) + { return CGRectGetWidth(self.bounds); - return myFrame.width; + } + else + { + MyFrame *myFrame = self.myFrame; + if (myFrame.width == CGFLOAT_MAX) + return CGRectGetWidth(self.bounds); + return myFrame.width; + } } -(CGFloat)myEstimatedHeight { - MyFrame *myFrame = self.myFrame; - if (myFrame.height == CGFLOAT_MAX) + if (![self.superview isKindOfClass:[MyBaseLayout class]]) + { return CGRectGetHeight(self.bounds); - return myFrame.height; + } + else + { + MyFrame *myFrame = self.myFrame; + if (myFrame.height == CGFLOAT_MAX) + return CGRectGetHeight(self.bounds); + return myFrame.height; + } } @@ -1214,13 +1201,13 @@ -(CGSize)myEstimateLayoutRect:(CGSize)size inSizeClass:(MySizeClass)sizeClass sb MyFrame *selfMyFrame = self.myFrame; if (selfMyFrame.multiple) - selfMyFrame.sizeClass = [self myBestSizeClass:sizeClass]; + selfMyFrame.sizeClass = [self myBestSizeClass:sizeClass myFrame:selfMyFrame]; for (UIView *sbv in self.subviews) { MyFrame *sbvmyFrame = sbv.myFrame; if (sbvmyFrame.multiple) - sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; + sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass myFrame:sbvmyFrame]; } BOOL hasSubLayout = NO; @@ -1428,13 +1415,14 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIView*)object chan UIView *sbvsc = object.myCurrentSizeClass; //这是什么意思? 这就是不注释的悲剧!!! - if (sbvsc.widthSizeInner.dimeWrapVal && sbvsc.heightSizeInner.dimeWrapVal) - { - [self setNeedsLayout]; - } - else if (sbvsc.widthSizeInner.dimeWrapVal || sbvsc.heightSizeInner.dimeWrapVal) - { - [object sizeToFit]; + // if (sbvsc.widthSizeInner.dimeWrapVal && sbvsc.heightSizeInner.dimeWrapVal) + // { + // [self setNeedsLayout]; + // } + if (sbvsc.widthSizeInner.dimeWrapVal || sbvsc.heightSizeInner.dimeWrapVal) + { + //[object sizeToFit]; + [self setNeedsLayout]; } } } @@ -1966,17 +1954,15 @@ -(void)layoutSubviews MyFrame *selfMyFrame = self.myFrame; if (selfMyFrame.multiple) - selfMyFrame.sizeClass = [self myBestSizeClass:sizeClass]; + selfMyFrame.sizeClass = [self myBestSizeClass:sizeClass myFrame:selfMyFrame]; for (UIView *sbv in self.subviews) { MyFrame *sbvmyFrame = sbv.myFrame; if (sbvmyFrame.multiple) - sbv.myFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; + sbv.myFrame.sizeClass = [sbv myBestSizeClass:sizeClass myFrame:sbvmyFrame]; if (!sbvmyFrame.hasObserver && sbvmyFrame.sizeClass != nil && !sbvmyFrame.sizeClass.useFrame) - { [self myAddSubviewObserver:sbv sbvmyFrame:sbvmyFrame]; - } } MyBaseLayout *lsc = (MyBaseLayout*)selfMyFrame.sizeClass; @@ -2023,7 +2009,7 @@ -(void)layoutSubviews //这里的位置需要进行有效像素的舍入处理,否则可能出现文本框模糊,以及视图显示可能多出一条黑线的问题。 //原因是当frame中的值不能有效的转化为最小可绘制的物理像素时就会出现模糊,虚化,多出黑线,以及layer处理圆角不圆的情况。 //所以这里要将frame中的点转化为有效的点。 - //这里之所以讲布局子视图的转化方法和一般子视图的转化方法区分开来是因为。我们要保证布局子视图不能出现细微的重叠,因为布局子视图有边界线 + //这里之所以将布局子视图的转化方法和一般子视图的转化方法区分开来是因为我们要保证布局子视图不能出现细微的重叠,因为布局子视图有边界线 //如果有边界线而又出现细微重叠的话,那么边界线将无法正常显示,因此这里做了一个特殊的处理。 CGRect rc; if ([sbv isKindOfClass:[MyBaseLayout class]]) @@ -2039,7 +2025,6 @@ -(void)layoutSubviews if (_myCGFloatErrorEqual(sbvTempBounds.size.height, sbvOldBounds.size.height, sSizeError)) sbvTempBounds.size.height = sbvOldBounds.size.height; - if (_myCGFloatErrorNotEqual(sbvTempBounds.size.width, sbvOldBounds.size.width, sSizeError)|| _myCGFloatErrorNotEqual(sbvTempBounds.size.height, sbvOldBounds.size.height, sSizeError)) { @@ -3009,7 +2994,7 @@ -(CGFloat)myGetBoundLimitMeasure:(MyLayoutSize*)boundDime sbv:(UIView*)sbv dimeT return value; MyLayoutValueType lValueType = boundDime.dimeValType; - if (lValueType == MyLayoutValueType_NSNumber || lValueType == MyLayoutValueType_Extreme) + if (lValueType == MyLayoutValueType_NSNumber || lValueType == MyLayoutValueType_Most) { value = boundDime.dimeNumVal.doubleValue; } @@ -3520,10 +3505,9 @@ -(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sb if (isEstimate && (sbvsc.heightSizeInner.dimeWrapVal || sbvsc.widthSizeInner.dimeWrapVal)) { [(MyBaseLayout*)sbv sizeThatFits:sbvmyFrame.frame.size inSizeClass:sizeClass]; + //因为estimateLayoutRect执行后会还原,所以这里要重新设置 if (sbvmyFrame.multiple) - { - sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为estimateLayoutRect执行后会还原,所以这里要重新设置 - } + sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass myFrame:sbvmyFrame]; } } @@ -3758,10 +3742,9 @@ -(void)myCalcSubviewsWrapContentSize:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasS if (isEstimate && isSbvWrap) { [(MyBaseLayout*)sbv sizeThatFits:sbvmyFrame.frame.size inSizeClass:sizeClass]; + //因为sizeThatFits执行后会还原,所以这里要重新设置 if (sbvmyFrame.multiple) - { - sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为sizeThatFits执行后会还原,所以这里要重新设置 - } + sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass myFrame:sbvmyFrame]; } } } @@ -3857,6 +3840,8 @@ -(void)mySetNeedLayoutAllSubviews:(UIView *)v @end +#pragma mark -- MyLayoutDragger + @implementation MyLayoutDragger @@ -3961,5 +3946,10 @@ -(void)dropView:(UIView *)view withEvent:(UIEvent *)event self.layout.autoresizesSubviews = YES; //让布局视图可以重新激发布局,这里还原为YES。 } +-(BOOL)isHovering +{ + return self.hasDragging && self.canHover && self.oldIndex == self.currentIndex; +} + @end diff --git a/MyLayout/Lib/MyGridLayout.m b/MyLayout/Lib/MyGridLayout.m index d90edba..1876b4f 100644 --- a/MyLayout/Lib/MyGridLayout.m +++ b/MyLayout/Lib/MyGridLayout.m @@ -740,7 +740,7 @@ -(void)showBorderline:(BOOL)show -(id)myBestHitGrid:(NSSet *)touches { MySizeClass sizeClass = [self myGetGlobalSizeClass]; - id bestSC = (id)[self myBestSizeClass:sizeClass]; + id bestSC = (id)[self myBestSizeClass:sizeClass myFrame:self.myFrame]; UITouch *touch = [touches anyObject]; CGPoint point = [touch locationInView:self]; diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index e02628e..51edb98 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -194,7 +194,7 @@ -(instancetype)myDefaultSizeClass; --(instancetype)myBestSizeClass:(MySizeClass)sizeClass; +-(instancetype)myBestSizeClass:(MySizeClass)sizeClass myFrame:(MyFrame*)myFrame; -(instancetype)myCurrentSizeClass; diff --git a/MyLayout/Lib/MyLayoutMath.h b/MyLayout/Lib/MyLayoutMath.h index 5c498b6..1cecf41 100644 --- a/MyLayout/Lib/MyLayoutMath.h +++ b/MyLayout/Lib/MyLayoutMath.h @@ -57,8 +57,8 @@ typedef enum : unsigned char MyLayoutValueType_Array, MyLayoutValueType_UILayoutSupport, MyLayoutValueType_SafeArea, - MyLayoutValueType_Extreme, - MyLayoutValueType_LayoutDimeDetach, + MyLayoutValueType_Most, + MyLayoutValueType_LayoutDimeClone, MyLayoutValueType_Weight, MyLayoutValueType_Wrap, MyLayoutValueType_Fill, diff --git a/MyLayout/Lib/MyLayoutPos.h b/MyLayout/Lib/MyLayoutPos.h index 315b5bb..3f5a7c9 100644 --- a/MyLayout/Lib/MyLayoutPos.h +++ b/MyLayout/Lib/MyLayoutPos.h @@ -8,7 +8,7 @@ #import "MyLayoutDef.h" -@class MyLayoutExtremePos; +@class MyLayoutMostPos; /** @@ -146,7 +146,7 @@ 5. UIView表示位置依赖指定视图的对应位置。 - 6.MyLayoutExtremePos表示位置是表示取数组中所有元素位置中的最大的一个或者最小的一个元素的位置值, 只有相对布局中的子视图的位置才能设置这种类型。 + 6.MyLayoutMostPos表示位置是表示取数组中所有元素位置中的最大的一个或者最小的一个元素的位置值, 只有相对布局中的子视图的位置才能设置这种类型。 7. nil表示位置的值被清除。 */ @@ -243,28 +243,6 @@ /** 在布局视图的宽度或者高度是固定的情况下,当某一列或者行中的所有子视图的间距值和尺寸超过父视图的尺寸时子视图的间距压缩比重,默认值为0表示不压缩。数字越大表明压缩的比重越大。目前只有线性布局和框架布局和流式布局中的子视图支持这个属性,而且这特性只在子视图的间距超过布局视图时才有效。 - - 子视图设置shrink属性时要注意如下几点: - - - 垂直线性布局中的子视图设置为非0时,表明当所有子视图的高度高于父布局视图时会对子视图的高度进行按比例压缩。 - - - 水平线性布局中的子视图设置为非0时,表明当所有子视图的宽度宽于父布局视图时会对子视图的宽度进行按比例压缩。 - - - 垂直流式布局中的子视图设置为非0时,表明当子视图所在行中的所有子视图的宽度宽于父布局视图时会对子视图的宽度进行按比例压缩。 - - - 水平流式布局中的子视图设置为非0时,表明当子视图所在列中的所有子视图的高度高于父布局视图时会对子视图的高度进行按比例压缩。 - - @note - 假设某个水平线性布局的宽度是100,其中有子视图A,B,C的宽度约束分别为:50,50,30,并且对应的shrink值分别为:0,1,2。因为三个子视图的 - 宽度总和为130已经超过父布局30的宽度。因此需要对A,B,C分别进行压缩处理。那A,B,C视图需要压缩的值分别为: - A: 30 * (0/(0+1+2)) = 0 - B: 30 * (1/(0+1+2)) = 10 - C: 30 * (2/(0+1+2)) = 20 - - 这样最终布局完成时A,B,C三个子视图的最终宽度分别为: 50, 40(50-10), 10(30-20)。最终三个子视图的总和不会再超出父视图的宽度了。 - - @note - shrink属性和子视图的weight属性的区别时,前者在剩余空间不足时起作用,后者在有剩余空间时起作用。 */ @property(nonatomic, assign) CGFloat shrink; @@ -279,10 +257,10 @@ @end -@interface MyLayoutPos(Detach) +@interface MyLayoutPos(Clone) -//从布局位置中分离出一个位置对象来。这个分离出来的位置值是源位置对象的值加上offsetVal。这个方法通常用于下面数组元素的构造 --(MyLayoutPos* (^)(CGFloat offsetVal))detach; +//从布局位置中克隆出一个位置对象来。这个克隆出来的位置值是源位置对象的值加上offsetVal。这个方法通常用于下面数组元素的构造 +-(MyLayoutPos* (^)(CGFloat offsetVal))clone; @end @@ -291,11 +269,11 @@ 我们可以从一个数组中获取众多位置的最大最小的位置值。 这里要求数组的元素只能是MyLayoutPos或者NSNumber两种对象类型的值。如果是NSNumber类型则是一个绝对位置值,也就是包括布局视图padding设置的偏移值。 */ -@interface NSArray(MyLayoutExtremePos) +@interface NSArray(MyLayoutMostPos) //从数组中得到最小的尺寸值。要求数组的元素必须是MyLayoutPos或者NSNumber类型 -@property(nonatomic, readonly) MyLayoutExtremePos *myMinPos; +@property(nonatomic, readonly) MyLayoutMostPos *myMinPos; //从数组中得到最小的尺寸值。要求数组的元素必须是MyLayoutPos或者NSNumber类型 -@property(nonatomic, readonly) MyLayoutExtremePos *myMaxPos; +@property(nonatomic, readonly) MyLayoutMostPos *myMaxPos; @end diff --git a/MyLayout/Lib/MyLayoutPos.m b/MyLayout/Lib/MyLayoutPos.m index 07ffbf6..0d2ef69 100644 --- a/MyLayout/Lib/MyLayoutPos.m +++ b/MyLayout/Lib/MyLayoutPos.m @@ -362,14 +362,14 @@ -(NSArray*)posArrVal } --(NSNumber*)posExtremeVal +-(NSNumber*)posMostVal { if (_posVal == nil || !self.isActive) return nil; - if (_posValType == MyLayoutValueType_Extreme) + if (_posValType == MyLayoutValueType_Most) { - return @([((MyLayoutExtremePos*)_posVal) getExtremePosFrom:self]); + return @([((MyLayoutMostPos*)_posVal) getMostPosFrom:self]); } return nil; @@ -442,9 +442,9 @@ -(MyLayoutPos*)__equalTo:(id)val _posValType = MyLayoutValueType_UILayoutSupport; } - else if ([val isKindOfClass:[MyLayoutExtremePos class]]) + else if ([val isKindOfClass:[MyLayoutMostPos class]]) { - _posValType = MyLayoutValueType_Extreme; + _posValType = MyLayoutValueType_Most; } else if ([val isKindOfClass:[UIView class]]) { @@ -721,24 +721,25 @@ -(NSString*)description @end -@implementation MyLayoutPos(Detach) +@implementation MyLayoutPos(Clone) --(MyLayoutPos* (^)(CGFloat offsetVal))detach +-(MyLayoutPos* (^)(CGFloat offsetVal))clone { return ^id(CGFloat offsetVal){ - MyLayoutPos *detachPos = [[[self class] allocWithZone:nil] init]; - detachPos->_offsetVal = offsetVal; - detachPos->_posVal = self; - detachPos->_posValType = MyLayoutValueType_LayoutDimeDetach; - return detachPos; + MyLayoutPos *clonedPos = [[[self class] allocWithZone:nil] init]; + clonedPos->_offsetVal = offsetVal; + clonedPos->_posVal = self; + clonedPos->_posValType = MyLayoutValueType_LayoutDimeClone; + return clonedPos; }; } @end +#pragma mark -- MyLayoutMostPos -@implementation MyLayoutExtremePos +@implementation MyLayoutMostPos { NSArray *_poss; BOOL _isMax; @@ -752,12 +753,11 @@ -(instancetype)initWith:(NSArray *)poss isMax:(BOOL)isMax _poss = poss; _isMax = isMax; } - return self; } --(CGFloat)getExtremePosFrom:(MyLayoutPos *)layoutPos +-(CGFloat)getMostPosFrom:(MyLayoutPos *)layoutPos { CGFloat retVal = _isMax ? -CGFLOAT_MAX : CGFLOAT_MAX; @@ -767,24 +767,21 @@ -(CGFloat)getExtremePosFrom:(MyLayoutPos *)layoutPos if ([pos isKindOfClass:[NSNumber class]]) { val = [(NSNumber*)pos doubleValue]; - - retVal = _isMax ? _myCGFloatMax(val, retVal) : _myCGFloatMin(val, retVal); } else if ([pos isKindOfClass:[MyLayoutPos class]]) { MyLayoutPos *lpos = (MyLayoutPos *)pos; CGFloat offsetVal = 0; - if (lpos.posValType == MyLayoutValueType_LayoutDimeDetach) + if (lpos.posValType == MyLayoutValueType_LayoutDimeClone) { offsetVal = lpos.offsetVal; lpos = (MyLayoutPos *)lpos.posVal; } + MyFrame *myFrame = lpos.view.myFrame; + if (layoutPos.pos & MyGravity_Vert_Mask) {//水平 - - MyFrame *myFrame = lpos.view.myFrame; - if (lpos.pos == MyGravity_Horz_Leading) { val = myFrame.leading + offsetVal; @@ -797,13 +794,9 @@ -(CGFloat)getExtremePosFrom:(MyLayoutPos *)layoutPos { val = myFrame.trailing - offsetVal; } - } else {//垂直 - - MyFrame *myFrame = lpos.view.myFrame; - if (lpos.pos == MyGravity_Vert_Top) { val = myFrame.top + offsetVal; @@ -817,13 +810,13 @@ -(CGFloat)getExtremePosFrom:(MyLayoutPos *)layoutPos val = myFrame.bottom - offsetVal; } } - - retVal = _isMax ? _myCGFloatMax(val, retVal) : _myCGFloatMin(val, retVal); } else { NSAssert(NO, @"oops!, invalid type, only support NSNumber or MyLayoutPos"); } + + retVal = _isMax ? _myCGFloatMax(val, retVal) : _myCGFloatMin(val, retVal); } return retVal; @@ -832,16 +825,16 @@ -(CGFloat)getExtremePosFrom:(MyLayoutPos *)layoutPos @end -@implementation NSArray(MyLayoutExtremePos) +@implementation NSArray(MyLayoutMostPos) --(MyLayoutExtremePos *)myMinPos +-(MyLayoutMostPos *)myMinPos { - return [[MyLayoutExtremePos alloc] initWith:self isMax:NO]; + return [[MyLayoutMostPos alloc] initWith:self isMax:NO]; } --(MyLayoutExtremePos *)myMaxPos +-(MyLayoutMostPos *)myMaxPos { - return [[MyLayoutExtremePos alloc] initWith:self isMax:YES]; + return [[MyLayoutMostPos alloc] initWith:self isMax:YES]; } @end diff --git a/MyLayout/Lib/MyLayoutPosInner.h b/MyLayout/Lib/MyLayoutPosInner.h index c0a850e..9c7535f 100644 --- a/MyLayout/Lib/MyLayoutPosInner.h +++ b/MyLayout/Lib/MyLayoutPosInner.h @@ -20,7 +20,7 @@ @property(nonatomic, readonly, strong) NSNumber *posNumVal; @property(nonatomic, readonly, strong) MyLayoutPos *posRelaVal; @property(nonatomic, readonly, strong) NSArray *posArrVal; -@property(nonatomic, readonly, strong) NSNumber *posExtremeVal; +@property(nonatomic, readonly, strong) NSNumber *posMostVal; @property(nonatomic, readonly, strong) MyLayoutPos *lBoundVal; @property(nonatomic, readonly, strong) MyLayoutPos *uBoundVal; @@ -60,11 +60,11 @@ @end -@interface MyLayoutExtremePos:NSObject +@interface MyLayoutMostPos:NSObject -(instancetype)initWith:(NSArray *)poss isMax:(BOOL)isMax; //获取极限值 --(CGFloat)getExtremePosFrom:(MyLayoutPos *)layoutPos; +-(CGFloat)getMostPosFrom:(MyLayoutPos *)layoutPos; @end diff --git a/MyLayout/Lib/MyLayoutSize.h b/MyLayout/Lib/MyLayoutSize.h index 30194b1..748eba2 100644 --- a/MyLayout/Lib/MyLayoutSize.h +++ b/MyLayout/Lib/MyLayoutSize.h @@ -8,7 +8,7 @@ #import "MyLayoutDef.h" -@class MyLayoutExtremeSize; +@class MyLayoutMostSize; /** *视图的布局尺寸类,用来设置视图在布局视图中宽度和高度的尺寸值。布局尺寸类是对尺寸的一个抽象,一个尺寸不一定描述为一个具体的数值,也有可能描述为和另外一个尺寸相等也就是依赖另外一个尺寸,同时一个尺寸可能也会有最大和最小值的限制等等。因此用MyLayoutSize类来描述这种尺寸的抽象概念。 @@ -63,7 +63,7 @@ /** - 设置尺寸的具体值,这个具体值可以设置为NSNumber, MyLayoutSize以及NSArray数组,UIView, MyLayoutExtremeSize和nil值。 + 设置尺寸的具体值,这个具体值可以设置为NSNumber, MyLayoutSize以及NSArray数组,UIView, MyLayoutMostSize和nil值。 1. 设置为NSNumber值表示指定具体的宽度或者高度数值 @@ -72,7 +72,8 @@ 3. 设置为NSArray数组的概念就是所有数组里面的子视图的尺寸平分父视图的尺寸。只有相对布局里面的子视图才支持这种设置。 4. 设置为UIView的概念就是尺寸依赖于指定视图的相对应的尺寸。 - 5. 设置为MyLayoutExtremeSize值表示取数组中所有元素尺寸中的最大的一个或者最小的一个元素的尺寸值。 + + 5. 设置为MyLayoutMostSize值表示取数组中所有元素尺寸中的最大的一个或者最小的一个元素的尺寸值。 这个对象从NSArray对象的Category属性:myMaxSize和myMinSize中获取。同时要求数组中的元素只能是MyLayoutSize或者NSNumber。 如果元素中有一个值为MyLayoutSize.wrap则表示自身的自适应尺寸也参与比较。 这个设置还有一个要求就是数组中的元素值如果是MyLayoutSize的话则要求这个尺寸必须在本视图之前就计算好的约束尺寸,否则可能设置无效。 @@ -98,7 +99,7 @@ -(MyLayoutSize* (^)(CGFloat val))min; /** - 设置尺寸的最小边界值,如果尺寸对象没有设置最小边界值,那么最小边界默认就是无穷小-CGFLOAT_MAX。lBound方法除了能设置为数值外,还可以设置为MyLayoutSize值和MyLayoutExtremeSize值和nil值,并且还可以指定增量值和倍数值。 + 设置尺寸的最小边界值,如果尺寸对象没有设置最小边界值,那么最小边界默认就是无穷小-CGFLOAT_MAX。lBound方法除了能设置为数值外,还可以设置为MyLayoutSize值和MyLayoutMostSize值和nil值,并且还可以指定增量值和倍数值。 1. 比如我们有一个UILabel的宽度是由内容决定的,但是最小的宽度大于等于父视图的宽度,则设置为: @code @@ -136,7 +137,7 @@ /** - 设置尺寸的最大边界值,如果尺寸对象没有设置最大边界值,那么最大边界默认就是无穷大CGFLOAT_MAX。uBound方法除了能设置为数值外,还可以设置为MyLayoutSize值和MyLayoutExtremeSize值和nil值,并且还可以指定增量值和倍数值。 + 设置尺寸的最大边界值,如果尺寸对象没有设置最大边界值,那么最大边界默认就是无穷大CGFLOAT_MAX。uBound方法除了能设置为数值外,还可以设置为MyLayoutSize值和MyLayoutMostSize值和nil值,并且还可以指定增量值和倍数值。 1. 比如我们有一个UILabel的宽度是由内容决定的,但是最大的宽度小于等于父视图的宽度,则设置为: @code @@ -203,7 +204,7 @@ 这样最终布局完成时A,B,C三个子视图的最终宽度分别为: 50, 40(50-10), 10(30-20)。最终三个子视图的总和不会再超出父视图的宽度了。 @note - shrink属性和子视图的weight属性的区别时,前者在剩余空间不足时起作用,后者在有剩余空间时起作用。 + shrink属性和子视图的weight属性的区别是:前者在剩余空间不足时起作用,后者在有剩余空间时起作用。 */ @property(nonatomic, assign) CGFloat shrink; @@ -221,10 +222,10 @@ @end -@interface MyLayoutSize(Detach) +@interface MyLayoutSize(Clone) -//从布局尺寸中分离出一个尺寸对象来。这个分离出来的尺寸值是源尺寸对象的值乘以multival再加上addVal。这个方法通常用于下面数组元素的构造 --(MyLayoutSize* (^)(CGFloat addVal, CGFloat multiVal))detach; +//从布局尺寸中克隆一个尺寸对象来。这个克隆出来的尺寸值是源尺寸对象的值乘以multival再加上addVal。这个方法通常用于下面数组元素的构造 +-(MyLayoutSize* (^)(CGFloat addVal, CGFloat multiVal))clone; @end @@ -233,12 +234,12 @@ 我们可以从一个数组中获取众多尺寸的最大最小的尺寸值。 这里要求数组的元素只能是MyLayoutSize或者NSNumber两种对象类型的值。 */ -@interface NSArray(MyLayoutExtremeSize) +@interface NSArray(MyLayoutMostSize) //从数组中得到最小的尺寸值。要求数组的元素必须是MyLayoutSize类型 -@property(nonatomic, readonly) MyLayoutExtremeSize *myMinSize; +@property(nonatomic, readonly) MyLayoutMostSize *myMinSize; //从数组中得到最小的尺寸值。要求数组的元素必须是MyLayoutSize类型 -@property(nonatomic, readonly) MyLayoutExtremeSize *myMaxSize; +@property(nonatomic, readonly) MyLayoutMostSize *myMaxSize; @end diff --git a/MyLayout/Lib/MyLayoutSize.m b/MyLayout/Lib/MyLayoutSize.m index 254d5eb..6765841 100644 --- a/MyLayout/Lib/MyLayoutSize.m +++ b/MyLayout/Lib/MyLayoutSize.m @@ -260,8 +260,8 @@ -(NSNumber*)dimeNumVal if (_dimeValType == MyLayoutValueType_NSNumber) return _dimeVal; - if (_dimeValType == MyLayoutValueType_Extreme) - return @([((MyLayoutExtremeSize*)_dimeVal) getExtremeSizeFrom:self]); + if (_dimeValType == MyLayoutValueType_Most) + return @([((MyLayoutMostSize*)_dimeVal) getMostSizeFrom:self]); return nil; } @@ -396,9 +396,9 @@ -(MyLayoutSize*)__equalTo:(id)val priority:(NSInteger)priority { _dimeValType = MyLayoutValueType_Array; } - else if ([val isKindOfClass:[MyLayoutExtremeSize class]]) + else if ([val isKindOfClass:[MyLayoutMostSize class]]) { - _dimeValType = MyLayoutValueType_Extreme; + _dimeValType = MyLayoutValueType_Most; } else { @@ -618,25 +618,26 @@ -(NSString*)description @end -@implementation MyLayoutSize(Detach) +@implementation MyLayoutSize(Clone) --(MyLayoutSize* (^)(CGFloat addVal, CGFloat multiVal))detach +-(MyLayoutSize* (^)(CGFloat addVal, CGFloat multiVal))clone { return ^id(CGFloat addVal, CGFloat multiVal){ - MyLayoutSize *detachSize = [[[self class] allocWithZone:nil] init]; - detachSize->_addVal = addVal; - detachSize->_multiVal = multiVal; - detachSize->_dimeVal = self; - detachSize->_dimeValType = MyLayoutValueType_LayoutDimeDetach; - return detachSize; + MyLayoutSize *clonedSize = [[[self class] allocWithZone:nil] init]; + clonedSize->_addVal = addVal; + clonedSize->_multiVal = multiVal; + clonedSize->_dimeVal = self; + clonedSize->_dimeValType = MyLayoutValueType_LayoutDimeClone; + return clonedSize; }; } @end +#pragma mark -- MyLayoutMostSize -@implementation MyLayoutExtremeSize +@implementation MyLayoutMostSize { NSArray *_sizes; BOOL _isMax; @@ -655,13 +656,14 @@ -(instancetype)initWith:(NSArray *)sizes isMax:(BOOL)isMax } --(CGFloat)getExtremeSizeFrom:(MyLayoutSize *)layoutSize +-(CGFloat)getMostSizeFrom:(MyLayoutSize *)layoutSize { CGFloat retVal = _isMax ? -CGFLOAT_MAX : CGFLOAT_MAX; for (id size in _sizes) { CGFloat val = 0; + if ([size isKindOfClass:[NSNumber class]]) { val = [(NSNumber*)size doubleValue]; @@ -673,31 +675,29 @@ -(CGFloat)getExtremeSizeFrom:(MyLayoutSize *)layoutSize else val = sz.height; } - - retVal = _isMax ? _myCGFloatMax(val, retVal) : _myCGFloatMin(val, retVal); } else if ([size isKindOfClass:[MyLayoutSize class]]) { MyLayoutSize *lsize = (MyLayoutSize *)size; - if (lsize.dimeValType == MyLayoutValueType_LayoutDimeDetach) - { - MyLayoutSize *llsize = (MyLayoutSize *)lsize.dimeVal; - val = (llsize.dime == MyGravity_Horz_Fill) ? llsize.view.myEstimatedWidth : llsize.view.myEstimatedHeight; - val *= lsize.multiVal; - val += lsize.addVal; - } - else + CGFloat addVal = 0; + CGFloat multiVal = 1; + if (lsize.dimeValType == MyLayoutValueType_LayoutDimeClone) { - val = (lsize.dime == MyGravity_Horz_Fill) ? lsize.view.myEstimatedWidth : lsize.view.myEstimatedHeight; + addVal = lsize.addVal; + multiVal = lsize.multiVal; + lsize = (MyLayoutSize *)lsize.dimeVal; } - - retVal = _isMax ? _myCGFloatMax(val, retVal) : _myCGFloatMin(val, retVal); - + + val = (lsize.dime == MyGravity_Horz_Fill) ? lsize.view.myEstimatedWidth : lsize.view.myEstimatedHeight; + val *= multiVal; + val += addVal; } else { NSAssert(NO, @"oops!, invalid type, only support NSNumber or MyLayoutSize"); } + + retVal = _isMax ? _myCGFloatMax(val, retVal) : _myCGFloatMin(val, retVal); } return retVal; @@ -706,16 +706,16 @@ -(CGFloat)getExtremeSizeFrom:(MyLayoutSize *)layoutSize @end -@implementation NSArray(MyLayoutExtremeSize) +@implementation NSArray(MyLayoutMostSize) --(MyLayoutExtremeSize *)myMinSize +-(MyLayoutMostSize *)myMinSize { - return [[MyLayoutExtremeSize alloc] initWith:self isMax:NO]; + return [[MyLayoutMostSize alloc] initWith:self isMax:NO]; } --(MyLayoutExtremeSize *)myMaxSize +-(MyLayoutMostSize *)myMaxSize { - return [[MyLayoutExtremeSize alloc] initWith:self isMax:YES]; + return [[MyLayoutMostSize alloc] initWith:self isMax:YES]; } @end diff --git a/MyLayout/Lib/MyLayoutSizeInner.h b/MyLayout/Lib/MyLayoutSizeInner.h index d1b5e50..9567adc 100644 --- a/MyLayout/Lib/MyLayoutSizeInner.h +++ b/MyLayout/Lib/MyLayoutSizeInner.h @@ -64,12 +64,12 @@ @end -@interface MyLayoutExtremeSize:NSObject +@interface MyLayoutMostSize:NSObject -(instancetype)initWith:(NSArray *)sizes isMax:(BOOL)isMax; //获取极限值 --(CGFloat)getExtremeSizeFrom:(MyLayoutSize *)layoutSize; +-(CGFloat)getMostSizeFrom:(MyLayoutSize *)layoutSize; @end diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index b777a03..f4840a5 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -60,10 +60,9 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( sbvmyFrame.leading = sbvmyFrame.trailing = sbvmyFrame.top = sbvmyFrame.bottom = CGFLOAT_MAX; + //因为sizeThatFits执行后会还原,所以这里要重新设置 if (sbvmyFrame.multiple) - { - sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass]; //因为sizeThatFits执行后会还原,所以这里要重新设置 - } + sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass myFrame:sbvmyFrame]; } } } @@ -187,9 +186,9 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; } - else if (sbvsc.centerXPosInner.posExtremeVal != nil) + else if (sbvsc.centerXPosInner.posMostVal != nil) { - sbvmyFrame.leading = sbvsc.centerXPosInner.posExtremeVal.doubleValue - sbvmyFrame.width / 2 + sbvsc.centerXPosInner.absVal; + sbvmyFrame.leading = sbvsc.centerXPosInner.posMostVal.doubleValue - sbvmyFrame.width / 2 + sbvsc.centerXPosInner.absVal; sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; } else if (sbvsc.centerXPosInner.posNumVal != nil) @@ -217,9 +216,9 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; } - else if (sbvsc.leadingPosInner.posExtremeVal != nil) + else if (sbvsc.leadingPosInner.posMostVal != nil) { - sbvmyFrame.leading = sbvsc.leadingPosInner.posExtremeVal.doubleValue + sbvsc.leadingPosInner.absVal; + sbvmyFrame.leading = sbvsc.leadingPosInner.posMostVal.doubleValue + sbvsc.leadingPosInner.absVal; sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; } else if (sbvsc.leadingPosInner.posNumVal != nil) @@ -242,9 +241,9 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv sbvmyFrame.leading = sbvmyFrame.trailing - sbvmyFrame.width; } - else if (sbvsc.trailingPosInner.posExtremeVal != nil) + else if (sbvsc.trailingPosInner.posMostVal != nil) { - sbvmyFrame.trailing = sbvsc.trailingPosInner.posExtremeVal.doubleValue - sbvsc.trailingPosInner.absVal + sbvsc.leadingPosInner.absVal; + sbvmyFrame.trailing = sbvsc.trailingPosInner.posMostVal.doubleValue - sbvsc.trailingPosInner.absVal + sbvsc.leadingPosInner.absVal; sbvmyFrame.leading = sbvmyFrame.trailing - sbvmyFrame.width; } else if (sbvsc.trailingPosInner.posNumVal != nil) @@ -358,16 +357,16 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; } - else if (sbvsc.baselinePosInner.posExtremeVal != nil) + else if (sbvsc.baselinePosInner.posMostVal != nil) { UIFont *sbvFont = [self myGetSubviewFont:sbv]; if (sbvFont != nil) { - sbvmyFrame.top = sbvsc.baselinePosInner.posExtremeVal.doubleValue + sbvsc.baselinePosInner.absVal - sbvFont.ascender - (sbvmyFrame.height - sbvFont.lineHeight) / 2; + sbvmyFrame.top = sbvsc.baselinePosInner.posMostVal.doubleValue + sbvsc.baselinePosInner.absVal - sbvFont.ascender - (sbvmyFrame.height - sbvFont.lineHeight) / 2; } else { - sbvmyFrame.top = sbvsc.baselinePosInner.posExtremeVal.doubleValue + sbvsc.baselinePosInner.absVal; + sbvmyFrame.top = sbvsc.baselinePosInner.posMostVal.doubleValue + sbvsc.baselinePosInner.absVal; } sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; @@ -406,9 +405,9 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; } - else if (sbvsc.centerYPosInner.posExtremeVal != nil) + else if (sbvsc.centerYPosInner.posMostVal != nil) { - sbvmyFrame.top = sbvsc.centerYPosInner.posExtremeVal.doubleValue + sbvsc.centerYPosInner.absVal - sbvmyFrame.height / 2; + sbvmyFrame.top = sbvsc.centerYPosInner.posMostVal.doubleValue + sbvsc.centerYPosInner.absVal - sbvmyFrame.height / 2; if (sbvmyFrame.top < 0 && lsc.heightSizeInner.dimeWrapVal) sbvmyFrame.top = 0; @@ -439,9 +438,9 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; } - else if (sbvsc.topPosInner.posExtremeVal != nil) + else if (sbvsc.topPosInner.posMostVal != nil) { - sbvmyFrame.top = sbvsc.topPosInner.posExtremeVal.doubleValue + sbvsc.topPosInner.absVal; + sbvmyFrame.top = sbvsc.topPosInner.posMostVal.doubleValue + sbvsc.topPosInner.absVal; sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; } else if (sbvsc.topPosInner.posNumVal != nil) @@ -463,9 +462,9 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL sbvmyFrame.top = sbvmyFrame.bottom - sbvmyFrame.height; } - else if (sbvsc.bottomPosInner.posExtremeVal != nil) + else if (sbvsc.bottomPosInner.posMostVal != nil) { - sbvmyFrame.bottom = sbvsc.bottomPosInner.posExtremeVal.doubleValue - sbvsc.bottomPosInner.absVal + sbvsc.topPosInner.absVal; + sbvmyFrame.bottom = sbvsc.bottomPosInner.posMostVal.doubleValue - sbvsc.bottomPosInner.absVal + sbvsc.topPosInner.absVal; sbvmyFrame.top = sbvmyFrame.bottom - sbvmyFrame.height; } else if (sbvsc.bottomPosInner.posNumVal != nil) @@ -749,9 +748,9 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame.leading -= sbvsc.leadingPosInner.absVal; } } - else if (sbvsc.leadingPosInner.posExtremeVal != nil) + else if (sbvsc.leadingPosInner.posMostVal != nil) { - sbvmyFrame.leading = sbvsc.leadingPosInner.posExtremeVal.doubleValue + sbvsc.leadingPosInner.absVal; + sbvmyFrame.leading = sbvsc.leadingPosInner.posMostVal.doubleValue + sbvsc.leadingPosInner.absVal; } else sbvmyFrame.leading = sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; @@ -765,9 +764,9 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame.trailing += sbvsc.trailingPosInner.absVal; } } - else if (sbvsc.trailingPosInner.posExtremeVal != nil) + else if (sbvsc.trailingPosInner.posMostVal != nil) { - sbvmyFrame.trailing = sbvsc.trailingPosInner.posExtremeVal.doubleValue - sbvsc.trailingPosInner.absVal; + sbvmyFrame.trailing = sbvsc.trailingPosInner.posMostVal.doubleValue - sbvsc.trailingPosInner.absVal; } else { @@ -866,9 +865,9 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc } } - else if (sbvsc.topPosInner.posExtremeVal != nil) + else if (sbvsc.topPosInner.posMostVal != nil) { - sbvmyFrame.top = sbvsc.topPosInner.posExtremeVal.doubleValue + sbvsc.topPosInner.absVal; + sbvmyFrame.top = sbvsc.topPosInner.posMostVal.doubleValue + sbvsc.topPosInner.absVal; } else sbvmyFrame.top = sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding; @@ -884,9 +883,9 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame.bottom += sbvsc.bottomPosInner.absVal; } } - else if (sbvsc.bottomPosInner.posExtremeVal != nil) + else if (sbvsc.bottomPosInner.posMostVal != nil) { - sbvmyFrame.bottom = sbvsc.bottomPosInner.posExtremeVal.doubleValue - sbvsc.bottomPosInner.absVal; + sbvmyFrame.bottom = sbvsc.bottomPosInner.posMostVal.doubleValue - sbvsc.bottomPosInner.absVal; } else { diff --git a/MyLayoutDemo/RLTest6ViewController.h b/MyLayoutDemo/RLTest6ViewController.h index 56fea66..74d0be0 100644 --- a/MyLayoutDemo/RLTest6ViewController.h +++ b/MyLayoutDemo/RLTest6ViewController.h @@ -9,7 +9,7 @@ #import /** - * 6.RelativeLayout - ExtremeSize + * 6.RelativeLayout - MostSize&MostPos */ @interface RLTest6ViewController : UIViewController diff --git a/MyLayoutDemo/RLTest6ViewController.m b/MyLayoutDemo/RLTest6ViewController.m index 327bb6d..300d5bc 100644 --- a/MyLayoutDemo/RLTest6ViewController.m +++ b/MyLayoutDemo/RLTest6ViewController.m @@ -20,67 +20,71 @@ @interface RLTest6ViewController () @implementation RLTest6ViewController --(void)loadView -{ - [super loadView]; - //宽度和高度。 - // -} - - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + /* + 本示例用来介绍最值约束的使用方式。什么是最值约束呢?在一些场景中我们希望一个视图的宽度或者高度是某一些宽度或者高度集合中的最大值或者最小值,同样在一些场景中 + 我们希望某个视图的某个方位的位置值是一些位置值集合中的最大或者最小值。这种尺寸或者位置是一个集合中的尺寸或者位置中的最大最小值的约束就称之为最值约束。 + + 为了实现最值约束我们对MyLayoutSize以及MyLayoutPos的equalTo方法的参数中分别添加了对MyLayoutMostSize以及MyLayoutMostPos类型值的支持。我们不需要关心MyLayoutMostSize以及MyLayoutMostPos的内部具体实现,只需要知道这两种类型的值是分别从NSArray数组的分类方法:myMaxSize,myMinSize,myMaxPos,myMinPos中获取得到。而对于NSArray数组中的元素类型,则要求必须是NSNumber类型或者MyLayoutSize或者MyLayoutPos类型。下面举例来说: + + 1.视图D的高度是: 视图A的宽度、视图B的高度、视图C的高度的一半、50 这四个值中的最大值。那么视图D的高度约束可以如下设置: + D.heightSize.equalTo(@[A.widthSize, B.heightSize, C.heightSize.clone(0, 0.5), @50].myMaxSize); + + 2.视图D的右边距是:视图A的左边距、视图B的右边距、视图C的左边距偏移20、50这四个值中的最小值。那么视图D的右边距约束可以如下设置: + D.rightPos.equalTo(@[A.leftPos,B.rightPos,C.leftPos.clone(20), @50].myMinPos); + + 3.视图C的宽度是:自身宽度、视图B的宽度-20、30这三个值的最小值。 + C.widthSize.equalTo(@(MyLayoutSize.wrap),B.widthSize.clone(-20,1),@30).myMinSize); + + 需要注意的是在使用最值约束时要求数组中的元素的约束必须是在当前约束计算前就已经完成约束计算,否则结果未可知。就以上面的例子来说在计算D的高度时,要求A的宽度,B的高度,C的高度都是已经完成了约束计算才有效。 + + 需要注意的是只有相对布局中的子视图的位置约束才支持位置的最值约束设置,其他布局中的子视图不支持!而尺寸最值约束则所有布局中的子视图都支持。 + */ MyRelativeLayout *rootLayout = [MyRelativeLayout new]; rootLayout.myMargin = 0; [self.view addSubview:rootLayout]; - MyRelativeLayout *layout1 = [self createLayoutName:@"张三" date:@"2019-10-07" detail:@"short detail"]; + //最值约束例子1 + MyRelativeLayout *layout1 = [self createLayout1]; layout1.topPos.equalTo(rootLayout.topPos); layout1.leftPos.equalTo(rootLayout.leftPos); - layout1.backgroundColor = [CFTool color:3]; - // [rootLayout addSubview:layout1]; + layout1.backgroundColor = [CFTool color:7]; + [rootLayout addSubview:layout1]; - MyRelativeLayout *layout2 = [self createLayoutName:@"欧阳大哥" date:@"2019-10-07" detail:@"this is a middle length detail"]; + //最值约束例子2 + MyRelativeLayout *layout2 = [self createLayout2]; layout2.topPos.equalTo(layout1.bottomPos).offset(20); layout2.leftPos.equalTo(rootLayout.leftPos); - layout2.backgroundColor = [CFTool color:4]; - // [rootLayout addSubview:layout2]; - - - MyRelativeLayout *layout3 = [self createLayoutName:@"李四" date:@"2019-10-07" detail:@"this is a long long long long long long long long length detail"]; - // layout3.topPos.equalTo(layout2.bottomPos).offset(20); - // layout3.leftPos.equalTo(rootLayout.leftPos); - layout3.backgroundColor = [CFTool color:5]; - [rootLayout addSubview:layout3]; - - - //三个例子: 底下的文字太少,底下的文字中等,底下的文字太长。 - - + layout2.backgroundColor = [CFTool color:8]; + [rootLayout addSubview:layout2]; } --(MyRelativeLayout*)createLayoutName:(NSString*)name date:(NSString*)date detail:(NSString*)detail +-(MyRelativeLayout*)createLayout1 { + //这个例子用来演示位置的最值约束设置。通过位置的最值约束我们设置某个位置的值为一批位置中的最大或者最小值。位置最值约束只能用于相对布局。 MyRelativeLayout *rootLayout = [MyRelativeLayout new]; rootLayout.widthSize.equalTo(@(MyLayoutSize.wrap)); rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); - //名字控件,尺寸是自适应的。 UILabel *nameLabel = [UILabel new]; - nameLabel.text = name; + nameLabel.text = @"欧阳大哥"; + nameLabel.font = [CFTool font:20]; nameLabel.widthSize.equalTo(@(MyLayoutSize.wrap)); nameLabel.heightSize.equalTo(@(MyLayoutSize.wrap)); - // [rootLayout addSubview:nameLabel]; + [rootLayout addSubview:nameLabel]; //详情控件,尺寸是自适应的,但是最宽是屏幕宽度减20,这里减20的原因是因为布局视图设置了左右padding为10。 UILabel *detailLabel = [UILabel new]; - detailLabel.text = detail; + detailLabel.text = @"继续!"; + detailLabel.backgroundColor = [CFTool color:9]; //宽度自适应,最宽是屏幕的宽度减去20 detailLabel.widthSize.equalTo(@(MyLayoutSize.wrap)).uBound(self.view.widthSize, -20, 1); detailLabel.heightSize.equalTo(@(MyLayoutSize.wrap)); @@ -88,25 +92,101 @@ -(MyRelativeLayout*)createLayoutName:(NSString*)name date:(NSString*)date detail detailLabel.leftPos.equalTo(nameLabel.leftPos); [rootLayout addSubview:detailLabel]; - //日期控件,右边和详情控件对齐,但是当详情控件的内容太少时,起码要和名字控件最小的距离是40 - UILabel *dateLabel = [UILabel new]; - dateLabel.text = date; - [dateLabel sizeToFit]; //这里直接计算出date的size是自适应的 -// [rootLayout addSubview:dateLabel]; - dateLabel.topPos.equalTo(nameLabel.topPos); + //按钮控件,右边和详情控件对齐,但是当详情控件的内容太少时,起码要和名字控件最小的距离是40 + UIButton *clickButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [clickButton setTitle:@"Click me" forState:UIControlStateNormal]; + clickButton.backgroundColor = [CFTool color:10]; + [clickButton sizeToFit]; //这里直接计算出date的size是自适应的 + clickButton.topPos.equalTo(nameLabel.topPos); //最新版本的相对布局可以让子视图的位置设置为某些视图位置中的最大或者最小值,也就是极限值,我们可以对一个数组调用扩展分类的方法myMaxPos或者myMinPos来获取 //到数组中元素的最大或者最小位置值。使用最大最小值的前提是在计算当前位置的约束时,要求数组中的元素的约束都是已经计算好了的,否则得到的结果是未可知,就如本例中 //在计算dateLabel的右边距时,detailLabel以及nameLabel的右边距都是已经计算好了的。 - dateLabel.rightPos.equalTo(@[detailLabel.rightPos, nameLabel.rightPos.detach(-1 *(40+dateLabel.frame.size.width))].myMaxPos); + clickButton.rightPos.equalTo(@[detailLabel.rightPos, nameLabel.rightPos.clone(-1 *(40+clickButton.frame.size.width))].myMaxPos); + [rootLayout addSubview:clickButton]; + + [clickButton addTarget:self action:@selector(handleClick:) forControlEvents:UIControlEventTouchUpInside]; + + + //这个控件的高度取nameLabel和detailLabel二个高度中的最小高度值。 + //这个控件的宽度取nameLabel和detailLabel二个宽度中的最大宽度值。 + //在设置最值尺寸约束时,要求数组中的约束尺寸是已经计算完毕了的,否则结果未可知。 + UILabel *subDetailLabel = [UILabel new]; + subDetailLabel.text = @"这是一句很长的文字,随着detail的增长而显示越多"; + subDetailLabel.backgroundColor = [CFTool color:10]; + subDetailLabel.topPos.equalTo(detailLabel.bottomPos).offset(10); + subDetailLabel.leftPos.equalTo(nameLabel.leftPos); + subDetailLabel.heightSize.equalTo(@[nameLabel.heightSize, detailLabel.heightSize].myMinSize); + subDetailLabel.widthSize.equalTo(@[nameLabel.widthSize, detailLabel.widthSize].myMaxSize); + [rootLayout addSubview:subDetailLabel]; + + return rootLayout; +} + +-(MyRelativeLayout*)createLayout2 +{ + MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + rootLayout.widthSize.equalTo(@(MyLayoutSize.wrap)); + rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); + rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); + + //名字控件,尺寸是自适应的。 + UILabel *nameLabel = [UILabel new]; + nameLabel.text = @"欧阳大哥"; + nameLabel.widthSize.equalTo(@(MyLayoutSize.wrap)); + nameLabel.heightSize.equalTo(@(MyLayoutSize.wrap)); + [rootLayout addSubview:nameLabel]; + + UILabel *detailLabel = [UILabel new]; + detailLabel.text = @"继续!"; + detailLabel.backgroundColor = [CFTool color:9]; + //宽度自适应,最宽是屏幕的宽度减去20 + detailLabel.widthSize.equalTo(@(90)); + detailLabel.heightSize.equalTo(@(MyLayoutSize.wrap)); + detailLabel.topPos.equalTo(nameLabel.bottomPos).offset(10); + detailLabel.leftPos.equalTo(nameLabel.leftPos); + [rootLayout addSubview:detailLabel]; + + //按钮控件,右边和详情控件对齐,但是当详情控件的内容太少时,起码要和名字控件最小的距离是40 + UIButton *clickButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [clickButton setTitle:@"Click me" forState:UIControlStateNormal]; + clickButton.backgroundColor = [CFTool color:10]; + [clickButton sizeToFit]; //这里直接计算出date的size是自适应 + clickButton.leftPos.equalTo(detailLabel.rightPos).offset(20); + //按钮的底部位置取100和detailLabel底部位置二者的最小值。 + //在这个例子中随着detailLabel的高度增加底部越来越大,但是clickButton的底部如果超过100则最终会取值100 + clickButton.bottomPos.equalTo(@[@100,detailLabel.bottomPos].myMinPos); + [rootLayout addSubview:clickButton]; + [clickButton addTarget:self action:@selector(handleClick:) forControlEvents:UIControlEventTouchUpInside]; + + + //这个控件的高度取50和detailLabel二个高度中的最小高度值。 + //这个控件的宽度取nameLabel宽度的一半加10,detailLabel高度的3/5,100三个宽度中的最大宽度值。 + //在设置最值尺寸约束时,要求数组中的约束尺寸是已经计算完毕了的,否则结果未可知。 + UILabel *subDetailLabel = [UILabel new]; + subDetailLabel.text = @"这是一句很长的文字,随着detail的增长而显示越多"; + subDetailLabel.backgroundColor = [CFTool color:10]; + subDetailLabel.topPos.equalTo(clickButton.bottomPos).offset(10); + subDetailLabel.leftPos.equalTo(detailLabel.rightPos).offset(10); + subDetailLabel.heightSize.equalTo(@[@50, detailLabel.heightSize].myMinSize); + subDetailLabel.widthSize.equalTo(@[nameLabel.widthSize.clone(10, 0.5), detailLabel.heightSize.clone(0,0.6), @(100)].myMaxSize); + [rootLayout addSubview:subDetailLabel]; + return rootLayout; } + - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } +-(IBAction)handleClick:(UIButton*)sender +{ + UILabel *label = (UILabel*)sender.superview.subviews[1]; + label.text = [NSString stringWithFormat:@"继续! %@", label.text]; +} + /* #pragma mark - Navigation diff --git a/MyLayoutDemo/ViewController.m b/MyLayoutDemo/ViewController.m index ef53b0c..682c986 100644 --- a/MyLayoutDemo/ViewController.m +++ b/MyLayoutDemo/ViewController.m @@ -150,7 +150,7 @@ -(NSArray*)demoTypeList @{@"title":NSLocalizedString(@"5.RelativeLayout - Boundary limit", @""), @"class":[RLTest5ViewController class] }, - @{@"title":NSLocalizedString(@"6.RelativeLayout - ExtremeSize", @""), + @{@"title":NSLocalizedString(@"6.RelativeLayout - MostSize&MostPos", @""), @"class":[RLTest6ViewController class] } ] diff --git a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings index fd53e74..3248686 100644 --- a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings +++ b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings @@ -23,6 +23,7 @@ "3.RelativeLayout - Centered" = "3.相对布局-子视图整体居中"; "4.RelativeLayout - Scroll&Dock" = "4.相对布局-滚动和停靠"; "5.RelativeLayout - Boundary limit" = "5.相对布局-边界约束"; +"6.RelativeLayout - MostSize&MostPos" = "6.相对布局-最值约束"; "1.TableLayout - Vert" = "1.表格布局-垂直表格"; "2.TableLayout - Waterfall(Horz)" = "2.表格布局-水平表格实现瀑布流"; "3.TableLayout - Intelligent Borderline" = "3.表格布局-表格和智能边界线"; diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index 9e0d2b5..ff15ce5 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -35,7 +35,7 @@ - (void)tearDown { -(void)testRLTest1VC { - for (int i = 1; i <= 5; i++) + for (int i = 1; i <= 6; i++) { Class cls = NSClassFromString([NSString stringWithFormat:@"RLTest%dViewController", i]); UIViewController *vc = [[cls alloc] init]; @@ -1029,7 +1029,7 @@ -(void)test123 label.myBottom = MyLayoutPos.safeAreaMargin; label.text = @"您好!!!"; label.backgroundColor = [UIColor redColor]; - label.widthSize.equalTo(@[@(MyLayoutSize.wrap), v1.widthSize.detach(0, 0.5)].myMaxSize); + label.widthSize.equalTo(@[@(MyLayoutSize.wrap), v1.widthSize.clone(0, 0.5)].myMaxSize); label.wrapContentHeight = YES; [rootLayout addSubview:label]; } From 8f091a0ff0fb59dde955c5481041907318e0c8fc Mon Sep 17 00:00:00 2001 From: youngsoft Date: Tue, 8 Oct 2019 23:56:03 +0800 Subject: [PATCH 049/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 110 +++++------------- MyLayout/Lib/MyLayoutSize.m | 13 ++- MyLayout/Lib/MyLinearLayout.m | 4 +- MyLayout/Lib/MyRelativeLayout.m | 13 +-- MyLayoutDemo/AllTest10Cell.m | 5 +- MyLayoutDemo/AllTest10HeaderView.m | 17 ++- MyLayoutDemo/AllTest11ViewController.m | 2 +- MyLayoutDemo/AllTest12ViewController.m | 10 +- MyLayoutDemo/AllTest1TableViewCell.m | 19 ++- .../AllTest1TableViewCellForAutoLayout.m | 14 +-- MyLayoutDemo/AllTest1ViewController.m | 6 +- MyLayoutDemo/AllTest2TableViewCell.m | 23 ++-- MyLayoutDemo/AllTest3ViewController.m | 20 ++-- MyLayoutDemo/AllTest4ViewController.m | 5 +- MyLayoutDemo/AllTest5ViewController.m | 3 +- MyLayoutDemo/AllTest6ViewController.m | 5 +- MyLayoutDemo/AllTest7ViewController.m | 81 ++++++------- MyLayoutDemo/AllTest8ViewController.m | 9 +- MyLayoutDemo/AllTest9CollectionViewCell.m | 5 +- MyLayoutDemo/FLLTest1ViewController.m | 4 +- MyLayoutDemo/FLLTest2ViewController.m | 4 +- MyLayoutDemo/FLLTest3ViewController.m | 4 +- MyLayoutDemo/FLLTest4ViewController.m | 14 +-- MyLayoutDemo/FLLTest5ViewController.m | 8 +- MyLayoutDemo/FLLTest6ViewController.m | 11 +- MyLayoutDemo/FLLTest7ViewController.m | 21 ++-- MyLayoutDemo/FOLTest2ViewController.m | 4 +- MyLayoutDemo/FOLTest3ViewController.m | 6 +- MyLayoutDemo/FOLTest4ViewController.m | 8 +- MyLayoutDemo/FOLTest5ViewController.m | 6 +- MyLayoutDemo/FOLTest6ViewController.m | 20 ++-- MyLayoutDemo/GLTest1ViewController.m | 4 +- MyLayoutDemo/GLTest3ViewController.m | 2 +- MyLayoutDemo/GLTest4ViewController.m | 2 +- MyLayoutDemo/LLTest1ViewController.m | 2 +- MyLayoutDemo/LLTest2ViewController.m | 32 ++--- MyLayoutDemo/LLTest3ViewController.m | 23 ++-- MyLayoutDemo/LLTest4ViewController.m | 21 ++-- MyLayoutDemo/LLTest5ViewController.m | 4 +- MyLayoutDemo/LLTest6ViewController.m | 7 +- MyLayoutDemo/LLTest7ViewController.m | 10 +- MyLayoutDemo/PLTest2ViewController.m | 7 +- MyLayoutDemo/PLTest3ViewController.m | 9 +- MyLayoutDemo/RLTest4ViewController.m | 2 +- MyLayoutDemo/RLTest5ViewController.m | 15 ++- MyLayoutDemo/TLTest2ViewController.m | 6 +- MyLayoutDemo/TLTest4ViewController.m | 4 +- .../zh-Hans.lproj/Localizable.strings | 4 +- MyLayoutTests/MyFloatLayoutTestCase.m | 6 +- MyLayoutTests/MyFlowLayoutTestCase.m | 15 +-- MyLayoutTests/MyFrameLayoutTestCase.m | 17 ++- MyLayoutTests/MyLayoutPerformanceTestCase.m | 2 +- MyLayoutTests/MyLinearLayoutTestCase.m | 61 +++++----- MyLayoutTests/MyNoLayoutSuperviewTestCase.m | 3 +- MyLayoutTests/MyRelativeLayoutTestCase.m | 90 ++++---------- 55 files changed, 343 insertions(+), 479 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index f55e318..dd347c2 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -1972,13 +1972,10 @@ -(void)layoutSubviews CGSize oldSelfSize = self.bounds.size; CGSize newSelfSize; if (_useCacheRects && selfMyFrame.width != CGFLOAT_MAX && selfMyFrame.height != CGFLOAT_MAX) - { newSelfSize = CGSizeMake(selfMyFrame.width, selfMyFrame.height); - } else - { newSelfSize = [self calcLayoutSize:[self myCalcSizeInNoLayoutSuperview:self.superview currentSize:oldSelfSize] isEstimate:NO pHasSubLayout:nil sizeClass:sizeClass sbs:nil]; - } + newSelfSize = _myCGSizeRound(newSelfSize); _useCacheRects = NO; @@ -1998,13 +1995,9 @@ -(void)layoutSubviews if (sbvmyFrame.leading != CGFLOAT_MAX && sbvmyFrame.top != CGFLOAT_MAX && !sbvsc.noLayout && !sbvsc.useFrame) { if (sbvmyFrame.width < 0) - { sbvmyFrame.width = 0; - } if (sbvmyFrame.height < 0) - { sbvmyFrame.height = 0; - } //这里的位置需要进行有效像素的舍入处理,否则可能出现文本框模糊,以及视图显示可能多出一条黑线的问题。 //原因是当frame中的值不能有效的转化为最小可绘制的物理像素时就会出现模糊,虚化,多出黑线,以及layer处理圆角不圆的情况。 @@ -2027,9 +2020,7 @@ -(void)layoutSubviews if (_myCGFloatErrorNotEqual(sbvTempBounds.size.width, sbvOldBounds.size.width, sSizeError)|| _myCGFloatErrorNotEqual(sbvTempBounds.size.height, sbvOldBounds.size.height, sSizeError)) - { sbv.bounds = sbvTempBounds; - } CGPoint sbvTempCenter = CGPointMake(rc.origin.x + sbv.layer.anchorPoint.x * sbvTempBounds.size.width, rc.origin.y + sbv.layer.anchorPoint.y * sbvTempBounds.size.height); @@ -2042,9 +2033,7 @@ -(void)layoutSubviews if (_myCGFloatErrorNotEqual(sbvTempCenter.x, sbvOldCenter.x, sSizeError)|| _myCGFloatErrorNotEqual(sbvTempCenter.y, sbvOldCenter.y, sSizeError)) - { sbv.center = sbvTempCenter; - } } else { @@ -2056,9 +2045,7 @@ -(void)layoutSubviews } if (sbvsc.visibility == MyVisibility_Gone && !sbv.isHidden) - { sbv.bounds = CGRectMake(sbvOldBounds.origin.x, sbvOldBounds.origin.y, 0, 0); - } if (sbvmyFrame.sizeClass.viewLayoutCompleteBlock != nil) { @@ -2069,6 +2056,7 @@ -(void)layoutSubviews if (sbvmyFrame.multiple) sbvmyFrame.sizeClass = [sbv myDefaultSizeClass]; + [sbvmyFrame reset]; } @@ -2170,13 +2158,9 @@ -(void)layoutSubviews if ((lsc.topPosInner.isSafeAreaPos || lsc.bottomPosInner.isSafeAreaPos) && [UIDevice currentDevice].systemVersion.doubleValue < 11 ) { if (lsc.topPosInner.isSafeAreaPos) - { centerPonintSelf.y = [lsc.topPosInner realPosIn:rectSuper.size.height] + self.layer.anchorPoint.y * rectSelf.size.height; - } else - { centerPonintSelf.y = rectSuper.size.height - rectSelf.size.height - [lsc.bottomPosInner realPosIn:rectSuper.size.height] + self.layer.anchorPoint.y * rectSelf.size.height; - } } //如果自己的父视图是非UIScrollView以及非布局视图。以及自己的宽度或者高度是包裹的时,并且如果设置了在父视图居中或者居下或者居右时要在父视图中更新自己的位置。 @@ -2221,9 +2205,7 @@ -(void)layoutSubviews //如果有变化则只调整自己的center。而不变化 if (!_myCGPointEqual(self.center, centerPonintSelf)) - { self.center = centerPonintSelf; - } } @@ -2325,17 +2307,12 @@ -(MyGravity)myGetSubviewVertGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc vertGravit { sbvVertGravity = vertGravity; if (sbvVertAligement != MyGravity_None) - { sbvVertGravity = sbvVertAligement; - } } else { - if (sbvVertAligement != MyGravity_None) - { sbvVertGravity = sbvVertAligement; - } if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { @@ -2410,9 +2387,7 @@ -(CGFloat)myCalcVertGravity:(MyGravity)vertGravity UIFont *sbvFont = nil; if (vertGravity == MyGravity_Vert_Baseline) - { sbvFont = [self myGetSubviewFont:sbv]; - } if (sbvFont == nil && vertGravity == MyGravity_Vert_Baseline) vertGravity = MyGravity_Vert_Top; @@ -2468,17 +2443,13 @@ -(MyGravity)myGetSubviewHorzGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc horzGravit { sbvHorzGravity = horzGravity; if (sbvHorzAligement != MyGravity_None) - { sbvHorzGravity = sbvHorzAligement; - } } else { if (sbvHorzAligement != MyGravity_None) - { sbvHorzGravity = sbvHorzAligement; - } if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { @@ -2571,9 +2542,7 @@ -(CGFloat)myCalcHorzGravity:(MyGravity)horzGravity //因为从右到左布局最后统一进行了转换,但是窗口居中是不按布局来控制的,所以这里为了保持不变需要进行特殊处理。 if ([MyBaseLayout isRTL]) - { pRect->origin.x = selfSize.width - pRect->origin.x - pRect->size.width; - } } } @@ -2641,7 +2610,7 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize if (lsc.leadingPosInner.posVal != nil && lsc.trailingPosInner.posVal != nil) { - if (lsc.widthSizeInner.priority == MyPriority_Low) + if ( lsc.widthSizeInner.dimeVal == nil || lsc.widthSizeInner.priority == MyPriority_Low) { CGFloat leadingMargin = [lsc.leadingPosInner realPosIn:rectSuper.size.width]; CGFloat trailingMargin = [lsc.trailingPosInner realPosIn:rectSuper.size.width]; @@ -2651,9 +2620,7 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize } if (size.width < 0) - { size.width = 0; - } } if (!ssc.heightSizeInner.dimeWrapVal) @@ -2670,7 +2637,7 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize if (lsc.topPosInner.posVal != nil && lsc.bottomPosInner.posVal != nil) { - if (lsc.heightSizeInner.priority == MyPriority_Low) + if (lsc.heightSizeInner.dimeVal == nil || lsc.heightSizeInner.priority == MyPriority_Low) { CGFloat topMargin = [lsc.topPosInner realPosIn:rectSuper.size.height]; CGFloat bottomMargin = [lsc.bottomPosInner realPosIn:rectSuper.size.height]; @@ -2680,10 +2647,7 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize } if (size.height < 0) - { size.height = 0; - } - } @@ -2759,10 +2723,12 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview if (lsc.leadingPosInner.posVal != nil && lsc.trailingPosInner.posVal != nil) { isAdjust = YES; - //如果是没有设置宽度约束,或者宽度约束的优先级很低都按左右边距来决定布局视图的宽度。 + //如果宽度约束的优先级很低都按左右边距来决定布局视图的宽度。 if (lsc.widthSizeInner.priority == MyPriority_Low) - { [lsc.widthSizeInner __clear]; + + if (lsc.widthSizeInner.dimeVal == nil) + { rectSelf.size.width = rectSuper.size.width - leadingMargin - trailingMargin; rectSelf.size.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:rectSelf.size.width sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; } @@ -2855,10 +2821,12 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview if (lsc.topPosInner.posVal != nil && lsc.bottomPosInner.posVal != nil) { isAdjust = YES; - //如果没有设置高度约束,或者高度约束优先级很低则按上下边距来决定布局视图高度。 - if (lsc.heightSizeInner.priority == MyPriority_Low || lsc.heightSizeInner.dimeVal == nil) - { + //如果高度约束优先级很低则按上下边距来决定布局视图高度。 + if (lsc.heightSizeInner.priority == MyPriority_Low) [lsc.heightSizeInner __clear]; + + if (lsc.heightSizeInner.dimeVal == nil) + { rectSelf.size.height = rectSuper.size.height - topMargin - bottomMargin; rectSelf.size.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:rectSelf.size.height sbvSize:rectSelf.size selfLayoutSize:rectSuper.size]; } @@ -2919,13 +2887,9 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview if (!_myCGRectEqual(rectSelf, oldRectSelf)) { if (rectSelf.size.width < 0) - { rectSelf.size.width = 0; - } if (rectSelf.size.height < 0) - { rectSelf.size.height = 0; - } if (CGAffineTransformIsIdentity(self.transform)) { @@ -2956,9 +2920,7 @@ -(CGFloat)myHeightFromFlexedHeightView:(UIView*)sbv sbvsc:(UIView*)sbvsc inWidth { UIImage *img = ((UIImageView*)sbv).image; if (img != nil && img.size.width != 0) - { h = img.size.height * (width / img.size.width); - } } } else if ([sbv isKindOfClass:[UIButton class]]) @@ -3025,13 +2987,9 @@ -(CGFloat)myGetBoundLimitMeasure:(MyLayoutSize*)boundDime sbv:(UIView*)sbv dimeT else { if (boundDime.dimeRelaVal.dime == MyGravity_Horz_Fill) - { value = boundDime.dimeRelaVal.view.myEstimatedWidth; - } else - { value = boundDime.dimeRelaVal.view.myEstimatedHeight; - } } } @@ -3150,14 +3108,9 @@ -(BOOL)myIsNoLayoutSubview:(UIView*)sbv return YES; if (sbv.isHidden) - { return sbvsc.visibility != MyVisibility_Invisible; - } else - { return sbvsc.visibility == MyVisibility_Gone; - } - } -(NSMutableArray*)myGetLayoutSubviews @@ -3171,22 +3124,15 @@ -(NSMutableArray*)myGetLayoutSubviewsFrom:(NSArray*)sbsFrom BOOL isReverseLayout = self.reverseLayout; if (isReverseLayout) - { [sbs addObjectsFromArray:[sbsFrom reverseObjectEnumerator].allObjects]; - } else - { [sbs addObjectsFromArray:sbsFrom]; - - } for (NSInteger i = sbs.count - 1; i >=0; i--) { UIView *sbv = sbs[i]; if ([self myIsNoLayoutSubview:sbv]) - { [sbs removeObjectAtIndex:i]; - } } return sbs; @@ -3375,9 +3321,7 @@ - (void)myAlterScrollViewContentSize:(CGSize)newSize lsc:(MyBaseLayout*)lsc (oldOffset.y <= 0 || oldOffset.y <= contsize.height - rectSuper.size.height)) { if (!CGPointEqualToPoint(scrolv.contentOffset, oldOffset)) - { scrolv.contentOffset = oldOffset; - } } } } @@ -3398,17 +3342,11 @@ -(MySizeClass)myGetGlobalSizeClass #if TARGET_OS_IOS UIDeviceOrientation ori = [UIDevice currentDevice].orientation; if (UIDeviceOrientationIsPortrait(ori)) - { sizeClass |= MySizeClass_Portrait; - } else if (UIDeviceOrientationIsLandscape(ori)) - { sizeClass |= MySizeClass_Landscape; - } - //如果 ori == UIDeviceOrientationUnknown 的话, 默认给竖屏设置 - else { + else //如果 ori == UIDeviceOrientationUnknown 的话, 默认给竖屏设置 sizeClass |= MySizeClass_Portrait; - }; #endif _myGlobalSizeClass = sizeClass; } @@ -3493,10 +3431,14 @@ -(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sb if ([sbv isKindOfClass:[MyBaseLayout class]]) { - if ((sbvsc.widthSizeInner.priority == MyPriority_Low) && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) + if (sbvsc.leadingPosInner != nil && + sbvsc.trailingPosInner != nil && + sbvsc.widthSizeInner.priority == MyPriority_Low) [sbvsc.widthSizeInner __clear]; - if ((sbvsc.heightSizeInner.priority == MyPriority_Low) && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) + if (sbvsc.topPosInner != nil && + sbvsc.bottomPosInner != nil && + sbvsc.heightSizeInner.priority == MyPriority_Low) [sbvsc.heightSizeInner __clear]; if (pHasSubLayout != nil && (sbvsc.heightSizeInner.dimeWrapVal || sbvsc.widthSizeInner.dimeWrapVal)) @@ -3535,9 +3477,13 @@ -(CGFloat)myGetSubviewWidthSizeValue:(UIView *)sbv {//宽度等于其他的依赖的视图。 if (sbvWidthSizeInner.dimeRelaVal == lsc.widthSizeInner) + { retVal = [sbvWidthSizeInner measureWith:selfSize.width - paddingLeading - paddingTrailing]; + } else if (sbvWidthSizeInner.dimeRelaVal == lsc.heightSizeInner) + { retVal = [sbvWidthSizeInner measureWith:selfSize.height - paddingTop - paddingBottom]; + } else { if (sbvWidthSizeInner.dimeRelaVal.dime == MyGravity_Horz_Fill) @@ -3570,9 +3516,13 @@ -(CGFloat)myGetSubviewHeightSizeValue:(UIView *)sbv else if (sbvHeightSizeInner.dimeRelaVal != nil && sbvHeightSizeInner.dimeRelaVal.view != sbv) {//高度等于其他依赖的视图 if (sbvHeightSizeInner.dimeRelaVal == lsc.heightSizeInner) + { retVal = [sbvHeightSizeInner measureWith:selfSize.height - paddingTop - paddingBottom]; + } else if (sbvHeightSizeInner.dimeRelaVal == lsc.widthSizeInner) + { retVal = [sbvHeightSizeInner measureWith:selfSize.width - paddingLeading - paddingTrailing]; + } else { if (sbvHeightSizeInner.dimeRelaVal.dime == MyGravity_Horz_Fill) @@ -3831,9 +3781,8 @@ -(void)mySetNeedLayoutAllSubviews:(UIView *)v for (UIView *sv in sbs) { if ([sv isKindOfClass:[MyBaseLayout class]]) - { [sv setNeedsLayout]; - } + [self mySetNeedLayoutAllSubviews:sv]; } } @@ -3951,5 +3900,4 @@ -(BOOL)isHovering return self.hasDragging && self.canHover && self.oldIndex == self.currentIndex; } - @end diff --git a/MyLayout/Lib/MyLayoutSize.m b/MyLayout/Lib/MyLayoutSize.m index 6765841..b5c1b59 100644 --- a/MyLayout/Lib/MyLayoutSize.m +++ b/MyLayout/Lib/MyLayoutSize.m @@ -65,7 +65,18 @@ -(id)init return ^id(id val){ [self __equalTo:val]; + + //如果尺寸是自适应,并且当前视图是布局视图则直接布局视图自身刷新布局,否则由视图的父视图来刷新布局,这里特殊处理。 + if ([val isKindOfClass:[NSNumber class]]) + { + if ([val integerValue] == MyLayoutSize.wrap && [_view isKindOfClass:[MyBaseLayout class]]) + { + [_view setNeedsLayout]; + return self; + } + } [self setNeedsLayout]; + return self; }; } @@ -511,7 +522,7 @@ -(void)__clear _uBoundVal = nil; _dimeVal = nil; _shrink = 0; - _priority = MyPriority_Low; + _priority = MyPriority_Normal; _dimeValType = MyLayoutValueType_Nil; } diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index b41615d..8813c93 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -215,7 +215,7 @@ - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation [sbvsc.widthSizeInner __clear]; //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 - if (sbvsc.widthSizeInner.priority == MyPriority_Low && sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil) + if (sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil && sbvsc.widthSizeInner.priority == MyPriority_Low) [sbvsc.widthSizeInner __clear]; //只要同时设置了高度或者比重属性则应该把尺寸设置为空 @@ -229,7 +229,7 @@ - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation [sbvsc.heightSizeInner __clear]; //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 - if (sbvsc.heightSizeInner.priority == MyPriority_Low && sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil) + if (sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil && sbvsc.heightSizeInner.priority == MyPriority_Low) [sbvsc.heightSizeInner __clear]; //只要同时设置了宽度或者比重属性则应该把宽度置空 diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index f4840a5..b1750b0 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -35,16 +35,15 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //只要同时设置了左右边距且宽度优先级很低则把宽度值置空 - if ((sbvsc.widthSizeInner.priority == MyPriority_Low)&& - sbvsc.leadingPosInner.posVal != nil && - sbvsc.trailingPosInner.posVal != nil) + if (sbvsc.leadingPosInner.posVal != nil && + sbvsc.trailingPosInner.posVal != nil && + sbvsc.widthSizeInner.priority == MyPriority_Low) [sbvsc.widthSizeInner __clear]; - //只要同时设置了上下边距且高度优先级很低则把高度值置空 - if ((sbvsc.heightSizeInner.priority == MyPriority_Low) && - sbvsc.topPosInner.posVal != nil && - sbvsc.bottomPosInner.posVal != nil) + if (sbvsc.topPosInner.posVal != nil && + sbvsc.bottomPosInner.posVal != nil && + sbvsc.heightSizeInner.priority == MyPriority_Low) [sbvsc.heightSizeInner __clear]; diff --git a/MyLayoutDemo/AllTest10Cell.m b/MyLayoutDemo/AllTest10Cell.m index 7498cb2..40f33ab 100644 --- a/MyLayoutDemo/AllTest10Cell.m +++ b/MyLayoutDemo/AllTest10Cell.m @@ -53,8 +53,7 @@ -(void)createLinearRootLayout _rootLayout.padding = UIEdgeInsetsMake(0, 65, 0, 10); _rootLayout.cacheEstimatedRect = YES; _rootLayout.myHorzMargin = MyLayoutPos.safeAreaMargin; - _rootLayout.wrapContentHeight = YES; - _rootLayout.wrapContentWidth = NO; + _rootLayout.myHeight = MyLayoutSize.wrap; //这里设置其他位置有间隔线而最后一行没有下划线。我们可以借助布局视图本身所提供的边界线来代替掉系统默认的cell之间的间隔线,因为布局视图的边界线所提供的能力要大于默认的间隔线。 MyBorderline *bld = [[MyBorderline alloc] initWithColor:[UIColor whiteColor]]; self.rootLayout.bottomBorderline = bld; @@ -71,7 +70,7 @@ -(void)createLinearRootLayout _commentsLabel.textColor = [UIColor blueColor]; _commentsLabel.font = [UIFont systemFontOfSize:12]; _commentsLabel.myHorzMargin = 0; - _commentsLabel.wrapContentHeight = YES; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + _commentsLabel.myHeight = MyLayoutSize.wrap; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将高度设置为自适应 [giveLikeLayout addSubview:_commentsLabel]; } diff --git a/MyLayoutDemo/AllTest10HeaderView.m b/MyLayoutDemo/AllTest10HeaderView.m index b029559..8aded08 100644 --- a/MyLayoutDemo/AllTest10HeaderView.m +++ b/MyLayoutDemo/AllTest10HeaderView.m @@ -42,8 +42,7 @@ -(void)createLinearRootLayout _rootLayout.padding = UIEdgeInsetsMake(10, 10, 0.3, 10); _rootLayout.backgroundColor = [UIColor whiteColor]; _rootLayout.myHorzMargin = MyLayoutPos.safeAreaMargin; - _rootLayout.wrapContentHeight = YES; - _rootLayout.wrapContentWidth = NO; + _rootLayout.myHeight = MyLayoutSize.wrap; [self.contentView addSubview:_rootLayout]; _headImageView = [UIImageView new]; @@ -72,7 +71,7 @@ -(void)createLinearRootLayout _textMessageLabel.text = @""; _textMessageLabel.myLeading = 0; _textMessageLabel.myTrailing = 0; - _textMessageLabel.wrapContentHeight = YES; + _textMessageLabel.myHeight = MyLayoutSize.wrap; [messageLayout addSubview:_textMessageLabel]; _nineFlowLayout = [[MyFlowLayout alloc] initWithOrientation:MyOrientation_Vert arrangedCount:3]; @@ -80,8 +79,7 @@ -(void)createLinearRootLayout _nineFlowLayout.myHorzMargin = 0; _nineFlowLayout.subviewHSpace = 5; _nineFlowLayout.subviewVSpace = 5; - _nineFlowLayout.wrapContentHeight = YES; - _nineFlowLayout.wrapContentWidth = NO; + _nineFlowLayout.myHeight = MyLayoutSize.wrap; [messageLayout addSubview:_nineFlowLayout]; _timeLabel = [UILabel new]; @@ -90,7 +88,7 @@ -(void)createLinearRootLayout [messageLayout addSubview:_timeLabel]; MyLinearLayout *hLinearLayout = [[MyLinearLayout alloc] initWithOrientation:MyOrientation_Horz]; - hLinearLayout.wrapContentHeight = YES; + hLinearLayout.myHeight = MyLayoutSize.wrap; hLinearLayout.gravity = MyGravity_Horz_Between | MyGravity_Vert_Center; hLinearLayout.myHorzMargin = 0; [messageLayout addSubview:hLinearLayout]; @@ -98,13 +96,12 @@ -(void)createLinearRootLayout _browLabel = [UILabel new]; _browLabel.text = @""; _browLabel.font = [UIFont systemFontOfSize:14]; - _browLabel.wrapContentWidth = YES; - _browLabel.wrapContentHeight = YES; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + _browLabel.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); //尺寸自适应。 [hLinearLayout addSubview:_browLabel]; MyLinearLayout *actionshLinearLayout = [[MyLinearLayout alloc] initWithOrientation:MyOrientation_Horz]; actionshLinearLayout.rightPadding = 5; - actionshLinearLayout.wrapContentHeight = YES; + actionshLinearLayout.myHeight = MyLayoutSize.wrap; actionshLinearLayout.gravity = MyGravity_Vert_Center; actionshLinearLayout.myHorzMargin = 0; [hLinearLayout addSubview:actionshLinearLayout]; @@ -136,7 +133,7 @@ -(void)createLinearRootLayout _giveLikeLabel.textColor = [UIColor blueColor]; _giveLikeLabel.font = [UIFont systemFontOfSize:12]; _giveLikeLabel.myHorzMargin = 0; - _giveLikeLabel.wrapContentHeight = YES; + _giveLikeLabel.myHeight = MyLayoutSize.wrap; [giveLikeLayout addSubview:_giveLikeLabel]; } diff --git a/MyLayoutDemo/AllTest11ViewController.m b/MyLayoutDemo/AllTest11ViewController.m index 4c2a77b..e5c605b 100644 --- a/MyLayoutDemo/AllTest11ViewController.m +++ b/MyLayoutDemo/AllTest11ViewController.m @@ -41,7 +41,7 @@ -(void)loadView //添加操作按钮。 MyFlowLayout *actionLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; - actionLayout.wrapContentHeight = YES; + actionLayout.myHeight = MyLayoutSize.wrap; actionLayout.gravity = MyGravity_Horz_Fill; //所有子视图水平填充,也就是所有子视图的宽度相等。 actionLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); actionLayout.subviewHSpace = 5; diff --git a/MyLayoutDemo/AllTest12ViewController.m b/MyLayoutDemo/AllTest12ViewController.m index 8a6c019..cd8e31e 100644 --- a/MyLayoutDemo/AllTest12ViewController.m +++ b/MyLayoutDemo/AllTest12ViewController.m @@ -26,8 +26,8 @@ - (void)viewDidLoad { // Do any additional setup after loading the view. /* 这个DEMO演示MyLayout和AutoLayout的代码结合的例子。因为布局视图也是一个普通的视图,因此可以把一个布局视图添加到现有的其他非布局父视图中并且对布局视图设置 - 约束。 因为布局视图具有wrapContent的特性,就如UILabel一样因为具有intrinsicContentSize的能力,因此不需要在约束中明确设置宽度或者高度约束。当一个布局视图 - 的高度或者宽度都是由子视图决定的,也就是wrapContent为YES时,布局视图也不需要明确的设置宽度或者高度的约束。而且其他视图还可以依赖这种布局视图尺寸的自包含的能力。 + 约束。 因为布局视图可以设置尺寸自适应,就如UILabel一样因为具有intrinsicContentSize的能力,因此不需要在约束中明确设置宽度或者高度约束。当一个布局视图 + 的高度或者宽度都是由子视图决定的,也就是尺寸设置为自适应时,布局视图也不需要明确的设置宽度或者高度的约束。而且其他视图还可以依赖这种布局视图尺寸的自包含的能力。 本例子由3个子示例组成。 @@ -85,7 +85,7 @@ -(void)demo1 //MyLayout中的约束设置方法 linelayout.orientation = MyOrientation_Vert; - linelayout.wrapContentSize = YES; + linelayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); linelayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); linelayout.subviewSpace = 10; @@ -138,7 +138,7 @@ -(void)demo2 //MyLayout中的约束设置 linelayout.orientation = MyOrientation_Vert; - linelayout.wrapContentHeight = YES; + linelayout.myHeight = MyLayoutSize.wrap; linelayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); linelayout.subviewSpace = 10; @@ -191,7 +191,7 @@ -(void)demo3 //MyLayout中的约束设置 linelayout.orientation = MyOrientation_Horz; - linelayout.wrapContentWidth = YES; + linelayout.myWidth = MyLayoutSize.wrap; linelayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); linelayout.subviewSpace = 10; linelayout.gravity = MyGravity_Vert_Fill; diff --git a/MyLayoutDemo/AllTest1TableViewCell.m b/MyLayoutDemo/AllTest1TableViewCell.m index 90405f8..976d988 100644 --- a/MyLayoutDemo/AllTest1TableViewCell.m +++ b/MyLayoutDemo/AllTest1TableViewCell.m @@ -116,12 +116,11 @@ -(void)createLinearRootLayout /* 在UITableViewCell中使用MyLayout中的布局时请将布局视图作为contentView的子视图。如果我们的UITableViewCell的高度是动态的,请务必在将布局视图添加到contentView之前进行如下设置: _rootLayout.widthSize.equalTo(self.contentView.widthSize); - _rootLayout.wrapContentHeight = YES; + _rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); */ // _rootLayout.widthSize.equalTo(self.contentView.widthSize); _rootLayout.myHorzMargin = MyLayoutPos.safeAreaMargin; - _rootLayout.wrapContentHeight = YES; - _rootLayout.wrapContentWidth = NO; + _rootLayout.myHeight = MyLayoutSize.wrap; [self.contentView addSubview:_rootLayout]; //如果您将布局视图作为子视图添加到UITableViewCell本身,并且同时用了myLeft和myRight来做边界的话,那么有可能最终展示的宽度会不正确。经过试验是因为对UITableViewCell本身的KVO监控所得到的新老尺寸的问题导致的这应该是iOS的一个BUG。所以这里建议最好是把布局视图添加到UITableViewCell的子视图contentView里面去。 @@ -153,7 +152,7 @@ -(void)createLinearRootLayout _textMessageLabel.textColor = [CFTool color:4]; _textMessageLabel.myLeading = 0; _textMessageLabel.myTrailing = 0; //垂直线性布局里面如果同时设置了左右边距则能确定子视图的宽度,这里表示宽度和父视图相等。 - _textMessageLabel.wrapContentHeight = YES; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + _textMessageLabel.myHeight = MyLayoutSize.wrap; //如果想让文本的高度是动态的,请将高度设置为自适应 [messageLayout addSubview:_textMessageLabel]; @@ -173,10 +172,10 @@ -(void)createRelativeRootLayout /* 在UITableViewCell中使用MyLayout中的布局时请将布局视图作为contentView的子视图。如果我们的UITableViewCell的高度是动态的,请务必在将布局视图添加到contentView之前进行如下设置: _rootLayout.widthSize.equalTo(self.contentView.widthSize); - _rootLayout.wrapContentHeight = YES; + _rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); */ _rootLayout.widthSize.equalTo(self.contentView.widthSize); - _rootLayout.wrapContentHeight = YES; + _rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); [self.contentView addSubview:_rootLayout]; @@ -201,7 +200,7 @@ -(void)createRelativeRootLayout _textMessageLabel.leadingPos.equalTo(_headImageView.trailingPos).offset(5); //文本消息的左边在头像视图的右边并偏移5个点。 _textMessageLabel.trailingPos.equalTo(_rootLayout.trailingPos); //文本消息的右边和父布局的右边对齐。上面2行代码也同时确定了文本消息的宽度。 _textMessageLabel.topPos.equalTo(_nickNameLabel.bottomPos).offset(5); //文本消息的顶部在昵称文本的底部并偏移5个点。 - _textMessageLabel.wrapContentHeight = YES; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + _textMessageLabel.heightSize.equalTo(@(MyLayoutSize.wrap)); //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将高度设置为自适应 [_rootLayout addSubview:_textMessageLabel]; @@ -223,10 +222,10 @@ -(void)createFloatRootLayout /* 在UITableViewCell中使用MyLayout中的布局时请将布局视图作为contentView的子视图。如果我们的UITableViewCell的高度是动态的,请务必在将布局视图添加到contentView之前进行如下设置: _rootLayout.widthSize.equalTo(self.contentView.widthSize); - _rootLayout.wrapContentHeight = YES; + _rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); */ _rootLayout.widthSize.equalTo(self.contentView.widthSize); - _rootLayout.wrapContentHeight = YES; + _rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); [self.contentView addSubview:_rootLayout]; /* @@ -250,7 +249,7 @@ -(void)createFloatRootLayout _textMessageLabel.font = [CFTool font:15]; _textMessageLabel.textColor = [CFTool color:4]; _textMessageLabel.weight = 1; //占用剩余宽度 - _textMessageLabel.wrapContentHeight = YES; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + _textMessageLabel.myHeight = MyLayoutSize.wrap; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将高度设置为自适应。 [_rootLayout addSubview:_textMessageLabel]; _imageMessageImageView = [UIImageView new]; diff --git a/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m b/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m index 508b4f0..0500d0c 100644 --- a/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m +++ b/MyLayoutDemo/AllTest1TableViewCellForAutoLayout.m @@ -107,8 +107,8 @@ -(void)createLinearRootLayout _rootLayout.bottomPadding = 5; //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! _rootLayout.cacheEstimatedRect = YES; - _rootLayout.wrapContentHeight = YES; - _rootLayout.wrapContentWidth = NO; + _rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); + _rootLayout.widthSize.equalTo(nil); [self.contentView addSubview:_rootLayout]; @@ -140,7 +140,7 @@ -(void)createLinearRootLayout _textMessageLabel.textColor = [CFTool color:4]; _textMessageLabel.myLeading = 0; _textMessageLabel.myTrailing = 0; //垂直线性布局里面如果同时设置了左右边距则能确定子视图的宽度,这里表示宽度和父视图相等。 - _textMessageLabel.wrapContentHeight = YES; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + _textMessageLabel.myHeight = MyLayoutSize.wrap; //如果想让文本的高度是动态的,请在设置明确宽度的情况下将高度设置为自适应。 [messageLayout addSubview:_textMessageLabel]; @@ -157,7 +157,7 @@ -(void)createRelativeRootLayout _rootLayout.bottomPadding = 5; //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! _rootLayout.cacheEstimatedRect = YES; - _rootLayout.wrapContentHeight = YES; + _rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); [self.contentView addSubview:_rootLayout]; @@ -182,7 +182,7 @@ -(void)createRelativeRootLayout _textMessageLabel.leadingPos.equalTo(_headImageView.trailingPos).offset(5); //文本消息的左边在头像视图的右边并偏移5个点。 _textMessageLabel.trailingPos.equalTo(_rootLayout.trailingPos); //文本消息的右边和父布局的右边对齐。上面2行代码也同时确定了文本消息的宽度。 _textMessageLabel.topPos.equalTo(_nickNameLabel.bottomPos).offset(5); //文本消息的顶部在昵称文本的底部并偏移5个点。 - _textMessageLabel.wrapContentHeight = YES; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + _textMessageLabel.heightSize.equalTo(@(MyLayoutSize.wrap)); //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将高度设置为自适应 [_rootLayout addSubview:_textMessageLabel]; @@ -201,7 +201,7 @@ -(void)createFloatRootLayout _rootLayout.bottomPadding = 5; //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! _rootLayout.cacheEstimatedRect = YES; - _rootLayout.wrapContentHeight = YES; + _rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); [self.contentView addSubview:_rootLayout]; /* @@ -225,7 +225,7 @@ -(void)createFloatRootLayout _textMessageLabel.font = [CFTool font:15]; _textMessageLabel.textColor = [CFTool color:4]; _textMessageLabel.weight = 1; //占用剩余宽度 - _textMessageLabel.wrapContentHeight = YES; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + _textMessageLabel.myHeight = MyLayoutSize.wrap; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将高度设置为自适应。 [_rootLayout addSubview:_textMessageLabel]; _imageMessageImageView = [UIImageView new]; diff --git a/MyLayoutDemo/AllTest1ViewController.m b/MyLayoutDemo/AllTest1ViewController.m index 2445915..b421e06 100644 --- a/MyLayoutDemo/AllTest1ViewController.m +++ b/MyLayoutDemo/AllTest1ViewController.m @@ -116,7 +116,7 @@ - (void)viewDidLoad { tableHeaderViewLayout.frame = CGRectMake(0, 0, self.tableView.frame.size.width, 100); - 而如果某个布局视图的高度有可能是动态的高度,也就是用了wrapContentHeight为YES时,可以不用指定明确的指定高度,但要指定宽度。而且在布局视图添加到self.tableView.tableHeaderView 之前一定要记得调用: + 而如果某个布局视图的高度有可能是动态的高度,也就是高度自适应,可以不用指定明确的指定高度,但要指定宽度。而且在布局视图添加到self.tableView.tableHeaderView 之前一定要记得调用: [tableHeaderViewLayout layoutIfNeeded] */ @@ -160,11 +160,11 @@ -(void)createTableHeaderView UILabel *label2 = [UILabel new]; - label2.text = NSLocalizedString(@" if you use layout view to realize the dynamic height tableHeaderView, please use frame to set view's width and use wrapContentHeight to set view's height. the layoutIfNeeded method is needed to call before the layout view assignment to the UITableview's tableHeaderView.", @""); + label2.text = NSLocalizedString(@" if you use layout view to realize the dynamic height tableHeaderView, please use frame to set view's width and set view's heightSize to MyLayoutSize.wrap. the layoutIfNeeded method is needed to call before the layout view assignment to the UITableview's tableHeaderView.", @""); label2.textColor = [CFTool color:4]; label2.font = [CFTool font:15]; label2.myHorzMargin = 5; - label2.wrapContentHeight = YES; + label2.myHeight = MyLayoutSize.wrap; label2.myTop = 10; [label2 sizeToFit]; [tableHeaderViewLayout addSubview:label2]; diff --git a/MyLayoutDemo/AllTest2TableViewCell.m b/MyLayoutDemo/AllTest2TableViewCell.m index 76655af..5b82040 100644 --- a/MyLayoutDemo/AllTest2TableViewCell.m +++ b/MyLayoutDemo/AllTest2TableViewCell.m @@ -94,7 +94,7 @@ -(void)createLinearRootLayout //中间用户信息是一个垂直线性布局:上部分是姓名,以及一些小图标这部分组成一个水平线性布局。下面是一行长的描述文字。 MyLinearLayout *userInfoLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - userInfoLayout.wrapContentHeight = YES; //高度由子视图决定 + userInfoLayout.myHeight = MyLayoutSize.wrap; //高度由子视图决定 userInfoLayout.weight = 1; //中间部分的宽度占用整个水平线性布局剩余的空间。 userInfoLayout.gravity = MyGravity_Horz_Fill; //里面的子视图宽度和布局视图相等。 userInfoLayout.subviewVSpace = 5; //子视图间距为5。 @@ -103,8 +103,7 @@ -(void)createLinearRootLayout //姓名信息部分,一个水平线性布局:左边名称,后面两个操作按钮,整体底部对齐。 MyLinearLayout *userNameLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; - userNameLayout.wrapContentHeight = YES; //高度由子视图决定 - userNameLayout.wrapContentWidth = NO; //因为布局的宽度是和父布局相等,因此这里必须要设置为NO!!否则会有约束冲突。 + userNameLayout.myHeight = MyLayoutSize.wrap; //高度由子视图决定 userNameLayout.subviewHSpace = 5; //子视图之间宽度间隔是5 userNameLayout.gravity = MyGravity_Vert_Bottom; //整体垂直底部对齐。 [userInfoLayout addSubview:userNameLayout]; @@ -115,7 +114,7 @@ -(void)createLinearRootLayout //_nameLabel的宽度根据内容自适应,但是最大的宽度是父视图的宽度的1倍,再减去5+14+5+14。这里的5是视图之间的间距,14是后面两个图片的宽度。 //这个设置的意思是_nameLabel的宽可以动态增长,但是不能超过父视图的宽度,并且要保证后面的2个图片视图显示出来。 //您可以通过uBound方法设置尺寸的最大上边界。具体参见对uBound的方法的详细介绍。 - _nameLabel.widthSize.equalTo(_nameLabel.widthSize).uBound(userNameLayout.widthSize, -(5 + 14 + 5 + 14), 1); + _nameLabel.widthSize.equalTo(@(MyLayoutSize.wrap)).uBound(userNameLayout.widthSize, -(5 + 14 + 5 + 14), 1); _nameLabel.heightSize.equalTo(@25); [userNameLayout addSubview:_nameLabel]; @@ -130,7 +129,7 @@ -(void)createLinearRootLayout _descLabel.textColor = [CFTool color:4]; _descLabel.font = [CFTool font:15]; _descLabel.adjustsFontSizeToFitWidth = YES; - _descLabel.wrapContentHeight = YES; //2行高度,高度根据内容确定。 + _descLabel.myHeight = MyLayoutSize.wrap; //2行高度,高度根据内容确定。 _descLabel.numberOfLines = 2; [userInfoLayout addSubview:_descLabel]; @@ -143,7 +142,7 @@ -(void)createLinearRootLayout _priceLabel.textAlignment = NSTextAlignmentRight; _priceLabel.adjustsFontSizeToFitWidth = YES; //宽度最宽为100,注意到这里使用了宏MYDIMESCALEW表示会根据屏幕的宽度来对100进行缩放。这个100是按iPhone6为标准设置的。具体请参考MyDimeScale类。 - _priceLabel.widthSize.equalTo(_priceLabel.widthSize).uBound(@(MYDIMESCALEW(100)), 0, 1).lBound(@(MYDIMESCALEW(50)), 0, 1); + _priceLabel.widthSize.equalTo(@(MyLayoutSize.wrap)).uBound(@(MYDIMESCALEW(100)), 0, 1).lBound(@(MYDIMESCALEW(50)), 0, 1); _priceLabel.heightSize.equalTo(@25); _priceLabel.myLeading = 10; [rootLayout addSubview:_priceLabel]; @@ -181,7 +180,7 @@ -(void)createRelativeRootLayout _priceLabel.trailingPos.equalTo(rootLayout.trailingPos); _priceLabel.centerYPos.equalTo(rootLayout.centerYPos); //priceLabel的宽度根据内容自适应,但是最大的宽度是100,最小的宽度是50。注意到这里使用了宏MYDIMESCALEW表示会根据屏幕的宽度来对100进行缩放。这个100是在DEMO中是按iPhone6为标准设置的。具体请参考MyDimeScale类的介绍。 - _priceLabel.widthSize.equalTo(_priceLabel.widthSize).uBound(@(MYDIMESCALEW(100)), 0, 1).lBound(@(MYDIMESCALEW(50)), 0, 1); + _priceLabel.widthSize.equalTo(@(MyLayoutSize.wrap)).uBound(@(MYDIMESCALEW(100)), 0, 1).lBound(@(MYDIMESCALEW(50)), 0, 1); _priceLabel.heightSize.equalTo(@25); [rootLayout addSubview:_priceLabel]; @@ -189,7 +188,7 @@ -(void)createRelativeRootLayout _nameLabel = [UILabel new]; _nameLabel.font = [CFTool font:17]; _nameLabel.textColor = [CFTool color:3]; - _nameLabel.widthSize.equalTo(_nameLabel.widthSize); //视图的宽度由内容包裹 + _nameLabel.widthSize.equalTo(@(MyLayoutSize.wrap)); //视图的宽度由内容包裹 _nameLabel.heightSize.equalTo(@25); _nameLabel.leadingPos.equalTo(_headImageView.trailingPos); //1.3.0版本最新支持。设置_nameLabel的右边距最大是_priceLabel的左边距,再偏移两个小图标和间距的距离。这样当_nameLabel的尺寸超过这个最大的右边距时就会自动的缩小视图的宽度。 @@ -213,7 +212,7 @@ -(void)createRelativeRootLayout _descLabel.textColor = [CFTool color:4]; _descLabel.font = [CFTool font:15]; _descLabel.adjustsFontSizeToFitWidth = YES; - _descLabel.wrapContentHeight = YES; //2行高度,高度根据内容确定。 + _descLabel.myHeight = MyLayoutSize.wrap; //2行高度,高度根据内容确定。 _descLabel.numberOfLines = 2; _descLabel.leadingPos.equalTo(_nameLabel.leadingPos); _descLabel.trailingPos.equalTo(_priceLabel.leadingPos).offset(10); @@ -253,7 +252,7 @@ -(void)createFloatRootLayout _priceLabel.reverseFloat = YES; _priceLabel.myLeading = 10; //priceLabel的宽度根据内容自适应,但是最大的宽度是100,最小的宽度是50。注意到这里使用了宏MYDIMESCALEW表示会根据屏幕的宽度来对100进行缩放。这个100是在DEMO中是按iPhone6为标准设置的。具体请参考MyDimeScale类的介绍。 - _priceLabel.widthSize.equalTo(_priceLabel.widthSize).uBound(@(MYDIMESCALEW(100)), 0, 1).lBound(@(MYDIMESCALEW(50)), 0, 1); + _priceLabel.widthSize.equalTo(@(MyLayoutSize.wrap)).uBound(@(MYDIMESCALEW(100)), 0, 1).lBound(@(MYDIMESCALEW(50)), 0, 1); _priceLabel.heightSize.equalTo(rootLayout.heightSize); [rootLayout addSubview:_priceLabel]; @@ -272,7 +271,7 @@ -(void)createFloatRootLayout //_nameLabel的宽度根据内容自适应,但是最大的宽度是父视图的宽度的1倍,再减去5+14+5+14。这里的5是视图之间的间距,14是后面两个图片的宽度。 //这个设置的意思是_nameLabel的宽可以动态增长,但是不能超过父视图的宽度,并且要保证后面的2个图片视图显示出来。 //您可以通过uBound方法设置尺寸的最大上边界。具体参见对uBound的方法的详细介绍。 - _nameLabel.widthSize.equalTo(_nameLabel.widthSize).uBound(userInfoLayout.widthSize, -(5 + 14 + 5 + 14), 1); + _nameLabel.widthSize.equalTo(@(MyLayoutSize.wrap)).uBound(userInfoLayout.widthSize, -(5 + 14 + 5 + 14), 1); _nameLabel.heightSize.equalTo(@25); [userInfoLayout addSubview:_nameLabel]; @@ -286,7 +285,7 @@ -(void)createFloatRootLayout _descLabel.textColor = [CFTool color:4]; _descLabel.font = [CFTool font:15]; _descLabel.adjustsFontSizeToFitWidth = YES; - _descLabel.wrapContentHeight = YES; //2行高度,高度根据内容确定。 + _descLabel.myHeight = MyLayoutSize.wrap; //2行高度,高度根据内容确定。 _descLabel.numberOfLines = 2; _descLabel.clearFloat = YES; _descLabel.weight = 1; diff --git a/MyLayoutDemo/AllTest3ViewController.m b/MyLayoutDemo/AllTest3ViewController.m index 1420c3b..58a241e 100644 --- a/MyLayoutDemo/AllTest3ViewController.m +++ b/MyLayoutDemo/AllTest3ViewController.m @@ -132,7 +132,7 @@ -(void)addHeaderLayout:(MyLinearLayout *)contentLayout { MyRelativeLayout *headerLayout = [MyRelativeLayout new]; headerLayout.backgroundImage = [UIImage imageNamed:@"bk1"]; //可以为布局直接设备背景图片。 - headerLayout.wrapContentHeight = YES; + headerLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); [contentLayout addSubview:headerLayout]; UIImageView *headerImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"head2"]]; @@ -278,7 +278,7 @@ -(void)addFlexedWidthLayout:(MyLinearLayout*)contentLayout leftLabel.backgroundColor = [CFTool color:5]; leftLabel.font = [CFTool font:14]; leftLabel.trailingPos.equalTo(@0.5).min(0); //右边浮动间距为0.5,最小为0 - leftLabel.wrapContentWidth = YES; //宽度由内容包裹 + leftLabel.widthSize.equalTo(@(MyLayoutSize.wrap)); [testLayout addSubview:leftLabel]; self.leftFlexedLabel = leftLabel; @@ -289,7 +289,7 @@ -(void)addFlexedWidthLayout:(MyLinearLayout*)contentLayout rightLabel.backgroundColor = [CFTool color:6]; rightLabel.font = [CFTool font:14]; rightLabel.leadingPos.equalTo(@0.5).min(0); //左边浮动间距为0.5,最小为0 - rightLabel.wrapContentWidth = YES; //宽度由内容包裹 + rightLabel.widthSize.equalTo(@(MyLayoutSize.wrap)); //宽度由内容包裹 [testLayout addSubview:rightLabel]; self.rightFlexedLabel = rightLabel; @@ -369,7 +369,7 @@ -(MyLinearLayout*)createActionLayout:(NSString*)title action:(SEL)action //左右内边距都是10,不包裹子视图,整体高度为50,里面的子布局垂直居中对齐。 actionLayout.leftPadding = 10; actionLayout.rightPadding = 10; - actionLayout.wrapContentWidth = NO; + actionLayout.widthSize.equalTo(nil); actionLayout.heightSize.equalTo(@50); actionLayout.gravity = MyGravity_Vert_Center; @@ -402,7 +402,7 @@ -(MyLinearLayout*)createSwitchLayout:(NSString*)title action:(SEL)action //左右边距都是10,不包裹子视图,整体高度为50,里面的子布局垂直居中对齐。 switchLayout.leftPadding = 10; switchLayout.rightPadding = 10; - switchLayout.wrapContentWidth = NO; + switchLayout.widthSize.equalTo(nil); switchLayout.heightSize.equalTo(@50); switchLayout.gravity = MyGravity_Vert_Center; @@ -540,15 +540,9 @@ -(void)handleRightFlexed:(UISegmentedControl*)segmented -(void)handleShrinkSwitch:(UISwitch *)sender { if (sender.isOn) - { - self.shrinkLayout.heightSize.equalTo(nil); - self.shrinkLayout.wrapContentHeight = YES; - } + self.shrinkLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); else - { self.shrinkLayout.heightSize.equalTo(@50); - self.shrinkLayout.wrapContentHeight = NO; - } [self.shrinkLayout layoutAnimationWithDuration:0.3]; } @@ -593,7 +587,7 @@ -(void)handleShowPopMenu:(MyBaseLayout*)sender itemLayout.gravity = MyGravity_Horz_Fill; itemLayout.subviewHSpace = 10; itemLayout.subviewVSpace = 10; - itemLayout.wrapContentHeight = YES; + itemLayout.myHeight = MyLayoutSize.wrap; [scrollView addSubview:itemLayout]; self.popmenuItemLayout = itemLayout; diff --git a/MyLayoutDemo/AllTest4ViewController.m b/MyLayoutDemo/AllTest4ViewController.m index 9fd41c1..7e559e4 100644 --- a/MyLayoutDemo/AllTest4ViewController.m +++ b/MyLayoutDemo/AllTest4ViewController.m @@ -58,7 +58,7 @@ - (void)viewDidLoad { _rootLayout.gravity = MyGravity_Horz_Fill; //设置垂直线性布局的水平填充值表明布局视图里面的所有子视图的宽度都和布局视图相等。 _rootLayout.widthSize.equalTo(scrollView.widthSize); - _rootLayout.wrapContentHeight = YES; //布局宽度和父视图一致,高度则由内容包裹。这是实现将布局视图加入滚动条视图并垂直滚动的标准方法。 + _rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); //布局宽度和父视图一致,高度则由内容包裹。这是实现将布局视图加入滚动条视图并垂直滚动的标准方法。 [scrollView addSubview:_rootLayout]; self.containerLayouts = [NSMutableArray new]; @@ -134,7 +134,7 @@ -(UIView*)createSupplementaryLayout:(NSString*)sectionTitle -(MyFlowLayout*)createCellContainerLayout:(NSInteger)arrangedCount { MyFlowLayout *containerLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:arrangedCount]; - containerLayout.wrapContentHeight = YES; + containerLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); containerLayout.gravity = MyGravity_Horz_Fill; //平均分配里面每个子视图的宽度或者拉伸子视图的宽度以便填充满整个布局。 containerLayout.subviewHSpace = 5; containerLayout.subviewVSpace = 5; @@ -147,7 +147,6 @@ -(MyFlowLayout*)createCellContainerLayout:(NSInteger)arrangedCount -(UIView*)createCellLayout1:(NSString*)image title:(NSString*)title { MyLinearLayout *cellLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - cellLayout.wrapContentHeight = NO; cellLayout.gravity = MyGravity_Horz_Fill; //里面所有子视图的宽度都跟父视图保持一致,这样子视图就不需要设置宽度了。 cellLayout.myHeight = 100; cellLayout.subviewVSpace = 5; //设置布局视图里面子视图之间的间距为5个点。 diff --git a/MyLayoutDemo/AllTest5ViewController.m b/MyLayoutDemo/AllTest5ViewController.m index 36fa6b9..ee29453 100644 --- a/MyLayoutDemo/AllTest5ViewController.m +++ b/MyLayoutDemo/AllTest5ViewController.m @@ -28,7 +28,6 @@ -(void)loadView //默认设置为垂直布局 MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); - rootLayout.wrapContentHeight = NO; rootLayout.gravity = MyGravity_Horz_Fill; rootLayout.subviewSpace = 10; rootLayout.backgroundColor = [UIColor whiteColor]; @@ -66,7 +65,7 @@ -(void)loadView //但是调用lsc.backgroundColor = xx 则会崩溃,因为fetchLayoutSizeClass返回的并不是真的视图对象。 MyLinearLayout *lsc = [rootLayout fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact copyFrom:MySizeClass_wAny | MySizeClass_hAny]; lsc.orientation = MyOrientation_Horz; - lsc.wrapContentWidth = NO; + lsc.widthSize.equalTo(nil); lsc.gravity = MyGravity_Vert_Fill; diff --git a/MyLayoutDemo/AllTest6ViewController.m b/MyLayoutDemo/AllTest6ViewController.m index 4833452..138309a 100644 --- a/MyLayoutDemo/AllTest6ViewController.m +++ b/MyLayoutDemo/AllTest6ViewController.m @@ -27,7 +27,6 @@ -(void)loadView MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - rootLayout.wrapContentHeight = NO; rootLayout.gravity = MyGravity_Horz_Fill; rootLayout.backgroundColor = [UIColor whiteColor]; self.view = rootLayout; @@ -35,7 +34,7 @@ -(void)loadView //创建顶部的菜单布局部分。 MyFlowLayout *menuLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; menuLayout.gravity = MyGravity_Horz_Fill; //水平填充所有尺寸。 - menuLayout.wrapContentHeight = YES; + menuLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); menuLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); menuLayout.subviewSpace = 10; [rootLayout addSubview:menuLayout]; @@ -114,7 +113,7 @@ -(void)loadView MyFlowLayout *menuLayoutSC = [menuLayout fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact copyFrom:MySizeClass_hAny | MySizeClass_wAny]; menuLayoutSC.orientation = MyOrientation_Horz; menuLayoutSC.gravity = MyGravity_Vert_Fill; - menuLayoutSC.wrapContentWidth = YES; + menuLayoutSC.widthSize.equalTo(@(MyLayoutSize.wrap)); UILabel *menu1LabelSC = [menu1Label fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact]; UILabel *menu2LabelSC = [menu2Label fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact]; diff --git a/MyLayoutDemo/AllTest7ViewController.m b/MyLayoutDemo/AllTest7ViewController.m index e9b4934..9bb68c3 100644 --- a/MyLayoutDemo/AllTest7ViewController.m +++ b/MyLayoutDemo/AllTest7ViewController.m @@ -38,8 +38,7 @@ -(void) loadView tipLabel.font = [CFTool font:16]; tipLabel.textColor = [CFTool color:3]; tipLabel.adjustsFontSizeToFitWidth = YES; - tipLabel.wrapContentHeight = YES; - [tipLabel sizeToFit]; + tipLabel.heightSize.equalTo(@(MyLayoutSize.wrap)); [rootLayout addSubview:tipLabel]; [self createDemo1:rootLayout]; @@ -78,18 +77,15 @@ -(void)createDemo1:(MyLinearLayout*)rootLayout tipLabel.text = @"1.下面的例子实现一行内多个子视图从左往右排列。如果在小屏幕下显示则会压缩所有子视图的空间,如果能够被容纳的话则正常显示。您可以分别在横竖屏下测试以及在iPhone4/5/6/6+上测试效果:"; tipLabel.font = [CFTool font:14]; tipLabel.adjustsFontSizeToFitWidth = YES; - tipLabel.wrapContentHeight = YES; + tipLabel.myHeight = MyLayoutSize.wrap; tipLabel.myTop = 10; - [tipLabel sizeToFit]; [rootLayout addSubview:tipLabel]; MyLinearLayout *contentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; - contentLayout.wrapContentWidth = NO; - contentLayout.wrapContentHeight = YES; + contentLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); contentLayout.subviewHSpace = 5; - contentLayout.shrinkType = MySubviewsShrink_Weight; //这个属性用来设置当子视图的总尺寸大于布局视图的尺寸时如何压缩这些具有固定尺寸的方法为按比例缩小。您可以分别试试设置为:MySubviewsShrink_Weight,MySubviewsShrink_Average,MySubviewsShrink_None,MySubviewsShrink_Auto四种值的效果。 - + contentLayout.backgroundColor = [CFTool color:0]; [rootLayout addSubview:contentLayout]; @@ -99,8 +95,9 @@ -(void)createDemo1:(MyLinearLayout*)rootLayout label1.font = [CFTool font:16]; label1.backgroundColor = [CFTool color:5]; label1.adjustsFontSizeToFitWidth = YES; - label1.wrapContentSize = YES; //尺寸等于视图的内容包裹。 - label1.widthSize.lBound(label1.widthSize,0,1); //并且最小宽度也等于自己,这样设置的话可以保证这个视图永远不会被压缩。您可以注释掉这句看看效果。 + label1.heightSize.equalTo(@(MyLayoutSize.wrap)); + label1.widthSize.equalTo(@(MyLayoutSize.wrap)); + label1.widthSize.shrink = 0; //不压缩! [contentLayout addSubview:label1]; //第二个子视图。 @@ -109,7 +106,9 @@ -(void)createDemo1:(MyLinearLayout*)rootLayout label2.font = [CFTool font:16]; label2.backgroundColor = [CFTool color:6]; label2.adjustsFontSizeToFitWidth = YES; - label2.wrapContentSize = YES; //尺寸等于自身的内容 + label2.heightSize.equalTo(@(MyLayoutSize.wrap)); + label2.widthSize.equalTo(@(MyLayoutSize.wrap)); + label2.widthSize.shrink = 1; //压缩 label2.numberOfLines = 1; //如果你只想要一行,那么要记得在设置包裹后设置行数。。 [contentLayout addSubview:label2]; @@ -119,7 +118,9 @@ -(void)createDemo1:(MyLinearLayout*)rootLayout label3.font = [CFTool font:15]; label3.backgroundColor = [CFTool color:7]; label3.adjustsFontSizeToFitWidth = YES; - label3.wrapContentSize = YES; + label3.heightSize.equalTo(@(MyLayoutSize.wrap)); + label3.widthSize.equalTo(@(MyLayoutSize.wrap)); + label3.widthSize.shrink = 1; //压缩 [contentLayout addSubview:label3]; label3.myTrailing = 0.5; //这句设置非常重要,设置为右间距为相对间距,从而达到如果屏幕小则会缩小固定尺寸,如果大则不会的效果。 @@ -133,14 +134,12 @@ -(void)createDemo2:(MyLinearLayout*)rootLayout tipLabel.text = @"2.下面的例子里面最右边的两个子视图的宽度是固定的,而第一个子视图则占用剩余的空间。您可以分别在横竖屏下测试以及在iPhone4/5/6/6+上测试效果:"; tipLabel.font = [CFTool font:14]; tipLabel.adjustsFontSizeToFitWidth = YES; - tipLabel.wrapContentHeight = YES; + tipLabel.myHeight = MyLayoutSize.wrap; tipLabel.myTop = 10; - [tipLabel sizeToFit]; [rootLayout addSubview:tipLabel]; MyLinearLayout *contentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; - contentLayout.wrapContentWidth = NO; - contentLayout.wrapContentHeight = YES; + contentLayout.myHeight = MyLayoutSize.wrap; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); contentLayout.subviewHSpace = 5; contentLayout.backgroundColor = [CFTool color:0]; @@ -152,8 +151,7 @@ -(void)createDemo2:(MyLinearLayout*)rootLayout label1.font = [CFTool font:15]; label1.backgroundColor = [CFTool color:5]; label1.adjustsFontSizeToFitWidth = YES; - [label1 sizeToFit]; - label1.wrapContentHeight = YES; //自动换行。 + label1.myHeight = MyLayoutSize.wrap; label1.weight = 1; //占用剩余的空间。 [contentLayout addSubview:label1]; @@ -199,14 +197,13 @@ -(void)createDemo3:(MyLinearLayout*)rootLayout tipLabel.text = @"3.下面的例子里面最右边的两个子视图的宽度是固定的,而第一个子视图的尺寸动态变化,但是最宽不能超过布局剩余的宽度。您可以分别在横竖屏下测试以及在iPhone4/5/6/6+上分别测试效果:"; tipLabel.font = [CFTool font:14]; tipLabel.adjustsFontSizeToFitWidth = YES; - tipLabel.wrapContentHeight = YES; + tipLabel.myHeight = MyLayoutSize.wrap; tipLabel.myTop = 10; [tipLabel sizeToFit]; [rootLayout addSubview:tipLabel]; MyLinearLayout *contentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; - contentLayout.wrapContentWidth = NO; - contentLayout.wrapContentHeight = YES; + contentLayout.myHeight = MyLayoutSize.wrap; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); contentLayout.subviewHSpace = 5; contentLayout.backgroundColor = [CFTool color:0]; @@ -218,7 +215,7 @@ -(void)createDemo3:(MyLinearLayout*)rootLayout label1.font = [CFTool font:14]; label1.backgroundColor = [CFTool color:5]; label1.tag = 1000; //为了测试用。。 - label1.wrapContentSize = YES; //尺寸由内容包裹 + label1.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); //尺寸由内容包裹 label1.myTrailing = 0.5; //设置相对间距 [contentLayout addSubview:label1]; @@ -272,7 +269,7 @@ -(void)createDemo4:(MyLinearLayout*)rootLayout tipLabel.text = @"4.下面的例子展示左右2个子视图的内容分别向两边延伸,但是不会重叠。这样做的好处就是不会产生空间的浪费。一个具体例子就是UITableviewCell中展示内容时,一部分在左边而一部分在右边,两边的内容长度都不确定,但是不能重叠以及浪费空间。 您可以分别在横竖屏下测试以及在iPhone4/5/6/6+上测试效果:"; tipLabel.font = [CFTool font:14]; tipLabel.adjustsFontSizeToFitWidth = YES; - tipLabel.wrapContentHeight = YES; + tipLabel.myHeight = MyLayoutSize.wrap; tipLabel.myTop = 10; [tipLabel sizeToFit]; [rootLayout addSubview:tipLabel]; @@ -284,8 +281,7 @@ -(void)createDemo4:(MyLinearLayout*)rootLayout [changeButton addTarget:self action:@selector(handleChangeText:) forControlEvents:UIControlEventTouchUpInside]; MyLinearLayout *contentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; - contentLayout.wrapContentWidth = NO; - contentLayout.wrapContentHeight = YES; + contentLayout.myHeight = MyLayoutSize.wrap; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); contentLayout.subviewHSpace = 20; contentLayout.shrinkType = MySubviewsShrink_Auto; //为了实现左右两边文本的自动缩放调整,必须要将线性布局的属性设置MySubviewsShrink_Auto。当设置为Auto属性时,必要要满足当前子视图中只有2个子视图的宽度设置为等于自身内容,否则无效。这个属性用来实现左右2个子视图根据内容来占用最佳的空间的例子。 @@ -306,7 +302,7 @@ -(void)createDemo4:(MyLinearLayout*)rootLayout UILabel *leadingLabel = [UILabel new]; leadingLabel.font = [UIFont systemFontOfSize:14]; leadingLabel.textColor = [UIColor redColor]; - leadingLabel.wrapContentSize = YES; + leadingLabel.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); leadingLabel.trailingPos.equalTo(@0.5); //设置右边的相对间距. [contentLayout addSubview:leadingLabel]; leadingLabel.tag = 1000; @@ -316,7 +312,7 @@ -(void)createDemo4:(MyLinearLayout*)rootLayout UILabel *trailingLabel = [UILabel new]; trailingLabel.font = [UIFont systemFontOfSize:14]; trailingLabel.textColor = [UIColor blueColor]; - trailingLabel.wrapContentSize = YES; + trailingLabel.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); trailingLabel.leadingPos.equalTo(@0.5); //设置右边的相对间距. [contentLayout addSubview:trailingLabel]; trailingLabel.tag = 2000; @@ -360,7 +356,7 @@ -(void)createDemo5:(MyLinearLayout*)rootLayout tipLabel.text = @"5.下面的例子中(响应式布局!!),您可以添加按钮来添加多个按钮形成多行多列的布局。在不同的屏幕尺寸下,子视图之间的间距会自动调整以便满足最佳的布局状态。比如多个子视图有规律排列,每个子视图的宽度是固定的,在iPhone4下以及iPhone6下都能放置4个子视图,但是iPhone4中子视图之间的间距要比iPhone6上的小,而在iPhone6+上则因为空间足够可以放置5个子视图。您可以分别在横竖屏下测试以及在iPhone4/5/6/6+上测试效果:"; tipLabel.font = [CFTool font:14]; tipLabel.adjustsFontSizeToFitWidth = YES; - tipLabel.wrapContentHeight = YES; + tipLabel.myHeight = MyLayoutSize.wrap; tipLabel.myTop = 10; [tipLabel sizeToFit]; [rootLayout addSubview:tipLabel]; @@ -370,7 +366,7 @@ -(void)createDemo5:(MyLinearLayout*)rootLayout MyFlowLayout *contentLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; contentLayout.backgroundColor = [CFTool color:0]; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); - contentLayout.wrapContentHeight = YES; + contentLayout.myHeight = MyLayoutSize.wrap; contentLayout.subviewVSpace = 5; //设置流式布局里面子视图之间的垂直间距。 [contentLayout setSubviewsSize:subviewWidth minSpace:5 maxSpace:10]; //这里面水平间距用浮动间距,浮动间距设置为子视图固定宽度为60,最小的间距为5,最大间距为10。注意这里要求所有子视图的宽度都是60。 [rootLayout addSubview:contentLayout]; @@ -451,7 +447,7 @@ -(void)createDemo6:(MyLinearLayout*)rootLayout tipLabel.text = @"6.下面的例子用来实现子视图依次从左往右添加,并且当空间不够时会自动压缩前面的所有子视图的宽度。而当所有子视图的宽度都到达了最小的阈值时就会自动换行,并继续添加上去。您可以分别在横竖屏下测试以及在iPhone4/5/6/6+上分别测试效果:"; tipLabel.font = [CFTool font:14]; tipLabel.adjustsFontSizeToFitWidth = YES; - tipLabel.wrapContentHeight = YES; + tipLabel.myHeight = MyLayoutSize.wrap; tipLabel.myTop = 10; [tipLabel sizeToFit]; [rootLayout addSubview:tipLabel]; @@ -481,14 +477,14 @@ -(void)createDemo7:(MyLinearLayout*)rootLayout tipLabel.text = @"7.下面的例子里面有多个宽度不一致的子视图,但是布局会根据屏幕的大小而智能的排列这些子视图,从而充分的利用好布局视图的空间。您可以分别在横竖屏下测试以及在iPhone4/5/6/6+上分别测试效果:"; tipLabel.font = [CFTool font:14]; tipLabel.adjustsFontSizeToFitWidth = YES; - tipLabel.wrapContentHeight = YES; + tipLabel.myHeight = MyLayoutSize.wrap; tipLabel.myTop = 10; [tipLabel sizeToFit]; [rootLayout addSubview:tipLabel]; MyFlowLayout *contentLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; - contentLayout.wrapContentHeight = YES; + contentLayout.myHeight = MyLayoutSize.wrap; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); contentLayout.subviewSpace = 5; contentLayout.backgroundColor = [CFTool color:0]; @@ -521,7 +517,7 @@ -(void)createDemo8:(MyLinearLayout*)rootLayout tipLabel.text = @"8.下面的例子中如果屏幕足够宽则左边视图居左,中间视图居中,右边视图居右。这时候不会产生滚动,而当屏幕宽度不足时则会压缩中间视图和两边视图之间的间距并且产生滚动效果。这样的例子也可以同样应用在纵向屏幕中:通常在大屏幕设备上中间的部分要居中显示,而在小屏幕上则依次排列产生滚动效果。 您可以分别在iPhone4/5/6/6+上以及横竖屏测试效果:"; tipLabel.font = [CFTool font:14]; tipLabel.adjustsFontSizeToFitWidth = YES; - tipLabel.wrapContentHeight = YES; + tipLabel.myHeight = MyLayoutSize.wrap; tipLabel.myTop = 10; [tipLabel sizeToFit]; [rootLayout addSubview:tipLabel]; @@ -538,7 +534,7 @@ -(void)createDemo8:(MyLinearLayout*)rootLayout contentLayout.gravity = MyGravity_Vert_Fill; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); contentLayout.subviewHSpace = 5; - contentLayout.widthSize.lBound(scrollView.widthSize,0,1); //默认水平线性布局的宽度是wrapContentWidth的但是最小的宽度和父视图相等,这样对于一些大尺寸屏幕因为能够容纳内容而不会产生滚动。 + contentLayout.widthSize.lBound(scrollView.widthSize,0,1); //默认水平线性布局的宽度是自适应但是最小的宽度和父视图相等,这样对于一些大尺寸屏幕因为能够容纳内容而不会产生滚动。 [scrollView addSubview:contentLayout]; @@ -556,7 +552,7 @@ -(void)createDemo8:(MyLinearLayout*)rootLayout label2.font = [CFTool font:15]; label2.backgroundColor = [CFTool color:6]; [label2 sizeToFit]; - //中间视图的左边间距是0.5,右边间距是0.5。表明中间视图的左右间距占用剩余的空间而达到居中的效果。这样在屏幕尺寸足够时则会产生居中效果,而屏幕尺寸不足时则会缩小间距,但是这里面最左边的最小间距是0而最右边的最小间距是30,这样布局视图因为具有wrapContentWidth属性所以会扩充宽度而达到滚动的效果。 + //中间视图的左边间距是0.5,右边间距是0.5。表明中间视图的左右间距占用剩余的空间而达到居中的效果。这样在屏幕尺寸足够时则会产生居中效果,而屏幕尺寸不足时则会缩小间距,但是这里面最左边的最小间距是0而最右边的最小间距是30,这样布局视图因为具有宽度自适应属性所以会扩充宽度而达到滚动的效果。 label2.leadingPos.equalTo(@0.5).min(0); label2.trailingPos.equalTo(@0.5).min(30); [contentLayout addSubview:label2]; @@ -579,7 +575,7 @@ -(void)createDemo9:(MyLinearLayout*)rootLayout tipLabel.text = @"9.下面的例子中最右边的视图如果能够被屏幕容纳则放在最右边,否则就会产生滚动效果。这个例子同样也可以应用在纵向屏幕中:很多页面里面最下边需要放一个按钮,如果屏幕尺寸够高则总是放在最底部,如果屏幕尺寸不够则会产生滚动效果。 您可以分别在iPhone4/5/6/6+上以及横竖屏测试效果:"; tipLabel.font = [CFTool font:14]; tipLabel.adjustsFontSizeToFitWidth = YES; - tipLabel.wrapContentHeight = YES; + tipLabel.myHeight = MyLayoutSize.wrap; tipLabel.myTop = 10; [tipLabel sizeToFit]; [rootLayout addSubview:tipLabel]; @@ -595,7 +591,7 @@ -(void)createDemo9:(MyLinearLayout*)rootLayout contentLayout.gravity = MyGravity_Vert_Fill; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); contentLayout.subviewHSpace = 5; - contentLayout.widthSize.lBound(scrollView.widthSize,0,1); //默认水平线性布局的宽度是wrapContentWidth的但是最小的宽度和父视图相等,这样对于一些大尺寸屏幕因为能够容纳内容而不会产生滚动。 + contentLayout.widthSize.lBound(scrollView.widthSize,0,1); //默认水平线性布局的宽度是自适应的但是最小的宽度和父视图相等,这样对于一些大尺寸屏幕因为能够容纳内容而不会产生滚动。 [scrollView addSubview:contentLayout]; @@ -621,7 +617,7 @@ -(void)createDemo9:(MyLinearLayout*)rootLayout label3.font = [CFTool font:15]; label3.backgroundColor = [CFTool color:7]; [label3 sizeToFit]; - label3.leadingPos.equalTo(@0.5).min(30); //最后一个视图的左边距占用剩余的空间,但是最低不能小于30。这样设置的意义是如果布局视图够宽则第三个子视图的左边间距是剩余的空间,这样就保证了第三个子视图总是在最右边。而如果剩余空间不够时,则因为这里最小的宽度是30,而布局视图又是wrapContentWidth,所以就会扩充布局视图的宽度,而产生滚动效果。这里的最小值30很重要,也就是第三个子视图和其他子视图的最小间距,具体设置多少就要看UI的界面效果图了。 + label3.leadingPos.equalTo(@0.5).min(30); //最后一个视图的左边距占用剩余的空间,但是最低不能小于30。这样设置的意义是如果布局视图够宽则第三个子视图的左边间距是剩余的空间,这样就保证了第三个子视图总是在最右边。而如果剩余空间不够时,则因为这里最小的宽度是30,而布局视图又是宽度自适应,所以就会扩充布局视图的宽度,而产生滚动效果。这里的最小值30很重要,也就是第三个子视图和其他子视图的最小间距,具体设置多少就要看UI的界面效果图了。 [contentLayout addSubview:label3]; } @@ -647,13 +643,12 @@ -(void)createDemo10:(MyLinearLayout*)rootLayout tipLabel.text = @"10.下面的例子中展示了一行中各个子视图的宽度和间距都将根据屏幕的尺寸来进行拉伸和收缩,这样不管在任何尺寸的屏幕下都能达到完美的适配。在实践中UI人员往往会按某个设备的尺寸给出一张效果图,那么我们只需要按这个效果图中的子视图的宽度来计算好所占用的宽度和间距的比例,然后我们通过对视图的宽度和间距按比例值进行设置,这样就会使得子视图的真实宽度和间距将根据屏幕的尺寸进行拉升和收缩。您可以分别在iPhone4/5/6/6+上以及横竖屏测试效果:"; tipLabel.font = [CFTool font:14]; tipLabel.adjustsFontSizeToFitWidth = YES; - tipLabel.wrapContentHeight = YES; + tipLabel.myHeight = MyLayoutSize.wrap; tipLabel.myTop = 10; [tipLabel sizeToFit]; [rootLayout addSubview:tipLabel]; MyLinearLayout *contentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; - contentLayout.wrapContentWidth = NO; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); contentLayout.myHeight = 60; //高度为60. contentLayout.gravity = MyGravity_Vert_Center; //内容垂直居中。 @@ -715,13 +710,12 @@ -(void)createDemo11:(MyLinearLayout*)rootLayout tipLabel.text = @"11.下面一个例子展示了当某个布局视图的尺寸能够容纳里面所有子视图的尺寸和间距时就按正常显示,而当尺寸不足以容纳所有子视图的尺寸和间距之和时我们就对子视图之间的间距进行压缩,以便能将所有子视图的内容都显示出来。您可以分别在iPhone4/5/6/6+上以及横竖屏测试效果:"; tipLabel.font = [CFTool font:14]; tipLabel.adjustsFontSizeToFitWidth = YES; - tipLabel.wrapContentHeight = YES; + tipLabel.myHeight = MyLayoutSize.wrap; tipLabel.myTop = 10; [tipLabel sizeToFit]; [rootLayout addSubview:tipLabel]; MyLinearLayout *contentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; - contentLayout.wrapContentWidth = NO; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); contentLayout.myHeight = 60; //高度为60. contentLayout.gravity = MyGravity_Vert_Center; //内容垂直居中。 @@ -755,13 +749,12 @@ -(void)createDemo12:(MyLinearLayout*)rootLayout tipLabel.text = @"12. 当布局视图下有多个子视图时有可能无法将这些子视图显示完全,而是需要将某些子视图的尺寸或者子视图之间的间距进行压缩处理。这里可以通过设置子视图尺寸中的shrink或者间距中的shrink值来进行处理。默认情况下这些值都是0表明不压缩,值越大压缩就越大"; tipLabel.font = [CFTool font:14]; tipLabel.adjustsFontSizeToFitWidth = YES; - tipLabel.wrapContentHeight = YES; + tipLabel.myHeight = MyLayoutSize.wrap; tipLabel.myTop = 10; [tipLabel sizeToFit]; [rootLayout addSubview:tipLabel]; MyLinearLayout *contentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; - contentLayout.wrapContentWidth = NO; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); contentLayout.heightSize.equalTo(@(MyLayoutSize.wrap)).min(60); contentLayout.gravity = MyGravity_Vert_Center; //内容垂直居中。 diff --git a/MyLayoutDemo/AllTest8ViewController.m b/MyLayoutDemo/AllTest8ViewController.m index 13d7f16..1ac17d1 100644 --- a/MyLayoutDemo/AllTest8ViewController.m +++ b/MyLayoutDemo/AllTest8ViewController.m @@ -41,7 +41,7 @@ - (void)viewDidLoad { // Do any additional setup after loading the view. /* - 本例子演示当把一个布局视图加入到非布局视图时的各种场景。当把一个布局视图加入到非布局父视图时,因为无法完全对非布局父视图进行控制。所以一些布局视图的属性将不再起作用了,但是基本的视图扩展属性: leftPos,rightPos,topPos,bottomPos,centerXPos,centerYPos,widthSize,heightSize,wrapContentWidth, wrapContentHeight这几个属性仍然有意义,只不过这些属性的equalTo方法能设置的类型有限,而且这些设置都只是基于父视图的。 + 本例子演示当把一个布局视图加入到非布局视图时的各种场景。当把一个布局视图加入到非布局父视图时,因为无法完全对非布局父视图进行控制。所以一些布局视图的属性将不再起作用了,但是基本的视图扩展属性: leftPos,rightPos,topPos,bottomPos,centerXPos,centerYPos,widthSize,heightSize这几个属性仍然有意义,只不过这些属性的equalTo方法能设置的类型有限,而且这些设置都只是基于父视图的。 */ @@ -128,11 +128,9 @@ - (void)viewDidLoad { /* - 这个例子用来演示让一个布局视图在非布局视图中居中,并且其尺寸是由子视图决定的,也就是wrapContentHeight设置为YES。 + 这个例子用来演示让一个布局视图在非布局视图中居中,并且其尺寸是由子视图决定的,也就是尺寸自适应 */ - - -(void)handleDemo1AddText:(UIButton*)sender { //这里可以看出当您调整了文字的长度,不需要编写任何更新布局视图位置的代码,系统会完全帮你自动更新布局,这样就简化了我们开发。 @@ -177,7 +175,7 @@ -(void)handleDemo1:(UIButton*)sender //文本 UILabel *label = [UILabel new]; - label.wrapContentHeight = YES; + label.myHeight = MyLayoutSize.wrap; label.font = [CFTool font:14]; label.text = @"这是一段具有动态高度的文本,同时他也会影响着布局视图的高度。您可以单击下面的按钮来添加文本来查看效果:"; [layout addSubview:label]; @@ -185,7 +183,6 @@ -(void)handleDemo1:(UIButton*)sender //按钮容器。如果您想让两个按钮水平排列则只需在btnContainer初始化中把方向改为:MyOrientation_Horz 。您可以尝试看看效果。 MyLinearLayout *btnContainer = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert /*MyOrientation_Horz*/]; - btnContainer.wrapContentHeight = YES; //高度由子视图确定。 btnContainer.subviewVSpace = 5; //视图之间的间距设置为5 btnContainer.subviewHSpace = 5; //视图之间的间距设置为5 btnContainer.gravity = MyGravity_Horz_Fill; //里面的子视图的宽度水平填充,如果是垂直线性布局则里面的所有子视图的宽度都和父视图相等。如果是水平线性布局则会均分所有子视图的宽度。 diff --git a/MyLayoutDemo/AllTest9CollectionViewCell.m b/MyLayoutDemo/AllTest9CollectionViewCell.m index bd337dd..7d9c05a 100644 --- a/MyLayoutDemo/AllTest9CollectionViewCell.m +++ b/MyLayoutDemo/AllTest9CollectionViewCell.m @@ -32,18 +32,17 @@ -(instancetype)initWithFrame:(CGRect)frame _rootLayout.bottomPadding = 5; _rootLayout.subviewVSpace = 10; _rootLayout.myHorzMargin = 0; - _rootLayout.wrapContentHeight = YES; _rootLayout.cacheEstimatedRect = YES; //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! [self.contentView addSubview:_rootLayout]; _titleLabel = [UILabel new]; - _titleLabel.widthSize.equalTo(_titleLabel.widthSize).max(100); + _titleLabel.widthSize.equalTo(@(MyLayoutSize.wrap)).max(100); _titleLabel.heightSize.equalTo(@30); [_rootLayout addSubview:_titleLabel]; _subtitleLabel = [UILabel new]; _subtitleLabel.myWidth = 70; - _subtitleLabel.wrapContentHeight = YES; + _subtitleLabel.myHeight = MyLayoutSize.wrap; [_rootLayout addSubview:_subtitleLabel]; } diff --git a/MyLayoutDemo/FLLTest1ViewController.m b/MyLayoutDemo/FLLTest1ViewController.m index e3310c0..9ccf400 100644 --- a/MyLayoutDemo/FLLTest1ViewController.m +++ b/MyLayoutDemo/FLLTest1ViewController.m @@ -35,7 +35,7 @@ -(void)loadView //添加操作按钮。 MyFlowLayout *actionLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:2]; - actionLayout.wrapContentHeight = YES; + actionLayout.myHeight = MyLayoutSize.wrap; actionLayout.gravity = MyGravity_Horz_Fill; //所有子视图水平填充,也就是所有子视图的宽度相等。 actionLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); actionLayout.subviewHSpace = 5; @@ -59,7 +59,7 @@ -(void)loadView flowLayoutSetLabel.font = [CFTool font:13]; flowLayoutSetLabel.textColor = [UIColor redColor]; flowLayoutSetLabel.adjustsFontSizeToFitWidth = YES; - flowLayoutSetLabel.wrapContentHeight = YES; + flowLayoutSetLabel.myHeight = MyLayoutSize.wrap; flowLayoutSetLabel.numberOfLines = 5; [rootLayout addSubview:flowLayoutSetLabel]; self.flowLayoutSetLabel = flowLayoutSetLabel; diff --git a/MyLayoutDemo/FLLTest2ViewController.m b/MyLayoutDemo/FLLTest2ViewController.m index 32684f3..c6e8e84 100644 --- a/MyLayoutDemo/FLLTest2ViewController.m +++ b/MyLayoutDemo/FLLTest2ViewController.m @@ -65,8 +65,8 @@ -(void)createTagButton:(NSString*)text tagButton.backgroundColor = [CFTool color:random()%15]; //这里可以看到尺寸宽度等于自己的尺寸宽度并且再增加10,且最小是40,意思是按钮的宽度是等于自身内容的宽度再加10,但最小的宽度是40 //如果没有这个设置,而是直接调用了sizeToFit则按钮的宽度就是内容的宽度。 - tagButton.widthSize.equalTo(tagButton.widthSize).add(10).min(40); - tagButton.heightSize.equalTo(tagButton.heightSize).add(10); //高度根据自身的内容再增加10 + tagButton.widthSize.equalTo(@(MyLayoutSize.wrap)).add(10).min(40); + tagButton.heightSize.equalTo(@(MyLayoutSize.wrap)).add(10); //高度根据自身的内容再增加10 [tagButton sizeToFit]; [tagButton addTarget:self action:@selector(handleDelTag:) forControlEvents:UIControlEventTouchUpInside]; [self.flowLayout addSubview:tagButton]; diff --git a/MyLayoutDemo/FLLTest3ViewController.m b/MyLayoutDemo/FLLTest3ViewController.m index 2d9b637..2de8feb 100644 --- a/MyLayoutDemo/FLLTest3ViewController.m +++ b/MyLayoutDemo/FLLTest3ViewController.m @@ -38,15 +38,13 @@ -(void)loadView MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; rootLayout.backgroundColor = [UIColor whiteColor]; rootLayout.gravity = MyGravity_Horz_Fill; //垂直线性布局里面的子视图的宽度和布局视图一致。 - rootLayout.wrapContentWidth = NO; - rootLayout.wrapContentHeight = NO; self.view = rootLayout; UILabel *tipLabel = [UILabel new]; tipLabel.font = [CFTool font:13]; tipLabel.text = NSLocalizedString(@" You can drag the following tag to adjust location in layout, MyLayout can use subview's useFrame,noLayout property and layout view's autoresizesSubviews propery to complete some position adjustment and the overall animation features: \n useFrame set to YES indicates subview is not controlled by the layout view but use its own frame to set the location and size instead.\n \n autoresizesSubviews set to NO indicate layout view will not do any layout operation, and will remain in the position and size of all subviews.\n \n noLayout set to YES indicate subview in the layout view just only take up the position and size but not real adjust the position and size when layouting.", @""); tipLabel.textColor = [CFTool color:4]; - tipLabel.wrapContentHeight = YES; //这两个属性结合着使用实现自动换行和文本的动态高度。 + tipLabel.heightSize.equalTo(@(MyLayoutSize.wrap)); //这两个属性结合着使用实现自动换行和文本的动态高度。 tipLabel.topPos.equalTo(self.topLayoutGuide); //子视图不会延伸到导航条屏幕下面。 [rootLayout addSubview:tipLabel]; diff --git a/MyLayoutDemo/FLLTest4ViewController.m b/MyLayoutDemo/FLLTest4ViewController.m index 2b78abe..5f7f409 100644 --- a/MyLayoutDemo/FLLTest4ViewController.m +++ b/MyLayoutDemo/FLLTest4ViewController.m @@ -33,7 +33,7 @@ -(void)loadView MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; rootLayout.backgroundColor = [CFTool color:11]; rootLayout.myHorzMargin = 0; - rootLayout.wrapContentHeight = YES; + rootLayout.myHeight = MyLayoutSize.wrap; rootLayout.subviewVSpace = 10; //子视图之间的间距设置为10 rootLayout.gravity = MyGravity_Horz_Fill; //所有子视图的宽度都和自己相等,这样子视图就不再需要设置宽度了。 [scrollView addSubview:rootLayout]; @@ -74,7 +74,7 @@ -(void)createFlowLayout1:(MyLinearLayout*)rootLayout //每行2列的垂直流式布局。 MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:2]; flowLayout.backgroundColor = [UIColor whiteColor]; - flowLayout.wrapContentHeight = YES; //高度由子视图决定。 + flowLayout.myHeight = MyLayoutSize.wrap; //高度由子视图决定。 flowLayout.gravity = MyGravity_Horz_Center; //所有子视图整体水平居中 flowLayout.arrangedGravity = MyGravity_Vert_Center; //每行子视图垂直居中对齐。您可以这里尝试设置为:MyGravity_Vert_Top, MyGravity_Vert_Bottom的效果。 flowLayout.padding = UIEdgeInsetsMake(20, 20, 20, 20); //四周内边距设置为20 @@ -233,7 +233,7 @@ -(void)createFlowLayout3:(MyLinearLayout *)rootLayout MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; flowLayout.backgroundColor = [CFTool color:0]; [rootLayout addSubview:flowLayout]; - flowLayout.wrapContentHeight = YES; + flowLayout.myHeight = MyLayoutSize.wrap; flowLayout.subviewSpace = 10; flowLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); @@ -310,7 +310,7 @@ -(void)createFlowLayout4:(MyLinearLayout *)rootLayout MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:2]; flowLayout.backgroundColor = [CFTool color:0]; [rootLayout addSubview:flowLayout]; - flowLayout.wrapContentHeight = YES; + flowLayout.myHeight = MyLayoutSize.wrap; flowLayout.subviewSpace = 10; flowLayout.arrangedGravity = MyGravity_Vert_Center; flowLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); @@ -327,7 +327,7 @@ -(void)createFlowLayout4:(MyLinearLayout *)rootLayout titleLabel.textColor = [CFTool color:5]; titleLabel.font = [CFTool font:14]; titleLabel.weight = 1; //对于指定数量的流式布局来说这个weight的是剩余的占比。 - titleLabel.wrapContentHeight = YES; + titleLabel.myHeight = MyLayoutSize.wrap; [flowLayout addSubview:titleLabel]; //第二行第一个固定,剩余的占据全部 @@ -338,7 +338,7 @@ -(void)createFlowLayout4:(MyLinearLayout *)rootLayout priceLabel.text = @"$123.23 - $200.12"; priceLabel.textColor = [UIColor redColor]; priceLabel.font = [CFTool font:13]; - priceLabel.wrapContentWidth = YES; + priceLabel.myWidth = MyLayoutSize.wrap; priceLabel.myHeight = 30; [flowLayout addSubview:priceLabel]; @@ -346,7 +346,7 @@ -(void)createFlowLayout4:(MyLinearLayout *)rootLayout UILabel *buyButton = [UILabel new]; buyButton.text = @"Buy"; buyButton.font = [CFTool font:12]; - buyButton.wrapContentWidth = YES; + buyButton.myWidth = MyLayoutSize.wrap; buyButton.myLeading = 20; buyButton.myHeight = 30; [flowLayout addSubview:buyButton]; diff --git a/MyLayoutDemo/FLLTest5ViewController.m b/MyLayoutDemo/FLLTest5ViewController.m index 35b9e77..6f19e75 100644 --- a/MyLayoutDemo/FLLTest5ViewController.m +++ b/MyLayoutDemo/FLLTest5ViewController.m @@ -105,7 +105,7 @@ -(void)createHorzPagingFlowLayout1:(UIView*)rootLayout //建立一个水平数量约束流式布局:每列展示3个子视图,每页展示9个子视图,整体从左往右滚动。 MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:3]; flowLayout.pagedCount = 9; //pagedCount设置为非0时表示开始分页展示的功能,这里表示每页展示9个子视图,这个数量必须是arrangedCount的倍数。 - flowLayout.wrapContentWidth = YES; //设置布局视图的宽度由子视图包裹,当水平流式布局的这个属性设置为YES,并和pagedCount搭配使用会产生分页从左到右滚动的效果。 + flowLayout.myWidth = MyLayoutSize.wrap; //设置布局视图的宽度由子视图包裹,当水平流式布局设置宽度自适应,并和pagedCount搭配使用会产生分页从左到右滚动的效果。 flowLayout.heightSize.equalTo(scrollView.heightSize); //因为是分页从左到右滚动,因此布局视图的高度必须设置为和父滚动视图相等。 /* 上面是实现一个水平流式布局分页且从左往右滚动的标准属性设置方法。 @@ -145,7 +145,7 @@ -(void)createHorzPagingFlowLayout2:(UIView*)rootLayout //建立一个水平数量约束流式布局:每列展示3个子视图,每页展示9个子视图,整体从上往下滚动。 MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:3]; flowLayout.pagedCount = 9; //pagedCount设置为非0时表示开始分页展示的功能,这里表示每页展示9个子视图,这个数量必须是arrangedCount的倍数。 - flowLayout.wrapContentHeight = YES; //设置布局视图的高度由子视图包裹,当水平流式布局的这个属性设置为YES,并和pagedCount搭配使用会产生分页从上到下滚动的效果。 + flowLayout.myHeight = MyLayoutSize.wrap; //设置布局视图的高度由子视图包裹,当水平流式布局的高度自适应,并和pagedCount搭配使用会产生分页从上到下滚动的效果。 flowLayout.widthSize.equalTo(scrollView.widthSize); //因为是分页从左到右滚动,因此布局视图的宽度必须设置为和父滚动视图相等。 /* 上面是实现一个水平流式布局分页且从上往下滚动的标准属性设置方法。 @@ -186,7 +186,7 @@ -(void)createVertPagingFlowLayout1:(UIView*)rootLayout //建立一个垂直数量约束流式布局:每列展示3个子视图,每页展示9个子视图,整体从上往下滚动。 MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; flowLayout.pagedCount = 9; //pagedCount设置为非0时表示开始分页展示的功能,这里表示每页展示9个子视图,这个数量必须是arrangedCount的倍数。 - flowLayout.wrapContentHeight = YES; //设置布局视图的高度由子视图包裹,当垂直流式布局的这个属性设置为YES,并和pagedCount搭配使用会产生分页从上到下滚动的效果。 + flowLayout.myHeight = MyLayoutSize.wrap; //设置布局视图的高度由子视图包裹,当垂直流式布局的高度自适应,并和pagedCount搭配使用会产生分页从上到下滚动的效果。 flowLayout.widthSize.equalTo(scrollView.widthSize); /* 上面是实现一个垂直流式布局分页且从上往下滚动的标准属性设置方法。 @@ -230,7 +230,7 @@ -(void)createVertPagingFlowLayout2:(UIView*)rootLayout //建立一个垂直数量约束流式布局:每列展示3个子视图,每页展示9个子视图,整体从左往右滚动。 MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; flowLayout.pagedCount = 9; //pagedCount设置为非0时表示开始分页展示的功能,这里表示每页展示9个子视图,这个数量必须是arrangedCount的倍数。 - flowLayout.wrapContentWidth = YES; //设置布局视图的宽度由子视图包裹,当垂直流式布局的这个属性设置为YES,并和pagedCount搭配使用会产生分页从左到右滚动的效果。 + flowLayout.myWidth = MyLayoutSize.wrap; //设置布局视图的宽度由子视图包裹,当垂直流式布局的宽度自适应,并和pagedCount搭配使用会产生分页从左到右滚动的效果。 flowLayout.heightSize.equalTo(scrollView.heightSize); /* 上面是实现一个垂直流式布局分页且从左往右滚动的标准属性设置方法。 diff --git a/MyLayoutDemo/FLLTest6ViewController.m b/MyLayoutDemo/FLLTest6ViewController.m index 3b5332b..498a432 100644 --- a/MyLayoutDemo/FLLTest6ViewController.m +++ b/MyLayoutDemo/FLLTest6ViewController.m @@ -33,7 +33,7 @@ -(void)loadView MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; rootLayout.backgroundColor = [CFTool color:0]; rootLayout.pagedCount = 9; - rootLayout.wrapContentHeight = YES; //上下滚动,每页9个。 + rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); //上下滚动,每页9个。 rootLayout.subviewSpace = 10; rootLayout.padding = UIEdgeInsetsMake(10, 5, 10, 5); rootLayout.leftPos.equalTo(@0).active = YES; //active属性用来表示是否让这个属性设置生效。 @@ -71,7 +71,7 @@ -(IBAction)handleTap:(UIButton*)sender self.rootLayout.bottomPos.active = !self.rootLayout.bottomPos.isActive; //当前是多行多列。 - if (self.rootLayout.wrapContentHeight) + if (self.rootLayout.heightSize.isWrap) { //换成单行单列 self.rootLayout.arrangedCount = 1; @@ -91,12 +91,11 @@ -(IBAction)handleTap:(UIButton*)sender } //这里切换水平滚动还是垂直滚动。 - self.rootLayout.wrapContentHeight = !self.rootLayout.wrapContentHeight; - self.rootLayout.wrapContentWidth = !self.rootLayout.wrapContentWidth; + self.rootLayout.heightSize.equalTo(self.rootLayout.heightSize.isWrap? nil : @(MyLayoutSize.wrap)); + self.rootLayout.widthSize.equalTo(self.rootLayout.widthSize.isWrap? nil : @(MyLayoutSize.wrap)); - - BOOL isHorzScroll = self.rootLayout.wrapContentWidth; + BOOL isHorzScroll = self.rootLayout.widthSize.isWrap; [UIView animateWithDuration:0.3 animations:^{ [self.rootLayout layoutIfNeeded]; //上面因为进行布局属性的设置变更,必定会激发重新布局,因此如果想要应用动画时可以在动画块内调用layoutIfNeeded来实现 diff --git a/MyLayoutDemo/FLLTest7ViewController.m b/MyLayoutDemo/FLLTest7ViewController.m index 359fbe1..5660d4a 100644 --- a/MyLayoutDemo/FLLTest7ViewController.m +++ b/MyLayoutDemo/FLLTest7ViewController.m @@ -20,7 +20,7 @@ -(void)createItems:(NSArray*)titles inFlowLayout:(MyFlowLayout*)flowLayout { UILabel *label = [UILabel new]; label.text = title; - label.wrapContentSize = YES; //内容自适应。 + label.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); label.backgroundColor = [CFTool color:(random()%14 + 1)]; label.font = [CFTool font:16]; [flowLayout addSubview:label]; @@ -55,13 +55,14 @@ -(void)loadView //水平瀑布流1。 UIScrollView *scrollView1 = [UIScrollView new]; - scrollView1.wrapContentHeight = YES; //这里可以设置滚动视图的高度为包裹属性,表示他的高度依赖于布局视图的高度。 + scrollView1.myHeight = MyLayoutSize.wrap; //这里可以设置滚动视图的高度为包裹属性,表示他的高度依赖于布局视图的高度。 [rootLayout addSubview:scrollView1]; MyFlowLayout *flowLayout1 = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:3]; flowLayout1.backgroundColor = [CFTool color:5]; - flowLayout1.wrapContentSize = YES; //流式布局的尺寸由里面的子视图的整体尺寸决定。 - flowLayout1.widthSize.lBound(scrollView1.widthSize, 0, 1); //虽然尺寸是包裹的,但是最小宽度不能小于父视图的宽度 + //流式布局的尺寸由里面的子视图的整体尺寸决定。 + flowLayout1.heightSize.equalTo(@(MyLayoutSize.wrap)); + flowLayout1.widthSize.equalTo(@(MyLayoutSize.wrap)).lBound(scrollView1.widthSize, 0, 1); //虽然尺寸是包裹的,但是最小宽度不能小于父视图的宽度 flowLayout1.autoArrange = YES; //通过将流式布局的autoArrange属性设置为YES可以实现里面的子视图进行紧凑的自动排列。 flowLayout1.subviewSpace = 10; flowLayout1.padding = UIEdgeInsetsMake(10, 10, 10, 10); @@ -71,13 +72,13 @@ -(void)loadView //水平瀑布流2。 UIScrollView *scrollView2 = [UIScrollView new]; - scrollView2.wrapContentHeight = YES; + scrollView2.myHeight = MyLayoutSize.wrap; [rootLayout addSubview:scrollView2]; MyFlowLayout *flowLayout2 = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:3]; flowLayout2.backgroundColor = [CFTool color:6]; - flowLayout2.wrapContentSize = YES; - flowLayout2.widthSize.lBound(scrollView2.widthSize, 0, 1); //虽然尺寸是包裹的,但是最小宽度不能小于父视图的宽度 + flowLayout2.heightSize.equalTo(@(MyLayoutSize.wrap)); + flowLayout2.widthSize.equalTo(@(MyLayoutSize.wrap)).lBound(scrollView2.widthSize, 0, 1); //虽然尺寸是包裹的,但是最小宽度不能小于父视图的宽度 flowLayout2.subviewSpace = 10; flowLayout2.padding = UIEdgeInsetsMake(10, 10, 10, 10); flowLayout2.arrangedGravity = MyGravity_Horz_Between; //通过将水平流式布局的arrangeGravity属性设置为MyGravity_Horz_Between,我们将得到里面的子视图在每行都会被紧凑的排列。大家可以看到和上面的将autoArrange设置为YES的不同的效果。 @@ -92,8 +93,7 @@ -(void)loadView MyFlowLayout *flowLayout3 = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; flowLayout3.backgroundColor = [CFTool color:5]; - flowLayout3.wrapContentHeight = YES; - flowLayout3.heightSize.lBound(scrollView3.heightSize, 0, 1); //虽然是包裹尺寸,但是最小不能小于父视图的高度。 + flowLayout3.heightSize.equalTo(@(MyLayoutSize.wrap)).lBound(scrollView3.heightSize, 0, 1); //虽然是包裹尺寸,但是最小不能小于父视图的高度。 flowLayout3.myHorzMargin = 0; flowLayout3.gravity = MyGravity_Horz_Fill; //均分宽度。 flowLayout3.autoArrange = YES; //通过将流式布局的autoArrange属性设置为YES可以实现里面的子视图进行紧凑的自动排列。 @@ -110,8 +110,7 @@ -(void)loadView MyFlowLayout *flowLayout4 = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; flowLayout4.backgroundColor = [CFTool color:6]; - flowLayout4.wrapContentHeight = YES; - flowLayout4.heightSize.lBound(scrollView4.heightSize, 0, 1); + flowLayout4.heightSize.equalTo(@(MyLayoutSize.wrap)).lBound(scrollView4.heightSize, 0, 1); flowLayout4.myHorzMargin = 0; flowLayout4.gravity = MyGravity_Horz_Fill; //均分宽度。 flowLayout4.arrangedGravity = MyGravity_Vert_Between; //通过将垂直流式布局的arrangeGravity属性设置为MyGravity_Vert_Between,我们将得到里面的子视图在每列都会被紧凑的排列。大家可以看到和上面的将autoArrange设置为YES的不同的效果。 diff --git a/MyLayoutDemo/FOLTest2ViewController.m b/MyLayoutDemo/FOLTest2ViewController.m index 22daad9..7697630 100644 --- a/MyLayoutDemo/FOLTest2ViewController.m +++ b/MyLayoutDemo/FOLTest2ViewController.m @@ -428,7 +428,7 @@ -(void)addSectionLayout:(NSInteger)sectionIndex MyFloatLayout *itemContainerLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; itemContainerLayout.tag = 1122; itemContainerLayout.backgroundColor = [UIColor whiteColor]; - itemContainerLayout.wrapContentHeight = YES; + itemContainerLayout.myHeight = MyLayoutSize.wrap; itemContainerLayout.intelligentBorderline = [[MyBorderline alloc] initWithColor:[UIColor lightGrayColor]]; [self.rootLayout addSubview:itemContainerLayout]; @@ -570,7 +570,7 @@ -(MyFloatLayout*)createItemLayout1_3:(FOLTest2DataModel*)dataModel subTitleLabel.myLeading = 5; subTitleLabel.clearFloat = YES; //清除浮动,另起一行。 subTitleLabel.weight = 1; - subTitleLabel.wrapContentHeight = YES; + subTitleLabel.myHeight = MyLayoutSize.wrap; [subTitleLabel sizeToFit]; [itemLayout addSubview:subTitleLabel]; diff --git a/MyLayoutDemo/FOLTest3ViewController.m b/MyLayoutDemo/FOLTest3ViewController.m index 23e8166..92e1b27 100644 --- a/MyLayoutDemo/FOLTest3ViewController.m +++ b/MyLayoutDemo/FOLTest3ViewController.m @@ -148,7 +148,7 @@ -(UIView*)createPictureNewsItemLayout:(FOLTest3DataModel*)dataModel tag:(NSInteg titleLabel.text = dataModel.title; titleLabel.textColor = [UIColor whiteColor]; titleLabel.weight = 1; //向左浮动,宽度和父视图保持一致。 - titleLabel.wrapContentHeight = YES; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + titleLabel.myHeight = MyLayoutSize.wrap; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将高度设置为自适应 [itemLayout addSubview:titleLabel]; itemLayout.gravity = MyGravity_Vert_Bottom; //将整个布局中的所有子视图垂直居底部。 @@ -173,7 +173,7 @@ -(UIView*)createWholeWidthTextNewsItemLayout:(FOLTest3DataModel*)dataModel tag:( titleLabel.text = dataModel.title; titleLabel.font = [UIFont boldSystemFontOfSize:17]; titleLabel.weight =1; //向左浮动,宽度和父视图保持一致。 - titleLabel.wrapContentHeight = YES; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + titleLabel.myHeight = MyLayoutSize.wrap; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将高度设置为自适应 [itemLayout addSubview:titleLabel]; //来源部分 @@ -208,7 +208,7 @@ -(MyBaseLayout*)createHalfWidthTextNewsItemLayout:(FOLTest3DataModel*)dataModel UILabel *titleLabel = [UILabel new]; titleLabel.text = dataModel.title; titleLabel.weight =1; //向左浮动,宽度和父视图保持一致。 - titleLabel.wrapContentHeight = YES; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将wrapContentHeight设置为YES。 + titleLabel.myHeight = MyLayoutSize.wrap; //如果想让文本消息的高度是动态的,请在设置明确宽度的情况下将高度设置为自适应 [itemLayout addSubview:titleLabel]; diff --git a/MyLayoutDemo/FOLTest4ViewController.m b/MyLayoutDemo/FOLTest4ViewController.m index 78f613c..25fe339 100644 --- a/MyLayoutDemo/FOLTest4ViewController.m +++ b/MyLayoutDemo/FOLTest4ViewController.m @@ -185,7 +185,7 @@ -(void)style1Layout:(MyLinearLayout*)contentLayout MyFloatLayout *floatLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; floatLayout.backgroundColor = [UIColor whiteColor]; floatLayout.padding = UIEdgeInsetsMake(20, 10, 20, 10); - floatLayout.wrapContentHeight = YES; + floatLayout.myHeight = MyLayoutSize.wrap; floatLayout.subviewHSpace = 30; //设置浮动布局里面子视图之间的水平间距。 floatLayout.subviewVSpace = 10; //设置浮动布局里面子视图之间的垂直间距。 [contentLayout addSubview:floatLayout]; @@ -265,7 +265,7 @@ -(void)style2Layout:(MyLinearLayout*)contentLayout MyFloatLayout *floatLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; floatLayout.backgroundColor = [UIColor whiteColor]; floatLayout.padding = UIEdgeInsetsMake(20, 5, 20, 5); - floatLayout.wrapContentHeight = YES; + floatLayout.myHeight = MyLayoutSize.wrap; floatLayout.subviewVSpace = 10; //设置浮动布局里面子视图之间的垂直间距。 [floatLayout setSubviewsSize:sTagWidth minSpace:8 maxSpace:CGFLOAT_MAX]; //这里面水平间距用浮动间距,浮动间距设置为子视图固定宽度为70,最小的间距为8. [contentLayout addSubview:floatLayout]; @@ -338,7 +338,7 @@ -(UIView*)createActionLayout MyFloatLayout *actionLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; actionLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); actionLayout.subviewHSpace = 5; - actionLayout.wrapContentHeight = YES; + actionLayout.myHeight = MyLayoutSize.wrap; actionLayout.bottomBorderline = [[MyBorderline alloc] initWithColor:[UIColor blackColor]]; @@ -370,7 +370,7 @@ -(UIView*)createSectionView:(NSString*)title image:(NSString*)image { MyLinearLayout *sectionLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - sectionLayout.wrapContentHeight = NO; + sectionLayout.heightSize.equalTo(nil); sectionLayout.layer.cornerRadius = 5; sectionLayout.layer.borderColor = [UIColor lightGrayColor].CGColor; sectionLayout.layer.borderWidth = 0.5; diff --git a/MyLayoutDemo/FOLTest5ViewController.m b/MyLayoutDemo/FOLTest5ViewController.m index cddc8fd..68562df 100644 --- a/MyLayoutDemo/FOLTest5ViewController.m +++ b/MyLayoutDemo/FOLTest5ViewController.m @@ -52,7 +52,7 @@ - (void)viewDidLoad { MyFloatLayout *rootLayout = [[MyFloatLayout alloc] initWithOrientation:MyOrientation_Vert]; rootLayout.myHorzMargin = 0; //宽度和滚动条视图保持一致。 - rootLayout.wrapContentHeight = YES; + rootLayout.myHeight = MyLayoutSize.wrap; rootLayout.subviewVSpace = 5; [scrollView addSubview:rootLayout]; @@ -70,7 +70,7 @@ - (void)viewDidLoad { label2.font = [CFTool font:15]; label2.weight = 1; //宽度占据全部 label2.clearFloat = YES; - label2.wrapContentHeight = YES; + label2.myHeight = MyLayoutSize.wrap; [rootLayout addSubview:label2]; //添加4个子图片。 @@ -101,7 +101,7 @@ - (void)viewDidLoad { descLabel.textColor = [CFTool color:4]; descLabel.font = [CFTool font:13]; descLabel.weight = 1; //占用剩余的宽度 - descLabel.wrapContentHeight = YES; //多行自动换行。 + descLabel.myHeight = MyLayoutSize.wrap; //多行自动换行。 [descLabel sizeToFit]; [rootLayout addSubview:descLabel]; diff --git a/MyLayoutDemo/FOLTest6ViewController.m b/MyLayoutDemo/FOLTest6ViewController.m index bb5c4b9..db9cfa8 100644 --- a/MyLayoutDemo/FOLTest6ViewController.m +++ b/MyLayoutDemo/FOLTest6ViewController.m @@ -72,13 +72,13 @@ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { -(void)createUserProfile1Layout:(MyLinearLayout*)rootLayout { - //这个例子建立一个只向上浮动的浮动布局视图,注意这里要想布局高度由子视图包裹的话则必须要设置布局视图的wrapContentHeight为YES。 - //当在水平浮动布局中设置wrapContentHeight为YES时,子视图不能逆向浮动只能向上浮动,并且子视图的weight不能设置为非0. - //当在水平浮动布局中设置wrapContentHeight为YES时,需要我们设置某个子视图的clearFloat为YES进行手动换行处理。 + //这个例子建立一个只向上浮动的浮动布局视图,注意这里要想布局高度由子视图包裹的话则必须要设置布局视图的高度自适应。 + //当在水平浮动布局中设置高度自适应,子视图不能逆向浮动只能向上浮动,并且子视图的weight不能设置为非0. + //当在水平浮动布局中设置高度自适应,需要我们设置某个子视图的clearFloat为YES进行手动换行处理。 MyFloatLayout *contentLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Horz]; contentLayout.backgroundColor = [UIColor whiteColor]; - contentLayout.wrapContentHeight = YES; + contentLayout.myHeight = MyLayoutSize.wrap; contentLayout.myHorzMargin = 0; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); contentLayout.subviewHSpace = 5; @@ -111,7 +111,7 @@ -(void)createUserProfile1Layout:(MyLinearLayout*)rootLayout addressLabel.text = @"联系地址:中华人民共和国北京市朝阳区盈科中心B座2楼,其他的我就不会再告诉你了。"; addressLabel.font = [CFTool font:15]; addressLabel.textColor = [CFTool color:4]; - addressLabel.wrapContentHeight = YES; + addressLabel.heightSize.equalTo(@(MyLayoutSize.wrap)); addressLabel.widthSize.equalTo(contentLayout.widthSize).add(-45); //40的头像宽度外加5的左右间距。 [addressLabel sizeToFit]; [contentLayout addSubview:addressLabel]; @@ -150,7 +150,7 @@ -(void)createUserProfile2Layout:(MyLinearLayout*)rootLayout MyFloatLayout *contentLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; contentLayout.backgroundColor = [UIColor whiteColor]; - contentLayout.wrapContentHeight = YES; + contentLayout.myHeight = MyLayoutSize.wrap; contentLayout.myHorzMargin = 0; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); [rootLayout addSubview:contentLayout]; @@ -238,7 +238,7 @@ -(void)createUserProfile3Layout:(MyLinearLayout*)rootLayout MyFloatLayout *contentLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Horz]; contentLayout.backgroundColor = [UIColor whiteColor]; - contentLayout.wrapContentHeight = YES; + contentLayout.myHeight = MyLayoutSize.wrap; contentLayout.myHorzMargin = 0; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); [rootLayout addSubview:contentLayout]; @@ -303,7 +303,7 @@ -(void)createUserProfile4Layout:(MyLinearLayout*)rootLayout { MyFloatLayout *contentLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; contentLayout.backgroundColor = [UIColor whiteColor]; - contentLayout.wrapContentHeight = YES; + contentLayout.myHeight = MyLayoutSize.wrap; contentLayout.myHorzMargin = 0; contentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); [rootLayout addSubview:contentLayout]; @@ -324,8 +324,8 @@ -(void)createUserProfile4Layout:(MyLinearLayout*)rootLayout editButton.textColor = [CFTool color:4]; editButton.layer.cornerRadius = 5; editButton.layer.masksToBounds = YES; - editButton.widthSize.equalTo(editButton.widthSize).add(20); - editButton.heightSize.equalTo(editButton.heightSize).add(4); + editButton.widthSize.equalTo(@(MyLayoutSize.wrap)).add(20); + editButton.heightSize.equalTo(@(MyLayoutSize.wrap)).add(4); editButton.reverseFloat = YES; [contentLayout addSubview:editButton]; diff --git a/MyLayoutDemo/GLTest1ViewController.m b/MyLayoutDemo/GLTest1ViewController.m index 9740316..acbf72b 100644 --- a/MyLayoutDemo/GLTest1ViewController.m +++ b/MyLayoutDemo/GLTest1ViewController.m @@ -48,7 +48,7 @@ -(void)loadView MyGridLayout *rootLayout = [MyGridLayout new]; rootLayout.myHorzMargin = 0; - rootLayout.wrapContentHeight = YES; + rootLayout.myHeight = MyLayoutSize.wrap; rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); rootLayout.subviewSpace = 10; //直接子栅格之间的间隔。 [scrollView addSubview:rootLayout]; @@ -196,7 +196,7 @@ -(void)loadView [rootLayout addRow:MyLayoutSize.wrap]; UILabel *shrinkLabel = [UILabel new]; - shrinkLabel.text = NSLocalizedString(@"This is a can automatically wrap text.To realize this function, you need to set the clear width, and set the wrapContentHeight to YES.You can try to switch different simulator or different orientation screen to see the effect.", @""); + shrinkLabel.text = NSLocalizedString(@"This is a can automatically wrap text.To realize this function, you need to set the width exact, and set the heightSize to MyLayoutSize.wrap.You can try to switch different simulator or different orientation screen to see the effect.", @""); shrinkLabel.backgroundColor = [CFTool color:2]; shrinkLabel.font = [CFTool font:14]; shrinkLabel.numberOfLines = 0; diff --git a/MyLayoutDemo/GLTest3ViewController.m b/MyLayoutDemo/GLTest3ViewController.m index 8750d8e..25dfc70 100644 --- a/MyLayoutDemo/GLTest3ViewController.m +++ b/MyLayoutDemo/GLTest3ViewController.m @@ -265,7 +265,7 @@ -(void)loadView scrollView.pagingEnabled = YES; MyFlowLayout *scrollFlowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:1]; scrollFlowLayout.pagedCount = 1; //pagedCount设置为非0时表示开始分页展示的功能,这里表示每页展示9个子视图,这个数量必须是arrangedCount的倍数。 - scrollFlowLayout.wrapContentWidth = YES; //设置布局视图的宽度由子视图包裹,当水平流式布局的这个属性设置为YES,并和pagedCount搭配使用会产生分页从左到右滚动的效果。 + scrollFlowLayout.widthSize.equalTo(@(MyLayoutSize.wrap)); //设置布局视图的宽度由子视图包裹,当水平流式布局的这个属性设置为YES,并和pagedCount搭配使用会产生分页从左到右滚动的效果。 scrollFlowLayout.heightSize.equalTo(scrollView.heightSize); //因为是分页从左到右滚动,因此布局视图的高度必须设置为和父滚动视图相等。 [scrollView addSubview:scrollFlowLayout]; diff --git a/MyLayoutDemo/GLTest4ViewController.m b/MyLayoutDemo/GLTest4ViewController.m index 5da37d8..62547c6 100644 --- a/MyLayoutDemo/GLTest4ViewController.m +++ b/MyLayoutDemo/GLTest4ViewController.m @@ -214,7 +214,7 @@ -(void)bindView scrollView.pagingEnabled = YES; MyFlowLayout *scrollFlowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:1]; scrollFlowLayout.pagedCount = 1; - scrollFlowLayout.wrapContentWidth = YES; + scrollFlowLayout.widthSize.equalTo(@(MyLayoutSize.wrap)); scrollFlowLayout.heightSize.equalTo(scrollView.heightSize); [scrollView addSubview:scrollFlowLayout]; NSArray *temp = @[@"bk1",@"bk2",@"bk3",@"bk1",@"bk2"]; diff --git a/MyLayoutDemo/LLTest1ViewController.m b/MyLayoutDemo/LLTest1ViewController.m index 7057715..8ae875f 100644 --- a/MyLayoutDemo/LLTest1ViewController.m +++ b/MyLayoutDemo/LLTest1ViewController.m @@ -101,7 +101,7 @@ -(void)loadView - MyLinearLayout *vertLayout = [self createVertSubviewLayout];//垂直线性布局的高度默认是由子视图的高度决定的,也就是wrapContentHeight默认设置为YES + MyLinearLayout *vertLayout = [self createVertSubviewLayout];//垂直线性布局的高度默认是由子视图的高度决定的,也就是高度自适应 vertLayout.myHorzMargin = 0; //对于垂直线性布局rootLayout的子视图vertLayout来说,如果同时设置了左右边距为0则表示子视图的宽度和父视图宽度相等。 [rootLayout addSubview:vertLayout]; diff --git a/MyLayoutDemo/LLTest2ViewController.m b/MyLayoutDemo/LLTest2ViewController.m index eec64c3..83b6ce6 100644 --- a/MyLayoutDemo/LLTest2ViewController.m +++ b/MyLayoutDemo/LLTest2ViewController.m @@ -33,12 +33,12 @@ -(void)loadView self.view = scrollView; /* - 这里的contentLayout是非布局视图UIScrollView的子视图。因为同时设置了myHorzMargin为0表示宽度和UIScrollView是保持一致;而高度则因为垂直线性布局的wrapContentHeight属性设置来确定,表示垂直线性布局的高度等于里面的所有子视图高度;而其中的x,y轴的位置则因为没有设置默认是0。 + 这里的contentLayout是非布局视图UIScrollView的子视图。因为同时设置了myHorzMargin为0表示宽度和UIScrollView是保持一致;而高度则因为垂直线性布局的高度默认是自适应,表示垂直线性布局的高度等于里面的所有子视图高度;而其中的x,y轴的位置则因为没有设置默认是0。 */ MyLinearLayout *contentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; contentLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); //设置布局内的子视图离自己的边距. contentLayout.myHorzMargin = 0; //同时指定左右边距为0表示宽度和父视图一样宽 - contentLayout.heightSize.lBound(scrollView.heightSize, 10, 1); //高度虽然是wrapContentHeight的。但是最小的高度不能低于父视图的高度加10. + contentLayout.heightSize.lBound(scrollView.heightSize, 10, 1); //高度虽然是自适应的。但是最小的高度不能低于父视图的高度加10. [scrollView addSubview:contentLayout]; self.contentLayout = contentLayout; @@ -142,7 +142,7 @@ -(void)createSection1:(MyLinearLayout*)contentLayout -(void)createSection2:(MyLinearLayout*)contentLayout { - //userInfoLayout的myHorzMargin确定了视图的x轴的位置和宽度;wrapContentHeight为YES确定了视图的高度;myTop确定了y轴上离兄弟视图间距20 + //userInfoLayout的myHorzMargin确定了视图的x轴的位置和宽度;myHeight设置为MyLayoutSize.wrap表示高度自适应;myTop确定了y轴上离兄弟视图间距20 MyLinearLayout *userInfoLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; userInfoLayout.layer.borderColor = [UIColor lightGrayColor].CGColor; userInfoLayout.layer.borderWidth = 0.5; @@ -150,7 +150,7 @@ -(void)createSection2:(MyLinearLayout*)contentLayout userInfoLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); userInfoLayout.myTop = 20; userInfoLayout.myHorzMargin = 0; - userInfoLayout.wrapContentHeight = YES; + userInfoLayout.myHeight = MyLayoutSize.wrap; [contentLayout addSubview:userInfoLayout]; //headImageView的sizeToFit确定了视图的尺寸;myCenterY确定了在y轴垂直居中;水平线性布局下的子视图可以自动算出在x轴的位置。 @@ -158,7 +158,7 @@ -(void)createSection2:(MyLinearLayout*)contentLayout headImageView.myCenterY = 0; [userInfoLayout addSubview:headImageView]; - //nameLayout是垂直线性布局因此默认的wrapContentHeight确定了视图的高度;weight=1设置宽度比重值,表示占用父布局infoLayout的剩余宽度;y轴上默认和父布局上边对齐;x轴则根据其在父布局下的顺序自动算出。这个部分也是一个水平线性布局套垂直线性布局的场景。 + //nameLayout是垂直线性布局因此默认高度自适应;weight=1设置宽度比重值,表示占用父布局infoLayout的剩余宽度;y轴上默认和父布局上边对齐;x轴则根据其在父布局下的顺序自动算出。这个部分也是一个水平线性布局套垂直线性布局的场景。 MyLinearLayout *nameLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; nameLayout.weight = 1.0; nameLayout.myLeading = 10; @@ -191,7 +191,7 @@ -(void)createSection2:(MyLinearLayout*)contentLayout userInfoLayout.myTop = 20; userInfoLayout.myLeading = userInfoLayout.myTrailing = 0; userInfoLayout.subviewHSpace = 10; //子视图的水平间距为10 - userInfoLayout.wrapContentHeight = YES; + userInfoLayout.myHeight = MyLayoutSize.wrap; userInfoLayout.gravity = MyGravity_Vert_Center; //里面的子视图整体垂直居中。 [contentLayout addSubview:userInfoLayout]; @@ -225,7 +225,7 @@ -(void)createSection2:(MyLinearLayout*)contentLayout -(void)createSection3:(MyLinearLayout*)contentLayout { - //ageLayout是垂直线性布局默认的wrapContentHeight决定了视图的高度;myHorzMargin决定了视图的x轴的位置和宽度;添加到垂直布局父视图的顺序决定了y轴的位置。 + //ageLayout是垂直线性布局默认高度自适应;myHorzMargin决定了视图的x轴的位置和宽度;添加到垂直布局父视图的顺序决定了y轴的位置。 MyLinearLayout *ageLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; ageLayout.layer.borderColor = [UIColor lightGrayColor].CGColor; ageLayout.layer.borderWidth = 0.5; @@ -246,7 +246,7 @@ -(void)createSection3:(MyLinearLayout*)contentLayout //垂直线性布局套水平线性布局 MyLinearLayout *ageSelectLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; ageSelectLayout.myTop = 5; - ageSelectLayout.wrapContentHeight = YES; + ageSelectLayout.myHeight = MyLayoutSize.wrap; ageSelectLayout.subviewHSpace = 10; //里面所有子视图之间的水平间距。 [ageLayout addSubview:ageSelectLayout]; @@ -275,7 +275,7 @@ -(void)createSection3:(MyLinearLayout*)contentLayout ageLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); ageLayout.myTop = 20; ageLayout.myLeading = ageLayout.myTrailing = 0; // 宽度和父布局相等 - ageLayout.wrapContentHeight = YES; //高度由子视图包裹。 + ageLayout.myHeight = MyLayoutSize.wrap; //高度由子视图包裹。 ageLayout.subviewVSpace = 5; //所有子视图垂直间距为5 ageLayout.subviewHSpace = 10; //所有子视图水平间距为10 [contentLayout addSubview:ageLayout]; @@ -319,7 +319,7 @@ -(void)createSection4:(MyLinearLayout*)contentLayout addressLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); addressLayout.myTop = 20; addressLayout.myLeading = addressLayout.myTrailing = 0; - addressLayout.wrapContentHeight = YES; + addressLayout.myHeight = MyLayoutSize.wrap; [contentLayout addSubview:addressLayout]; @@ -330,14 +330,14 @@ -(void)createSection4:(MyLinearLayout*)contentLayout [addressLayout addSubview:addressTitleLabel]; - //addressLabel的y轴位置和父布局视图上边对齐;x轴的位置则根据添加到父布局的顺序确定;视图的宽度由weight=1表示占用父视图的剩余宽度决定;视图的高度由wrapContentHeight设置为YES表示高度由内容动态决定。 + //addressLabel的y轴位置和父布局视图上边对齐;x轴的位置则根据添加到父布局的顺序确定;视图的宽度由weight=1表示占用父视图的剩余宽度决定;视图的高度根据内容自适应。 UILabel *addressLabel = [UILabel new]; addressLabel.text = NSLocalizedString(@"Winterless Building, West Dawang Road, Chaoyang district CBD, Beijing, People's Republic of China", @""); addressLabel.textColor = [CFTool color:4]; addressLabel.font = [CFTool font:14]; addressLabel.myLeading = 10; addressLabel.weight = 1.0; - addressLabel.wrapContentHeight = YES; //这个属性设置为YES表示视图的高度动态确定。设置这个属性的前提是必须有指定视图的宽度. + addressLabel.myHeight = MyLayoutSize.wrap; //这个属性设置为YES表示视图的高度动态确定。设置这个属性的前提是必须有指定视图的宽度. [addressLayout addSubview:addressLabel]; } @@ -351,7 +351,7 @@ -(void)createSection5:(MyLinearLayout*)contentLayout sexLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); sexLayout.myTop = 20; sexLayout.myLeading = sexLayout.myTrailing = 0; - sexLayout.wrapContentHeight = YES; + sexLayout.myHeight = MyLayoutSize.wrap; [contentLayout addSubview:sexLayout]; @@ -392,7 +392,7 @@ -(void)createSection6:(MyLinearLayout*)contentLayout UILabel *baselineLabel = [UILabel new]; baselineLabel.text = @"Baseline view"; - baselineLabel.wrapContentSize = YES; + baselineLabel.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); baselineLabel.font = [CFTool font:20]; baselineLabel.backgroundColor = [CFTool color:5]; baselineLabel.alignment = MyGravity_Vert_Center; //标准视图垂直居中。 @@ -400,7 +400,7 @@ -(void)createSection6:(MyLinearLayout*)contentLayout UILabel *rightLabel = [UILabel new]; rightLabel.text = @"Right view"; - rightLabel.wrapContentSize = YES; + rightLabel.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); rightLabel.font = [CFTool font:32]; rightLabel.backgroundColor = [CFTool color:6]; [baselineLayout addSubview:rightLabel]; @@ -413,7 +413,7 @@ -(void)createSection6:(MyLinearLayout*)contentLayout -(void)createSection7:(MyLinearLayout*)contentLayout { UILabel *shrinkLabel = [UILabel new]; - shrinkLabel.text = NSLocalizedString(@"This is a can automatically wrap text.To realize this function, you need to set the clear width, and set the wrapContentHeight to YES.You can try to switch different simulator or different orientation screen to see the effect.", @""); + shrinkLabel.text = NSLocalizedString(@"This is a can automatically wrap text.To realize this function, you need to set the width exact, and set the heightSize to MyLayoutSize.wrap.You can try to switch different simulator or different orientation screen to see the effect.", @""); shrinkLabel.backgroundColor = [CFTool color:2]; shrinkLabel.font = [CFTool font:14]; shrinkLabel.myTop = 20; diff --git a/MyLayoutDemo/LLTest3ViewController.m b/MyLayoutDemo/LLTest3ViewController.m index bb05251..2a7ba6d 100644 --- a/MyLayoutDemo/LLTest3ViewController.m +++ b/MyLayoutDemo/LLTest3ViewController.m @@ -39,7 +39,7 @@ -(void)loadView 通过上面的几个场景我们可以看出gravity属性的设置可以在很大程度上简化布局视图里面的子视图的布局属性的设置的,通过gravity属性的设置我们可以控制布局视图里面所有子视图的整体停靠方向和填充的尺寸。在使用gravity属性时需要明确如下几个条件: 1.当使用gravity属性时意味着布局视图必须要有明确的尺寸才有意义,因为有确定的尺寸才能决定里面的子视图的停靠的方位。 - 2.布局视图的wrapContentHeight设置为YES时是和gravity上设置垂直停靠方向以及垂直填充是互斥的;而布局视图的wrapContentWidth设置为YES时是和gravity上设置水平停靠方向和水平填充是互斥的。(也有特殊情况就是布局视图设置了最小尺寸限制时才有效) + 2.布局视图的高度自适应设置是和gravity上设置垂直停靠方向以及垂直填充是互斥的;而布局视图的宽度自适应是和gravity上设置水平停靠方向和水平填充是互斥的。(也有特殊情况就是布局视图设置了最小尺寸限制时才有效) 3.布局视图的gravity的属性的优先级要高于子视图的边距和尺寸设置,但是低于子视图的alignment属性的设置。 */ @@ -108,14 +108,14 @@ -(void)createVertLayoutGravityActionLayout:(MyLinearLayout*)contentLayout actionTitleLabel.text = NSLocalizedString(@"Vertical layout gravity control, you can click the following different button to show the effect:", @""); actionTitleLabel.textColor = [CFTool color:4]; actionTitleLabel.adjustsFontSizeToFitWidth = YES; - actionTitleLabel.wrapContentHeight = YES; + actionTitleLabel.myHeight = MyLayoutSize.wrap; actionTitleLabel.myTop = 10; [contentLayout addSubview:actionTitleLabel]; //用流式布局来创建动作菜单布局。流式布局请参考后面关于流式布局的DEMO。 MyFlowLayout *actionLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; - actionLayout.wrapContentHeight = YES; + actionLayout.myHeight = MyLayoutSize.wrap; actionLayout.gravity = MyGravity_Horz_Fill; //平均分配里面所有子视图的宽度 actionLayout.subviewHSpace = 5; actionLayout.subviewVSpace = 5; //设置里面子视图的水平和垂直间距。 @@ -159,7 +159,6 @@ -(void)createVertGravityLayout:(MyLinearLayout*)contentLayout MyLinearLayout *vertGravityLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - vertGravityLayout.wrapContentHeight = NO; vertGravityLayout.backgroundColor = [CFTool color:0]; vertGravityLayout.myHeight = 160; vertGravityLayout.myTop = 10; @@ -200,14 +199,14 @@ -(void)createHorzLayoutGravityActionLayout:(MyLinearLayout*)contentLayout actionTitleLabel.textColor = [CFTool color:4]; actionTitleLabel.text = NSLocalizedString(@"Horizontal layout gravity control, you can click the following different button to show the effect:", @""); actionTitleLabel.adjustsFontSizeToFitWidth = YES; - actionTitleLabel.wrapContentHeight = YES; + actionTitleLabel.myHeight = MyLayoutSize.wrap; actionTitleLabel.myTop = 10; [contentLayout addSubview:actionTitleLabel]; //用流式布局来创建动作菜单布局。流式布局请参考后面关于流式布局的DEMO。 MyFlowLayout *actionLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; - actionLayout.wrapContentHeight = YES; + actionLayout.myHeight = MyLayoutSize.wrap; actionLayout.gravity = MyGravity_Horz_Fill; //平均分配里面所有子视图的宽度 actionLayout.subviewHSpace = 5; actionLayout.subviewVSpace = 5; //设置里面子视图的水平和垂直间距。 @@ -250,7 +249,6 @@ -(void)createHorzGravityLayout:(MyLinearLayout*)contentLayout MyLinearLayout *horzGravityLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; horzGravityLayout.backgroundColor = [CFTool color:0]; - horzGravityLayout.wrapContentWidth = NO; //因为默认水平线性布局的宽度由子视图包裹,但这里的宽度由父布局决定的,所有这里必须设置为NO。 horzGravityLayout.myHeight = 200; horzGravityLayout.myTop = 10; horzGravityLayout.myLeading = 20; @@ -259,24 +257,24 @@ -(void)createHorzGravityLayout:(MyLinearLayout*)contentLayout self.horzGravityLayout = horzGravityLayout; UILabel *v1 = [self createLabel:NSLocalizedString(@"test text1", @"") backgroundColor:[CFTool color:5]]; - v1.wrapContentHeight = YES; + v1.myHeight = MyLayoutSize.wrap; v1.myWidth = 60; [self.horzGravityLayout addSubview:v1]; UILabel *v2 = [self createLabel:NSLocalizedString(@"always alignment to top", @"") backgroundColor:[CFTool color:6]]; - v2.wrapContentHeight = YES; + v2.myHeight = MyLayoutSize.wrap; v2.myWidth = 60; v2.alignment = MyGravity_Vert_Top; //对于水平布局里面的子视图可以通过这个属性来设置垂直对齐的方位,这样即使布局视图设置了gravity属性,这个视图的对齐都不会受到影响。 [self.horzGravityLayout addSubview:v2]; UILabel *v3 = [self createLabel:NSLocalizedString(@"test text3 test text3 test text3", @"") backgroundColor:[CFTool color:7]]; - v3.wrapContentHeight = YES; + v3.myHeight = MyLayoutSize.wrap; v3.myWidth = 60; [self.horzGravityLayout addSubview:v3]; UILabel *v4 = [self createLabel:NSLocalizedString(@"set top and bottom margin to determine height", @"") backgroundColor:[CFTool color:8]]; - v4.wrapContentHeight = YES; + v4.numberOfLines = 0; v4.myTop = 20; v4.myBottom = 10; v4.myWidth = 60; @@ -432,8 +430,7 @@ -(void)handleHorzLayoutGravity:(UIButton*)button -(void)handleNavigationTitleCentre:(id)sender { MyLinearLayout *navigationItemLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - navigationItemLayout.wrapContentHeight = NO; - navigationItemLayout.wrapContentWidth = NO; //将线性布局放入navigationItem.titleView需要把包裹属性设置为NO。 + navigationItemLayout.heightSize.equalTo(nil); //将布局放入navigationItem的titleView时不要设置高度约束 //通过MyGravity_Horz_Window_Center的设置总是保证在窗口的中间而不是布局视图的中间。 navigationItemLayout.gravity = MyGravity_Horz_Window_Center | MyGravity_Vert_Center; diff --git a/MyLayoutDemo/LLTest4ViewController.m b/MyLayoutDemo/LLTest4ViewController.m index 9ab7916..f480ae3 100644 --- a/MyLayoutDemo/LLTest4ViewController.m +++ b/MyLayoutDemo/LLTest4ViewController.m @@ -21,7 +21,7 @@ @implementation LLTest4ViewController -(void)loadView { /* - 这个例子详细说明wrapContentHeight和wrapContentWidth的包裹属性的设置、以及边界线性的设定、以及布局中可局部缩放背景图片的设定方法。 + 这个例子详细说明高度和宽度的自适应设置、以及边界线性的设定、以及布局中可局部缩放背景图片的设定方法。 */ self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 @@ -33,15 +33,20 @@ -(void)loadView UIView *contentView = [UIView new]; contentView.backgroundColor = [CFTool color:5]; [self.view addSubview:contentView]; - contentView.wrapContentWidth = YES; - contentView.wrapContentHeight = YES; //如果一个非布局父视图里面有布局子视图,那么这个非布局父视图也是可以设置wrapContentHeight和wrapContentWidth的,他表示的意义是这个非布局父视图的尺寸由里面的布局子视图的尺寸来决定的。这个功能是在1.3.3版本支持的。 还有一个场景是非布局父视图是一个UIScrollView。他是左右滚动的,但是滚动视图的高度是由里面的布局子视图确定的,而宽度则是和窗口保持一致。这样只需要将滚动视图的宽度设置为和屏幕保持一致,高度设置为wrapContentHeight,并且把一个水平线性布局添加到滚动视图即可。 + + + /* + 如果一个非布局父视图里面有布局子视图,那么这个非布局父视图也是可以设置高度和宽度自适应,他表示的意义是这个非布局父视图的尺寸由里面的布局子视图的尺寸来决定的。 + 还有一个场景是非布局父视图是一个UIScrollView。他是左右滚动的,但是滚动视图的高度是由里面的布局子视图确定的,而宽度则是和窗口保持一致。 + 这样只需要将滚动视图的宽度设置为和屏幕保持一致,高度设置为自适应,并且把一个水平线性布局添加到滚动视图即可。 + */ + contentView.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); self.rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; self.rootLayout.layer.borderWidth = 1; self.rootLayout.layer.borderColor = [UIColor lightGrayColor].CGColor; - self.rootLayout.wrapContentHeight = YES; - self.rootLayout.wrapContentWidth = YES; //布局的高度和宽度由子视图决定 + self.rootLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); self.rootLayout.myTop = 10; self.rootLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); self.rootLayout.zeroPadding = NO; //这个属性设置为NO时表示当布局视图的尺寸是wrap也就是由子视图决定时并且在没有任何子视图是不会参与布局视图高度的计算的。您可以在这个DEMO的测试中将所有子视图都删除掉,看看效果,然后注释掉这句代码看看效果。 @@ -70,8 +75,7 @@ -(MyLinearLayout*)addWrapContentLayout { MyLinearLayout *wrapContentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; - wrapContentLayout.wrapContentHeight = YES; - wrapContentLayout.wrapContentWidth = YES; //布局的高度和宽度由子视图决定 + wrapContentLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); //布局的高度和宽度由子视图决定 wrapContentLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); wrapContentLayout.subviewHSpace = 5; @@ -104,8 +108,7 @@ -(MyLinearLayout*)addWrapContentLayout actionLayout.layer.borderColor = [CFTool color:9].CGColor; actionLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); actionLayout.subviewVSpace = 5; - actionLayout.wrapContentWidth = YES; - actionLayout.wrapContentHeight = YES; //布局的高度和宽度由子视图决定 + actionLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); //布局的高度和宽度由子视图决定 [wrapContentLayout addSubview:actionLayout]; diff --git a/MyLayoutDemo/LLTest5ViewController.m b/MyLayoutDemo/LLTest5ViewController.m index 067feb3..54447da 100644 --- a/MyLayoutDemo/LLTest5ViewController.m +++ b/MyLayoutDemo/LLTest5ViewController.m @@ -65,15 +65,13 @@ -(void)loadView 如果布局视图里面的子视图使用了相对尺寸和相对间距我们必须要满足如下的条件: - 1.垂直线性布局里面如果有子视图设置了weight或者指定了垂直相对间距,则wrapContentHeight设置将失效;水平线性布局里面如果有子视图设置为weight或者指定了水平相对间距,则wrapContentWidth设置将失效。 + 1.垂直线性布局里面如果有子视图设置了weight,则高度约束设置将失效;水平线性布局里面如果有子视图设置为weight,则宽度约束设置将失效。 2.如果布局视图里面的子视图使用了相对间距和相对尺寸则必须要明确指定布局视图的宽度或者高度,否则相对设置可能会失效。 */ MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; rootLayout.backgroundColor = [CFTool color:0]; - rootLayout.wrapContentWidth = NO; - rootLayout.wrapContentHeight = NO; self.view = rootLayout; diff --git a/MyLayoutDemo/LLTest6ViewController.m b/MyLayoutDemo/LLTest6ViewController.m index c2b86ab..c582f73 100644 --- a/MyLayoutDemo/LLTest6ViewController.m +++ b/MyLayoutDemo/LLTest6ViewController.m @@ -57,7 +57,6 @@ -(void)loadView } MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - rootLayout.wrapContentHeight = NO; rootLayout.backgroundColor = [UIColor whiteColor]; [rootLayout setTarget:self action:@selector(handleHideKeyboard:)]; //设置布局上的触摸事件。布局视图支持触摸事件的设置,可以使用setTarget方法来实现。 @@ -131,12 +130,12 @@ -(void)loadView textView.delegate = self; //左右边距为布局的10%,距离底部间距为65%,高度自适应,但高度最高为300,最低为30 - //wrapContentHeight和max,min的结合能做到一些完美的自动伸缩功能。 + //高度自适应设置和max,min的结合能做到一些完美的自动伸缩功能。 textView.myLeading = 0.05; textView.myTrailing = 0.05; textView.myBottom = 0.65; - textView.wrapContentHeight = YES; - textView.heightSize.max(300).min(60); //虽然wrapContentHeight属性设置了视图的高度为动态高度,但是仍然不能超过300的高度以及不能小于60的高度。 + //虽然高度自适应,但是仍然不能超过300的高度以及不能小于60的高度。 + textView.heightSize.equalTo(@(MyLayoutSize.wrap)).max(300).min(60); [rootLayout addSubview:textView]; diff --git a/MyLayoutDemo/LLTest7ViewController.m b/MyLayoutDemo/LLTest7ViewController.m index c3d2926..a6e8cc4 100644 --- a/MyLayoutDemo/LLTest7ViewController.m +++ b/MyLayoutDemo/LLTest7ViewController.m @@ -42,14 +42,12 @@ -(void)loadView rootLayout.backgroundColor = [UIColor whiteColor]; rootLayout.gravity = MyGravity_Horz_Fill; //设置里面所有子视图的宽度填充布局视图的宽度。 rootLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); - rootLayout.wrapContentHeight = NO; - rootLayout.wrapContentWidth = NO; rootLayout.subviewVSpace = 5; self.view = rootLayout; //创建动作布局 MyLinearLayout *action1Layout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; - action1Layout.wrapContentHeight = YES; + action1Layout.heightSize.equalTo(@(MyLayoutSize.wrap)); action1Layout.topPos.equalTo(self.topLayoutGuide); [rootLayout addSubview:action1Layout]; @@ -60,7 +58,7 @@ -(void)loadView //创建动作布局 MyLinearLayout *action2Layout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; - action2Layout.wrapContentHeight = YES; + action2Layout.heightSize.equalTo(@(MyLayoutSize.wrap)); [rootLayout addSubview:action2Layout]; [action2Layout addSubview:[self createActionButton:NSLocalizedString(@"average size centered",@"") tag:400]]; @@ -72,8 +70,6 @@ -(void)loadView self.testLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; self.testLayout.backgroundColor = [CFTool color:0]; self.testLayout.gravity = MyGravity_Horz_Fill; //所有子视图水平宽度充满布局,这样就不需要分别设置每个子视图的宽度了。 - self.testLayout.wrapContentHeight = NO; - self.testLayout.wrapContentWidth = NO; self.testLayout.weight = 1.0; self.testLayout.leftPadding = 10; self.testLayout.rightPadding = 10; @@ -129,7 +125,7 @@ -(UIButton*)createActionButton:(NSString*)title tag:(NSInteger)tag button.titleLabel.textAlignment = NSTextAlignmentCenter; button.titleLabel.font = [CFTool font:14]; [button sizeToFit]; - button.heightSize.equalTo(button.heightSize).add(20); //高度等于内容的高度再加20 + button.heightSize.equalTo(@(MyLayoutSize.wrap)).add(20); //高度自适应外加20的 button.layer.borderColor = [UIColor lightGrayColor].CGColor; button.layer.borderWidth = 0.5; button.layer.cornerRadius = 4; diff --git a/MyLayoutDemo/PLTest2ViewController.m b/MyLayoutDemo/PLTest2ViewController.m index 6dd873b..15e7c7f 100644 --- a/MyLayoutDemo/PLTest2ViewController.m +++ b/MyLayoutDemo/PLTest2ViewController.m @@ -58,10 +58,9 @@ -(void)loadView self.view = scrollView; _pathLayout = [MyTestPathLayou new]; - _pathLayout.wrapContentHeight = YES; - _pathLayout.wrapContentWidth = YES; //这里面的布局视图的宽度和高度都是wrap属性,因此这个例子里面出现不同函数切换时不会立即得到真实的位置,而是要在添加或者删除子视图后才会更新真实的高度和宽度,这个并不是一个BUG。 - _pathLayout.widthSize.lBound(scrollView.widthSize, 0, 1); - _pathLayout.heightSize.lBound(scrollView.heightSize, 0, 1); //设置最小的宽度和高度和父视图保持一致。 +//这里面的布局视图的宽度和高度都是wrap属性,因此这个例子里面出现不同函数切换时不会立即得到真实的位置,而是要在添加或者删除子视图后才会更新真实的高度和宽度,这个并不是一个BUG。 + _pathLayout.widthSize.equalTo(@(MyLayoutSize.wrap)).lBound(scrollView.widthSize, 0, 1); + _pathLayout.heightSize.equalTo(@(MyLayoutSize.wrap)).lBound(scrollView.heightSize, 0, 1); //设置最小的宽度和高度和父视图保持一致。 _pathLayout.padding = UIEdgeInsetsMake(20, 20, 20, 20); [scrollView addSubview:_pathLayout]; diff --git a/MyLayoutDemo/PLTest3ViewController.m b/MyLayoutDemo/PLTest3ViewController.m index 7c3abc0..76125f2 100644 --- a/MyLayoutDemo/PLTest3ViewController.m +++ b/MyLayoutDemo/PLTest3ViewController.m @@ -33,8 +33,8 @@ -(id)initWithImage:(NSString*)image title:(NSString*)title index:(NSInteger)inde self = [super init]; if (self != nil) { - self.wrapContentHeight = YES; - self.wrapContentWidth = YES; + self.widthSize.equalTo(@(MyLayoutSize.wrap)); + self.heightSize.equalTo(@(MyLayoutSize.wrap)); _circleView = [MyPathLayout new]; //这里这是为路径布局的原因是其中的numLabel是跟随园所在的位置而确定的。 _circleView.widthSize.equalTo(@60); @@ -129,12 +129,13 @@ -(void)loadView centerButton.titleLabel.font = [CFTool font:20]; centerButton.layer.borderWidth = 5; centerButton.layer.borderColor = [UIColor whiteColor].CGColor; - centerButton.widthSize.equalTo(_pathLayout.widthSize).multiply(0.5).add(-30); //宽度是父视图宽度的一半再减去30 + centerButton.widthSize.equalTo(@[_pathLayout.widthSize, _pathLayout.heightSize].myMinSize).multiply(0.5).add(-30); + //宽度是父视图宽度或者高度最小者的一半再减去30 + centerButton.heightSize.equalTo(centerButton.widthSize); //高度等于宽度。 centerButton.viewLayoutCompleteBlock = ^(MyBaseLayout *layout, UIView *sbv) { //viewLayoutCompleteBlock是在1.2.3中添加的新功能,目的是给完成了布局的子视图一个机会进行一些特殊的处理,viewLayoutCompleteBlock只会在子视图布局完成后调用一次.其中的sbv就是子视图自己,而layout则是父布局视图。因为这个block是完成布局后执行的。所以这时候子视图的frame值已经被计算出来,因此您可以在这里设置一些和frame关联的属性。 sbv.layer.cornerRadius = sbv.frame.size.width / 2; //这里取子视图的圆角半径为宽度的一半,也就是形成了圆形按钮。 - sbv.heightSize.equalTo(@(sbv.frame.size.width)); //这里取子视图的高度等于他的宽度。 }; [centerButton addTarget:self action:@selector(handleClick:) forControlEvents:UIControlEventTouchUpInside]; diff --git a/MyLayoutDemo/RLTest4ViewController.m b/MyLayoutDemo/RLTest4ViewController.m index c023b1a..4faba6b 100644 --- a/MyLayoutDemo/RLTest4ViewController.m +++ b/MyLayoutDemo/RLTest4ViewController.m @@ -58,8 +58,8 @@ -(void)loadView MyRelativeLayout *rootLayout = [MyRelativeLayout new]; rootLayout.insetsPaddingFromSafeArea = ~UIRectEdgeBottom; //为了防止拉到底部时iPhoneX设备的抖动发生,不能将底部安全区叠加到padding中去。 rootLayout.widthSize.equalTo(scrollView.widthSize); + rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); - rootLayout.wrapContentHeight = YES; [scrollView addSubview:rootLayout]; diff --git a/MyLayoutDemo/RLTest5ViewController.m b/MyLayoutDemo/RLTest5ViewController.m index 26c58da..28c338a 100644 --- a/MyLayoutDemo/RLTest5ViewController.m +++ b/MyLayoutDemo/RLTest5ViewController.m @@ -33,7 +33,7 @@ -(void)loadView MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; rootLayout.leadingPos.equalTo(@0); rootLayout.trailingPos.equalTo(@0); - rootLayout.wrapContentHeight = YES; + rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); rootLayout.subviewVSpace = 10; [scrollView addSubview:rootLayout]; @@ -93,7 +93,7 @@ -(void)createDemo1:(UIView*)rootLayout MyRelativeLayout *containerLayout = [MyRelativeLayout new]; containerLayout.leadingPos.equalTo(rootLayout.leadingPos); containerLayout.trailingPos.equalTo(rootLayout.trailingPos); - containerLayout.wrapContentHeight = YES; + containerLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); containerLayout.topPadding = 6; containerLayout.bottomPadding = 6; containerLayout.backgroundColor = [CFTool color:0]; @@ -149,7 +149,7 @@ -(void)createDemo2:(UIView*)rootLayout MyRelativeLayout *containerLayout = [MyRelativeLayout new]; containerLayout.leadingPos.equalTo(rootLayout.leadingPos); containerLayout.trailingPos.equalTo(rootLayout.trailingPos); - containerLayout.wrapContentHeight = YES; + containerLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); containerLayout.padding = UIEdgeInsetsMake(6, 6, 6, 6); containerLayout.backgroundColor = [CFTool color:0]; [rootLayout addSubview:containerLayout]; @@ -179,7 +179,7 @@ -(void)createDemo2:(UIView*)rootLayout flexedLabel.font = [CFTool font:17]; flexedLabel.textColor = [CFTool color:4]; flexedLabel.lineBreakMode = NSLineBreakByCharWrapping; - flexedLabel.wrapContentHeight = YES; //高度自动计算。 + flexedLabel.heightSize.equalTo(@(MyLayoutSize.wrap)); //高度自动计算。 flexedLabel.leadingPos.equalTo(leadingImageView.trailingPos).offset(5); //左边等于leadingImageView的右边 flexedLabel.topPos.equalTo(leadingImageView.topPos); //顶部和leadingImageView相等。 [containerLayout addSubview:flexedLabel]; @@ -238,7 +238,7 @@ -(void)createDemo3:(UIView*)rootLayout leadingLabel.text = @"Click me:"; leadingLabel.textColor = [CFTool color:4]; leadingLabel.widthSize.equalTo(@100); //宽度固定为100 - leadingLabel.wrapContentHeight = YES; //高度由子视图的内容确定,自动计算高度。 + leadingLabel.heightSize.equalTo(@(MyLayoutSize.wrap)); //高度由子视图的内容确定,自动计算高度。 leadingLabel.topPos.lBound(containerLayout.topPos,0); //最小的上边界是父布局的顶部。 leadingLabel.bottomPos.uBound(containerLayout.bottomPos, 0); //最大的下边界是父布局的底部 //通过这两个位置的最小最大边界设置,视图leadingLabel将会在这个范围内垂直居中显示,并且当高度超过这个边界时,会自动的压缩子视图的高度。 @@ -259,9 +259,8 @@ -(void)createDemo3:(UIView*)rootLayout trailingLabel.trailingPos.equalTo(containerLayout.trailingPos); //和父布局视图右对齐。 trailingLabel.centerYPos.equalTo(leadingLabel.centerYPos); //和左边视图垂直居中对齐。 trailingLabel.leadingPos.lBound(leadingLabel.trailingPos, 10); //右边视图的最小边界是等于左边视图的右边再偏移10,这样当右边视图的宽度超过这个最小边界时则会自动压缩视图的宽度。 - trailingLabel.widthSize.equalTo(trailingLabel.widthSize); //宽度等于自身的宽度。这个设置和上面的leadingPos.lBound方法配合使用实现子视图宽度的压缩。 - trailingLabel.wrapContentHeight = YES; //高度动态调整 - trailingLabel.heightSize.uBound(containerLayout.heightSize, 0, 1); //但是最大的高度等于父布局视图的高度(注意这里内部自动减去了padding的值) + trailingLabel.widthSize.equalTo(@(MyLayoutSize.wrap)); //宽度等于自身的宽度。这个设置和上面的leadingPos.lBound方法配合使用实现子视图宽度的压缩。 + trailingLabel.heightSize.equalTo(@(MyLayoutSize.wrap)).uBound(containerLayout.heightSize, 0, 1); //但是最大的高度等于父布局视图的高度(注意这里内部自动减去了padding的值) [containerLayout addSubview:trailingLabel]; //添加手势处理。 diff --git a/MyLayoutDemo/TLTest2ViewController.m b/MyLayoutDemo/TLTest2ViewController.m index bf2ed68..098cad9 100644 --- a/MyLayoutDemo/TLTest2ViewController.m +++ b/MyLayoutDemo/TLTest2ViewController.m @@ -36,8 +36,7 @@ -(void)loadView rootLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); //分别设置表格布局里面的行间距、列间距、内部padding边距。 rootLayout.widthSize.equalTo(scrollView.widthSize); - rootLayout.wrapContentHeight = YES; //布局宽度和父视图一致,高度则由内容包裹。这是实现将布局视图加入滚动条视图并垂直滚动的标准方法。 - rootLayout.wrapContentWidth = NO; + rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap));//布局宽度和父视图一致,高度则由内容包裹。这是实现将布局视图加入滚动条视图并垂直滚动的标准方法。 [scrollView addSubview:rootLayout]; self.rootLayout = rootLayout; @@ -73,7 +72,6 @@ -(UIView*)createColLayout:(NSString*)image title:(NSString*)title { MyLinearLayout *colLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; colLayout.gravity = MyGravity_Horz_Fill; //里面所有子视图的宽度都跟父视图保持一致,这样子视图就不需要设置宽度了。 - colLayout.wrapContentHeight = YES; colLayout.subviewVSpace = 5; //设置布局视图里面子视图之间的间距为5个点。 colLayout.backgroundColor = [CFTool color:0]; colLayout.highlightedOpacity = 0.3; //设置触摸事件按下时的不透明度,来响应按下状态。 @@ -81,7 +79,7 @@ -(UIView*)createColLayout:(NSString*)image title:(NSString*)title UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:image]]; - imageView.wrapContentHeight = YES; //这个属性重点注意!! 对于UIImageView来说,如果我们设置了这个属性为YES的话,表示视图的高度会根据视图的宽度进行等比例的缩放来确定,从而防止图片显示时出现变形的情况。 + imageView.myHeight = MyLayoutSize.wrap; //这个属性重点注意!! 对于UIImageView来说,如果我们设置了高度自适应的话,表示视图的高度会根据视图的宽度进行等比例的缩放来确定,从而防止图片显示时出现变形的情况。 [colLayout addSubview:imageView]; UILabel *titleLabel = [UILabel new]; diff --git a/MyLayoutDemo/TLTest4ViewController.m b/MyLayoutDemo/TLTest4ViewController.m index ac94d72..0384822 100644 --- a/MyLayoutDemo/TLTest4ViewController.m +++ b/MyLayoutDemo/TLTest4ViewController.m @@ -137,8 +137,8 @@ -(MyBaseLayout*)itemFrom:(NSString*)itemString alignment:(NSTextAlignment)alignm else { itemLayout.gravity = MyGravity_Horz_Fill; - itemLayout.wrapContentHeight = YES; - label.wrapContentHeight = YES; + itemLayout.myHeight = MyLayoutSize.wrap; + label.myHeight = MyLayoutSize.wrap; } diff --git a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings index 3248686..47cf8b2 100644 --- a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings +++ b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings @@ -89,7 +89,7 @@ "Show&Hide the Text"="点击按钮显示隐藏文本"; "Show more》"="点击查看更多》"; "Close up《" ="点击收起《"; -"This is a can automatically wrap text.To realize this function, you need to set the clear width, and set the wrapContentHeight to YES.You can try to switch different simulator or different orientation screen to see the effect."="这是一段可以自动换行的文本。为了实现这个功能,您需要设置明确的宽度,并且把属性wrapContentHeight设置为YES。您可以尝试着切换不同尺寸的模拟器或者横竖屏来看看效果。"; +"This is a can automatically wrap text.To realize this function, you need to set the width exact, and set the heightSize to MyLayoutSize.wrap.You can try to switch different simulator or different orientation screen to see the effect."="这是一段可以自动换行的文本。为了实现这个功能,您需要设置明确的宽度,并且把heightSize设置为MyLayoutSize.wrap。您可以尝试着切换不同尺寸的模拟器或者横竖屏来看看效果。"; //LLTest3ViewController "centered title" = "标题居中"; @@ -230,7 +230,7 @@ //AllTest1ViewController "add tableHeaderView(please touch me)"="设置tableHeaderView(点我试试)"; -" if you use layout view to realize the dynamic height tableHeaderView, please use frame to set view's width and use wrapContentHeight to set view's height. the layoutIfNeeded method is needed to call before the layout view assignment to the UITableview's tableHeaderView."=" 布局视图实现具有动态高度的tableHeaderView时,宽度需要用frame指定,高度则设置wrapContentHeight为YES,并且在赋值给UITableview的tableHeaderView之前需要调用layoutIfNeeded方法来明确高度。"; +" if you use layout view to realize the dynamic height tableHeaderView, please use frame to set view's width and set view's heightSize to MyLayoutSize.wrap. the layoutIfNeeded method is needed to call before the layout view assignment to the UITableview's tableHeaderView."=" 布局视图实现具有动态高度的tableHeaderView时,宽度需要用frame指定,高度heightSize设置为MyLayoutSize.wrap,并且在赋值给UITableview的tableHeaderView之前需要调用layoutIfNeeded方法来明确高度。"; "add tableFooterView"="设置tableFooterView"; "the layoutIfNeeded is not need to call when you use frame to set layout view's size"="如果通过frame设置了明确的尺寸则不需要调用layoutIfNeeded"; diff --git a/MyLayoutTests/MyFloatLayoutTestCase.m b/MyLayoutTests/MyFloatLayoutTestCase.m index 2d68916..ab0b8e9 100644 --- a/MyLayoutTests/MyFloatLayoutTestCase.m +++ b/MyLayoutTests/MyFloatLayoutTestCase.m @@ -46,7 +46,6 @@ -(void)testSubviewSizeDependent //垂直线性布局 { MyFloatLayout *rootLayout1 = [[MyFloatLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Vert]; - rootLayout1.wrapContentHeight = NO; //1. 子视图宽度等于自身高度 UILabel *label1 = [UILabel new]; label1.myHeight = 100; @@ -56,7 +55,7 @@ -(void)testSubviewSizeDependent //2. 子视图高度等于自身宽度 UILabel *label2 = [UILabel new]; - label2.wrapContentWidth = YES; + label2.widthSize.equalTo(@(MyLayoutSize.wrap)); label2.heightSize.equalTo(label2.widthSize); label2.text = @"hello World"; [rootLayout1 addSubview:label2]; @@ -105,7 +104,6 @@ -(void)testSubviewSizeDependent //水平线性布局 { MyFloatLayout *rootLayout1 = [[MyFloatLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Horz]; - rootLayout1.wrapContentWidth = NO; //1. 子视图宽度等于自身高度 UILabel *label1 = [UILabel new]; label1.myHeight = 100; @@ -115,7 +113,7 @@ -(void)testSubviewSizeDependent //2. 子视图高度等于自身宽度 UILabel *label2 = [UILabel new]; - label2.wrapContentWidth = YES; + label2.widthSize.equalTo(@(MyLayoutSize.wrap)); label2.heightSize.equalTo(label2.widthSize); label2.text = @"hello World"; [rootLayout1 addSubview:label2]; diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index 0c83748..44381c3 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -43,7 +43,7 @@ -(void)testWrapContentSize { //测试内容约束布局的宽度自适应和高度自适应的设置。 MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; - rootLayout.wrapContentSize = YES; + rootLayout.mySize = CGSizeMake(MyLayoutSize.wrap,MyLayoutSize.wrap); rootLayout.padding = UIEdgeInsetsMake(10, 20, 30, 40); rootLayout.subviewHSpace = 5; rootLayout.subviewVSpace = 5; @@ -76,7 +76,7 @@ -(void)testSubviewSizeDependent //垂直线性布局 { MyFlowLayout *rootLayout1 = [[MyFlowLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Vert arrangedCount:4]; - rootLayout1.wrapContentHeight = NO; + rootLayout1.heightSize.equalTo(nil); //1. 子视图宽度等于自身高度 UILabel *label1 = [UILabel new]; label1.myHeight = 100; @@ -86,7 +86,7 @@ -(void)testSubviewSizeDependent //2. 子视图高度等于自身宽度 UILabel *label2 = [UILabel new]; - label2.wrapContentWidth = YES; + label2.widthSize.equalTo(@(MyLayoutSize.wrap)); label2.heightSize.equalTo(label2.widthSize); label2.text = @"hello World"; [rootLayout1 addSubview:label2]; @@ -135,7 +135,6 @@ -(void)testSubviewSizeDependent //水平线性布局 { MyFlowLayout *rootLayout1 = [[MyFlowLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Horz arrangedCount:4]; - rootLayout1.wrapContentWidth = NO; //1. 子视图宽度等于自身高度 UILabel *label1 = [UILabel new]; label1.myHeight = 100; @@ -145,7 +144,7 @@ -(void)testSubviewSizeDependent //2. 子视图高度等于自身宽度 UILabel *label2 = [UILabel new]; - label2.wrapContentWidth = YES; + label2.widthSize.equalTo(@(MyLayoutSize.wrap)); label2.heightSize.equalTo(label2.widthSize); label2.text = @"hello World"; [rootLayout1 addSubview:label2]; @@ -195,7 +194,6 @@ -(void)testSubviewSizeDependent //垂直线性布局 { MyFlowLayout *rootLayout1 = [[MyFlowLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Vert arrangedCount:0]; - rootLayout1.wrapContentHeight = NO; //1. 子视图宽度等于自身高度 UILabel *label1 = [UILabel new]; label1.myHeight = 100; @@ -205,7 +203,7 @@ -(void)testSubviewSizeDependent //2. 子视图高度等于自身宽度 UILabel *label2 = [UILabel new]; - label2.wrapContentWidth = YES; + label2.widthSize.equalTo(@(MyLayoutSize.wrap)); label2.heightSize.equalTo(label2.widthSize); label2.text = @"hello World"; [rootLayout1 addSubview:label2]; @@ -254,7 +252,6 @@ -(void)testSubviewSizeDependent //水平线性布局 { MyFlowLayout *rootLayout1 = [[MyFlowLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Horz arrangedCount:0]; - rootLayout1.wrapContentWidth = NO; //1. 子视图宽度等于自身高度 UILabel *label1 = [UILabel new]; label1.myHeight = 100; @@ -264,7 +261,7 @@ -(void)testSubviewSizeDependent //2. 子视图高度等于自身宽度 UILabel *label2 = [UILabel new]; - label2.wrapContentWidth = YES; + label2.widthSize.equalTo(@(MyLayoutSize.wrap)); label2.heightSize.equalTo(label2.widthSize); label2.text = @"hello World"; [rootLayout1 addSubview:label2]; diff --git a/MyLayoutTests/MyFrameLayoutTestCase.m b/MyLayoutTests/MyFrameLayoutTestCase.m index ae5f58a..2f46588 100644 --- a/MyLayoutTests/MyFrameLayoutTestCase.m +++ b/MyLayoutTests/MyFrameLayoutTestCase.m @@ -53,7 +53,7 @@ -(void)testblurred label1.font = [UIFont systemFontOfSize:17]; label1.myCenterY = 0; label1.myLeft = 10; - label1.wrapContentSize = YES; + label1.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); [frameLayout addSubview:label1]; @@ -63,7 +63,7 @@ -(void)testblurred label2.font = [UIFont systemFontOfSize:17]; label2.myTop = 200; label2.myLeft = 10; - label2.wrapContentSize = YES; + label2.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); [frameLayout addSubview:label2]; @@ -90,7 +90,7 @@ - (void)testWrapContent { MyFrameLayout *frameLayout = [MyFrameLayout new]; frameLayout.padding = UIEdgeInsetsMake(20, 10, 5, 6); - frameLayout.wrapContentSize = YES; + frameLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); frameLayout.zeroPadding = NO; @@ -180,8 +180,7 @@ -(void)testSizeDependent -(void)testWrapContent2 { MyFrameLayout * dataview = [[MyFrameLayout alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 0)]; - dataview.heightSize.min([UIScreen mainScreen].bounds.size.height); - dataview.wrapContentHeight = YES; + dataview.heightSize.equalTo(@(MyLayoutSize.wrap)).min([UIScreen mainScreen].bounds.size.height); //上面在滚动视图下。 MyLinearLayout * dataContentV = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; @@ -189,14 +188,14 @@ -(void)testWrapContent2 dataContentV.bottomPadding = 64; // + 10; dataContentV.myCenterX = 0; dataContentV.myCenterY = 0; - dataContentV.wrapContentHeight = YES; + dataContentV.myHeight = MyLayoutSize.wrap; dataContentV.myHorzMargin = 0; [dataview addSubview:dataContentV]; MyLinearLayout * subrootview1 = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; subrootview1.gravity = MyGravity_Horz_Fill; - subrootview1.wrapContentHeight = YES; + subrootview1.myHeight = MyLayoutSize.wrap; subrootview1.myHorzMargin = 0; subrootview1.padding = UIEdgeInsetsMake(0, 10, 0, 10); [dataContentV addSubview:subrootview1]; @@ -259,7 +258,7 @@ -(void)testWrapContent3 { //测试一个布局视图的尺寸是包裹的,同时里面的子视图设置了宽高。 MyFrameLayout *rootLayout = [MyFrameLayout new]; - rootLayout.wrapContentSize = YES; + rootLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); rootLayout.padding = UIEdgeInsetsMake(10, 20, 30, 40); //1.同时设置了上下和左右。没有设置高度。 @@ -296,7 +295,7 @@ -(void)testWrapContent3 [v2 removeFromSuperview]; UILabel *label = [UILabel new]; - label.wrapContentSize = YES; + label.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); label.text = @"您好!"; label.myMargin = 20; CGSize lablesz = [label sizeThatFits:CGSizeZero]; diff --git a/MyLayoutTests/MyLayoutPerformanceTestCase.m b/MyLayoutTests/MyLayoutPerformanceTestCase.m index 3f83c64..9836520 100644 --- a/MyLayoutTests/MyLayoutPerformanceTestCase.m +++ b/MyLayoutTests/MyLayoutPerformanceTestCase.m @@ -151,7 +151,7 @@ -(UIView*)linearlayout_createFrame -(UIView*)linearlayout_createMyLayout { MyLinearLayout *containerView = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 100, 100) orientation:MyOrientation_Vert]; - containerView.wrapContentHeight = NO; + containerView.heightSize.equalTo(nil); for (int i = 0; i < self.counts; i++) { diff --git a/MyLayoutTests/MyLinearLayoutTestCase.m b/MyLayoutTests/MyLinearLayoutTestCase.m index 32e79f6..2a17f56 100644 --- a/MyLayoutTests/MyLinearLayoutTestCase.m +++ b/MyLayoutTests/MyLinearLayoutTestCase.m @@ -80,7 +80,7 @@ -(void)testSubviewSizeDependent //垂直线性布局 { MyLinearLayout *rootLayout1 = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Vert]; - rootLayout1.wrapContentHeight = NO; + rootLayout1.heightSize.equalTo(nil); //1. 子视图宽度等于自身高度 UILabel *label1 = [UILabel new]; label1.myHeight = 100; @@ -90,7 +90,7 @@ -(void)testSubviewSizeDependent //2. 子视图高度等于自身宽度 UILabel *label2 = [UILabel new]; - label2.wrapContentWidth = YES; + label2.widthSize.equalTo(@(MyLayoutSize.wrap)); label2.heightSize.equalTo(label2.widthSize); label2.text = @"hello World"; [rootLayout1 addSubview:label2]; @@ -139,7 +139,7 @@ -(void)testSubviewSizeDependent //水平线性布局 { MyLinearLayout *rootLayout1 = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Horz]; - rootLayout1.wrapContentWidth = NO; + rootLayout1.widthSize.equalTo(nil); //1. 子视图宽度等于自身高度 UILabel *label1 = [UILabel new]; label1.myHeight = 100; @@ -149,7 +149,7 @@ -(void)testSubviewSizeDependent //2. 子视图高度等于自身宽度 UILabel *label2 = [UILabel new]; - label2.wrapContentWidth = YES; + label2.widthSize.equalTo(@(MyLayoutSize.wrap)); label2.heightSize.equalTo(label2.widthSize); label2.text = @"hello World"; [rootLayout1 addSubview:label2]; @@ -203,7 +203,7 @@ -(void)testSubviewSizeDependent2 //测试隐藏、比重、尺寸依赖。 MyLinearLayout *layout2 = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 200) orientation:MyOrientation_Horz]; - layout2.wrapContentWidth = NO; + layout2.widthSize.equalTo(nil); UIButton *zoneBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; @@ -251,7 +251,7 @@ -(void)testWeight MyLinearLayout* rootLayout1 = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 375, 667) orientation:MyOrientation_Horz]; // rootLayout1.myMargin = 0; rootLayout1.backgroundColor = [UIColor redColor]; - rootLayout1.wrapContentWidth = NO; + rootLayout1.widthSize.equalTo(nil); for (int i = 0; i < 4; i++) { @@ -292,7 +292,7 @@ -(void)testWrapContentHeight2 UILabel *timeLabel = UILabel.new; timeLabel.myHorzMargin = 0; - timeLabel.wrapContentHeight = YES; + timeLabel.myHeight = MyLayoutSize.wrap; timeLabel.textAlignment = NSTextAlignmentCenter; timeLabel.text = @"剩余时间为"; [layout addSubview:timeLabel]; @@ -300,7 +300,7 @@ -(void)testWrapContentHeight2 // 汇率 MyLinearLayout *convertLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; convertLayout.backgroundColor = [UIColor greenColor]; - convertLayout.wrapContentHeight = YES; + convertLayout.myHeight = MyLayoutSize.wrap; convertLayout.gravity = MyGravity_Vert_Center; convertLayout.subviewHSpace = 7; [layout addSubview:convertLayout]; @@ -308,7 +308,7 @@ -(void)testWrapContentHeight2 NSArray *items = @[@"$454", @"^sdsf"]; for (int i=0; i"; [convertLayout addSubview:btn]; } @@ -337,28 +337,27 @@ -(void)testWrapGravityMinMaxShrink //测试自适应,停靠,最大和最小。 MyLinearLayout *testLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; testLayout.widthSize.min(200).max(300); - testLayout.heightSize.min(40).max(100); + testLayout.heightSize.equalTo(@(MyLayoutSize.wrap)).min(40).max(100); testLayout.shrinkType = MySubviewsShrink_Average; testLayout.subviewHSpace = 10; - testLayout.wrapContentHeight = YES; testLayout.gravity = MyGravity_Center; UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; [button setTitle:@"点我" forState:UIControlStateNormal]; - button.wrapContentSize = YES; + button.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); [testLayout addSubview:button]; UILabel *label1 = [[UILabel alloc] init]; - label1.wrapContentSize = YES; + label1.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); label1.text = @"文本1"; label1.backgroundColor = [UIColor grayColor]; [testLayout addSubview:label1]; UILabel *label2 = [[UILabel alloc] init]; label2.text = @"文本2"; - label2.wrapContentSize = YES; + label2.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); label2.backgroundColor = [UIColor cyanColor]; [testLayout addSubview:label2]; @@ -397,7 +396,7 @@ -(void)testBetweenAndAround //测试布局视图的gravity属性的between和around特性。 MyLinearLayout *layout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 100, 100) orientation:MyOrientation_Vert]; - layout.wrapContentSize = NO; + layout.heightSize.equalTo(nil); //一个子视图下的垂直和水平的差异。 UIView *v1 = [UIView new]; @@ -418,14 +417,12 @@ -(void)testBetweenAndAround layout.orientation = MyOrientation_Vert; layout.gravity = MyGravity_Vert_Around; - layout.wrapContentSize = NO; [layout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(0,35,30,30)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); layout.orientation = MyOrientation_Horz; layout.gravity = MyGravity_Horz_Around; - layout.wrapContentSize = NO; [layout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(35,0,30,30)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); @@ -437,28 +434,24 @@ -(void)testBetweenAndAround layout.orientation = MyOrientation_Vert; layout.gravity = MyGravity_Vert_Between; - layout.wrapContentSize = NO; [layout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,70,30,30)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); layout.orientation = MyOrientation_Horz; layout.gravity = MyGravity_Horz_Between; - layout.wrapContentSize = NO; [layout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(70,0,30,30)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); layout.orientation = MyOrientation_Vert; layout.gravity = MyGravity_Vert_Around; - layout.wrapContentSize = NO; [layout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(0,60,30,30)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); layout.orientation = MyOrientation_Horz; layout.gravity = MyGravity_Horz_Around; - layout.wrapContentSize = NO; [layout layoutIfNeeded]; XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(60,0,30,30)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); @@ -470,14 +463,14 @@ -(void)testFillAndStretch if (1){ MyLinearLayout *rootLayout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 0, 400) orientation:MyOrientation_Vert]; rootLayout.padding = UIEdgeInsetsMake(10, 10, 20, 20); - rootLayout.wrapContentWidth = YES; - rootLayout.wrapContentHeight = NO; + rootLayout.widthSize.equalTo(@(MyLayoutSize.wrap)); + rootLayout.heightSize.equalTo(nil); //视图1宽度依赖父视图,高度设置。 UILabel *v1 = [UILabel new]; v1.text = @"你好"; //iPhone8模拟器 v1.myHorzMargin = 10; - v1.wrapContentHeight = YES; + v1.myHeight = MyLayoutSize.wrap; [rootLayout addSubview:v1]; //视图2宽度定值,右边对齐,高度不设置。 @@ -520,14 +513,14 @@ -(void)testFillAndStretch if (1){ MyLinearLayout *rootLayout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 0, 400) orientation:MyOrientation_Vert]; rootLayout.padding = UIEdgeInsetsMake(10, 10, 20, 20); - rootLayout.wrapContentWidth = YES; - rootLayout.wrapContentHeight = NO; + rootLayout.widthSize.equalTo(@(MyLayoutSize.wrap)); + rootLayout.heightSize.equalTo(nil); //视图1宽度依赖父视图,高度设置。 UILabel *v1 = [UILabel new]; v1.text = @"你好"; //iPhone8模拟器 v1.myHorzMargin = 10; - v1.wrapContentHeight = YES; + v1.myHeight = MyLayoutSize.wrap; [rootLayout addSubview:v1]; //视图2宽度定值,右边对齐,高度不设置。 @@ -571,14 +564,14 @@ -(void)testFillAndStretch if (1){ MyLinearLayout *rootLayout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 400, 0) orientation:MyOrientation_Horz]; rootLayout.padding = UIEdgeInsetsMake(10, 10, 20, 20); - rootLayout.wrapContentWidth = NO; - rootLayout.wrapContentHeight = YES; + rootLayout.widthSize.equalTo(nil); + rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); //视图1高度依赖父视图,宽度设置。 UILabel *v1 = [UILabel new]; v1.text = @"你好"; //iPhone8模拟器 v1.myVertMargin = 10; - v1.wrapContentWidth = YES; + v1.myWidth = MyLayoutSize.wrap; [rootLayout addSubview:v1]; //视图2高度定值,下边对齐,宽度不设置。 @@ -621,14 +614,14 @@ -(void)testFillAndStretch if (1){ MyLinearLayout *rootLayout = [[MyLinearLayout alloc] initWithFrame:CGRectMake(0, 0, 400, 0) orientation:MyOrientation_Horz]; rootLayout.padding = UIEdgeInsetsMake(10, 10, 20, 20); - rootLayout.wrapContentWidth = NO; - rootLayout.wrapContentHeight = YES; + rootLayout.widthSize.equalTo(nil); + rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); //视图1高度依赖父视图,宽度设置。 UILabel *v1 = [UILabel new]; v1.text = @"你好"; //iPhone8模拟器 v1.myVertMargin = 10; - v1.wrapContentWidth = YES; + v1.myWidth = MyLayoutSize.wrap; [rootLayout addSubview:v1]; //视图2高度定值,下边对齐,宽度不设置。 diff --git a/MyLayoutTests/MyNoLayoutSuperviewTestCase.m b/MyLayoutTests/MyNoLayoutSuperviewTestCase.m index 0cdcd70..a4d1ae8 100644 --- a/MyLayoutTests/MyNoLayoutSuperviewTestCase.m +++ b/MyLayoutTests/MyNoLayoutSuperviewTestCase.m @@ -64,8 +64,7 @@ - (void)testExample1 { MyFrameLayout *layout6 = [MyFrameLayout new]; - layout6.wrapContentWidth = YES; - layout6.wrapContentHeight = YES; + layout6.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); layout6.myCenterX = 20; layout6.myBottom = 20; [containerView addSubview:layout6]; diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index ff15ce5..e95eba7 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -57,7 +57,7 @@ - (void)testHidden { MyRelativeLayout *rootLayout = [MyRelativeLayout new]; rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); - rootLayout.wrapContentHeight = YES; + rootLayout.myHeight = MyLayoutSize.wrap; UILabel *shopNameLabel = [UILabel new]; shopNameLabel.topPos.equalTo(rootLayout.topPos).offset(10); @@ -111,7 +111,7 @@ - (void)testHidden { -(void)testWrapContentHeight1 { MyRelativeLayout *rootLayout = [MyRelativeLayout new]; - rootLayout.wrapContentHeight = YES; + rootLayout.myHeight = MyLayoutSize.wrap; rootLayout.bottomPadding = 20; rootLayout.topPadding = 10; rootLayout.leadingPadding = 10; @@ -175,8 +175,7 @@ -(void)testWrapContentHeight1 //125 MyLinearLayout * lineLayout=[[MyLinearLayout alloc]initWithOrientation:MyOrientation_Vert]; - lineLayout.wrapContentHeight=YES; - lineLayout.wrapContentWidth=NO; + lineLayout.myHeight = MyLayoutSize.wrap; lineLayout.topPos.equalTo(orderLabel.bottomPos).offset(5); lineLayout.myLeft=lineLayout.myRight=10; [rootLayout addSubview:lineLayout]; @@ -208,8 +207,8 @@ -(void)testWrapContentHeight1 for (int i = 0; i < 3; i++) { MyLinearLayout *horzLayout=[[MyLinearLayout alloc]initWithOrientation:MyOrientation_Horz]; - horzLayout.wrapContentHeight=YES; - horzLayout.wrapContentWidth=NO; + horzLayout.myHeight = MyLayoutSize.wrap; + horzLayout.widthSize.equalTo(nil); horzLayout.myLeft=horzLayout.myRight=0; UILabel *v1 = [UILabel new]; @@ -291,7 +290,7 @@ -(void)testWrapContentHeight1 -(void)testWrapContentHeight2 { MyRelativeLayout *rootRelativeView = [MyRelativeLayout new]; - rootRelativeView.wrapContentHeight = YES; + rootRelativeView.myHeight = MyLayoutSize.wrap; UIView *verticalLine = [UIView new]; verticalLine.leftPos.equalTo(rootRelativeView.leftPos).offset(16); @@ -314,7 +313,7 @@ -(void)testWrapContentHeight2 [rootRelativeView addSubview:dateLabel]; UILabel *newsTitleLabel = [UILabel new]; - newsTitleLabel.wrapContentHeight = YES; + newsTitleLabel.myHeight = MyLayoutSize.wrap; newsTitleLabel.topPos.equalTo(dateLabel.bottomPos).offset(5); newsTitleLabel.leftPos.equalTo(dateLabel.leftPos); newsTitleLabel.rightPos.equalTo(dateLabel.rightPos); @@ -343,7 +342,7 @@ -(void)testWrapContentHeight2 -(void)testWrapContentHeight3 { MyRelativeLayout * midView = [MyRelativeLayout new]; - midView.wrapContentSize = YES; + midView.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); UILabel * cartypeLabel = [UILabel new]; cartypeLabel.mySize = CGSizeMake(90, 30); @@ -389,8 +388,7 @@ -(void)testWrapContentHeight3 -(void)testWrapContentWidth1 { MyRelativeLayout *rootLayout = [MyRelativeLayout new]; - rootLayout.wrapContentHeight = YES; - rootLayout.wrapContentWidth = YES; + rootLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); rootLayout.bottomPadding = 20; rootLayout.topPadding = 10; rootLayout.leadingPadding = 10; @@ -481,7 +479,7 @@ -(void)testWrapContentWidth2 MyRelativeLayout *rootLayout = [MyRelativeLayout new]; - rootLayout.wrapContentWidth = YES; + rootLayout.myWidth = MyLayoutSize.wrap; //随机生成N个数字保存到数组里面。 @@ -674,13 +672,13 @@ -(void)testDemo1 MyRelativeLayout* relative = [MyRelativeLayout new]; // relative.widthSize.equalTo(self.contentView.widthSize); - relative.wrapContentHeight = YES; + relative.myHeight = MyLayoutSize.wrap; _layoutRoot = relative; // 头像区域 MyLinearLayout* linear = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - linear.wrapContentSize = YES; + linear.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); linear.padding = UIEdgeInsetsMake(12, 15, 12, 15); linear.myLeading = 0.0f; [_layoutRoot addSubview:linear]; @@ -716,15 +714,14 @@ -(void)testDemo1 lbl.font = [UIFont systemFontOfSize:12]; [lbl setMinimumScaleFactor:10.0f]; [lbl setTextColor:[UIColor greenColor]]; - lbl.wrapContentSize = YES; - lbl.widthSize.equalTo(lbl.widthSize).uBound(_layoutAccessory.widthSize,-2,1); + lbl.heightSize.equalTo(@(MyLayoutSize.wrap)); + lbl.widthSize.equalTo(@(MyLayoutSize.wrap)).uBound(_layoutAccessory.widthSize,-2,1); [lbl setNumberOfLines:1]; [_layoutAccessory addSubview:lbl]; // 附加区域底部 linear = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; linear.gravity = MyGravity_Vert_Center|MyGravity_Horz_Right; - linear.wrapContentHeight = NO; linear.widthSize.equalTo(_layoutAccessory.widthSize); linear.myHeight = 20.0f; linear.subviewHSpace = 4.0f; @@ -763,8 +760,6 @@ -(void)testDemo1 // 中间区域 linear = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - linear.wrapContentWidth = NO; - linear.wrapContentHeight = YES; linear.myVertMargin = 0.0f; linear.heightSize.min(67.0f); linear.leadingPos.equalTo(_layoutPortrait.trailingPos); @@ -777,7 +772,7 @@ -(void)testDemo1 // 标题区域 relative = [MyRelativeLayout new]; relative.widthSize.equalTo(_layoutContent.widthSize); - relative.wrapContentHeight = YES; + relative.myHeight = MyLayoutSize.wrap; [_layoutContent addSubview:relative]; MyRelativeLayout * _layoutTitle = relative; @@ -785,7 +780,7 @@ -(void)testDemo1 lbl = [UILabel new]; lbl.text = @"asdfklajdf爱的色放就爱"; lbl.myLeading = 0.0f; - lbl.wrapContentSize = YES; + lbl.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); [lbl setFont:[UIFont systemFontOfSize:17]]; [lbl setTextColor:[UIColor greenColor]]; lbl.numberOfLines = 1; @@ -811,7 +806,7 @@ -(void)testDemo1 // 摘要 linear = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; linear.widthSize.equalTo(_layoutContent.widthSize); - linear.wrapContentHeight = YES; + linear.myHeight = MyLayoutSize.wrap; linear.subviewHSpace = 2.0f; [_layoutContent addSubview:linear]; MyLinearLayout *_layoutSummary = linear; @@ -819,7 +814,7 @@ -(void)testDemo1 // 发送状态(例如:发送中,发送失败) imgv = [UIImageView new]; [imgv setContentMode:UIViewContentModeScaleAspectFit]; - imgv.wrapContentSize = YES; + imgv.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); [imgv setHidden:YES]; [_layoutSummary addSubview:imgv]; @@ -827,7 +822,7 @@ -(void)testDemo1 lbl = [UILabel new]; [lbl setTextAlignment:NSTextAlignmentCenter]; [lbl setFont:[UIFont systemFontOfSize:12]]; - lbl.wrapContentSize = YES; + lbl.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); [lbl setNumberOfLines:1]; [lbl setHidden:YES]; [_layoutSummary addSubview:lbl]; @@ -835,7 +830,7 @@ -(void)testDemo1 // 状态(包括:未读,已读,草稿,有人@) lbl = [UILabel new]; [lbl setFont:[UIFont systemFontOfSize:12]]; - lbl.wrapContentSize = YES; + lbl.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); [lbl setNumberOfLines:1]; [lbl setHidden:YES]; [_layoutSummary addSubview:lbl]; @@ -844,7 +839,7 @@ -(void)testDemo1 lbl = [UILabel new]; [lbl setFont:[UIFont systemFontOfSize:12]]; lbl.weight = 1.0f; - lbl.wrapContentSize = YES; + lbl.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); [lbl setNumberOfLines:1]; [_layoutSummary addSubview:lbl]; @@ -915,10 +910,9 @@ -(void)testhideandubound zoneBtn.heightSize.equalTo(zoneBtn.heightSize).add(3); nameLab.myCenterY = 0; - nameLab.wrapContentSize = YES; + nameLab.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); nameLab.leftPos.lBound(zoneBtn.rightPos, 15); nameLab.rightPos.uBound(placeholderBtn.leftPos, 15); - nameLab.heightSize.equalTo(nameLab.heightSize); nameLab.text = @"这是阿斯蒂芬阿道夫阿斯蒂芬安防安防阿斯蒂芬安防大师傅阿斯蒂芬阿斯蒂芬安防"; placeholderBtn.myCenterY = 0; @@ -987,9 +981,8 @@ -(void)testMaxHeightAndWidth [rellayout addSubview:label]; label.myLeft = 10; - label.wrapContentWidth = YES; - label.widthSize.max(100); - label.wrapContentHeight = YES; + label.widthSize.equalTo(@(MyLayoutSize.wrap)).max(100); + label.heightSize.equalTo(@(MyLayoutSize.wrap)); vv.topPos.equalTo(label.topPos); @@ -1030,46 +1023,13 @@ -(void)test123 label.text = @"您好!!!"; label.backgroundColor = [UIColor redColor]; label.widthSize.equalTo(@[@(MyLayoutSize.wrap), v1.widthSize.clone(0, 0.5)].myMaxSize); - label.wrapContentHeight = YES; + label.heightSize.equalTo(@(MyLayoutSize.wrap)); [rootLayout addSubview:label]; } -(void)testMaxAndMin { -// MyRelativeLayout *rootLayout = [MyRelativeLayout new]; -// rootLayout.wrapContentWidth = YES; -// rootLayout.myVertMargin = 0; -// rootLayout.backgroundColor = [UIColor redColor]; -// [self.view addSubview:rootLayout]; -// rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); -// rootLayout.topPadding = MyLayoutPos.safeAreaMargin + 100; -// -// -// UILabel *l1 = [UILabel new]; -// l1.text = @"您好"; -// l1.backgroundColor = [UIColor blueColor]; -// l1.wrapContentSize = YES; -// [rootLayout addSubview:l1]; -// -// UILabel *l3 = [UILabel new]; -// l3.text = @"ak"; -// l3.wrapContentSize = YES; -// l3.topPos.equalTo(l1.bottomPos).offset(10); -// l3.leftPos.equalTo(l1.leftPos); -// l3.backgroundColor = [UIColor greenColor]; -// [rootLayout addSubview:l3]; -// -// UILabel *l2 = [UILabel new]; -// l2.text = @"2019-04-03"; -// [l2 sizeToFit]; -// [rootLayout addSubview:l2]; -// l2.topPos.equalTo(l1.topPos); -// l2.rightPos.equalTo(l3.rightPos); -// l2.rightPos.min(-1 *(l2.frame.size.width + 30 + 50)); -// - - } -(void)testExample1 From c9ac36dd52d2b98ad7ebc4e7415834c50c32d7fe Mon Sep 17 00:00:00 2001 From: youngsoft Date: Wed, 9 Oct 2019 09:23:04 +0800 Subject: [PATCH 050/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlowLayout.m | 14 +++ MyLayout/Lib/MyLayoutSizeClass.h | 1 + MyLayout/Lib/MyLayoutSizeClass.m | 4 +- .../Base.lproj/FLLTest2ViewController.xib | 86 ++++++++++++------- MyLayoutDemo/FLLTest2ViewController.m | 52 +++++------ .../zh-Hans.lproj/FLLTest2ViewController.xib | 74 +++++++++++----- 6 files changed, 152 insertions(+), 79 deletions(-) diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index ea051a9..1cc022f 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -120,6 +120,20 @@ -(MyGravity)arrangedGravity return self.myCurrentSizeClass.arrangedGravity; } +-(BOOL)gravityAlways +{ + return self.myCurrentSizeClass.gravityAlways; +} + +-(void)setGravityAlways:(BOOL)gravityAlways +{ + MyFlowLayout *lsc = self.myCurrentSizeClass; + if (lsc.gravityAlways != gravityAlways) + { + lsc.gravityAlways = gravityAlways; + [self setNeedsLayout]; + } +} -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace { diff --git a/MyLayout/Lib/MyLayoutSizeClass.h b/MyLayout/Lib/MyLayoutSizeClass.h index c6e479f..1399a11 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.h +++ b/MyLayout/Lib/MyLayoutSizeClass.h @@ -161,6 +161,7 @@ @property(nonatomic,assign) MyGravity arrangedGravity; @property(nonatomic,assign) BOOL autoArrange; +@property(nonatomic,assign) BOOL gravityAlways; @property(nonatomic,assign) NSInteger arrangedCount; @property(nonatomic, assign) NSInteger pagedCount; diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index ba27481..bfe459b 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -870,6 +870,7 @@ - (id)copyWithZone:(NSZone *)zone lsc.arrangedCount = self.arrangedCount; lsc.autoArrange = self.autoArrange; + lsc.gravityAlways = self.gravityAlways; lsc.arrangedGravity = self.arrangedGravity; lsc.subviewSize = self.subviewSize; lsc.minSpace = self.minSpace; @@ -884,10 +885,11 @@ -(NSString*)debugDescription { NSString *dbgDesc = [super debugDescription]; - dbgDesc = [NSString stringWithFormat:@"%@\nFlowLayout: \narrangedCount=%ld\nautoArrange=%@\narrangedGravity=%hu\npagedCount=%ld", + dbgDesc = [NSString stringWithFormat:@"%@\nFlowLayout: \narrangedCount=%ld\nautoArrange=%@\ngravityAlways=%@\narrangedGravity=%hu\npagedCount=%ld", dbgDesc, (long)self.arrangedCount, self.autoArrange ? @"YES":@"NO", + self.gravityAlways? @"YES":@"NO", self.arrangedGravity, (long)self.pagedCount ]; diff --git a/MyLayoutDemo/Base.lproj/FLLTest2ViewController.xib b/MyLayoutDemo/Base.lproj/FLLTest2ViewController.xib index 66cdec6..b76b467 100644 --- a/MyLayoutDemo/Base.lproj/FLLTest2ViewController.xib +++ b/MyLayoutDemo/Base.lproj/FLLTest2ViewController.xib @@ -1,9 +1,12 @@ - - + + + + + - - + + @@ -15,11 +18,11 @@ - + - + @@ -51,7 +54,7 @@ - + @@ -62,66 +65,96 @@ - - + + - - + - + + + + + + + - + @@ -142,9 +175,9 @@ - + - + @@ -167,19 +200,14 @@ - + - + - - - - - diff --git a/MyLayoutDemo/FLLTest2ViewController.m b/MyLayoutDemo/FLLTest2ViewController.m index c6e8e84..b8d4690 100644 --- a/MyLayoutDemo/FLLTest2ViewController.m +++ b/MyLayoutDemo/FLLTest2ViewController.m @@ -34,9 +34,6 @@ - (void)viewDidLoad { [self createTagButton:NSLocalizedString(@"click to remove tag", @"")]; [self createTagButton:NSLocalizedString(@"tag2", @"")]; [self createTagButton:NSLocalizedString(@"MyLayout can used in XIB&SB", @"")]; - - UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"gravity\nalways" style:UIBarButtonItemStylePlain target:self action:@selector(handleChangeGravityAlways:)]; - self.navigationItem.rightBarButtonItem = item; } - (void)didReceiveMemoryWarning { @@ -75,12 +72,28 @@ -(void)createTagButton:(NSString*)text #pragma mark -- Handle Method --(IBAction)handleChangeGravityAlways:(id)sender -{ - self.flowLayout.gravityAlways = !self.flowLayout.gravityAlways; +- (IBAction)handleAddTag:(id)sender { + + if (self.tagTextField.text.length == 0) + return; + + [self createTagButton:self.tagTextField.text]; + + self.tagTextField.text = @""; + + [self.flowLayout layoutAnimationWithDuration:0.2]; + +} + +- (IBAction)handleDelTag:(UIButton*)sender { + + [sender removeFromSuperview]; + + [self.flowLayout layoutAnimationWithDuration:0.2]; } -- (IBAction)handleShrinkMargin:(UISwitch *)sender { + +- (IBAction)handleAdjustSpaceChange:(UISwitch *)sender { //间距拉伸 if (sender.isOn) @@ -91,7 +104,7 @@ - (IBAction)handleShrinkMargin:(UISwitch *)sender { [self.flowLayout layoutAnimationWithDuration:0.2]; } -- (IBAction)handleShrinkContent:(UISwitch *)sender { +- (IBAction)handleAdjustSizeChange:(UISwitch *)sender { //内容拉伸 if (sender.isOn) @@ -103,7 +116,7 @@ - (IBAction)handleShrinkContent:(UISwitch *)sender { } -- (IBAction)handleShrinkAuto:(UISwitch *)sender { +- (IBAction)handleAutoArrangeChange:(UISwitch *)sender { //自动调整位置。 if (sender.isOn) @@ -115,25 +128,12 @@ - (IBAction)handleShrinkAuto:(UISwitch *)sender { } -- (IBAction)handleAddTag:(id)sender { - - if (self.tagTextField.text.length == 0) - return; - - [self createTagButton:self.tagTextField.text]; - - self.tagTextField.text = @""; - - [self.flowLayout layoutAnimationWithDuration:0.2]; - +-(IBAction)handleGravityAlwaysChange:(id)sender +{ + self.flowLayout.gravityAlways = !self.flowLayout.gravityAlways; } -- (IBAction)handleDelTag:(UIButton*)sender { - - [sender removeFromSuperview]; - - [self.flowLayout layoutAnimationWithDuration:0.2]; -} + @end diff --git a/MyLayoutDemo/zh-Hans.lproj/FLLTest2ViewController.xib b/MyLayoutDemo/zh-Hans.lproj/FLLTest2ViewController.xib index b7f4a63..21f83b9 100644 --- a/MyLayoutDemo/zh-Hans.lproj/FLLTest2ViewController.xib +++ b/MyLayoutDemo/zh-Hans.lproj/FLLTest2ViewController.xib @@ -1,9 +1,12 @@ - - + + + + + - - + + @@ -15,11 +18,11 @@ - + - + @@ -51,7 +54,7 @@ - + @@ -62,7 +65,7 @@ - + @@ -77,7 +80,7 @@ - + - + - + + + + + + + + + - + - + + + + + + + - + @@ -142,9 +175,9 @@ - + - + @@ -167,19 +200,14 @@ - + - + - - - - - From 7942c3bef93ab0a0e92d6398f78e2ac4f2154492 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Wed, 9 Oct 2019 17:56:24 +0800 Subject: [PATCH 051/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout.xcodeproj/project.pbxproj | 20 +++++++++++++------ MyLayout/Lib/MyFlexLayout.h | 8 +++++++- MyLayout/Lib/MyFlowLayout.h | 2 +- MyLayout/Lib/MyGridLayout.m | 4 ++-- MyLayoutDemo/FLLTest4ViewController.m | 20 ++++++++++++++++--- ...wController.h => FLXTest1ViewController.h} | 6 +++--- ...wController.m => FLXTest1ViewController.m} | 14 ++++++++----- MyLayoutDemo/ViewController.m | 14 ++++++++----- 8 files changed, 62 insertions(+), 26 deletions(-) rename MyLayoutDemo/{FLLTest9ViewController.h => FLXTest1ViewController.h} (58%) rename MyLayoutDemo/{FLLTest9ViewController.m => FLXTest1ViewController.m} (97%) diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index 87a1a25..d45c2c0 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -166,7 +166,7 @@ 20A45EC52318FCA50026A18C /* MyFlexLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DF42402318F4EA0078CAA0 /* MyFlexLayout.m */; }; 20B46A8D1F8A79C300826372 /* layoutdemo8.gif in Resources */ = {isa = PBXBuildFile; fileRef = 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */; }; 20DCF333208C3BFB007A879B /* FOLTest7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */; }; - 20DF423E2318A6000078CAA0 /* FLLTest9ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DF423D2318A6000078CAA0 /* FLLTest9ViewController.m */; }; + 20DF423E2318A6000078CAA0 /* FLXTest1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DF423D2318A6000078CAA0 /* FLXTest1ViewController.m */; }; 20DF42412318F4EA0078CAA0 /* MyFlexLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 20DF423F2318F4EA0078CAA0 /* MyFlexLayout.h */; }; 20DF42422318F4EA0078CAA0 /* MyFlexLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DF42402318F4EA0078CAA0 /* MyFlexLayout.m */; }; 20F0DFFD2111749A00CFCE8C /* AllTest11ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F0DFFC2111749A00CFCE8C /* AllTest11ViewController.m */; }; @@ -417,8 +417,8 @@ 20B46A8C1F8A79C300826372 /* layoutdemo8.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = layoutdemo8.gif; sourceTree = ""; }; 20DCF331208C3BEF007A879B /* FOLTest7ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FOLTest7ViewController.h; sourceTree = ""; }; 20DCF332208C3BFB007A879B /* FOLTest7ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FOLTest7ViewController.m; sourceTree = ""; }; - 20DF423C2318A5EE0078CAA0 /* FLLTest9ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest9ViewController.h; sourceTree = ""; }; - 20DF423D2318A6000078CAA0 /* FLLTest9ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest9ViewController.m; sourceTree = ""; }; + 20DF423C2318A5EE0078CAA0 /* FLXTest1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXTest1ViewController.h; sourceTree = ""; }; + 20DF423D2318A6000078CAA0 /* FLXTest1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXTest1ViewController.m; sourceTree = ""; }; 20DF423F2318F4EA0078CAA0 /* MyFlexLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyFlexLayout.h; sourceTree = ""; }; 20DF42402318F4EA0078CAA0 /* MyFlexLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyFlexLayout.m; sourceTree = ""; }; 20F0DFFB2111749A00CFCE8C /* AllTest11ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AllTest11ViewController.h; sourceTree = ""; }; @@ -536,6 +536,7 @@ 18D3C8FC1EDF053000D3DE43 /* RelativeLayoutDemo */, 18D3C9001EDF056900D3DE43 /* TableLayoutDemo */, 18D3C8FD1EDF053D00D3DE43 /* FlowLayoutDemo */, + 20BA39E0234DD6BF003F22D2 /* FlexLayoutDemo */, 18D3C8FF1EDF055C00D3DE43 /* FloatLayoutDemo */, 205CFA8B1F49BCAF00355489 /* GridLayoutDemo */, 18D3C8FE1EDF055000D3DE43 /* PathLayoutDemo */, @@ -615,8 +616,6 @@ 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */, 20F0DFFE21120A8D00CFCE8C /* FLLTest8ViewController.h */, 20F0DFFF21120A8D00CFCE8C /* FLLTest8ViewController.m */, - 20DF423C2318A5EE0078CAA0 /* FLLTest9ViewController.h */, - 20DF423D2318A6000078CAA0 /* FLLTest9ViewController.m */, ); name = FlowLayoutDemo; sourceTree = ""; @@ -899,6 +898,15 @@ name = GridLayoutDemo; sourceTree = ""; }; + 20BA39E0234DD6BF003F22D2 /* FlexLayoutDemo */ = { + isa = PBXGroup; + children = ( + 20DF423C2318A5EE0078CAA0 /* FLXTest1ViewController.h */, + 20DF423D2318A6000078CAA0 /* FLXTest1ViewController.m */, + ); + name = FlexLayoutDemo; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -1184,7 +1192,7 @@ 18D3C95E1EDF07F800D3DE43 /* FOLTest5ViewController.m in Sources */, 18D3C99C1EDF09BE00D3DE43 /* CFTool.m in Sources */, 18D3C9141EDF074900D3DE43 /* LLTest4ViewController.m in Sources */, - 20DF423E2318A6000078CAA0 /* FLLTest9ViewController.m in Sources */, + 20DF423E2318A6000078CAA0 /* FLXTest1ViewController.m in Sources */, 18D3C9931EDF08F800D3DE43 /* ViewController.m in Sources */, 18D3C93B1EDF07C000D3DE43 /* FLLTest3ViewController.m in Sources */, 205643181F55A16400E8BDDE /* MyLayoutMath.m in Sources */, diff --git a/MyLayout/Lib/MyFlexLayout.h b/MyLayout/Lib/MyFlexLayout.h index 66ed488..d511cc6 100644 --- a/MyLayout/Lib/MyFlexLayout.h +++ b/MyLayout/Lib/MyFlexLayout.h @@ -19,6 +19,7 @@ -(MyFlexItem* (^)(CGFloat))flex_basis; -(MyFlexItem* (^)(int))align_self; +//设置具体的宽度值,当宽度值大于0小于1是表明的是相对宽度,你也可以设置MyLayoutSize.wrap和MyLayoutSize.fill来设置特殊宽度。 -(MyFlexItem* (^)(CGFloat))width; -(MyFlexItem* (^)(CGFloat))height; -(MyFlexItem* (^)(CGFloat))margin_top; @@ -79,11 +80,16 @@ @interface UIView(MyFlexLayout) +//我们可以借助视图的flexItem来设置当视图在flexbox中的一些属性。 @property(nonatomic, readonly, strong) MyFlexItem *flexItem; @end -//row必须指定宽度如果没有则是和父视图等宽,如果没有指定高度则高度自适应。column则反之。 + +/* + * FlexLayout布局是为了兼容flexbox语法而建立了一个布局,它是从MyFlowLayout派生。在MyFlowLayout中也是支持类似flexbox的一些特性的 + * 但是它的属性和flexbox不兼容和一致,因此提供一个新的类MyFlexLayout来完全支持flexbox. + */ @interface MyFlexLayout:MyFlowLayout @property(nonatomic, readonly, strong, readonly) MyFlex *flex; diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index 158710a..0657412 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -228,7 +228,7 @@ /** 单独为某一行或者一列定制gravity停靠对齐属性,默认情况下布局视图的gravity作用于所有行或者列的停靠对齐。如果你想单独定制某一行或者某一列的停靠对齐方式时 可以通过设置这个block属性。lineGravity的入参是布局对象和当前行列的索引值,索引值以0开始,返回的是此行的停靠对齐方式,如果返回MyGravity_None则表示使用 - 布局默认的gravity停靠对齐属性。 + 布局默认的gravity停靠对齐属性。如果您的gravity属性设置的是Fill的话则有可能通过这个进行定制化会出现一些异常。 */ @property(nonatomic, copy) MyGravity (^lineGravity)(MyFlowLayout *layout, NSInteger lineIndex); diff --git a/MyLayout/Lib/MyGridLayout.m b/MyLayout/Lib/MyGridLayout.m index 1876b4f..933a8d2 100644 --- a/MyLayout/Lib/MyGridLayout.m +++ b/MyLayout/Lib/MyGridLayout.m @@ -1298,8 +1298,8 @@ -(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; sbvmyFrame.frame = sbv.bounds; - //如果子视图不设置任何约束但是又是包裹的则这里特殊处理。 - if (sbvsc.widthSizeInner == nil && sbvsc.heightSizeInner == nil && !sbvsc.wrapContentSize) + //如果子视图不设置任何约束要进行特殊处理。 + if (sbvsc.widthSizeInner.dimeVal == nil && sbvsc.heightSizeInner.dimeVal == nil) { CGSize size = CGSizeZero; if (grid.superGrid.subGridsType == MySubGridsType_Row) diff --git a/MyLayoutDemo/FLLTest4ViewController.m b/MyLayoutDemo/FLLTest4ViewController.m index 5f7f409..4632e27 100644 --- a/MyLayoutDemo/FLLTest4ViewController.m +++ b/MyLayoutDemo/FLLTest4ViewController.m @@ -21,7 +21,7 @@ @implementation FLLTest4ViewController -(void)loadView { /* - 这个例子主要展示流式布局对子视图weight属性的支持。对于垂直流式布局来说,子视图的weight值用来指定子视图的宽度在当前行剩余空间所占用的比例值,比如某个流式布局的宽度是100,而每行的数量为2个,且假如第一个子视图的宽度为20,则如果第二个子视图的weight设置为1的话则第二个子视图的真实宽度 = (100-20)*1 = 80。而假如第二个子视图的weight设置为0.5的话则第二个子视图的真实宽度 = (100 - 20) * 0.5 = 40。 + 这个例子主要展示流式布局对子视图weight属性的支持以及对特定行进行对齐停靠的定制支持。对于垂直流式布局来说,子视图的weight值用来指定子视图的宽度在当前行剩余空间所占用的比例值,比如某个流式布局的宽度是100,而每行的数量为2个,且假如第一个子视图的宽度为20,则如果第二个子视图的weight设置为1的话则第二个子视图的真实宽度 = (100-20)*1 = 80。而假如第二个子视图的weight设置为0.5的话则第二个子视图的真实宽度 = (100 - 20) * 0.5 = 40。 对于水平流式布局来说weight值用来指定一列内的剩余高度的比重值。 通过对子视图weight值的合理使用,可以很方便的替换掉需要用线性布局来实现的嵌套布局的能力。 @@ -129,7 +129,6 @@ -(void)createFlowLayout1:(MyLinearLayout*)rootLayout //the fourth line: forgot password. UIView *placeholderView2 = [UIView new]; //因为流式布局这里面每行两列,所以这里建立一个宽高为0的占位视图。我们可以在流式布局中通过使用占位视图来充满行的数量。 - placeholderView2.weight = 1; [flowLayout addSubview:placeholderView2]; UIButton *forgetPasswordButton = [UIButton buttonWithType:UIButtonTypeSystem]; @@ -143,7 +142,6 @@ -(void)createFlowLayout1:(MyLinearLayout*)rootLayout rememberLabel.text = @"Remember me:"; rememberLabel.textColor = [CFTool color:4]; rememberLabel.font = [CFTool font:15]; - rememberLabel.weight = 1; rememberLabel.alignment = MyGravity_Vert_Bottom; //流式布局通过arrangedGravity设置每行的对齐方式,如果某个子视图不想使用默认的对齐方式则可以通过alignment属性来单独设置对齐方式,这个例子中所有都是居中对齐,但是这个标题则是底部对齐。 [rememberLabel sizeToFit]; [flowLayout addSubview:rememberLabel]; @@ -167,6 +165,22 @@ -(void)createFlowLayout1:(MyLinearLayout*)rootLayout //第六行因为最后只有一个按钮,所以这里不需要建立占位视图。 + //我们可以通过lineGravity属性来实现为每一行进行不同的对齐方式定制,如果返回MyGravity_None则表示用gravity属性设置的对齐方式来进行处理。 + flowLayout.lineGravity = ^MyGravity(MyFlowLayout *layout, NSInteger lineIndex) { + + switch (lineIndex) { + case 3: + return MyGravity_Horz_Right; //第3行右对齐 + break; + case 4: + return MyGravity_Horz_Between; //第4行水平间距拉伸。 + break; + default: + return MyGravity_None; //其他行按gravity属性所指定的停靠对齐方式 + break; + } + }; + } diff --git a/MyLayoutDemo/FLLTest9ViewController.h b/MyLayoutDemo/FLXTest1ViewController.h similarity index 58% rename from MyLayoutDemo/FLLTest9ViewController.h rename to MyLayoutDemo/FLXTest1ViewController.h index 41ae62c..c5bc616 100644 --- a/MyLayoutDemo/FLLTest9ViewController.h +++ b/MyLayoutDemo/FLXTest1ViewController.h @@ -1,5 +1,5 @@ // -// FLLTest9ViewController.h +// FLXTest1ViewController.h // MyLayoutDemo // // Created by oubaiquan on 2018/8/1. @@ -8,7 +8,7 @@ #import -/*9.FlexLayout - flex box*/ -@interface FLLTest9ViewController : UIViewController +/*1.FlexLayout - flex box*/ +@interface FLXTest1ViewController : UIViewController @end diff --git a/MyLayoutDemo/FLLTest9ViewController.m b/MyLayoutDemo/FLXTest1ViewController.m similarity index 97% rename from MyLayoutDemo/FLLTest9ViewController.m rename to MyLayoutDemo/FLXTest1ViewController.m index b30ffc1..9a2b772 100644 --- a/MyLayoutDemo/FLLTest9ViewController.m +++ b/MyLayoutDemo/FLXTest1ViewController.m @@ -1,23 +1,23 @@ // -// FLLTest9ViewController.m +// FLXTest1ViewController.m // MyLayoutDemo // // Created by oubaiquan on 2018/8/1. // Copyright © 2018年 YoungSoft. All rights reserved. // -#import "FLLTest9ViewController.h" +#import "FLXTest1ViewController.h" #import "MyLayout.h" #import "CFTool.h" -@interface FLLTest9ViewController () +@interface FLXTest1ViewController () -(UIButton*)createActionButton:(NSString*)title action:(SEL)action; @end -@implementation FLLTest9ViewController +@implementation FLXTest1ViewController //创建动作操作按钮。 -(UIButton*)createActionButton:(NSString*)title action:(SEL)action @@ -26,7 +26,6 @@ -(UIButton*)createActionButton:(NSString*)title action:(SEL)action [button setTitle:title forState:UIControlStateNormal]; button.titleLabel.font = [CFTool font:14]; [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside]; - button.myHeight = 30; button.layer.borderColor = [UIColor lightGrayColor].CGColor; button.layer.borderWidth = 0.5; @@ -58,22 +57,27 @@ -(void)loadView [self createActionButton:NSLocalizedString(@"flex-direction", @"") action:@selector(handleFlex_Direction:)].flexItem .width(1/3.0) + .height(30) .addTo(actionLayout); [self createActionButton:NSLocalizedString(@"flex-wrap", @"") action:@selector(handleFlex_Wrap:)].flexItem .width(1/3.0) + .height(30) .addTo(actionLayout); [self createActionButton:NSLocalizedString(@"justify-content", @"") action:@selector(handleJustify_Content:)].flexItem .width(1/3.0) + .height(30) .addTo(actionLayout); [self createActionButton:NSLocalizedString(@"align-items", @"") action:@selector(handleAlign_Items:)].flexItem .width(1/3.0) + .height(30) .addTo(actionLayout); [self createActionButton:NSLocalizedString(@"align-content", @"") action:@selector(handleAlign_Content:)].flexItem .width(1/3.0) + .height(30) .addTo(actionLayout); diff --git a/MyLayoutDemo/ViewController.m b/MyLayoutDemo/ViewController.m index 682c986..5f85902 100644 --- a/MyLayoutDemo/ViewController.m +++ b/MyLayoutDemo/ViewController.m @@ -43,7 +43,8 @@ #import "FLLTest6ViewController.h" #import "FLLTest7ViewController.h" #import "FLLTest8ViewController.h" -#import "FLLTest9ViewController.h" + +#import "FLXTest1ViewController.h" #import "AllTest1ViewController.h" @@ -198,13 +199,16 @@ -(NSArray*)demoTypeList }, @{@"title":NSLocalizedString(@"8.FlowLayout - Flex space", @""), @"class":[FLLTest8ViewController class] - }, - @{@"title":NSLocalizedString(@"9.FlowLayout - Flexbox", @""), - @"class":[FLLTest9ViewController class] } ] }, - + @{@"type_title":@"Flex布局(FlexLayout)", + @"type_desc":@"fll.png", + @"type_vclist":@[@{@"title":NSLocalizedString(@"1.FlexLayout - Flexlayout", @""), + @"class":[FLXTest1ViewController class] + } + ] + }, @{@"type_title":@"浮动布局(FloatLayout)", @"type_desc":@"flo.png", @"type_vclist":@[@{@"title":NSLocalizedString(@"1.FloatLayout - Float", @""), From b476985070c55cdcfa01332ffc8298cc78c4cd38 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Fri, 11 Oct 2019 11:38:24 +0800 Subject: [PATCH 052/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 21 +++++ MyLayout/Lib/MyFlexLayout.h | 70 +++++++++++----- MyLayout/Lib/MyFlexLayout.m | 115 ++++++++++++++------------ MyLayout/Lib/MyFlowLayout.h | 12 ++- MyLayout/Lib/MyFlowLayout.m | 18 ++-- MyLayout/Lib/MyLayoutSizeClass.h | 2 +- MyLayout/Lib/MyLayoutSizeClass.m | 6 +- MyLayoutDemo/FLLTest1ViewController.m | 17 ++++ MyLayoutDemo/FLLTest2ViewController.m | 2 +- MyLayoutDemo/FLXTest1ViewController.m | 6 ++ 10 files changed, 179 insertions(+), 90 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27f1b77..6bcf479 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,27 @@ # 版本变更日志 **MyLayout**的所有版本的变更日志都将会在这里记录. +1.添加新的布局MyFlexbox +2.添加新的停靠和对齐属性Around, Stretch +3.添加和抽象对拖动的支持。 +4.添加对iOS13的黑白模式的支持。 +5.流式布局添加单独设置行内停靠对齐的支持。 +6.流式布局添加让所有行都受到对齐停靠影响的属性。 +7.添加对最值约束的设置。 +8.添加对视图尺寸和位置进行压缩的设置。 +9.流式布局和浮动布局增加对基线对齐的支持。 +10.浮动布局添加对尺寸自适应的支持。 + +修改: +1.修改对wrapConentSize的支持。 +2. + +BUG修复: +1.修复在使用sizeclass时对位置对象进行克隆的一个BUG。导致无法。。。 +2.修复相对布局下的一个尺寸自适应计算的一个BUG。 + + + --- ## [V1.8.0](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.8.0)(2019/06/25) diff --git a/MyLayout/Lib/MyFlexLayout.h b/MyLayout/Lib/MyFlexLayout.h index d511cc6..0e4353b 100644 --- a/MyLayout/Lib/MyFlexLayout.h +++ b/MyLayout/Lib/MyFlexLayout.h @@ -8,24 +8,40 @@ #import "MyFlowLayout.h" +//定义flex的方向类型。 +typedef int MyFlexDirection; +//定义flex的换行类型。 +typedef int MyFlexWrap; +//定义flex的停靠对齐类型。 +typedef int MyFlexGravity; + @interface MyFlexItem:NSObject -+(CGFloat)auto; +//因为auto是C语言关键字不能直接使用,所以这里加一个_前缀。 +@property(class, readonly, assign) CGFloat _auto; + +//条目的顺序设置 -(MyFlexItem* (^)(NSInteger))order; +//条目的尺寸比重设置,默认为0表示不按比重 -(MyFlexItem* (^)(CGFloat))flex_grow; +//条目的压缩比重设置,默认为1,表示当会进行压缩 -(MyFlexItem* (^)(CGFloat))flex_shrink; +//条目的尺寸设置,可以设置为_auto,固定值,相对值。你可以使用这个属性也可以通过width/height来设置。 -(MyFlexItem* (^)(CGFloat))flex_basis; --(MyFlexItem* (^)(int))align_self; +//行内条目自身的对齐方式。 +-(MyFlexItem* (^)(MyFlexGravity))align_self; //设置具体的宽度值,当宽度值大于0小于1是表明的是相对宽度,你也可以设置MyLayoutSize.wrap和MyLayoutSize.fill来设置特殊宽度。 -(MyFlexItem* (^)(CGFloat))width; -(MyFlexItem* (^)(CGFloat))height; +//条目的外间距设置。 -(MyFlexItem* (^)(CGFloat))margin_top; -(MyFlexItem* (^)(CGFloat))margin_bottom; -(MyFlexItem* (^)(CGFloat))margin_left; -(MyFlexItem* (^)(CGFloat))margin_right; +-(MyFlexItem* (^)(CGFloat))margin; -(__kindof UIView* (^)(UIView*))addTo; @@ -38,37 +54,49 @@ @interface MyFlex:MyFlexItem -+(int)row; -+(int)row_reverse; -+(int)column; -+(int)column_reverse; +//方向枚举 +@property(class, readonly, assign) MyFlexDirection row; +@property(class, readonly, assign) MyFlexDirection row_reverse; +@property(class, readonly, assign) MyFlexDirection column; +@property(class, readonly, assign) MyFlexDirection column_reverse; + +//换行枚举 +@property(class, readonly, assign) MyFlexWrap nowrap; +@property(class, readonly, assign) MyFlexWrap wrap; +@property(class, readonly, assign) MyFlexWrap wrap_reverse; -+(int)nowrap; -+(int)wrap; -+(int)wrap_reverse; +//停靠对齐枚举 +@property(class, readonly, assign) MyFlexGravity flex_start; +@property(class, readonly, assign) MyFlexGravity flex_end; +@property(class, readonly, assign) MyFlexGravity center; +@property(class, readonly, assign) MyFlexGravity space_between; +@property(class, readonly, assign) MyFlexGravity sapce_around; +@property(class, readonly, assign) MyFlexGravity baseline; +@property(class, readonly, assign) MyFlexGravity stretch; -+(int)flex_start; -+(int)flex_end; -+(int)center; -+(int)space_between; -+(int)sapce_around; -+(int)baseline; -+(int)stretch; --(MyFlex* (^)(int))flex_direction; +//方向设置 +-(MyFlex* (^)(MyFlexDirection))flex_direction; --(MyFlex* (^)(int))flex_wrap; +//换行设置 +-(MyFlex* (^)(MyFlexWrap))flex_wrap; +//通过 | 运算来结合 wrap 和direction -(MyFlex* (^)(int))flex_flow; --(MyFlex* (^)(int))justify_content; +//行的停靠设置 +-(MyFlex* (^)(MyFlexGravity))justify_content; --(MyFlex* (^)(int))align_items; +//行内条目的对齐设置 +-(MyFlex* (^)(MyFlexGravity))align_items; --(MyFlex* (^)(int))align_content; +//整体的停靠设置 +-(MyFlex* (^)(MyFlexGravity))align_content; +//内边距设置 -(MyFlex* (^)(UIEdgeInsets))padding; +//条目之间的垂直和水平间距设置 -(MyFlex* (^)(CGFloat))vert_space; -(MyFlex* (^)(CGFloat))horz_space; diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index c05362d..54409df 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -47,7 +47,7 @@ @implementation MyFlexItem __weak UIView *_view; } -+(CGFloat)auto ++(CGFloat)_auto { return _sauto; } @@ -114,23 +114,23 @@ -(instancetype)initWithView:(UIView*)view; { return ^(UIView *val) { - if (_width != CGFLOAT_MAX) - { - if (_width == MyLayoutSize.fill) - [self->_view.widthSize __equalTo:val]; - else if (_width < 1 && _width > 0) - [[self->_view.widthSize __equalTo:val.widthSize] __multiply:_width]; - else; - } - - if (_height != CGFLOAT_MAX) - { - if (_height == MyLayoutSize.fill) - [self->_view.heightSize __equalTo:val]; - else if (_height < 1 && _height > 0) - [[self->_view.heightSize __equalTo:val.heightSize] __multiply:_height]; - else; - } +// if (_width != CGFLOAT_MAX) +// { +// if (_width == MyLayoutSize.fill) +// [self->_view.widthSize __equalTo:val]; +// else if (_width < 1 && _width > 0) +// [[self->_view.widthSize __equalTo:val.widthSize] __multiply:_width]; +// else; +// } +// +// if (_height != CGFLOAT_MAX) +// { +// if (_height == MyLayoutSize.fill) +// [self->_view.heightSize __equalTo:val]; +// else if (_height < 1 && _height > 0) +// [[self->_view.heightSize __equalTo:val.heightSize] __multiply:_height]; +// else; +// } [val addSubview:self->_view]; return self->_view; @@ -141,21 +141,21 @@ -(instancetype)initWithView:(UIView*)view; { return ^id(CGFloat val) { _width = val; - if (_width == MyLayoutSize.fill) - { - if (self->_view.superview) - [self->_view.widthSize __equalTo:self->_view.superview]; - } - else - { - if (_width < 1 && _width > 0) - { - if (self->_view.superview) - [[self->_view.widthSize __equalTo:self->_view.superview] __multiply:_width]; - } - else - self->_view.myWidth = _width; - } +// if (_width == MyLayoutSize.fill) +// { +// if (self->_view.superview) +// [self->_view.widthSize __equalTo:self->_view.superview]; +// } +// else +// { +// if (_width < 1 && _width > 0) +// { +// if (self->_view.superview) +// [[self->_view.widthSize __equalTo:self->_view.superview] __multiply:_width]; +// } +// else +// self->_view.myWidth = _width; +// } return self; }; } @@ -164,21 +164,21 @@ -(instancetype)initWithView:(UIView*)view; { return ^id(CGFloat val) { _height = val; - if (_height == MyLayoutSize.fill) - { - if (self->_view.superview) - [self->_view.heightSize __equalTo:self->_view.superview]; - } - else - { - if (_height < 1 && _height > 0) - { - if (self->_view.superview) - [[self->_view.heightSize __equalTo:self->_view.superview] __multiply:_height]; - } - else - self->_view.myHeight = _height; - } +// if (_height == MyLayoutSize.fill) +// { +// if (self->_view.superview) +// [self->_view.heightSize __equalTo:self->_view.superview]; +// } +// else +// { +// if (_height < 1 && _height > 0) +// { +// if (self->_view.superview) +// [[self->_view.heightSize __equalTo:self->_view.superview] __multiply:_height]; +// } +// else +// self->_view.myHeight = _height; +// } return self; }; } @@ -215,6 +215,18 @@ -(instancetype)initWithView:(UIView*)view; }; } +-(MyFlexItem* (^)(CGFloat))margin +{ + return ^id(CGFloat val) { + self->_view.myLeft = val; + self->_view.myRight = val; + self->_view.myTop = val; + self->_view.myBottom = val; + return self; + }; +} + + -(UIView*)view { return self->_view; @@ -430,9 +442,9 @@ -(instancetype)init if (self != nil) { _flex = [[MyFlex alloc] initWithView:self]; - self.orientation = MyOrientation_Vert; - self.arrangedCount = NSIntegerMax; //单行 - self.gravityAlways = YES; //flexbox对所有行都让停靠生效。 + self.orientation = MyOrientation_Vert; //默认row + self.arrangedCount = NSIntegerMax; //默认单行 + self.isFlex = YES; //满足flexbox的需求。 } return self; } @@ -487,6 +499,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( flex_wrap = _snowrap; } + //flex_shrink if (lsc.orientation == MyOrientation_Vert) { diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index 0657412..d79a605 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -218,11 +218,15 @@ /** - 是否停靠属性gravity在所有行中都有效。默认是NO,表示停靠属性不会在最后一行生效。当设置为YES时则所有行的子视图都会受到gravity属性设置的影响。 - 在一些场景中,往往最后一行的子视图个数并没有填充满布局视图,如果这时候设置了gravity时产生的效果并不美观。所以默认情况下最后一行的子视图 - 并不会受到gravity设置的影响,但是特殊情况除外:1.只有一行时,2.最后一行的数量和其他行的数量一样时 这两种情况gravity会影响所有子视图。 + 布局是否是兼容flexbox规则的布局,默认是NO。当设置为YES时有两个特性会产生差异: + 1.停靠属性gravity在所有行中都有效。在一些场景中,往往最后一行的子视图个数并没有填充满布局视图,如果这时候设置了gravity时产生的效果并不美观。 + 所以默认情况下最后一行的子视图并不会受到gravity设置的影响,但是特殊情况除外:1.只有一行时,2.最后一行的数量和其他行的数量一样时 这两种情况gravity会影响所有子视图。 因此当isFlex为YES时则所有行和列都会受到gravity属性的影响。 + + 2.子视图的weight属性可以和子视图的尺寸约束共存。默认情况下在垂直流式布局中如果子视图设置了weight属性则子视图的宽度约束将不起作用, + 而在水平流式布局中如果子视图设置了weight属性则子视图的高度约束将不起作用。另外在流式内容约束布局中weight表示的是剩余空间的比重。 + 因此当isFlex设置为YES时,表示子视图的weight可以和尺寸约束共存,并且weight就是表示行内的剩余空间的比重。 */ -@property(nonatomic, assign) BOOL gravityAlways; +@property(nonatomic, assign) BOOL isFlex; /** diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 1cc022f..6857bb5 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -120,17 +120,17 @@ -(MyGravity)arrangedGravity return self.myCurrentSizeClass.arrangedGravity; } --(BOOL)gravityAlways +-(BOOL)isFlex { - return self.myCurrentSizeClass.gravityAlways; + return self.myCurrentSizeClass.isFlex; } --(void)setGravityAlways:(BOOL)gravityAlways +-(void)setIsFlex:(BOOL)isFlex { MyFlowLayout *lsc = self.myCurrentSizeClass; - if (lsc.gravityAlways != gravityAlways) + if (lsc.isFlex != isFlex) { - lsc.gravityAlways = gravityAlways; + lsc.isFlex = isFlex; [self setNeedsLayout]; } } @@ -368,7 +368,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger case MyGravity_Horz_Between: { //总宽度减去最大的宽度。再除以数量表示每个应该扩展的空间。最后一行无效(如果最后一行的数量和其他行的数量一样以及总共就只有一行除外)。 - if ((self.gravityAlways || startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) + if ((self.isFlex || startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) { addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / (count - 1); } @@ -396,7 +396,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger if (lsc.arrangedCount == 0 && averageArrange) { //不是最后一行。。 - if (self.gravityAlways || startIndex != sbs.count) + if (self.isFlex || startIndex != sbs.count) { addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / count; } @@ -599,7 +599,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger case MyGravity_Vert_Between: { //总高度减去最大的高度。再除以数量表示每个应该扩展的空间。最后一列无效(如果最后一列的数量和其他列的数量一样以及总共就只有一列除外)。 - if ((self.gravityAlways || startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) + if ((self.isFlex || startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) { addYFill = (selfSize.height - paddingVert - colMaxHeight) / (count - 1); } @@ -625,7 +625,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger //处理内容拉伸的情况。 if (lsc.arrangedCount == 0 && averageArrange) { - if (self.gravityAlways || startIndex != sbs.count) + if (self.isFlex || startIndex != sbs.count) { addYFill = (selfSize.height - paddingVert - colMaxHeight) / count; } diff --git a/MyLayout/Lib/MyLayoutSizeClass.h b/MyLayout/Lib/MyLayoutSizeClass.h index 1399a11..e4dc5ef 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.h +++ b/MyLayout/Lib/MyLayoutSizeClass.h @@ -161,7 +161,7 @@ @property(nonatomic,assign) MyGravity arrangedGravity; @property(nonatomic,assign) BOOL autoArrange; -@property(nonatomic,assign) BOOL gravityAlways; +@property(nonatomic,assign) BOOL isFlex; @property(nonatomic,assign) NSInteger arrangedCount; @property(nonatomic, assign) NSInteger pagedCount; diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index bfe459b..0b833c3 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -870,7 +870,7 @@ - (id)copyWithZone:(NSZone *)zone lsc.arrangedCount = self.arrangedCount; lsc.autoArrange = self.autoArrange; - lsc.gravityAlways = self.gravityAlways; + lsc.isFlex = self.isFlex; lsc.arrangedGravity = self.arrangedGravity; lsc.subviewSize = self.subviewSize; lsc.minSpace = self.minSpace; @@ -885,11 +885,11 @@ -(NSString*)debugDescription { NSString *dbgDesc = [super debugDescription]; - dbgDesc = [NSString stringWithFormat:@"%@\nFlowLayout: \narrangedCount=%ld\nautoArrange=%@\ngravityAlways=%@\narrangedGravity=%hu\npagedCount=%ld", + dbgDesc = [NSString stringWithFormat:@"%@\nFlowLayout: \narrangedCount=%ld\nautoArrange=%@\nisFlex=%@\narrangedGravity=%hu\npagedCount=%ld", dbgDesc, (long)self.arrangedCount, self.autoArrange ? @"YES":@"NO", - self.gravityAlways? @"YES":@"NO", + self.isFlex? @"YES":@"NO", self.arrangedGravity, (long)self.pagedCount ]; diff --git a/MyLayoutDemo/FLLTest1ViewController.m b/MyLayoutDemo/FLLTest1ViewController.m index 9ccf400..f0364b6 100644 --- a/MyLayoutDemo/FLLTest1ViewController.m +++ b/MyLayoutDemo/FLLTest1ViewController.m @@ -178,6 +178,9 @@ -(void)handleAdjustVertGravity:(id)sender vertGravity = MyGravity_Vert_Fill; break; case MyGravity_Vert_Fill: + vertGravity = MyGravity_Vert_Stretch; + break; + case MyGravity_Vert_Stretch: { vertGravity = MyGravity_Vert_Top; [self.flowLayout.subviews makeObjectsPerformSelector:@selector(sizeToFit)]; @@ -218,6 +221,9 @@ -(void)handleAdjustHorzGravity:(id)sender horzGravity = MyGravity_Horz_Fill; break; case MyGravity_Horz_Fill: + horzGravity = MyGravity_Horz_Stretch; + break; + case MyGravity_Horz_Stretch: { horzGravity = MyGravity_Horz_Left; [self.flowLayout.subviews makeObjectsPerformSelector:@selector(sizeToFit)]; @@ -254,6 +260,9 @@ -(void)handleAdjustArrangeGravity:(id)sender vertArrangeGravity = MyGravity_Vert_Fill; break; case MyGravity_Vert_Fill: + vertArrangeGravity = MyGravity_Vert_Stretch; + break; + case MyGravity_Vert_Stretch: { vertArrangeGravity = MyGravity_Vert_Top; [self.flowLayout.subviews makeObjectsPerformSelector:@selector(sizeToFit)]; @@ -277,6 +286,8 @@ -(void)handleAdjustArrangeGravity:(id)sender horzArrangeGravity = MyGravity_Horz_Fill; break; case MyGravity_Horz_Fill: + horzArrangeGravity = MyGravity_Horz_Stretch; + case MyGravity_Horz_Stretch: { horzArrangeGravity = MyGravity_Horz_Left; [self.flowLayout.subviews makeObjectsPerformSelector:@selector(sizeToFit)]; @@ -359,6 +370,9 @@ -(NSString*)gravityInfo:(MyGravity)gravity case MyGravity_Vert_Around: vertGravityStr = @"MyGravity_Vert_Around"; break; + case MyGravity_Vert_Stretch: + vertGravityStr = @"MyGravity_Vert_Stretch"; + break; case MyGravity_Vert_Window_Center: vertGravityStr = @"MyGravity_Vert_Window_Center"; break; @@ -387,6 +401,9 @@ -(NSString*)gravityInfo:(MyGravity)gravity case MyGravity_Horz_Around: horzGravityStr = @"MyGravity_Horz_Around"; break; + case MyGravity_Horz_Stretch: + horzGravityStr = @"MyGravity_Horz_Stretch"; + break; case MyGravity_Horz_Window_Center: horzGravityStr = @"MyGravity_Horz_Window_Center"; break; diff --git a/MyLayoutDemo/FLLTest2ViewController.m b/MyLayoutDemo/FLLTest2ViewController.m index b8d4690..130ac84 100644 --- a/MyLayoutDemo/FLLTest2ViewController.m +++ b/MyLayoutDemo/FLLTest2ViewController.m @@ -130,7 +130,7 @@ - (IBAction)handleAutoArrangeChange:(UISwitch *)sender { -(IBAction)handleGravityAlwaysChange:(id)sender { - self.flowLayout.gravityAlways = !self.flowLayout.gravityAlways; + self.flowLayout.isFlex = !self.flowLayout.isFlex; } diff --git a/MyLayoutDemo/FLXTest1ViewController.m b/MyLayoutDemo/FLXTest1ViewController.m index 9a2b772..55bc5a9 100644 --- a/MyLayoutDemo/FLXTest1ViewController.m +++ b/MyLayoutDemo/FLXTest1ViewController.m @@ -47,6 +47,9 @@ -(void)loadView .height(MyLayoutSize.fill) .addTo(self.view); + + + MyFlexLayout *actionLayout = MyFlexLayout.new.flex .flex_direction(MyFlex.row) .flex_wrap(MyFlex.wrap) @@ -54,6 +57,9 @@ -(void)loadView .height(MyLayoutSize.wrap) .addTo(rootLayout); + + + [self createActionButton:NSLocalizedString(@"flex-direction", @"") action:@selector(handleFlex_Direction:)].flexItem .width(1/3.0) From dbe46b0598d637e848a446aa059ceadccbcc3654 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Tue, 15 Oct 2019 10:27:26 +0800 Subject: [PATCH 053/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 3 + MyLayout/Lib/MyFlexLayout.h | 100 ++- MyLayout/Lib/MyFlexLayout.m | 528 ++++++------- MyLayout/Lib/MyFlowLayout.m | 795 +++++++++---------- MyLayoutDemo/AllTest8ViewController.m | 1 - MyLayoutDemo/FLLTest5ViewController.m | 1 + MyLayoutDemo/FLXTest1ViewController.m | 1022 ++++++++++++++++++++----- MyLayoutTests/MyFlowLayoutTestCase.m | 70 ++ 8 files changed, 1640 insertions(+), 880 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index dd347c2..23803ae 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -3017,6 +3017,9 @@ -(CGFloat)myGetBoundLimitMeasure:(MyLayoutSize*)boundDime sbv:(UIView*)sbv dimeT -(CGFloat)myValidMeasure:(MyLayoutSize*)dime sbv:(UIView*)sbv calcSize:(CGFloat)calcSize sbvSize:(CGSize)sbvSize selfLayoutSize:(CGSize)selfLayoutSize { + if (calcSize < 0.0) + calcSize = 0.0; + if (dime == nil) return calcSize; diff --git a/MyLayout/Lib/MyFlexLayout.h b/MyLayout/Lib/MyFlexLayout.h index 0e4353b..b1d5c28 100644 --- a/MyLayout/Lib/MyFlexLayout.h +++ b/MyLayout/Lib/MyFlexLayout.h @@ -8,18 +8,52 @@ #import "MyFlowLayout.h" -//定义flex的方向类型。 -typedef int MyFlexDirection; -//定义flex的换行类型。 -typedef int MyFlexWrap; -//定义flex的停靠对齐类型。 -typedef int MyFlexGravity; +//定义flex的方向类型。 +typedef enum : int { + MyFlexDirection_Row, + MyFlexDirection_Column, + MyFlexDirection_Row_Reverse, + MyFlexDirection_Column_Reverse +} MyFlexDirection; + +//定义flex的换行类型 +typedef enum : int { + MyFlexWrap_NoWrap = 0, + MyFlexWrap_Wrap = 4, + MyFlexWrap_Wrap_Reverse = 12 +}MyFlexWrap; + +//定义flex的停靠对齐 +typedef enum : int { + MyFlexGravity_Flex_Start, + MyFlexGravity_Flex_End, + MyFlexGravity_Center, + MyFlexGravity_Space_Between, + MyFlexGravity_Space_Around, + MyFlexGravity_Baseline, + MyFlexGravity_Stretch +}MyFlexGravity; + +extern const int MyFlex_Auto; @interface MyFlexItem:NSObject -//因为auto是C语言关键字不能直接使用,所以这里加一个_前缀。 -@property(class, readonly, assign) CGFloat _auto; +//您可以用链式语法进行属性设置,也可以直接通过属性赋值进行设置和获取。 +@property(nonatomic, weak, readonly) __kindof UIView *view; +@property(nonatomic, assign) NSInteger order_val; +@property(nonatomic, assign) CGFloat flex_grow_val; +@property(nonatomic, assign) CGFloat flex_shrink_val; +@property(nonatomic, assign) CGFloat flex_basis_val; +@property(nonatomic, assign) MyFlexGravity align_self_val; +@property(nonatomic, assign) CGFloat width_val; +@property(nonatomic, assign) CGFloat height_val; +@property(nonatomic, assign) CGFloat margin_top_val; +@property(nonatomic, assign) CGFloat margin_bottom_val; +@property(nonatomic, assign) CGFloat margin_left_val; +@property(nonatomic, assign) CGFloat margin_right_val; +@property(nonatomic, assign) MyVisibility visibility_val; + //条目的顺序设置 @@ -32,68 +66,52 @@ typedef int MyFlexGravity; -(MyFlexItem* (^)(CGFloat))flex_basis; //行内条目自身的对齐方式。 -(MyFlexItem* (^)(MyFlexGravity))align_self; - //设置具体的宽度值,当宽度值大于0小于1是表明的是相对宽度,你也可以设置MyLayoutSize.wrap和MyLayoutSize.fill来设置特殊宽度。 -(MyFlexItem* (^)(CGFloat))width; +-(MyFlexItem* (^)(CGFloat))min_width; +-(MyFlexItem* (^)(CGFloat))max_width; -(MyFlexItem* (^)(CGFloat))height; +-(MyFlexItem* (^)(CGFloat))min_height; +-(MyFlexItem* (^)(CGFloat))max_height; + //条目的外间距设置。 -(MyFlexItem* (^)(CGFloat))margin_top; -(MyFlexItem* (^)(CGFloat))margin_bottom; -(MyFlexItem* (^)(CGFloat))margin_left; -(MyFlexItem* (^)(CGFloat))margin_right; -(MyFlexItem* (^)(CGFloat))margin; - - +//是否可见 +-(MyFlexItem* (^)(MyVisibility))visibility; +//添加到父视图中 -(__kindof UIView* (^)(UIView*))addTo; -@property(nonatomic, weak, readonly) __kindof UIView *view; - @end -@class MyFlexLayout; @interface MyFlex:MyFlexItem -//方向枚举 -@property(class, readonly, assign) MyFlexDirection row; -@property(class, readonly, assign) MyFlexDirection row_reverse; -@property(class, readonly, assign) MyFlexDirection column; -@property(class, readonly, assign) MyFlexDirection column_reverse; - -//换行枚举 -@property(class, readonly, assign) MyFlexWrap nowrap; -@property(class, readonly, assign) MyFlexWrap wrap; -@property(class, readonly, assign) MyFlexWrap wrap_reverse; - -//停靠对齐枚举 -@property(class, readonly, assign) MyFlexGravity flex_start; -@property(class, readonly, assign) MyFlexGravity flex_end; -@property(class, readonly, assign) MyFlexGravity center; -@property(class, readonly, assign) MyFlexGravity space_between; -@property(class, readonly, assign) MyFlexGravity sapce_around; -@property(class, readonly, assign) MyFlexGravity baseline; -@property(class, readonly, assign) MyFlexGravity stretch; - +@property(nonatomic, assign) MyFlexDirection flex_direction_val; +@property(nonatomic, assign) MyFlexWrap flex_wrap_val; +@property(nonatomic, assign) MyFlexGravity justify_content_val; +@property(nonatomic, assign) MyFlexGravity align_items_val; +@property(nonatomic, assign) MyFlexGravity align_content_val; +@property(nonatomic, assign) UIEdgeInsets padding_val; +@property(nonatomic, assign) CGFloat vert_space_val; +@property(nonatomic, assign) CGFloat horz_space_val; //方向设置 -(MyFlex* (^)(MyFlexDirection))flex_direction; - //换行设置 -(MyFlex* (^)(MyFlexWrap))flex_wrap; - //通过 | 运算来结合 wrap 和direction -(MyFlex* (^)(int))flex_flow; - //行的停靠设置 -(MyFlex* (^)(MyFlexGravity))justify_content; - //行内条目的对齐设置 -(MyFlex* (^)(MyFlexGravity))align_items; - //整体的停靠设置 -(MyFlex* (^)(MyFlexGravity))align_content; - //内边距设置 -(MyFlex* (^)(UIEdgeInsets))padding; //条目之间的垂直和水平间距设置 @@ -101,8 +119,6 @@ typedef int MyFlexGravity; -(MyFlex* (^)(CGFloat))horz_space; -@property(nonatomic, weak, readonly) MyFlexLayout *layout; - @end diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index 54409df..da42451 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -13,67 +13,88 @@ const char * const ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM = "ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM"; -static const int _sauto = -1; - -static const int _srow = 0; -static const int _srow_reverse = 2; -static const int _scolumn = 1; -static const int _scolumn_reverse = 3; - -static const int _snowrap = 0; -static const int _swrap = 4; -static const int _swrap_reverse = 12; - -static const int _sflex_start = 0; -static const int _sflex_end = 1; -static const int _scenter = 2; -static const int _sspace_between = 3; -static const int _sspace_around = 4; -static const int _sbaseline = 5; -static const int _sstretch = 6; + const int MyFlex_Auto = -1; @implementation MyFlexItem { @package - int _align_self; - NSInteger _order; - CGFloat _flex_grow; - CGFloat _flex_shrink; - CGFloat _flex_basis; - CGFloat _width; - CGFloat _height; - __weak UIView *_view; } -+(CGFloat)_auto -{ - return _sauto; -} - -(instancetype)initWithView:(UIView*)view; { self = [super init]; if (self != nil) { - _order = 0; - _flex_grow = 0; - _flex_basis = _sauto; - _flex_shrink = 1; - _align_self = _sauto; + _order_val = 0; + _flex_grow_val = 0; + _flex_basis_val = MyFlex_Auto; + _flex_shrink_val = 1; + _align_self_val = MyFlex_Auto; _view = view; - _width = CGFLOAT_MAX; - _height = CGFLOAT_MAX; + _width_val = 0; + _height_val = 0; } return self; } +-(CGFloat)margin_top_val +{ + return self.view.myTop; +} + +-(void)setMargin_top_val:(CGFloat)margin_top_val +{ + self.view.myTop = margin_top_val; +} + +-(CGFloat)margin_bottom_val +{ + return self.view.myBottom; +} + +-(void)setMargin_bottom_val:(CGFloat)margin_bottom_val +{ + self.view.myBottom = margin_bottom_val; +} + +-(CGFloat)margin_left_val +{ + return self.view.myLeft; +} + +-(void)setMargin_left_val:(CGFloat)margin_left_val +{ + self.view.myLeft = margin_left_val; +} + +-(CGFloat)margin_right_val +{ + return self.view.myRight; +} + +-(void)setMargin_right_val:(CGFloat)margin_right_val +{ + self.view.myRight = margin_right_val; +} + +-(MyVisibility)visibility_val +{ + return self.view.visibility; +} + +-(void)setVisibility_val:(MyVisibility)visibility_val +{ + self.view.visibility = visibility_val; +} + + -(MyFlexItem* (^)(NSInteger))order { return ^id(NSInteger val) { - self->_order = val; + self.order_val = val; return self; }; } @@ -81,7 +102,7 @@ -(instancetype)initWithView:(UIView*)view; -(MyFlexItem* (^)(CGFloat))flex_grow { return ^id(CGFloat val) { - self->_flex_grow = val; + self.flex_grow_val = val; return self; }; } @@ -89,7 +110,7 @@ -(instancetype)initWithView:(UIView*)view; -(MyFlexItem* (^)(CGFloat))flex_shrink { return ^id(CGFloat val) { - self->_flex_shrink = val; + self.flex_shrink_val = val; return self; }; } @@ -97,15 +118,15 @@ -(instancetype)initWithView:(UIView*)view; -(MyFlexItem* (^)(CGFloat))flex_basis { return ^id(CGFloat val) { - self->_flex_basis = val; + self.flex_basis_val = val; return self; }; } --(MyFlexItem* (^)(int))align_self +-(MyFlexItem* (^)(MyFlexGravity))align_self { - return ^id(int val) { - self->_align_self = val; + return ^id(MyFlexGravity val) { + self.align_self_val = val; return self; }; } @@ -114,48 +135,35 @@ -(instancetype)initWithView:(UIView*)view; { return ^(UIView *val) { -// if (_width != CGFLOAT_MAX) -// { -// if (_width == MyLayoutSize.fill) -// [self->_view.widthSize __equalTo:val]; -// else if (_width < 1 && _width > 0) -// [[self->_view.widthSize __equalTo:val.widthSize] __multiply:_width]; -// else; -// } -// -// if (_height != CGFLOAT_MAX) -// { -// if (_height == MyLayoutSize.fill) -// [self->_view.heightSize __equalTo:val]; -// else if (_height < 1 && _height > 0) -// [[self->_view.heightSize __equalTo:val.heightSize] __multiply:_height]; -// else; -// } - - [val addSubview:self->_view]; - return self->_view; + //当前是布局视图,并且父视图是非布局视图则特殊设置。 + if ([self.view isKindOfClass:[MyFlexLayout class]] && ![val isKindOfClass:[MyBaseLayout class]]) + [self setSizeConstraintWithSuperview:val]; + + [val addSubview:self.view]; + return self.view; }; } -(MyFlexItem* (^)(CGFloat))width { return ^id(CGFloat val) { - _width = val; -// if (_width == MyLayoutSize.fill) -// { -// if (self->_view.superview) -// [self->_view.widthSize __equalTo:self->_view.superview]; -// } -// else -// { -// if (_width < 1 && _width > 0) -// { -// if (self->_view.superview) -// [[self->_view.widthSize __equalTo:self->_view.superview] __multiply:_width]; -// } -// else -// self->_view.myWidth = _width; -// } + self.width_val = val; + return self; + }; +} + +-(MyFlexItem* (^)(CGFloat))min_width +{ + return ^id(CGFloat val) { + self.view.widthSize.min(val); + return self; + }; +} + +-(MyFlexItem* (^)(CGFloat))max_width +{ + return ^id(CGFloat val) { + self.view.widthSize.max(val); return self; }; } @@ -163,22 +171,23 @@ -(instancetype)initWithView:(UIView*)view; -(MyFlexItem* (^)(CGFloat))height { return ^id(CGFloat val) { - _height = val; -// if (_height == MyLayoutSize.fill) -// { -// if (self->_view.superview) -// [self->_view.heightSize __equalTo:self->_view.superview]; -// } -// else -// { -// if (_height < 1 && _height > 0) -// { -// if (self->_view.superview) -// [[self->_view.heightSize __equalTo:self->_view.superview] __multiply:_height]; -// } -// else -// self->_view.myHeight = _height; -// } + self.height_val = val; + return self; + }; +} + +-(MyFlexItem* (^)(CGFloat))min_height +{ + return ^id(CGFloat val) { + self.view.heightSize.min(val); + return self; + }; +} + +-(MyFlexItem* (^)(CGFloat))max_height +{ + return ^id(CGFloat val) { + self.view.heightSize.max(val); return self; }; } @@ -186,7 +195,7 @@ -(instancetype)initWithView:(UIView*)view; -(MyFlexItem* (^)(CGFloat))margin_top { return ^id(CGFloat val) { - self->_view.myTop = val; + self.view.myTop = val; return self; }; } @@ -194,7 +203,7 @@ -(instancetype)initWithView:(UIView*)view; -(MyFlexItem* (^)(CGFloat))margin_bottom { return ^id(CGFloat val) { - self->_view.myBottom = val; + self.view.myBottom = val; return self; }; } @@ -202,7 +211,7 @@ -(instancetype)initWithView:(UIView*)view; -(MyFlexItem* (^)(CGFloat))margin_left { return ^id(CGFloat val) { - self->_view.myLeft = val; + self.view.myLeft = val; return self; }; } @@ -210,7 +219,7 @@ -(instancetype)initWithView:(UIView*)view; -(MyFlexItem* (^)(CGFloat))margin_right { return ^id(CGFloat val) { - self->_view.myRight = val; + self.view.myRight = val; return self; }; } @@ -218,124 +227,111 @@ -(instancetype)initWithView:(UIView*)view; -(MyFlexItem* (^)(CGFloat))margin { return ^id(CGFloat val) { - self->_view.myLeft = val; - self->_view.myRight = val; - self->_view.myTop = val; - self->_view.myBottom = val; + self.view.myLeft = val; + self.view.myRight = val; + self.view.myTop = val; + self.view.myBottom = val; return self; }; } +-(MyFlexItem* (^)(MyVisibility))visibility +{ + return ^id(MyVisibility val) { + self.view.visibility = val; + return self; + }; +} --(UIView*)view +-(void)setSizeConstraintWithSuperview:(UIView*)superview { - return self->_view; + //宽度设置 + if (self.width_val == MyLayoutSize.wrap) + [self.view.widthSize __equalTo:@(MyLayoutSize.wrap)]; + else if (self.width_val == MyLayoutSize.fill) + [self.view.widthSize __equalTo:superview.widthSize]; + else if (self.width_val > 0 && self.width_val < 1) + [[self.view.widthSize __equalTo:superview.widthSize] __multiply:self.width_val]; + else if (self.width_val == 0.0) + [self.view.widthSize __equalTo:nil]; + else + [self.view.widthSize __equalTo:@(self.width_val)]; + + //高度设置 + if (self.height_val == MyLayoutSize.wrap) + [self.view.heightSize __equalTo:@(MyLayoutSize.wrap)]; + else if (self.height_val == MyLayoutSize.fill) + [self.view.heightSize __equalTo:superview.heightSize]; + else if (self.height_val > 0 && self.height_val < 1) + [[self.view.heightSize __equalTo:superview.heightSize] __multiply:self.height_val]; + else if (self.height_val == 0.0) + [self.view.heightSize __equalTo:nil]; + else + [self.view.heightSize __equalTo:@(self.height_val)]; } @end @implementation MyFlex -{ - @package - int _flex_direction; - int _flex_wrap; - int _justify_content; - int _align_items; - int _align_content; -} -+(int)row +-(instancetype)initWithView:(UIView*)view { - return _srow; + self = [super initWithView:view]; + if (self != nil) + { + _flex_direction_val = MyFlexDirection_Row; + _flex_wrap_val = MyFlexWrap_NoWrap; + _justify_content_val = MyFlexGravity_Flex_Start; + _align_items_val = MyFlexGravity_Stretch; + _align_content_val = MyFlexGravity_Stretch; + } + return self; } -+(int)row_reverse -{ - return _srow_reverse; -} -+(int)column -{ - return _scolumn; -} -+(int)column_reverse +-(UIEdgeInsets)padding_val { - return _scolumn_reverse; + return ((MyFlexLayout*)self.view).padding; } -+(int)nowrap -{ - return _snowrap; -} -+(int)wrap -{ - return _swrap; -} -+(int)wrap_reverse +-(void)setPadding_val:(UIEdgeInsets)padding_val { - return _swrap_reverse; + ((MyFlexLayout*)self.view).padding = padding_val; } -+(int)flex_start +-(CGFloat)vert_space_val { - return _sflex_start; + return ((MyFlexLayout*)self.view).subviewVSpace; } -+(int)flex_end -{ - return _sflex_end; -} -+(int)center -{ - return _scenter; -} -+(int)space_between -{ - return _sspace_between; -} -+(int)sapce_around -{ - return _sspace_around; -} -+(int)baseline -{ - return _sbaseline; -} -+(int)stretch + +-(void)setVert_space_val:(CGFloat)vert_space_val { - return _sstretch; + ((MyFlexLayout*)self.view).subviewVSpace = vert_space_val; } --(instancetype)initWithView:(UIView*)view +-(CGFloat)horz_space_val { - self = [super initWithView:view]; - if (self != nil) - { - _flex_direction = _srow; - _flex_wrap = _snowrap; - _justify_content = _sflex_start; - _align_items = _sstretch; - _align_content = _sstretch; - } - return self; + return ((MyFlexLayout*)self.view).subviewHSpace; } --(MyFlexLayout*)layout +-(void)setHorz_space_val:(CGFloat)horz_space_val { - return (MyFlexLayout*)_view; + ((MyFlexLayout*)self.view).subviewHSpace = horz_space_val; } --(MyFlex* (^)(int))flex_direction + +-(MyFlex* (^)(MyFlexDirection))flex_direction { - return ^id(int val){ - self->_flex_direction = val; + return ^id(MyFlexDirection val){ + self.flex_direction_val = val; return self; }; } --(MyFlex* (^)(int))flex_wrap +-(MyFlex* (^)(MyFlexWrap))flex_wrap { - return ^id(int val){ - self->_flex_wrap = val; + return ^id(MyFlexWrap val){ + self.flex_wrap_val = val; return self; }; } @@ -344,33 +340,34 @@ -(MyFlexLayout*)layout { return ^id(int val) { //取方向值。 - int direction = val & 0x03; + MyFlexDirection direction = val & 0x03; //取换行值。 - int wrap = val & 0x0c; + MyFlexWrap wrap = val & 0x0c; return self.flex_direction(direction).flex_wrap(wrap); }; } --(MyFlex* (^)(int))justify_content +-(MyFlex* (^)(MyFlexGravity))justify_content { - return ^id(int val) { - self->_justify_content = val; + + return ^id(MyFlexGravity val) { + self.justify_content_val = val; return self; }; } --(MyFlex* (^)(int))align_items +-(MyFlex* (^)(MyFlexGravity))align_items { - return ^id(int val) { - self->_align_items = val; + return ^id(MyFlexGravity val) { + self.align_items_val = val; return self; }; } --(MyFlex* (^)(int))align_content +-(MyFlex* (^)(MyFlexGravity))align_content { - return ^id(int val) { - self->_align_content = val; + return ^id(MyFlexGravity val) { + self.align_content_val = val; return self; }; } @@ -378,7 +375,7 @@ -(MyFlexLayout*)layout -(MyFlex* (^)(UIEdgeInsets))padding { return ^id(UIEdgeInsets val) { - self.layout.padding = val; + ((MyFlexLayout*)self.view).padding = val; return self; }; } @@ -386,7 +383,7 @@ -(MyFlexLayout*)layout -(MyFlex* (^)(CGFloat))vert_space { return ^id(CGFloat val) { - self.layout.subviewVSpace = val; + ((MyFlexLayout*)self.view).subviewVSpace = val; return self; }; } @@ -394,7 +391,7 @@ -(MyFlexLayout*)layout -(MyFlex* (^)(CGFloat))horz_space { return ^id(CGFloat val) { - self.layout.subviewHSpace = val; + ((MyFlexLayout*)self.view).subviewHSpace = val; return self; }; } @@ -403,13 +400,6 @@ -(MyFlexLayout*)layout @implementation UIView(MyFlexLayout) --(UIView* (^)(UIView*))add -{ - return ^id(UIView* val) { - [self addSubview:val]; - return self; - }; -} -(MyFlexItem*)flexItem { @@ -455,27 +445,40 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyFlexLayout *lsc = self.myCurrentSizeClass; //最先设置方向。 - switch (self.flex->_flex_direction) { - case _scolumn_reverse: //column_reverse + switch (self.flex.flex_direction_val) { + case MyFlexDirection_Column_Reverse: //column_reverse lsc.orientation = MyOrientation_Horz; - lsc.layoutTransform = CGAffineTransformMake(1,0,0,-1,0,0); + lsc.layoutTransform = CGAffineTransformMake(1,0,0,-1,0,0); //垂直翻转 break; - case _scolumn: //column; + case MyFlexDirection_Column: //column; lsc.orientation = MyOrientation_Horz; lsc.layoutTransform = CGAffineTransformIdentity; break; - case _srow_reverse: //row_reverse + case MyFlexDirection_Row_Reverse: //row_reverse lsc.orientation = MyOrientation_Vert; - lsc.layoutTransform = CGAffineTransformMake(-1,0,0,1,0,0); + lsc.layoutTransform = CGAffineTransformMake(-1,0,0,1,0,0); //水平翻转 break; - case _srow: + case MyFlexDirection_Row: default: lsc.orientation = MyOrientation_Vert; lsc.layoutTransform = CGAffineTransformIdentity; break; } - int flex_wrap = self.flex->_flex_wrap; + //设置换行. + switch (self.flex.flex_wrap_val) { + case MyFlexWrap_Wrap: + lsc.arrangedCount = 0; + break; + case MyFlexWrap_Wrap_Reverse: + lsc.arrangedCount = 0; + lsc.layoutTransform = CGAffineTransformConcat(lsc.layoutTransform, (lsc.orientation == MyOrientation_Vert)? CGAffineTransformMake(1,0,0,-1,0,0):CGAffineTransformMake(-1,0,0,1,0,0)); + break; + case MyFlexWrap_NoWrap: + default: + lsc.arrangedCount = NSIntegerMax; + break; + } //处理子视图的flexitem设置。 if (sbs == nil) @@ -484,7 +487,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //按order排序。 [sbs sortWithOptions:NSSortStable usingComparator:^NSComparisonResult(UIView* _Nonnull obj1, UIView* _Nonnull obj2) { - return obj1.flexItem->_order - obj2.flexItem->_order; + return obj1.flexItem.order_val - obj2.flexItem.order_val; }]; for (UIView *sbv in sbs) @@ -493,60 +496,54 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( UIView *sbvsc = sbv.myCurrentSizeClass; //flex_grow,如果子视图有设置grow则父视图的换行不起作用。 - sbvsc.weight = flexItem->_flex_grow; - if (flexItem->_flex_grow != 0) - { - flex_wrap = _snowrap; - } - + sbvsc.weight = flexItem.flex_grow_val; //flex_shrink if (lsc.orientation == MyOrientation_Vert) - { - sbvsc.widthSize.shrink = flexItem->_flex_shrink !=_sauto?flexItem->_flex_shrink:0; - } + sbvsc.widthSize.shrink = flexItem.flex_shrink_val != MyFlex_Auto? flexItem.flex_shrink_val:0; else - { - sbvsc.heightSize.shrink = flexItem->_flex_shrink !=_sauto?flexItem->_flex_shrink:0; - } + sbvsc.heightSize.shrink = flexItem.flex_shrink_val != MyFlex_Auto? flexItem.flex_shrink_val:0; - //伸缩基准值设置。 - if (flexItem->_flex_basis != _sauto) + [flexItem setSizeConstraintWithSuperview:self]; + + //基准值设置。 + if (flexItem.flex_basis_val != MyFlex_Auto) { if (lsc.orientation == MyOrientation_Vert) { - if (flexItem->_flex_basis < 1) - [[sbvsc.widthSize __equalTo:lsc.widthSize] __multiply:flexItem->_flex_basis]; + if (flexItem.flex_basis_val < 1 && flexItem.flex_basis_val > 0) + [[sbvsc.widthSize __equalTo:lsc.widthSize] __multiply:flexItem.flex_basis_val]; else - [sbvsc.widthSize __equalTo:@(flexItem->_flex_basis)]; + [sbvsc.widthSize __equalTo:@(flexItem.flex_basis_val)]; } else { - if (flexItem->_flex_basis < 1) - [[sbvsc.heightSize __equalTo:lsc.heightSize] __multiply:flexItem->_flex_basis]; + if (flexItem.flex_basis_val < 1 && flexItem.flex_basis_val > 0) + [[sbvsc.heightSize __equalTo:lsc.heightSize] __multiply:flexItem.flex_basis_val]; else - [sbvsc.heightSize __equalTo:@(flexItem->_flex_basis)]; + [sbvsc.heightSize __equalTo:@(flexItem.flex_basis_val)]; } } //对齐方式设置。 - switch (flexItem->_align_self) { - case _sauto: + int align_self = flexItem.align_self_val; + switch (align_self) { + case MyFlex_Auto: sbvsc.alignment = MyGravity_None; break; - case _sflex_start: + case MyFlexGravity_Flex_Start: sbvsc.alignment = (lsc.orientation == MyOrientation_Vert)? MyGravity_Vert_Top : MyGravity_Horz_Leading; break; - case _sflex_end: + case MyFlexGravity_Flex_End: sbvsc.alignment = (lsc.orientation == MyOrientation_Vert)? MyGravity_Vert_Bottom : MyGravity_Horz_Trailing; break; - case _scenter: + case MyFlexGravity_Center: sbvsc.alignment = (lsc.orientation == MyOrientation_Vert)? MyGravity_Vert_Center : MyGravity_Horz_Center; break; - case _sbaseline: + case MyFlexGravity_Baseline: sbvsc.alignment = (lsc.orientation == MyOrientation_Vert)? MyGravity_Vert_Baseline : MyGravity_None; break; - case _sstretch: + case MyFlexGravity_Stretch: sbvsc.alignment = (lsc.orientation == MyOrientation_Vert)? MyGravity_Vert_Stretch : MyGravity_Horz_Stretch; break; default: @@ -555,55 +552,36 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( } - //再次处理布局视图的其他属性设置,这里因为子视图的一些特性会影响布局视图的属性设置,所以这里放在子视图后面。 - - //设置换行,如果子视图有grow则不支持换行。 - switch (flex_wrap) { - case _swrap: - lsc.arrangedCount = 0; - lsc.layoutTransform = CGAffineTransformIdentity; - break; - case _swrap_reverse: - lsc.arrangedCount = 0; - lsc.layoutTransform = (lsc.orientation == MyOrientation_Vert)? CGAffineTransformMake(-1,0,0,1,0,0):CGAffineTransformMake(1,0,0,-1,0,0); - break; - case _snowrap: - default: - lsc.arrangedCount = NSIntegerMax; - lsc.layoutTransform = CGAffineTransformIdentity; - break; - } - //设置主轴的水平对齐和拉伸 MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = lsc.gravity & MyGravity_Vert_Mask; - switch (self.flex->_justify_content) { - case _sflex_end: + switch (self.flex.justify_content_val) { + case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Vert) lsc.gravity = MyGravity_Horz_Trailing | vertGravity; else lsc.gravity = MyGravity_Vert_Bottom | horzGravity; break; - case _scenter: + case MyFlexGravity_Center: if (lsc.orientation == MyOrientation_Vert) lsc.gravity = MyGravity_Horz_Center | vertGravity; else lsc.gravity = MyGravity_Vert_Center | horzGravity; break; - case _sspace_between: + case MyFlexGravity_Space_Between: if (lsc.orientation == MyOrientation_Vert) lsc.gravity = MyGravity_Horz_Between | vertGravity; else lsc.gravity = MyGravity_Vert_Between | horzGravity; break; - case _sspace_around: + case MyFlexGravity_Space_Around: if (lsc.orientation == MyOrientation_Vert) lsc.gravity = MyGravity_Horz_Around | vertGravity; else lsc.gravity = MyGravity_Vert_Around | horzGravity; break; - case _sflex_start: + case MyFlexGravity_Flex_Start: if (lsc.orientation == MyOrientation_Vert) lsc.gravity = MyGravity_Horz_Leading | vertGravity; else @@ -616,32 +594,32 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyGravity vertArrangedGravity = lsc.arrangedGravity & MyGravity_Horz_Mask; MyGravity horzArrangedGravity = lsc.arrangedGravity & MyGravity_Vert_Mask; - switch (self.flex->_align_items) { - case _sflex_end: + switch (self.flex.align_items_val) { + case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Vert) lsc.arrangedGravity = MyGravity_Vert_Bottom | horzArrangedGravity; else lsc.arrangedGravity = MyGravity_Horz_Trailing | vertArrangedGravity; break; - case _scenter: + case MyFlexGravity_Center: if (lsc.orientation == MyOrientation_Vert) lsc.arrangedGravity = MyGravity_Vert_Center | horzArrangedGravity; else lsc.arrangedGravity = MyGravity_Horz_Center | vertArrangedGravity; break; - case _sbaseline: + case MyFlexGravity_Baseline: if (lsc.orientation == MyOrientation_Vert) lsc.arrangedGravity = MyGravity_Vert_Baseline | horzArrangedGravity; else lsc.arrangedGravity = MyGravity_Horz_Leading | vertArrangedGravity; break; - case _sflex_start: + case MyFlexGravity_Flex_Start: if (lsc.orientation == MyOrientation_Vert) lsc.arrangedGravity = MyGravity_Vert_Top | horzArrangedGravity; else lsc.arrangedGravity = MyGravity_Horz_Leading | vertArrangedGravity; break; - case _sstretch: + case MyFlexGravity_Stretch: default: if (lsc.orientation == MyOrientation_Vert) lsc.arrangedGravity = MyGravity_Vert_Stretch | horzArrangedGravity; @@ -655,38 +633,38 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //只有换行才有用,单行不起作用。 if (lsc.arrangedCount == 0) { - switch (self.flex->_align_content) { - case _sflex_end: + switch (self.flex.align_content_val) { + case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Horz) lsc.gravity = MyGravity_Horz_Trailing | vertGravity; else lsc.gravity = MyGravity_Vert_Bottom | horzGravity; break; - case _scenter: + case MyFlexGravity_Center: if (lsc.orientation == MyOrientation_Horz) lsc.gravity = MyGravity_Horz_Center | vertGravity; else lsc.gravity = MyGravity_Vert_Center | horzGravity; break; - case _sspace_between: + case MyFlexGravity_Space_Between: if (lsc.orientation == MyOrientation_Horz) lsc.gravity = MyGravity_Horz_Between | vertGravity; else lsc.gravity = MyGravity_Vert_Between | horzGravity; break; - case _sspace_around: + case MyFlexGravity_Space_Around: if (lsc.orientation == MyOrientation_Horz) lsc.gravity = MyGravity_Horz_Around | vertGravity; else lsc.gravity = MyGravity_Vert_Around | horzGravity; break; - case _sflex_start: + case MyFlexGravity_Flex_Start: if (lsc.orientation == MyOrientation_Horz) lsc.gravity = MyGravity_Horz_Leading | vertGravity; else lsc.gravity = MyGravity_Vert_Top | horzGravity; break; - case _sstretch: + case MyFlexGravity_Stretch: default: if (lsc.orientation == MyOrientation_Horz) lsc.gravity = MyGravity_Horz_Stretch | vertGravity; diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 6857bb5..95080ac 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -225,51 +225,70 @@ -(id)createSizeClassInstance - (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalWeight:(CGFloat)totalWeight sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count { + //如果浮动宽度都是小于等于0因为没有拉升必要,所以直接返回 + if (totalFloatWidth <= 0.0) + return; + + CGFloat incOffset = 0; for (NSInteger j = startIndex - count; j < startIndex; j++) { UIView *sbv = sbs[j]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + CGFloat oldWidth = sbvmyFrame.width; if (sbvsc.weight != 0) { CGFloat tempWidth = _myCGFloatRound((totalFloatWidth * sbvsc.weight / totalWeight)); - if (sbvsc.widthSizeInner != nil) + if (sbvsc.widthSizeInner != nil && sbvsc.widthSizeInner.dimeVal == nil) tempWidth = [sbvsc.widthSizeInner measureWith:tempWidth]; totalFloatWidth -= tempWidth; totalWeight -= sbvsc.weight; - sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:tempWidth sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; + sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:tempWidth + sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } + + //第一个子视图不偏移。 + if (j != startIndex - count) + sbvmyFrame.leading += incOffset; + sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; + incOffset += (sbvmyFrame.width - oldWidth); } } - (void)myCalcHorzLayoutSinglelineWeight:(CGSize)selfSize totalFloatHeight:(CGFloat)totalFloatHeight totalWeight:(CGFloat)totalWeight sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count { + if (totalFloatHeight <= 0.0) + return; + + CGFloat incOffset = 0.0; for (NSInteger j = startIndex - count; j < startIndex; j++) { UIView *sbv = sbs[j]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + CGFloat oldHeight = sbvmyFrame.height; if (sbvsc.weight != 0) { CGFloat tempHeight = _myCGFloatRound((totalFloatHeight * sbvsc.weight / totalWeight)); - if (sbvsc.heightSizeInner != nil) + if (sbvsc.heightSizeInner != nil && sbvsc.heightSizeInner.dimeVal == nil) tempHeight = [sbvsc.heightSizeInner measureWith:tempHeight]; totalFloatHeight -= tempHeight; totalWeight -= sbvsc.weight; - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:tempHeight sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; + sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:tempHeight + sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:[sbvsc.widthSizeInner measureWith: sbvmyFrame.height ] sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - } + + if (j != startIndex - count) + sbvmyFrame.top += incOffset; + sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; + incOffset += (sbvmyFrame.height - oldHeight); } } @@ -323,8 +342,9 @@ - (void)myCalcHorzLayoutSinglelineHeightShrink:(CGSize)selfSize totalFloatHeight } -- (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger)rowIndex rowMaxHeight:(CGFloat)rowMaxHeight rowMaxWidth:(CGFloat)rowMaxWidth rowTotalShrink:(CGFloat)rowTotalShrink horzGravity:(MyGravity)horzGravity vertAlignment:(MyGravity)vertAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +- (CGFloat)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger)rowIndex rowMaxHeight:(CGFloat)rowMaxHeight rowMaxWidth:(CGFloat)rowMaxWidth rowTotalShrink:(CGFloat)rowTotalShrink horzGravity:(MyGravity)horzGravity vertAlignment:(MyGravity)vertAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc { + CGFloat lineMaxHeight = rowMaxHeight; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; CGFloat paddingHorz = paddingLeading + paddingTrailing; @@ -337,6 +357,9 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger rowMaxWidth = selfSize.width - paddingHorz; //计算每行的gravity情况。 + CGFloat addXPos = 0; //多出来的空隙区域,用于停靠处理。 + CGFloat addXFill = 0; //多出来的平均区域,用于拉伸间距或者尺寸 + MyGravity lineHorzGravity = horzGravity; if (self.lineGravity != nil) { @@ -347,64 +370,55 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger lineHorzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lineHorzGravity]; } - - CGFloat addXPos = 0; //多出来的空隙区域,用于停靠处理。 - CGFloat addXFill = 0; //多出来的平均区域,用于拉伸间距或者尺寸 - BOOL averageArrange = (lineHorzGravity == MyGravity_Horz_Fill || lineHorzGravity == MyGravity_Horz_Stretch); - - if (!averageArrange || lsc.arrangedCount == 0) + switch (lineHorzGravity) { - switch (lineHorzGravity) { - case MyGravity_Horz_Center: - { - addXPos = (selfSize.width - paddingHorz - rowMaxWidth) / 2; - } - break; - case MyGravity_Horz_Trailing: - { - addXPos = selfSize.width - paddingHorz - rowMaxWidth; //因为具有不考虑左边距,而原来的位置增加了左边距,因此 - } - break; - case MyGravity_Horz_Between: - { - //总宽度减去最大的宽度。再除以数量表示每个应该扩展的空间。最后一行无效(如果最后一行的数量和其他行的数量一样以及总共就只有一行除外)。 - if ((self.isFlex || startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) - { - addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / (count - 1); - } - } - break; - case MyGravity_Horz_Around: + case MyGravity_Horz_Center: + { + addXPos = (selfSize.width - paddingHorz - rowMaxWidth) / 2; + } + break; + case MyGravity_Horz_Trailing: + { + addXPos = selfSize.width - paddingHorz - rowMaxWidth; //因为具有不考虑左边距,而原来的位置增加了左边距,因此 + } + break; + case MyGravity_Horz_Between: + { + //总宽度减去最大的宽度。再除以数量表示每个应该扩展的空间。最后一行无效(如果最后一行的数量和其他行的数量一样以及总共就只有一行除外)。 + if ((lsc.isFlex || startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) { - //多于一个拉伸间距,只有一个则居中处理。 - if (count > 1) - { - addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / count; - addXPos = addXFill / 2.0; - } - else - { - addXPos = (selfSize.width - paddingHorz - rowMaxWidth) / 2; - } + addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / (count - 1); } - break; - default: - break; } - - //处理内容拉伸的情况。这里是只有内容约束布局才支持尺寸拉伸。 - if (lsc.arrangedCount == 0 && averageArrange) + break; + case MyGravity_Horz_Around: { - //不是最后一行。。 - if (self.isFlex || startIndex != sbs.count) + //多于一个拉伸间距,只有一个则居中处理。 + if (count > 1) { addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / count; + addXPos = addXFill / 2.0; + } + else + { + addXPos = (selfSize.width - paddingHorz - rowMaxWidth) / 2; } } + break; + default: + break; + } + + //处理内容拉伸的情况。这里是只有内容约束布局才支持尺寸拉伸。 + if (lsc.arrangedCount == 0 && lineHorzGravity == MyGravity_Horz_Fill) + { + //不是最后一行。。 + if (lsc.isFlex || startIndex != sbs.count) + addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / count; } //压缩减少的尺寸汇总。 - CGFloat totalShrinkSize = 0; + CGFloat totalShrinkSize = 0.0; //基线位置 CGFloat baselinePos = CGFLOAT_MAX; //将整行的位置进行调整。 @@ -429,34 +443,23 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger //如果不是最后一行就画下面, if (startIndex != sbs.count) - { sbvl.bottomBorderline = self.intelligentBorderline; - } //如果不是最后一列就画右边, if (j < startIndex - 1) - { sbvl.trailingBorderline = self.intelligentBorderline; - } //如果最后一行的最后一个没有满列数时 if (j == sbs.count - 1 && lsc.arrangedCount != count ) - { sbvl.trailingBorderline = self.intelligentBorderline; - } //如果有垂直间距则不是第一行就画上 if (vertSpace != 0 && startIndex - count != 0) - { sbvl.topBorderline = self.intelligentBorderline; - } //如果有水平间距则不是第一列就画左 if (horzSpace != 0 && j != startIndex - count) - { sbvl.leadingBorderline = self.intelligentBorderline; - } - } } } @@ -492,52 +495,67 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger totalShrinkSize += (sbvsc.trailingPosInner.shrink / rowTotalShrink) * floatingWidth; } - //内容约束布局并且是拉伸尺寸。。 - if (lsc.arrangedCount == 0 && averageArrange) + //内容约束布局并且是填充尺寸或者拉升尺寸。 + if (addXFill != 0.0) { - //只拉伸宽度不拉伸间距 - if (lineHorzGravity == MyGravity_Horz_Stretch) - { - if (sbvsc.widthSizeInner.dimeVal == nil) - sbvmyFrame.width += addXFill; - } - else + if (lsc.arrangedCount == 0 && lineHorzGravity == MyGravity_Horz_Fill) { sbvmyFrame.width += addXFill; + if (j != startIndex - count) + sbvmyFrame.leading += addXFill * (j - (startIndex - count)); + + //特殊处理一下高度依赖宽度,以及宽度是固定但是高度自适应的情况,但这里有可能引起当前行的最高值的变化。 + + BOOL hasHeightChange = NO; + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + {//特殊处理高度等于宽度的情况 + sbvmyFrame.height = [sbvsc.heightSizeInner measureWith:sbvmyFrame.width]; + sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + hasHeightChange = YES; + } + + if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) + {//特殊处理高度自适应的情况。 + sbvmyFrame.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:sbvmyFrame.width]; + sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + hasHeightChange = YES; + } + + if (hasHeightChange) + { + //得到最大的行高, + if (_myCGFloatLess(lineMaxHeight, sbvmyFrame.top + sbvmyFrame.height + sbvsc.bottomPosInner.absVal)) + lineMaxHeight = sbvmyFrame.top + sbvmyFrame.height + sbvsc.bottomPosInner.absVal; + } } - - if (j != startIndex - count) + else { + //其他的只拉伸间距 sbvmyFrame.leading += addXFill * (j - (startIndex - count)); } } - else - { - //其他的只拉伸间距 - sbvmyFrame.leading += addXFill * (j - (startIndex - count)); - } switch (sbvVertAlignment) { case MyGravity_Vert_Center: { - sbvmyFrame.top += (rowMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal - sbvmyFrame.height) / 2; + sbvmyFrame.top += (lineMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal - sbvmyFrame.height) / 2; } break; case MyGravity_Vert_Bottom: { - sbvmyFrame.top += rowMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal - sbvmyFrame.height; + sbvmyFrame.top += lineMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal - sbvmyFrame.height; } break; case MyGravity_Vert_Fill: { - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rowMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:lineMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } break; case MyGravity_Vert_Stretch: { if (sbvsc.heightSizeInner.dimeVal == nil) { - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rowMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:lineMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } } break; @@ -554,11 +572,13 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger } } } + + return lineMaxHeight; } -- (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger)colIndex colMaxWidth:(CGFloat)colMaxWidth colMaxHeight:(CGFloat)colMaxHeight colTotalShrink:(CGFloat)colTotalShrink vertGravity:(MyGravity)vertGravity horzAlignment:(MyGravity)horzAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +- (CGFloat)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger)colIndex colMaxWidth:(CGFloat)colMaxWidth colMaxHeight:(CGFloat)colMaxHeight colTotalShrink:(CGFloat)colTotalShrink vertGravity:(MyGravity)vertGravity horzAlignment:(MyGravity)horzAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc { - + CGFloat lineMaxWidth = colMaxWidth; CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingVert = paddingTop + paddingBottom; @@ -571,6 +591,8 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger colMaxHeight = selfSize.height - paddingVert; //计算每行的gravity情况。 + CGFloat addYPos = 0; + CGFloat addYFill = 0; MyGravity lineVertGravity = vertGravity; if (self.lineGravity != nil) { @@ -579,57 +601,49 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger lineVertGravity = vertGravity; } - CGFloat addYPos = 0; - CGFloat addYFill = 0; - - BOOL averageArrange = (lineVertGravity == MyGravity_Vert_Fill || lineVertGravity == MyGravity_Vert_Stretch); - if (!averageArrange || lsc.arrangedCount == 0) + switch (lineVertGravity) { - switch (lineVertGravity) { - case MyGravity_Vert_Center: - { - addYPos = (selfSize.height - paddingVert - colMaxHeight) / 2; - } - break; - case MyGravity_Vert_Bottom: - { - addYPos = selfSize.height - paddingVert - colMaxHeight; - } - break; - case MyGravity_Vert_Between: - { - //总高度减去最大的高度。再除以数量表示每个应该扩展的空间。最后一列无效(如果最后一列的数量和其他列的数量一样以及总共就只有一列除外)。 - if ((self.isFlex || startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) - { - addYFill = (selfSize.height - paddingVert - colMaxHeight) / (count - 1); - } - } - break; - case MyGravity_Vert_Around: + case MyGravity_Vert_Center: + { + addYPos = (selfSize.height - paddingVert - colMaxHeight) / 2; + } + break; + case MyGravity_Vert_Bottom: + { + addYPos = selfSize.height - paddingVert - colMaxHeight; + } + break; + case MyGravity_Vert_Between: + { + //总高度减去最大的高度。再除以数量表示每个应该扩展的空间。最后一列无效(如果最后一列的数量和其他列的数量一样以及总共就只有一列除外)。 + if ((lsc.isFlex || startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) { - if (count > 1) - { - addYFill = (selfSize.height - paddingVert - colMaxHeight) / count; - addYPos = addYFill / 2.0; - } - else - { - addYPos = (selfSize.height - paddingVert - colMaxHeight) / 2; - } + addYFill = (selfSize.height - paddingVert - colMaxHeight) / (count - 1); } - break; - default: - break; } - - //处理内容拉伸的情况。 - if (lsc.arrangedCount == 0 && averageArrange) + break; + case MyGravity_Vert_Around: { - if (self.isFlex || startIndex != sbs.count) + if (count > 1) + { + addYFill = (selfSize.height - paddingVert - colMaxHeight) / count; + addYPos = addYFill / 2.0; + } + else { - addYFill = (selfSize.height - paddingVert - colMaxHeight) / count; + addYPos = (selfSize.height - paddingVert - colMaxHeight) / 2; } } + break; + default: + break; + } + + //处理内容拉伸的情况。 + if (lsc.arrangedCount == 0 && lineVertGravity == MyGravity_Vert_Fill) + { + if (lsc.isFlex || startIndex != sbs.count) + addYFill = (selfSize.height - paddingVert - colMaxHeight) / count; } //压缩减少的尺寸汇总。 @@ -657,35 +671,23 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger //如果不是最后一行就画下面, if (j < startIndex - 1) - { sbvl.bottomBorderline = self.intelligentBorderline; - } //如果不是最后一列就画右边, if (startIndex != sbs.count ) - { sbvl.trailingBorderline = self.intelligentBorderline; - - } //如果最后一行的最后一个没有满列数时 if (j == sbs.count - 1 && lsc.arrangedCount != count ) - { sbvl.bottomBorderline = self.intelligentBorderline; - } //如果有垂直间距则不是第一行就画上 if (vertSpace != 0 && j != startIndex - count) - { sbvl.topBorderline = self.intelligentBorderline; - } //如果有水平间距则不是第一列就画左 if (horzSpace != 0 && startIndex - count != 0 ) - { sbvl.leadingBorderline = self.intelligentBorderline; - - } } } } @@ -713,52 +715,54 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger totalShrinkSize += (sbvsc.bottomPosInner.shrink / colTotalShrink) * floatingHeight; } - if (lsc.arrangedCount == 0 && averageArrange) + //内容约束布局并且是填充尺寸或者拉升尺寸。 + if (addYFill != 0.0) { - //只拉伸宽度不拉伸间距 - - if (lineVertGravity == MyGravity_Vert_Stretch) - { - if (sbvsc.heightSizeInner.dimeVal == nil) - sbvmyFrame.height += addYFill; - } - else + if (lsc.arrangedCount == 0 && lineVertGravity == MyGravity_Vert_Fill) { sbvmyFrame.height += addYFill; + if (j != startIndex - count) + sbvmyFrame.top += addYFill * (j - (startIndex - count)); + + //特殊考虑一下高度等于宽度的问题 + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + sbvmyFrame.width = [sbvsc.widthSizeInner measureWith:sbvmyFrame.height]; + sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + + //得到最大的行宽, + if (_myCGFloatLess(lineMaxWidth, sbvmyFrame.leading + sbvmyFrame.width + sbvsc.trailingPosInner.absVal)) + lineMaxWidth = sbvmyFrame.top + sbvmyFrame.leading + sbvmyFrame.width + sbvsc.trailingPosInner.absVal; + } } - - if (j != startIndex - count) + else { + //只拉伸间距 sbvmyFrame.top += addYFill * (j - (startIndex - count)); } } - else - { - //只拉伸间距 - sbvmyFrame.top += addYFill * (j - (startIndex - count)); - } switch (sbvHorzAlignment) { case MyGravity_Horz_Center: { - sbvmyFrame.leading += (colMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal - sbvmyFrame.width) / 2; + sbvmyFrame.leading += (lineMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal - sbvmyFrame.width) / 2; } break; case MyGravity_Horz_Trailing: { - sbvmyFrame.leading += colMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal - sbvmyFrame.width; + sbvmyFrame.leading += lineMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal - sbvmyFrame.width; } break; case MyGravity_Horz_Fill: { - sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:colMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:lineMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } break; case MyGravity_Horz_Stretch: { if (sbvsc.widthSizeInner.dimeVal == nil) { - sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:colMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:lineMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } } break; @@ -767,6 +771,8 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger } } } + + return lineMaxWidth; } @@ -823,9 +829,7 @@ -(void)myCalcAutoArrangeSinglelineSubviews:(NSMutableArray*)sbs CGFloat s1 = [self myCalcSinglelineSize:calcArray space:space]; CGFloat s2 = [self myCalcSinglelineSize:bestSinglelineArray space:space]; if (_myCGFloatLess(fabs(selfSize - s1), fabs(selfSize - s2)) && _myCGFloatLessOrEqual(s1, selfSize) ) - { [bestSinglelineArray setArray:calcArray]; - } return; } @@ -842,9 +846,7 @@ -(void)myCalcAutoArrangeSinglelineSubviews:(NSMutableArray*)sbs { CGFloat s2 = [self myCalcSinglelineSize:bestSinglelineArray space:space]; if (_myCGFloatLess(fabs(selfSize - s1), fabs(selfSize - s2))) - { [bestSinglelineArray setArray:calcArray2]; - } if (_myCGFloatEqual(s1, selfSize)) break; @@ -858,7 +860,9 @@ -(void)myCalcAutoArrangeSinglelineSubviews:(NSMutableArray*)sbs } else + { break; + } } @@ -977,6 +981,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab NSMutableIndexSet *arrangeIndexSet = [NSMutableIndexSet new]; NSInteger rowIndex = 0; //行的索引。 NSInteger arrangedIndex = 0; + CGFloat rowTotalWeight = 0.0; NSInteger i = 0; for (; i < sbs.count; i++) { @@ -994,37 +999,41 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab //计算子视图的宽度。 if (subviewSize != 0) { - rect.size.width = subviewSize; + rect.size.width = subviewSize - leadingSpace - trailingSpace; + } + else if (sbvsc.widthSizeInner.dimeVal != nil) + { + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; } else if (sbvsc.weight != 0) { - //如果过了,则表示当前的剩余空间为0了,所以就按新的一行来算。。 - CGFloat floatWidth = selfSize.width - paddingHorz - rowMaxWidth; - if (_myCGFloatLessOrEqual(floatWidth, 0)) + if (lsc.isFlex) { - floatWidth += rowMaxWidth; - arrangedIndex = 0; + rect.size.width = 0; + } + else + { + //如果过了,则表示当前的剩余空间为0了,所以就按新的一行来算。。 + CGFloat floatWidth = selfSize.width - paddingHorz - rowMaxWidth; + if (_myCGFloatLessOrEqual(floatWidth, 0)) + { + floatWidth += rowMaxWidth; + arrangedIndex = 0; + } + + if (arrangedIndex != 0) + floatWidth -= horzSpace; + + rect.size.width = (floatWidth + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace; } - - if (arrangedIndex != 0) - floatWidth -= horzSpace; - - rect.size.width = (floatWidth + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace; - - } - else - { - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; } rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - //计算子视图的高度。 rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) {//特殊处理高度等于宽度的情况 rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; @@ -1039,7 +1048,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab } - //计算xPos的值加上leadingSpace + rect.size.width + trailingSpace 的值要小于整体的宽度。 CGFloat place = xPos + leadingSpace + rect.size.width + trailingSpace; if (arrangedIndex != 0) @@ -1051,14 +1059,18 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的宽度和布局视图保持一致。 if (!lsc.widthSizeInner.dimeWrapVal && (place - selfSize.width > 0.0001)) { + [arrangeIndexSet addIndex:i - arrangedIndex]; + + //如果是flex并且比重不为0则拉伸所有子视图。 + if (lsc.isFlex && rowTotalWeight != 0.0) + { + //这里只减paddingTrailing的原因是xPos中已经带有paddingLeading了,所以不需要再次减paddingLeading. + [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingTrailing - xPos totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; + } + xPos = paddingLeading; yPos += vertSpace; - yPos += rowMaxHeight; - - - [arrangeIndexSet addIndex:i - arrangedIndex]; - //计算前面每行的gravity情况。 - [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + yPos += [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; //计算单独的sbv的宽度是否大于整体的宽度。如果大于则缩小宽度。 if (_myCGFloatGreat(leadingSpace + trailingSpace + rect.size.width, selfSize.width - paddingHorz)) @@ -1083,6 +1095,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab rowMaxHeight = 0; rowMaxWidth = 0; + rowTotalWeight = 0; arrangedIndex = 0; rowIndex++; @@ -1102,28 +1115,32 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab if (_myCGFloatLess(rowMaxWidth, (xPos - paddingLeading))) rowMaxWidth = (xPos - paddingLeading); - + if (lsc.isFlex && sbvsc.weight != 0) + rowTotalWeight += sbvsc.weight; sbvmyFrame.frame = rect; - arrangedIndex++; - } //内容填充约束布局的宽度包裹计算。 if (lsc.widthSizeInner.dimeWrapVal) - { selfSize.width = maxWidth; - } //最后一行 [arrangeIndexSet addIndex:i - arrangedIndex]; - [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + if (lsc.isFlex && rowTotalWeight != 0.0) + { + //这里只减paddingTrailing的原因是xPos中已经带有paddingLeading了,所以不需要再次减paddingLeading. + [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingTrailing - xPos totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; + } + rowMaxHeight = [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; if (lsc.heightSizeInner.dimeWrapVal) + { selfSize.height = yPos + paddingBottom + rowMaxHeight; + } else { CGFloat addYPos = 0; @@ -1142,6 +1159,10 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab { if (arrangeIndexSet.count > 0) fill = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / arrangeIndexSet.count; + + //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' + if (fill < 0 && vertGravity == MyGravity_Vert_Stretch) + fill = 0; } else if (vertGravity == MyGravity_Vert_Between) { @@ -1177,7 +1198,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab if (vertGravity == MyGravity_Vert_Stretch) { UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.heightSizeInner == nil) + if (sbvsc.heightSizeInner.dimeVal == nil) sbvmyFrame.height += fill; } else @@ -1189,17 +1210,13 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab sbvmyFrame.top += between * lineidx; if (vertGravity == MyGravity_Vert_Around && lineidx == 0) - { sbvmyFrame.top += (between / 2.0); - } } } } - return selfSize; - } @@ -1224,8 +1241,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; MyGravity vertAlign = lsc.arrangedGravity & MyGravity_Horz_Mask; - - CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; CGFloat subviewSize = [self myCalcMaxMinSubviewSize:selfSize.width - paddingHorz lsc:(MyFlowLayoutViewSizeClass*)lsc arrangedCount:arrangedCount space:&horzSpace]; @@ -1271,14 +1286,17 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray } - - BOOL averageArrange = (horzGravity == MyGravity_Horz_Fill); - + //平均宽度,当布局的gravity设置为Horz_Fill时指定这个平均宽度值。 + CGFloat averageWidth = 0.0; + if (horzGravity == MyGravity_Horz_Fill) + averageWidth = (selfSize.width - paddingHorz - (arrangedCount - 1) * horzSpace) / arrangedCount; + + //行内子视图的索引号 NSInteger arrangedIndex = 0; NSInteger i = 0; CGFloat rowTotalShrink = 0.0; //某一行的总压缩比重。 - CGFloat rowTotalWeight = 0; - CGFloat rowTotalFixedWidth = 0; + CGFloat rowTotalWeight = 0.0; + CGFloat rowTotalFixedWidth = 0.0; for (; i < sbs.count; i++) { UIView *sbv = sbs[i]; @@ -1290,12 +1308,12 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray { arrangedIndex = 0; - if (rowTotalWeight != 0 && !averageArrange) + if (rowTotalWeight != 0 && horzGravity != MyGravity_Horz_Fill) { [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedCount]; } - if (rowTotalShrink != 0 && !averageArrange) + if (rowTotalShrink != 0 && horzGravity != MyGravity_Horz_Fill) { [self myCalcVertLayoutSinglelineWidthShrink:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalShrink:rowTotalShrink sbs:sbs startIndex:i count:arrangedCount]; } @@ -1307,73 +1325,78 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; + CGFloat topSpace = sbvsc.topPosInner.absVal; + CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; CGRect rect = sbvmyFrame.frame; //计算每行的宽度。 - if (sbvsc.weight != 0) + if (averageWidth != 0.0) { - rowTotalWeight += sbvsc.weight; + rect.size.width = averageWidth - leadingSpace - trailingSpace; } - else + else if (subviewSize != 0.0) { - if (subviewSize != 0) - rect.size.width = subviewSize; - else if (pagingItemWidth != 0) - rect.size.width = pagingItemWidth; + rect.size.width = subviewSize - leadingSpace - trailingSpace; + } + else if (pagingItemWidth != 0.0) + { + rect.size.width = pagingItemWidth - leadingSpace - trailingSpace; + } + else if (sbvsc.widthSizeInner.dimeVal != nil) + { + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + + if (pagingItemHeight != 0) + rect.size.height = pagingItemHeight - topSpace - bottomSpace; + else + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + } else { - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - {//特殊处理宽度等于高度的情况 - - if (pagingItemHeight != 0) - rect.size.height = pagingItemHeight; - else - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - - rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - } - else - { - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; - } + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; } - - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - - rowTotalFixedWidth += rect.size.width; + } + else if (sbvsc.weight != 0.0) + { //在没有设置任何约束,并且weight不为0时则使用比重来求宽度,因此这预先将宽度设置为0 + rect.size.width = 0.0; } + + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + + if (sbvsc.weight != 0.0) + rowTotalWeight += sbvsc.weight; + + //计算总的压缩比 + rowTotalShrink += sbvsc.leadingPosInner.shrink + sbvsc.trailingPosInner.shrink; + rowTotalShrink += sbvsc.widthSizeInner.shrink; + + rowTotalFixedWidth += rect.size.width; rowTotalFixedWidth += leadingSpace + trailingSpace; if (arrangedIndex != (arrangedCount - 1)) rowTotalFixedWidth += horzSpace; - sbvmyFrame.frame = rect; arrangedIndex++; - //计算总的压缩比 - if (!averageArrange) - { - rowTotalShrink += sbvsc.leadingPosInner.shrink + sbvsc.trailingPosInner.shrink; - if (sbvsc.weight != 0) - rowTotalShrink += sbvsc.widthSizeInner.shrink; - } } //最后一行。 if (arrangedIndex < arrangedCount) rowTotalFixedWidth -= horzSpace; - if (rowTotalWeight != 0 && !averageArrange) + if (rowTotalWeight != 0 && horzGravity != MyGravity_Horz_Fill) { [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; } //如果有压缩子视图的处理则需要压缩子视图。 - if (rowTotalShrink != 0 && !averageArrange) + if (rowTotalShrink != 0 && horzGravity != MyGravity_Horz_Fill) { [self myCalcVertLayoutSinglelineWidthShrink:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalShrink:rowTotalShrink sbs:sbs startIndex:i count:arrangedIndex]; } @@ -1391,7 +1414,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray NSInteger rowIndex = 0; //行索引 CGFloat pageWidth = 0; //页宽。 - CGFloat averageWidth = (selfSize.width - paddingHorz - (arrangedCount - 1) * horzSpace) / arrangedCount; arrangedIndex = 0; rowTotalShrink = 0; i = 0; @@ -1405,8 +1427,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (arrangedIndex >= arrangedCount) { arrangedIndex = 0; - yPos += rowMaxHeight; yPos += vertSpace; + yPos += [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; //分别处理水平分页和垂直分页。 if (isHorzPaging) @@ -1428,20 +1450,16 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray //如果是分页滚动则要多添加垂直间距。 if (i % lsc.pagedCount == 0) { - if (isPagingScroll) { yPos -= vertSpace; yPos += paddingVert; - } } } xPos = paddingLeading + pageWidth; - [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - rowMaxHeight = 0; rowMaxWidth = 0; rowTotalShrink = 0; @@ -1455,20 +1473,15 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; - if (averageArrange) - { - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:averageWidth - leadingSpace - trailingSpace sbvSize:rect.size selfLayoutSize:selfSize]; - } - if (pagingItemHeight != 0) - rect.size.height = pagingItemHeight; + rect.size.height = pagingItemHeight - topSpace - bottomSpace; else rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - //再算一次宽度。 - if (!averageArrange) + //再算一次宽度,只有比重为0并且不压缩的情况下计算。否则有可能前面被压缩或者被拉升而又会在这里重置了 + if (sbvsc.weight == 0.0 && sbvsc.widthSizeInner.shrink == 0 && horzGravity != MyGravity_Horz_Fill) { rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; } @@ -1480,7 +1493,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } - if (!averageArrange && sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner && horzGravity != MyGravity_Horz_Fill) {//特殊处理宽度等于高度的情况 rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; @@ -1566,17 +1579,14 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray sbvmyFrame.frame = rect; arrangedIndex++; - //这里只对间距进行压缩比重的计算。 - if (!averageArrange) - { - rowTotalShrink += sbvsc.leadingPosInner.shrink + sbvsc.trailingPosInner.shrink; - } + //这里只对间距进行压缩比重的计算,因为前面压缩了宽度,这里只需要压缩间距了。 + rowTotalShrink += sbvsc.leadingPosInner.shrink + sbvsc.trailingPosInner.shrink; } - //最后一行 - [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - - maxHeight += paddingBottom; + //最后一行,有可能因为行宽的压缩导致那些高度依赖宽度以及高度自适应的视图会增加高度,从而使得行高被调整。 + CGFloat lastlineRowMaxHeight = [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + //在计算总体行高时,需要考虑这种高度出现变化的情况。 + maxHeight += paddingBottom + (lastlineRowMaxHeight - rowMaxHeight); if (lsc.heightSizeInner.dimeWrapVal) { @@ -1611,6 +1621,10 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray { if (arranges > 0) fill = (selfSize.height - maxHeight) / arranges; + + //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' + if (fill < 0 && vertGravity == MyGravity_Vert_Stretch) + fill = 0; } else if (vertGravity == MyGravity_Vert_Between) { @@ -1650,14 +1664,12 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray //如果是vert_around那么第0行应该添加一半的between值。 if (vertGravity == MyGravity_Vert_Around && lineidx == 0) - { sbvmyFrame.top += (between / 2.0); - } } } } - if (lsc.widthSizeInner.dimeWrapVal && !averageArrange) + if (lsc.widthSizeInner.dimeWrapVal) { selfSize.width = maxWidth + paddingTrailing; @@ -1669,7 +1681,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (_myCGFloatLess(selfSize.width, totalPages * CGRectGetWidth(self.superview.bounds))) selfSize.width = totalPages * CGRectGetWidth(self.superview.bounds); } - } return selfSize; @@ -1736,6 +1747,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab NSMutableIndexSet *arrangeIndexSet = [NSMutableIndexSet new]; NSInteger colIndex = 0; NSInteger arrangedIndex = 0; + CGFloat colTotalWeight = 0.0; NSInteger i = 0; for (; i < sbs.count; i++) { @@ -1755,27 +1767,33 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab if (subviewSize != 0) { - rect.size.height = subviewSize; + rect.size.height = subviewSize - topSpace - bottomSpace; + } + else if (sbvsc.heightSizeInner.dimeVal != nil) + { + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; } else if (sbvsc.weight != 0) { - //如果过了,则表示当前的剩余空间为0了,所以就按新的一行来算。。 - CGFloat floatHeight = selfSize.height - paddingVert - colMaxHeight; - if (_myCGFloatLessOrEqual(floatHeight, 0)) + if (lsc.isFlex) { - floatHeight += colMaxHeight; - arrangedIndex = 0; + rect.size.height = 0; + } + else + { + //如果过了,则表示当前的剩余空间为0了,所以就按新的一行来算。。 + CGFloat floatHeight = selfSize.height - paddingVert - colMaxHeight; + if (_myCGFloatLessOrEqual(floatHeight, 0)) + { + floatHeight += colMaxHeight; + arrangedIndex = 0; + } + + if (arrangedIndex != 0) + floatHeight -= vertSpace; + + rect.size.height = (floatHeight + sbvsc.heightSizeInner.addVal) * sbvsc.weight - topSpace - bottomSpace; } - - if (arrangedIndex != 0) - floatHeight -= vertSpace; - - rect.size.height = (floatHeight + sbvsc.heightSizeInner.addVal) * sbvsc.weight - topSpace - bottomSpace; - - } - else - { - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; } rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; @@ -1786,15 +1804,12 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) {//特殊处理宽度等于高度的情况 rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; } - - //计算yPos的值加上topSpace + rect.size.height + bottomSpace的值要小于整体的高度。 CGFloat place = yPos + topSpace + rect.size.height + bottomSpace; if (arrangedIndex != 0) @@ -1806,14 +1821,17 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的宽度和布局视图保持一致。 if (!lsc.heightSizeInner.dimeWrapVal && (place - selfSize.height > 0.0001)) { + [arrangeIndexSet addIndex:i - arrangedIndex]; + + if (lsc.isFlex && colTotalWeight != 0) + { + //因为yPos中已经包含了paddingTop,所以这里不需要再减了。 + [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingBottom - yPos totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; + } + yPos = paddingTop; xPos += horzSpace; - xPos += colMaxWidth; - - - //计算每行的gravity情况。 - [arrangeIndexSet addIndex:i - arrangedIndex]; - [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + xPos += [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; //计算单独的sbv的高度是否大于整体的高度。如果大于则缩小高度。 if (_myCGFloatGreat(topSpace + bottomSpace + rect.size.height, selfSize.height - paddingVert)) @@ -1830,6 +1848,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab colMaxWidth = 0; colMaxHeight = 0; arrangedIndex = 0; + colTotalWeight = 0; colIndex++; } @@ -1847,23 +1866,32 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab if (_myCGFloatLess(colMaxHeight, (yPos - paddingTop))) colMaxHeight = (yPos - paddingTop); - sbvmyFrame.frame = rect; + if (lsc.isFlex && sbvsc.weight != 0) + colTotalWeight += sbvsc.weight; + sbvmyFrame.frame = rect; arrangedIndex++; } if (lsc.heightSizeInner.dimeWrapVal) - { selfSize.height = maxHeight; - } //最后一行 [arrangeIndexSet addIndex:i - arrangedIndex]; - [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + + if (lsc.isFlex && colTotalWeight != 0) + { + //因为yPos中已经包含了paddingTop,所以这里不需要再减了。 + [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingBottom - yPos totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; + } + + colMaxWidth = [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; if (lsc.widthSizeInner.dimeWrapVal) + { selfSize.width = xPos + paddingTrailing + colMaxWidth; + } else { CGFloat addXPos = 0; @@ -1882,6 +1910,10 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab { if (arrangeIndexSet.count > 0) fill = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / arrangeIndexSet.count; + + //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' + if (fill < 0 && horzGravity == MyGravity_Horz_Stretch) + fill = 0; } else if (horzGravity == MyGravity_Horz_Between) { @@ -1928,10 +1960,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab sbvmyFrame.leading += between * lineidx; if (horzGravity == MyGravity_Horz_Around && lineidx == 0) - { sbvmyFrame.leading += (between / 2.0); - } - } } } @@ -2010,12 +2039,15 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray } - BOOL averageArrange = (vertGravity == MyGravity_Vert_Fill); - + //平均高度,当布局的gravity设置为Vert_Fill时指定这个平均高度值。 + CGFloat averageHeight = 0.0; + if (vertGravity == MyGravity_Vert_Fill) + averageHeight = (selfSize.height - paddingVert - (arrangedCount - 1) * vertSpace) / arrangedCount; + NSInteger arrangedIndex = 0; NSInteger i = 0; - CGFloat colTotalWeight = 0; - CGFloat colTotalFixedHeight = 0; + CGFloat colTotalWeight = 0.0; + CGFloat colTotalFixedHeight = 0.0; CGFloat colTotalShrink = 0.0; //某一行的总压缩比重。 for (; i < sbs.count; i++) { @@ -2027,12 +2059,12 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray { arrangedIndex = 0; - if (colTotalWeight != 0 && !averageArrange) + if (colTotalWeight != 0 && vertGravity != MyGravity_Vert_Fill) { [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedCount]; } - if (colTotalShrink != 0 && !averageArrange) + if (colTotalShrink != 0 && vertGravity != MyGravity_Vert_Fill) { [self myCalcHorzLayoutSinglelineHeightShrink:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalShrink:colTotalShrink sbs:sbs startIndex:i count:arrangedCount]; } @@ -2045,64 +2077,68 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; + CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; + CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; if (pagingItemWidth != 0) - rect.size.width = pagingItemWidth; + rect.size.width = pagingItemWidth - leadingSpace - trailingSpace; else rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - - if (sbvsc.weight != 0) + if (averageHeight != 0.0) { - colTotalWeight += sbvsc.weight; + rect.size.height = averageHeight - topSpace - bottomSpace; } - else + else if (subviewSize != 0) + { + rect.size.height = subviewSize - topSpace - bottomSpace; + } + else if (pagingItemHeight != 0) + { + rect.size.height = pagingItemHeight - topSpace - bottomSpace; + } + else if (sbvsc.heightSizeInner.dimeVal != nil) { - if (subviewSize != 0) - rect.size.height = subviewSize; - else if (pagingItemHeight != 0) - rect.size.height = pagingItemHeight; - else - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) {//特殊处理高度等于宽度的情况 rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } - - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - {//特殊处理宽度等于高度的情况 - rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + else + { + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; } - - colTotalFixedHeight += rect.size.height; + } + else if (sbvsc.weight != 0.0) + { + rect.size.height = 0; + } + + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; } - colTotalFixedHeight += topSpace + bottomSpace; + if (sbvsc.weight != 0) + colTotalWeight += sbvsc.weight; + //计算总的压缩比 + colTotalShrink += sbvsc.topPosInner.shrink + sbvsc.bottomPosInner.shrink; + colTotalShrink += sbvsc.heightSizeInner.shrink; + + colTotalFixedHeight += rect.size.height; + colTotalFixedHeight += topSpace + bottomSpace; if (arrangedIndex != (arrangedCount - 1)) colTotalFixedHeight += vertSpace; - sbvmyFrame.frame = rect; arrangedIndex++; - - //计算总的压缩比 - if (!averageArrange) - { - colTotalShrink += sbvsc.topPosInner.shrink + sbvsc.bottomPosInner.shrink; - if (sbvsc.weight != 0) - colTotalShrink += sbvsc.heightSizeInner.shrink; - } } //最后一行。 @@ -2110,12 +2146,12 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray if (arrangedIndex < arrangedCount) colTotalFixedHeight -= vertSpace; - if (colTotalWeight != 0 && !averageArrange) + if (colTotalWeight != 0 && vertGravity != MyGravity_Vert_Fill) { [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; } - if (colTotalShrink != 0 && !averageArrange) + if (colTotalShrink != 0 && vertGravity != MyGravity_Vert_Fill) { [self myCalcHorzLayoutSinglelineHeightShrink:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalShrink:colTotalShrink sbs:sbs startIndex:i count:arrangedIndex]; } @@ -2133,7 +2169,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray NSInteger colIndex = 0; CGFloat pageHeight = 0; //页高 - CGFloat averageHeight = (selfSize.height - paddingVert - (arrangedCount - 1) * vertSpace) / arrangedCount; arrangedIndex = 0; colTotalShrink = 0; i = 0; @@ -2146,8 +2181,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray if (arrangedIndex >= arrangedCount) { arrangedIndex = 0; - xPos += colMaxWidth; xPos += horzSpace; + xPos += [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc];; //分别处理水平分页和垂直分页。 if (isVertPaging) @@ -2161,7 +2196,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray xPos = paddingLeading; } - } if (isHorzPaging) @@ -2169,7 +2203,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray //如果是分页滚动则要多添加垂直间距。 if (i % lsc.pagedCount == 0) { - if (isPagingScroll) { xPos -= horzSpace; @@ -2182,9 +2215,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray yPos = paddingTop + pageHeight; - //计算每行的gravity情况。 - [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - colMaxWidth = 0; colMaxHeight = 0; colTotalShrink = 0; @@ -2197,15 +2227,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; - - if (averageArrange) - { - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:averageHeight - topSpace - bottomSpace sbvSize:rect.size selfLayoutSize:selfSize]; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:[sbvsc.widthSizeInner measureWith: rect.size.height ] sbvSize:rect.size selfLayoutSize:selfSize]; - } - //得到最大的列宽 if (_myCGFloatLess(colMaxWidth, leadingSpace + trailingSpace + rect.size.width)) colMaxWidth = leadingSpace + trailingSpace + rect.size.width; @@ -2289,31 +2310,13 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray arrangedIndex++; //这里只对间距进行压缩比重的计算。 - if (!averageArrange) - { - colTotalShrink += sbvsc.topPosInner.shrink + sbvsc.bottomPosInner.shrink; - } + colTotalShrink += sbvsc.topPosInner.shrink + sbvsc.bottomPosInner.shrink; } //最后一列 - [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - - if (lsc.heightSizeInner.dimeWrapVal && !averageArrange) - { - selfSize.height = maxHeight + paddingBottom; - - //只有在父视图为滚动视图,且开启了分页滚动时才会扩充具有包裹设置的布局视图的宽度。 - if (isVertPaging && isPagingScroll) - { - //算出页数来。如果包裹计算出来的宽度小于指定页数的宽度,因为要分页滚动所以这里会扩充布局的宽度。 - NSInteger totalPages = floor((sbs.count + lsc.pagedCount - 1.0 ) / lsc.pagedCount); - if (_myCGFloatLess(selfSize.height, totalPages * CGRectGetHeight(self.superview.bounds))) - selfSize.height = totalPages * CGRectGetHeight(self.superview.bounds); - } - } + CGFloat lastlineColMaxWidth = [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - - maxWidth += paddingTrailing; + maxWidth += paddingTrailing + (lastlineColMaxWidth - colMaxWidth); if (lsc.widthSizeInner.dimeWrapVal) { @@ -2349,6 +2352,10 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray { if (arranges > 0) fill = (selfSize.width - maxWidth) / arranges; + + //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' + if (fill < 0 && horzGravity == MyGravity_Horz_Stretch) + fill = 0; } else if (horzGravity == MyGravity_Horz_Between) { @@ -2388,13 +2395,25 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray //如果是horz_around那么第0行应该添加一半的between值。 if (horzGravity == MyGravity_Horz_Around && lineidx == 0) - { sbvmyFrame.leading += (between / 2.0); - } } } } + if (lsc.heightSizeInner.dimeWrapVal) + { + selfSize.height = maxHeight + paddingBottom; + + //只有在父视图为滚动视图,且开启了分页滚动时才会扩充具有包裹设置的布局视图的宽度。 + if (isVertPaging && isPagingScroll) + { + //算出页数来。如果包裹计算出来的宽度小于指定页数的宽度,因为要分页滚动所以这里会扩充布局的宽度。 + NSInteger totalPages = floor((sbs.count + lsc.pagedCount - 1.0 ) / lsc.pagedCount); + if (_myCGFloatLess(selfSize.height, totalPages * CGRectGetHeight(self.superview.bounds))) + selfSize.height = totalPages * CGRectGetHeight(self.superview.bounds); + } + } + return selfSize; } diff --git a/MyLayoutDemo/AllTest8ViewController.m b/MyLayoutDemo/AllTest8ViewController.m index 1ac17d1..7d9dbc3 100644 --- a/MyLayoutDemo/AllTest8ViewController.m +++ b/MyLayoutDemo/AllTest8ViewController.m @@ -162,7 +162,6 @@ -(void)handleDemo1:(UIButton*)sender layout.myTrailing = 0.2; //左右边距0.2表示相对边距,也就是左右边距都是父视图总宽度的20%,这样布局视图的宽度就默认为父视图的60%了。 layout.myCenterY = 0; //布局视图在父视图中垂直居中出现。 //layout.myBottom = 0; //布局视图在父视图中底部出现。您可以注释上面居中的代码并解开这句看看效果。 - [self.view addSubview:layout]; //标题 UILabel *titleLabel = [UILabel new]; diff --git a/MyLayoutDemo/FLLTest5ViewController.m b/MyLayoutDemo/FLLTest5ViewController.m index 6f19e75..5aa1607 100644 --- a/MyLayoutDemo/FLLTest5ViewController.m +++ b/MyLayoutDemo/FLLTest5ViewController.m @@ -76,6 +76,7 @@ -(void)addAllItemSubviews:(MyFlowLayout*)flowLayout label.textAlignment = NSTextAlignmentCenter; label.backgroundColor = [CFTool color:random() % 14 + 1]; label.text = [NSString stringWithFormat:@"%d",i]; + label.myMargin = 5; //同时带有四边的间距! [flowLayout addSubview:label]; } diff --git a/MyLayoutDemo/FLXTest1ViewController.m b/MyLayoutDemo/FLXTest1ViewController.m index 55bc5a9..a6adcf9 100644 --- a/MyLayoutDemo/FLXTest1ViewController.m +++ b/MyLayoutDemo/FLXTest1ViewController.m @@ -12,210 +12,204 @@ @interface FLXTest1ViewController () --(UIButton*)createActionButton:(NSString*)title action:(SEL)action; +@property(nonatomic, strong) UISegmentedControl *flex_directionSeg; +@property(nonatomic, strong) UISegmentedControl *flex_wrapSeg; +@property(nonatomic, strong) UISegmentedControl *justify_contentSeg; +@property(nonatomic, strong) UISegmentedControl *align_itemsSeg; +@property(nonatomic, strong) UISegmentedControl *align_contentSeg; + +@property(nonatomic, strong) UILabel *flexlayoutStyleDescLabel; + +@property(nonatomic, strong) MyFlexLayout *contentLayout; @end @implementation FLXTest1ViewController -//创建动作操作按钮。 --(UIButton*)createActionButton:(NSString*)title action:(SEL)action +-(void)loadView { - UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; - [button setTitle:title forState:UIControlStateNormal]; - button.titleLabel.font = [CFTool font:14]; - [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside]; - button.layer.borderColor = [UIColor lightGrayColor].CGColor; - button.layer.borderWidth = 0.5; + MyFlexLayout *rootLayout = MyFlexLayout.new.flex + .flex_direction(MyFlexDirection_Column) + .vert_space(10) + .view; + self.view = rootLayout; - return button; + //布局属性设置。 + MyFlexLayout *flexAttrLayout = MyFlexLayout.new.flex + .flex_direction(MyFlexDirection_Row) + .align_items(MyFlexGravity_Center) + .width(MyLayoutSize.fill) + .height(MyLayoutSize.wrap) + .addTo(rootLayout); -} - - --(void)loadView -{ - [super loadView]; + UILabel *flexAttrTitleLabel = UILabel.new.flexItem + .width(MyLayoutSize.wrap) + .height(MyLayoutSize.wrap) + .addTo(flexAttrLayout); - self.view.backgroundColor = [UIColor whiteColor]; - - MyFlexLayout *rootLayout = MyFlexLayout.new.flex - .flex_direction(MyFlex.column) - .flex_wrap(MyFlex.nowrap) + flexAttrTitleLabel.text = @"flex:"; + + UISegmentedControl *flexAttrSeg = UISegmentedControl.new.flexItem + .flex_grow(1) + .height(MyLayoutSize.wrap) + .addTo(flexAttrLayout); + + [flexAttrSeg insertSegmentWithTitle:@"flex-direction" atIndex:0 animated:NO]; + [flexAttrSeg insertSegmentWithTitle:@"flex-wrap" atIndex:1 animated:NO]; + [flexAttrSeg insertSegmentWithTitle:@"justify-content" atIndex:2 animated:NO]; + [flexAttrSeg insertSegmentWithTitle:@"align_items" atIndex:3 animated:NO]; + [flexAttrSeg insertSegmentWithTitle:@"align_content" atIndex:4 animated:NO]; + [flexAttrSeg addTarget:self action:@selector(handleFlexLayoutAttributeChange:) forControlEvents:UIControlEventValueChanged]; + + UISegmentedControl *flex_directionSeg = UISegmentedControl.new.flexItem .width(MyLayoutSize.fill) - .height(MyLayoutSize.fill) - .addTo(self.view); + .height(MyLayoutSize.wrap) + .addTo(rootLayout); + + [flex_directionSeg insertSegmentWithTitle:@"row" atIndex:0 animated:NO]; + [flex_directionSeg insertSegmentWithTitle:@"row_reverse" atIndex:1 animated:NO]; + [flex_directionSeg insertSegmentWithTitle:@"column" atIndex:2 animated:NO]; + [flex_directionSeg insertSegmentWithTitle:@"column_reverse" atIndex:3 animated:NO]; + [flex_directionSeg addTarget:self action:@selector(handleFlex_Direction:) forControlEvents:UIControlEventValueChanged]; + self.flex_directionSeg = flex_directionSeg; + UISegmentedControl *flex_wrapSeg = UISegmentedControl.new.flexItem + .width(MyLayoutSize.fill) + .height(MyLayoutSize.wrap) + .visibility(MyVisibility_Gone) + .addTo(rootLayout); + [flex_wrapSeg insertSegmentWithTitle:@"nowrap" atIndex:0 animated:NO]; + [flex_wrapSeg insertSegmentWithTitle:@"wrap" atIndex:1 animated:NO]; + [flex_wrapSeg insertSegmentWithTitle:@"wrap_reverse" atIndex:2 animated:NO]; + [flex_wrapSeg addTarget:self action:@selector(handleFlex_Wrap:) forControlEvents:UIControlEventValueChanged]; + self.flex_wrapSeg = flex_wrapSeg; - MyFlexLayout *actionLayout = MyFlexLayout.new.flex - .flex_direction(MyFlex.row) - .flex_wrap(MyFlex.wrap) + UISegmentedControl *justify_contentSeg = UISegmentedControl.new.flexItem .width(MyLayoutSize.fill) .height(MyLayoutSize.wrap) + .visibility(MyVisibility_Gone) .addTo(rootLayout); - + [justify_contentSeg insertSegmentWithTitle:@"flex-start" atIndex:0 animated:NO]; + [justify_contentSeg insertSegmentWithTitle:@"flex-end" atIndex:1 animated:NO]; + [justify_contentSeg insertSegmentWithTitle:@"center" atIndex:2 animated:NO]; + [justify_contentSeg insertSegmentWithTitle:@"space-between" atIndex:3 animated:NO]; + [justify_contentSeg insertSegmentWithTitle:@"space-around" atIndex:4 animated:NO]; + [justify_contentSeg addTarget:self action:@selector(handleJustify_Content:) forControlEvents:UIControlEventValueChanged]; + self.justify_contentSeg = justify_contentSeg; + UISegmentedControl *align_itemsSeg = UISegmentedControl.new.flexItem + .width(MyLayoutSize.fill) + .height(MyLayoutSize.wrap) + .visibility(MyVisibility_Gone) + .addTo(rootLayout); + [align_itemsSeg insertSegmentWithTitle:@"flex-start" atIndex:0 animated:NO]; + [align_itemsSeg insertSegmentWithTitle:@"flex-end" atIndex:1 animated:NO]; + [align_itemsSeg insertSegmentWithTitle:@"center" atIndex:2 animated:NO]; + [align_itemsSeg insertSegmentWithTitle:@"stretch" atIndex:3 animated:NO]; + [align_itemsSeg insertSegmentWithTitle:@"baseline" atIndex:4 animated:NO]; + [align_itemsSeg addTarget:self action:@selector(handleAlign_Items:) forControlEvents:UIControlEventValueChanged]; + self.align_itemsSeg = align_itemsSeg; + - [self createActionButton:NSLocalizedString(@"flex-direction", @"") action:@selector(handleFlex_Direction:)].flexItem - .width(1/3.0) - .height(30) - .addTo(actionLayout); - [self createActionButton:NSLocalizedString(@"flex-wrap", @"") action:@selector(handleFlex_Wrap:)].flexItem - .width(1/3.0) - .height(30) - .addTo(actionLayout); + UISegmentedControl *align_contentSeg = UISegmentedControl.new.flexItem + .width(MyLayoutSize.fill) + .height(MyLayoutSize.wrap) + .visibility(MyVisibility_Gone) + .addTo(rootLayout); - [self createActionButton:NSLocalizedString(@"justify-content", @"") action:@selector(handleJustify_Content:)].flexItem - .width(1/3.0) - .height(30) - .addTo(actionLayout); + [align_contentSeg insertSegmentWithTitle:@"flex-start" atIndex:0 animated:NO]; + [align_contentSeg insertSegmentWithTitle:@"flex-end" atIndex:1 animated:NO]; + [align_contentSeg insertSegmentWithTitle:@"center" atIndex:2 animated:NO]; + [align_contentSeg insertSegmentWithTitle:@"space-between" atIndex:3 animated:NO]; + [align_contentSeg insertSegmentWithTitle:@"space-around" atIndex:4 animated:NO]; + [align_contentSeg insertSegmentWithTitle:@"stretch" atIndex:5 animated:NO]; + [align_contentSeg addTarget:self action:@selector(handleAlign_Content:) forControlEvents:UIControlEventValueChanged]; + self.align_contentSeg = align_contentSeg; + + MyFlexLayout *paddingLayout = MyFlexLayout.new.flex + .flex_direction(MyFlexDirection_Row) + .align_items(MyFlexGravity_Center) + .width(MyLayoutSize.fill) + .height(MyLayoutSize.wrap) + .addTo(rootLayout); - [self createActionButton:NSLocalizedString(@"align-items", @"") action:@selector(handleAlign_Items:)].flexItem - .width(1/3.0) - .height(30) - .addTo(actionLayout); + UILabel *paddingTitleLabel = UILabel.new.flexItem + .width(MyLayoutSize.wrap) + .height(MyLayoutSize.wrap) + .addTo(paddingLayout); - [self createActionButton:NSLocalizedString(@"align-content", @"") action:@selector(handleAlign_Content:)].flexItem - .width(1/3.0) - .height(30) - .addTo(actionLayout); + paddingTitleLabel.text = @"padding:"; + UISwitch *paddingSwitch = UISwitch.new.flexItem + .width(MyLayoutSize.wrap) + .height(MyLayoutSize.wrap) + .addTo(paddingLayout); - MyFlexLayout *contentLayout = MyFlexLayout.new.flex - .vert_space(10) - .horz_space(10) - .flex_wrap(MyFlex.wrap) + [paddingSwitch addTarget:self action:@selector(handlePaddingChange:) forControlEvents:UIControlEventValueChanged]; + + MyFlexLayout *spaceLayout = MyFlexLayout.new.flex + .flex_direction(MyFlexDirection_Row) + .align_items(MyFlexGravity_Center) .width(MyLayoutSize.fill) - .flex_grow(1) + .height(MyLayoutSize.wrap) .addTo(rootLayout); + UILabel *spaceTitleLabel = UILabel.new.flexItem + .width(MyLayoutSize.wrap) + .height(MyLayoutSize.wrap) + .addTo(spaceLayout); - for (int i = 0; i < 6; i++) - { - UILabel *label = UILabel.new.flexItem - .width(100) - .height(100) - .addTo(contentLayout); - - label.backgroundColor = [UIColor redColor]; - - } + spaceTitleLabel.text = @"space:"; + UISwitch *spaceSwitch = UISwitch.new.flexItem + .width(MyLayoutSize.wrap) + .height(MyLayoutSize.wrap) + .addTo(spaceLayout); + [spaceSwitch addTarget:self action:@selector(handleSpaceChange:) forControlEvents:UIControlEventValueChanged]; + UILabel *flexlayoutStyleDescLabel = UILabel.new.flexItem + .width(MyLayoutSize.fill) + .height(MyLayoutSize.wrap) + .addTo(rootLayout); -// -// //添加容器。 -// MyFlexLayout *contentLayout = MyFlexLayout.new.flex + flexlayoutStyleDescLabel.text = @""; + flexlayoutStyleDescLabel.textColor = [CFTool color:6]; + self.flexlayoutStyleDescLabel = flexlayoutStyleDescLabel; + + UIButton *button = UIButton.new.flexItem + .width(MyLayoutSize.fill) + .height(MyLayoutSize.wrap) + .addTo(rootLayout); + + [button setTitle:@"Add Subview" forState:UIControlStateNormal]; + [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [button addTarget:self action:@selector(handleAddItem:) forControlEvents:UIControlEventTouchUpInside]; + + +// UIScrollView *scrollView = UIScrollView.new.flexItem // .width(MyLayoutSize.fill) -// .height(MyLayoutSize.) -// -// +// .flex_grow(1) +// .addTo(rootLayout); - -// -// //添加操作按钮。 -// MyFlowLayout *actionLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:2]; -// actionLayout.wrapContentHeight = YES; -// actionLayout.gravity = MyGravity_Horz_Fill; //所有子视图水平填充,也就是所有子视图的宽度相等。 -// actionLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); -// actionLayout.subviewHSpace = 5; -// actionLayout.subviewVSpace = 5; -// [rootLayout addSubview:actionLayout]; -// -// [actionLayout addSubview: -// ]; -// [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"adjust arrangedCount", @"") -// action:@selector(handleAdjustArrangedCount:)]]; -// [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"adjust vert gravity", @"") -// action:@selector(handleAdjustVertGravity:)]]; -// [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"adjust horz gravity", @"") -// action:@selector(handleAdjustHorzGravity:)]]; -// [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"adjust align", @"") -// action:@selector(handleAdjustArrangeGravity:)]]; -// [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"adjust spacing", @"") -// action:@selector(handleAdjustMargin:)]]; -// -// UILabel *flowLayoutSetLabel = [UILabel new]; -// flowLayoutSetLabel.font = [CFTool font:13]; -// flowLayoutSetLabel.textColor = [UIColor redColor]; -// flowLayoutSetLabel.adjustsFontSizeToFitWidth = YES; -// flowLayoutSetLabel.wrapContentHeight = YES; -// flowLayoutSetLabel.numberOfLines = 5; -// [rootLayout addSubview:flowLayoutSetLabel]; -// self.flowLayoutSetLabel = flowLayoutSetLabel; -// -// UIScrollView *scrollView = [UIScrollView new]; -// scrollView.alwaysBounceHorizontal = YES; -// scrollView.alwaysBounceVertical = YES; -// scrollView.weight = 1; //占用剩余高度。 -// scrollView.myTop = 10; -// [rootLayout addSubview:scrollView]; -// -// -// MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; -// flowLayout.backgroundColor = [CFTool color:0]; -// flowLayout.frame = CGRectMake(0, 0, 800, 800); -// flowLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); -// flowLayout.subviewVSpace = 5; -// flowLayout.subviewHSpace = 5; -// [scrollView addSubview:flowLayout]; -// self.flowLayout = flowLayout; -// -// NSArray *imageArray = @[@"minions1",@"minions2",@"minions3",@"minions4",@"head1"]; -// for (int i = 0; i < 30; i++) -// { -// UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageArray[random()%5]]]; -// [imageView sizeToFit]; -// imageView.layer.borderColor = [CFTool color:5].CGColor; -// imageView.layer.borderWidth = 0.5; -// [self.flowLayout addSubview:imageView]; -// } -// -// -// [self flowlayoutInfo]; -// -// -// -// -// MyFlexLayout *layout = MyFlexLayout.new.flex -// .flex_wrap(MyFlex.wrap) -// .justify_content(MyFlex.space_between) -// .flex_direction(MyFlex.row) -// .align_items(MyFlex.center) -// .align_content(MyFlex.stretch) -// .padding(UIEdgeInsetsMake(10, 10, 10, 10)) -// .vert_space(10) -// .horz_space(10) -// .margin_left(0) -// .margin_right(0) -// .margin_top(0) -// .margin_bottom(0) -// .addTo(self.view); -// -// for (int i = 0; i < 2; i++) -// { -// UILabel *label = UILabel.new.flexItem -// .width(600) -// .height(200) -// .order(2-i) -// .align_self(MyFlex.flex_start) -// .flex_grow(1) -// .flex_shrink(1) -// .flex_basis(100) -// .addTo(layout); -// -// label.text = [NSString stringWithFormat:@"%d",i]; -// label.backgroundColor = UIColor.redColor; -// } -// + MyFlexLayout *contentLayout = MyFlexLayout.new.flex + .width(MyLayoutSize.fill) + .flex_grow(1) + .addTo(rootLayout); + + contentLayout.backgroundColor = [UIColor lightGrayColor]; + self.contentLayout = contentLayout; + + flexAttrSeg.selectedSegmentIndex = 0; + self.flex_directionSeg.selectedSegmentIndex = 0; + [self handleFlex_Direction:self.flex_directionSeg]; } @@ -241,36 +235,716 @@ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { } */ +-(void)updateStyleDesc +{ + NSString *strFlexDirection = @""; + switch (self.contentLayout.flex.flex_direction_val) { + case MyFlexDirection_Row: + strFlexDirection =@"row;"; + break; + case MyFlexDirection_Column: + strFlexDirection = @"column;"; + break; + case MyFlexDirection_Row_Reverse: + strFlexDirection = @"row-reverse;"; + break; + case MyFlexDirection_Column_Reverse: + strFlexDirection = @"column-reverse;"; + break; + default: + break; + } + + NSString *strFlexWrap = @""; + switch (self.contentLayout.flex.flex_wrap_val) { + case MyFlexWrap_NoWrap: + strFlexWrap = @"nowrap;"; + break; + case MyFlexWrap_Wrap: + strFlexWrap = @"wrap;"; + break; + case MyFlexWrap_Wrap_Reverse: + strFlexWrap = @"wrap-reverse;"; + break; + default: + break; + } + + NSString *strJustifyContent = @""; + switch (self.contentLayout.flex.justify_content_val) { + case MyFlexGravity_Flex_Start: + strJustifyContent = @"flex-start;"; + break; + case MyFlexGravity_Flex_End: + strJustifyContent = @"flex-end;"; + break; + case MyFlexGravity_Center: + strJustifyContent = @"center;"; + break; + case MyFlexGravity_Space_Between: + strJustifyContent = @"space-between;"; + break; + case MyFlexGravity_Space_Around: + strJustifyContent = @"space-around;"; + default: + break; + } + + NSString *strAlignItems = @""; + switch (self.contentLayout.flex.align_items_val) { + case MyFlexGravity_Flex_End: + strAlignItems = @"flex-end;"; + break; + case MyFlexGravity_Center: + strAlignItems = @"center;"; + break; + case MyFlexGravity_Baseline: + strAlignItems = @"baseline;"; + break; + case MyFlexGravity_Flex_Start: + strAlignItems = @"flex-start;"; + break; + case MyFlexGravity_Stretch: + strAlignItems = @"stretch;"; + break; + default:; + } + + NSString *strAlignContent = @""; + switch (self.contentLayout.flex.align_content_val) { + case MyFlexGravity_Flex_End: + strAlignContent = @"flex-end;"; + break; + case MyFlexGravity_Center: + strAlignContent = @"center;"; + break; + case MyFlexGravity_Space_Between: + strAlignContent = @"space-between;"; + break; + case MyFlexGravity_Flex_Start: + strAlignContent = @"flex-start;"; + break; + case MyFlexGravity_Space_Around: + strAlignContent = @"space-around;"; + break; + case MyFlexGravity_Stretch: + strAlignContent = @"stretch;"; + break; + default:; + } + + self.flexlayoutStyleDescLabel.text = [NSString stringWithFormat:@"Style=\"flex-direction:%@ flex-wrap:%@ justify-content:%@ align-items:%@ align-content:%@\"", + strFlexDirection, + strFlexWrap, + strJustifyContent, + strAlignItems, + strAlignContent]; + +} + + +-(void)editFlexItem:(UIView*)itemView +{ + //创建一个 + MyFlexLayout *dialogLayout = MyFlexLayout.new.flex + .flex_direction(MyFlexDirection_Row) + .align_items(MyFlexGravity_Center) + .flex_wrap(MyFlexWrap_Wrap) + .padding(UIEdgeInsetsMake(10, 10, 10, 10)) + .vert_space(10) + .horz_space(10) + .width(220) + .height(MyLayoutSize.wrap) + .margin_top(80) + .margin_left((self.view.window.frame.size.width - 200)/2.0) + .addTo(self.view.window); + + dialogLayout.backgroundColor = [CFTool color:2]; + + UILabel *widthLabel = UILabel.new.flexItem + .width(MyLayoutSize.wrap) + .height(MyLayoutSize.wrap) + .addTo(dialogLayout); + + widthLabel.text = @"width:"; + + UITextField *widthTextField = UITextField.new.flexItem + .width(100) + .flex_grow(1) + .height(30) + .addTo(dialogLayout); + + widthTextField.tag = 100; + widthTextField.borderStyle = UITextBorderStyleRoundedRect; + + UILabel *heightLabel = UILabel.new.flexItem + .width(MyLayoutSize.wrap) + .height(MyLayoutSize.wrap) + .addTo(dialogLayout); + + heightLabel.text = @"height:"; + + UITextField *heightTextField = UITextField.new.flexItem + .width(100) + .flex_grow(1) + .height(30) + .addTo(dialogLayout); + + heightTextField.tag = 200; + heightTextField.borderStyle = UITextBorderStyleRoundedRect; + + + UILabel *orderLabel = UILabel.new.flexItem + .width(MyLayoutSize.wrap) + .height(MyLayoutSize.wrap) + .addTo(dialogLayout); + + orderLabel.text = @"order:"; + + UITextField *orderTextField = UITextField.new.flexItem + .width(100) + .flex_grow(1) + .height(30) + .addTo(dialogLayout); + + orderTextField.tag = 300; + orderTextField.borderStyle = UITextBorderStyleRoundedRect; + + + UILabel *flex_growLabel = UILabel.new.flexItem + .width(MyLayoutSize.wrap) + .height(MyLayoutSize.wrap) + .addTo(dialogLayout); + + flex_growLabel.text = @"flex-grow:"; + + UITextField *flex_growTextField = UITextField.new.flexItem + .width(100) + .flex_grow(1) + .height(30) + .addTo(dialogLayout); + + flex_growTextField.tag = 400; + flex_growTextField.borderStyle = UITextBorderStyleRoundedRect; + + + UILabel *flex_shrinkLabel = UILabel.new.flexItem + .width(MyLayoutSize.wrap) + .height(MyLayoutSize.wrap) + .addTo(dialogLayout); + + flex_shrinkLabel.text = @"flex-shrink:"; + + UITextField *flex_shrinkTextField = UITextField.new.flexItem + .width(100) + .flex_grow(1) + .height(30) + .addTo(dialogLayout); + + flex_shrinkTextField.tag = 500; + flex_shrinkTextField.borderStyle = UITextBorderStyleRoundedRect; + + + UILabel *flex_basisLabel = UILabel.new.flexItem + .width(MyLayoutSize.wrap) + .height(MyLayoutSize.wrap) + .addTo(dialogLayout); + + flex_basisLabel.text = @"flex-basis:"; + + UITextField *flex_basisTextField = UITextField.new.flexItem + .width(100) + .flex_grow(1) + .height(30) + .addTo(dialogLayout); + + flex_basisTextField.tag = 600; + flex_basisTextField.borderStyle = UITextBorderStyleRoundedRect; + + + UILabel *align_selfLabel = UILabel.new.flexItem + .width(MyLayoutSize.wrap) + .height(MyLayoutSize.wrap) + .addTo(dialogLayout); + + align_selfLabel.text = @"align-self:"; + + UITextField *align_selfTextField = UITextField.new.flexItem + .width(100) + .flex_grow(1) + .height(30) + .addTo(dialogLayout); + + align_selfTextField.tag = 700; + align_selfTextField.borderStyle = UITextBorderStyleRoundedRect; + + + UIButton *addButton = UIButton.new.flexItem + .flex_grow(1) + .width(50) + .height(30) + .addTo(dialogLayout); + + + if (itemView != nil) + { + addButton.tag = (NSInteger)itemView; + [addButton setTitle:@"Save" forState:UIControlStateNormal]; + } + else + [addButton setTitle:@"Add" forState:UIControlStateNormal]; + + [addButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [addButton addTarget:self action:@selector(handleSaveItem:) forControlEvents:UIControlEventTouchUpInside]; + + UIButton *closeButton = UIButton.new.flexItem + .flex_grow(1) + .width(50) + .height(30) + .addTo(dialogLayout); + + [closeButton setTitle:@"Close" forState:UIControlStateNormal]; + [closeButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + + [closeButton addTarget:self action:@selector(handleCloseDialog:) forControlEvents:UIControlEventTouchUpInside]; + + + if (itemView != nil) + { + if (itemView.flexItem.width_val == MyLayoutSize.wrap) + widthTextField.text = @"wrap"; + else if (itemView.flexItem.width_val == MyLayoutSize.fill) + widthTextField.text = @"fill"; + else if (itemView.flexItem.width_val != 0) + widthTextField.text = [@(itemView.flexItem.width_val) stringValue]; + else + widthTextField.text = @""; + + + if (itemView.flexItem.height_val == MyLayoutSize.wrap) + heightTextField.text = @"wrap"; + else if (itemView.flexItem.height_val == MyLayoutSize.fill) + heightTextField.text = @"fill"; + else if (itemView.flexItem.height_val != 0) + heightTextField.text = [@(itemView.flexItem.height_val) stringValue]; + else + heightTextField.text = @""; + + + if (itemView.flexItem.order_val != 0) + orderTextField.text = [@(itemView.flexItem.order_val) stringValue]; + + + if (itemView.flexItem.flex_grow_val != 0) + flex_growTextField.text = [@(itemView.flexItem.flex_grow_val) stringValue]; + + if (itemView.flexItem.flex_shrink_val != 1) + flex_shrinkTextField.text = [@(itemView.flexItem.flex_shrink_val) stringValue]; + + if (itemView.flexItem.flex_basis_val != MyFlex_Auto) + flex_basisTextField.text = [@(itemView.flexItem.flex_basis_val) stringValue]; + + switch (itemView.flexItem.align_self_val) { + case MyFlexGravity_Flex_Start: + align_selfTextField.text = @"flex-start"; + break; + case MyFlexGravity_Flex_End: + align_selfTextField.text = @"flex-end"; + break; + case MyFlexGravity_Center: + align_selfTextField.text = @"center"; + break; + case MyFlexGravity_Baseline: + align_selfTextField.text = @"baseline"; + break; + case MyFlexGravity_Stretch: + align_selfTextField.text = @"stretch"; + break; + default: + break; + } + } +} + + #pragma mark -- Handle Method --(void)handleFlex_Direction:(id)sender +-(IBAction)handleFlexLayoutAttributeChange:(UISegmentedControl*)sender +{ + self.flex_directionSeg.flexItem.visibility(MyVisibility_Gone); + self.flex_wrapSeg.flexItem.visibility(MyVisibility_Gone); + self.justify_contentSeg.flexItem.visibility(MyVisibility_Gone); + self.align_itemsSeg.flexItem.visibility(MyVisibility_Gone); + self.align_contentSeg.flexItem.visibility(MyVisibility_Gone); + + switch (sender.selectedSegmentIndex) { + case 0: + { + self.flex_directionSeg.flexItem.visibility(MyVisibility_Visible); + switch (self.contentLayout.flex.flex_direction_val) { + case MyFlexDirection_Row: + self.flex_directionSeg.selectedSegmentIndex = 0; + break; + case MyFlexDirection_Column: + self.flex_directionSeg.selectedSegmentIndex = 2; + break; + case MyFlexDirection_Row_Reverse: + self.flex_directionSeg.selectedSegmentIndex = 1; + break; + case MyFlexDirection_Column_Reverse: + self.flex_directionSeg.selectedSegmentIndex = 3; + default: + break; + } + } + break; + case 1: + { + self.flex_wrapSeg.flexItem.visibility(MyVisibility_Visible); + switch (self.contentLayout.flex.flex_wrap_val) { + case MyFlexWrap_Wrap: + self.flex_wrapSeg.selectedSegmentIndex = 1; + break; + case MyFlexWrap_NoWrap: + self.flex_wrapSeg.selectedSegmentIndex = 0; + break; + case MyFlexWrap_Wrap_Reverse: + self.flex_wrapSeg.selectedSegmentIndex = 2; + break; + default: + break; + } + } + break; + case 2: + { + self.justify_contentSeg.flexItem.visibility(MyVisibility_Visible); + switch (self.contentLayout.flex.justify_content_val) { + case MyFlexGravity_Flex_Start: + self.justify_contentSeg.selectedSegmentIndex = 0; + break; + case MyFlexGravity_Flex_End: + self.justify_contentSeg.selectedSegmentIndex = 1; + break; + case MyFlexGravity_Center: + self.justify_contentSeg.selectedSegmentIndex = 2; + break; + case MyFlexGravity_Space_Between: + self.justify_contentSeg.selectedSegmentIndex = 3; + break; + case MyFlexGravity_Space_Around: + self.justify_contentSeg.selectedSegmentIndex = 4; + default: + break; + } + } + break; + case 3: + { + self.align_itemsSeg.flexItem.visibility(MyVisibility_Visible); + switch (self.contentLayout.flex.align_items_val) { + case MyFlexGravity_Flex_Start: + self.align_itemsSeg.selectedSegmentIndex = 0; + break; + case MyFlexGravity_Flex_End: + self.align_itemsSeg.selectedSegmentIndex = 1; + break; + case MyFlexGravity_Center: + self.align_itemsSeg.selectedSegmentIndex = 2; + break; + case MyFlexGravity_Stretch: + self.align_itemsSeg.selectedSegmentIndex = 3; + break; + case MyFlexGravity_Baseline: + self.align_itemsSeg.selectedSegmentIndex = 4; + break; + default: + break; + } + } + break; + case 4: + { + self.align_contentSeg.flexItem.visibility(MyVisibility_Visible); + switch (self.contentLayout.flex.align_content_val) { + case MyFlexGravity_Flex_Start: + self.align_contentSeg.selectedSegmentIndex = 0; + break; + case MyFlexGravity_Flex_End: + self.align_contentSeg.selectedSegmentIndex = 1; + break; + case MyFlexGravity_Center: + self.align_contentSeg.selectedSegmentIndex = 2; + break; + case MyFlexGravity_Space_Between: + self.align_contentSeg.selectedSegmentIndex = 3; + break; + case MyFlexGravity_Space_Around: + self.align_contentSeg.selectedSegmentIndex = 4; + break; + case MyFlexGravity_Stretch: + self.align_contentSeg.selectedSegmentIndex = 5; + break; + default:; + } + } + break; + default: + break; + } +} + +-(void)handleFlex_Direction:(UISegmentedControl*)sender { - + switch (sender.selectedSegmentIndex) { + case 0: + self.contentLayout.flex.flex_direction(MyFlexDirection_Row); + break; + case 1: + self.contentLayout.flex.flex_direction(MyFlexDirection_Row_Reverse); + break; + case 2: + self.contentLayout.flex.flex_direction(MyFlexDirection_Column); + break; + case 3: + self.contentLayout.flex.flex_direction(MyFlexDirection_Column_Reverse); + case 4: + default: + break; + } + [self updateStyleDesc]; + [self.contentLayout setNeedsLayout]; +} + +-(void)handleFlex_Wrap:(UISegmentedControl*)sender +{ + switch (sender.selectedSegmentIndex) { + case 0: + self.contentLayout.flex.flex_wrap(MyFlexWrap_NoWrap); + break; + case 1: + self.contentLayout.flex.flex_wrap(MyFlexWrap_Wrap); + break; + case 2: + self.contentLayout.flex.flex_wrap(MyFlexWrap_Wrap_Reverse); + break; + default: + break; + } + [self updateStyleDesc]; + [self.contentLayout setNeedsLayout]; } --(void)handleFlex_Wrap:(id)sender +-(void)handleJustify_Content:(UISegmentedControl*)sender { - + switch (sender.selectedSegmentIndex) { + case 0: + self.contentLayout.flex.justify_content(MyFlexGravity_Flex_Start); + break; + case 1: + self.contentLayout.flex.justify_content(MyFlexGravity_Flex_End); + break; + case 2: + self.contentLayout.flex.justify_content(MyFlexGravity_Center); + break; + case 3: + self.contentLayout.flex.justify_content(MyFlexGravity_Space_Between); + break; + case 4: + self.contentLayout.flex.justify_content(MyFlexGravity_Space_Around); + break; + default: + break; + } + [self updateStyleDesc]; + [self.contentLayout setNeedsLayout]; } --(void)handleJustify_Content:(id)sender +-(void)handleAlign_Items:(UISegmentedControl*)sender { - + switch (sender.selectedSegmentIndex) { + case 0: + self.contentLayout.flex.align_items(MyFlexGravity_Flex_Start); + break; + case 1: + self.contentLayout.flex.align_items(MyFlexGravity_Flex_End); + break; + case 2: + self.contentLayout.flex.align_items(MyFlexGravity_Center); + break; + case 3: + self.contentLayout.flex.align_items(MyFlexGravity_Stretch); + break; + case 4: + self.contentLayout.flex.align_items(MyFlexGravity_Baseline); + break; + default: + break; + } + [self updateStyleDesc]; + [self.contentLayout setNeedsLayout]; +} + + +-(void)handleAlign_Content:(UISegmentedControl*)sender +{ + switch (sender.selectedSegmentIndex) { + case 0: + self.contentLayout.flex.align_content(MyFlexGravity_Flex_Start); + break; + case 1: + self.contentLayout.flex.align_content(MyFlexGravity_Flex_End); + break; + case 2: + self.contentLayout.flex.align_content(MyFlexGravity_Center); + break; + case 3: + self.contentLayout.flex.align_content(MyFlexGravity_Space_Between); + break; + case 4: + self.contentLayout.flex.align_content(MyFlexGravity_Space_Around); + break; + case 5: + self.contentLayout.flex.align_content(MyFlexGravity_Stretch); + break; + default: + break; + } + + [self updateStyleDesc]; + [self.contentLayout setNeedsLayout]; +} + +-(IBAction)handleSpaceChange:(UISwitch*)sender +{ + if (sender.isOn) + self.contentLayout.flex.vert_space(10).horz_space(10); + else + self.contentLayout.flex.vert_space(0).horz_space(0); +} + + +-(IBAction)handlePaddingChange:(UISwitch*)sender +{ + if (sender.isOn) + self.contentLayout.flex.padding(UIEdgeInsetsMake(20, 20, 20, 20)); + else + self.contentLayout.flex.padding(UIEdgeInsetsZero); } --(void)handleAlign_Items:(id)sender + +-(IBAction)handleAddItem:(UIButton*)sender { - + [self editFlexItem:nil]; } +-(IBAction)handleCloseDialog:(UIButton*)sender +{ + [sender.superview removeFromSuperview]; +} --(void)handleAlign_Content:(id)sender +-(IBAction)handleSaveItem:(UIButton*)sender { + + UIButton *itemView = nil; + if (sender.tag != 0) + itemView = (__bridge UIButton*)((void*)sender.tag); + + UITextField *widthTextField = [sender.superview viewWithTag:100]; + UITextField *heightTextField = [sender.superview viewWithTag:200]; + UITextField *orderTextField = [sender.superview viewWithTag:300]; + UITextField *flex_growTextField = [sender.superview viewWithTag:400]; + UITextField *flex_shrinkTextField = [sender.superview viewWithTag:500]; + UITextField *flex_basisTextField = [sender.superview viewWithTag:600]; + UITextField *align_selfTextField = [sender.superview viewWithTag:700]; + + if (itemView == nil) + { + itemView = [UIButton new]; + itemView.backgroundColor = [CFTool color:arc4random_uniform(14) + 1]; + [self.contentLayout addSubview:itemView]; + + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleModifyItemView:)]; + [itemView addGestureRecognizer:tapGesture]; + UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleRemoveItemView:)]; + [itemView addGestureRecognizer:longPressGesture]; + + } + + //设置属性!! + if (widthTextField.text.length == 0 && heightTextField.text.length == 0) + return; + + NSString *widthStr = widthTextField.text; + if ([widthStr isEqualToString:@"wrap"]) + itemView.flexItem.width_val = MyLayoutSize.wrap; + else if ([widthStr isEqualToString:@"fill"]) + itemView.flexItem.width_val = MyLayoutSize.fill; + else + itemView.flexItem.width_val = widthStr.doubleValue; + + NSString *heightStr = heightTextField.text; + if ([heightStr isEqualToString:@"wrap"]) + itemView.flexItem.height_val = MyLayoutSize.wrap; + else if ([heightStr isEqualToString:@"fill"]) + itemView.flexItem.height_val = MyLayoutSize.fill; + else + itemView.flexItem.height_val = heightStr.doubleValue; + + [itemView setTitle:orderTextField.text forState:UIControlStateNormal]; + itemView.flexItem.order_val = orderTextField.text.integerValue; + + + itemView.flexItem.flex_grow_val = flex_growTextField.text.doubleValue; + + if (flex_shrinkTextField.text.length > 0) + itemView.flexItem.flex_shrink_val = flex_shrinkTextField.text.doubleValue; + else + itemView.flexItem.flex_shrink_val = 1; + + if (flex_basisTextField.text.length > 0) + itemView.flexItem.flex_basis_val = flex_basisTextField.text.doubleValue; + else + itemView.flexItem.flex_basis_val = MyFlex_Auto; + + if (align_selfTextField.text.length > 0) + { + if ([align_selfTextField.text isEqualToString:@"flex-start"]) + itemView.flexItem.align_self_val = MyFlexGravity_Flex_Start; + else if ([align_selfTextField.text isEqualToString:@"flex-end"]) + itemView.flexItem.align_self_val = MyFlexGravity_Flex_End; + else if ([align_selfTextField.text isEqualToString:@"center"]) + itemView.flexItem.align_self_val = MyFlexGravity_Center; + else if ([align_selfTextField.text isEqualToString:@"baseline"]) + itemView.flexItem.align_self_val = MyFlexGravity_Baseline; + else if ([align_selfTextField.text isEqualToString:@"stretch"]) + itemView.flexItem.align_self_val = MyFlexGravity_Stretch; + else + itemView.flexItem.align_self_val = MyFlex_Auto; + } + else + { + itemView.flexItem.align_self_val = MyFlex_Auto; + } + + //销毁对话框。 + [sender.superview removeFromSuperview]; + + [self.contentLayout setNeedsLayout]; +} +-(IBAction)handleModifyItemView:(UITapGestureRecognizer*)sender +{ + [self editFlexItem:sender.view]; +} + +-(IBAction)handleRemoveItemView:(UILongPressGestureRecognizer*)sender +{ + [sender.view removeFromSuperview]; } diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index 44381c3..755a601 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -310,5 +310,75 @@ -(void)testSubviewSizeDependent } +-(void)testWrapContentSize2 +{ + //测试一个布局宽度固定,高度包裹,然后子视图的高度依赖宽度,或者子视图高度自适应,然后又有压缩的场景,看是否会导致行高不对,或者整个行高不对。 + + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; + rootLayout.frame = CGRectMake(0, 0, 110, 0); + rootLayout.padding = UIEdgeInsetsMake(10, 10, 5, 5); + rootLayout.mySize = CGSizeMake(110, MyLayoutSize.wrap); + rootLayout.subviewSpace = 6; + rootLayout.gravity = MyGravity_Horz_Fill; + + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(10, 20); + v1.myMargin = 5; + [rootLayout addSubview:v1]; + + UIView *v2 = [UIView new]; + v2.myWidth = 30; + v2.heightSize.equalTo(v2.widthSize); + v2.myMargin = 6; + [rootLayout addSubview:v2]; + + + UIView *v3 = [UIView new]; + v3.mySize = CGSizeMake(10, 50); + v3.myMargin = 2; + [rootLayout addSubview:v3]; + + UIView *v4 = [UIView new]; + v4.myWidth = 20; + v4.heightSize.equalTo(v4.widthSize).multiply(0.5).add(10); + v4.myMargin = 3; + [rootLayout addSubview:v4]; + + UILabel *v5 = [UILabel new]; + v5.text = @"测试测试测试"; + v5.frame = CGRectMake(0, 0, 20, 0); + v5.heightSize.equalTo(@(MyLayoutSize.wrap)); + [rootLayout addSubview:v5]; + + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,110,197.5)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(15,15,12.5,20)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(44.5,16,32.5,32.5)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(90.5,12,12.5,50)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(13,73.5,20,20)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(42,70.5,20,122)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + + rootLayout.isFlex = YES; + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + + NSLog(@""); + //> +// <__NSArrayM 0x600002d2db00>( +// >, +// >, +// >, +// > +} + @end From 2aba00a5a70bb91f0ddd3f41c8a51a7230771abc Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Thu, 17 Oct 2019 19:48:59 +0800 Subject: [PATCH 054/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlowLayout.m | 195 +++++++++++++++++++++++++++--------- 1 file changed, 145 insertions(+), 50 deletions(-) diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 95080ac..d53c69c 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -292,6 +292,51 @@ - (void)myCalcHorzLayoutSinglelineWeight:(CGSize)selfSize totalFloatHeight:(CGFl } } +- (void)myAdjustVertLayoutSinglelineWidth:(CGSize)selfSize rowIndex:(NSInteger)rowIndex floatingWidth:(CGFloat)floatingWidth totalWeight:(CGFloat)totalWeight horzGravity:(MyGravity)horzGravity sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc +{ + if (floatingWidth <= 0.0) + return; + + MyGravity lineHorzGravity = horzGravity; + if (self.lineGravity != nil) + { + lineHorzGravity = self.lineGravity(self, rowIndex); + if (lineHorzGravity == MyGravity_None) + lineHorzGravity = horzGravity; + else + lineHorzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lineHorzGravity]; + } + + CGFloat addXFill = 0; + if (lineHorzGravity == MyGravity_Horz_Fill && totalWeight != 0.0) + { + //流式布局中最后一行不会进行拉伸处理。 + if (lsc.isFlex || startIndex != sbs.count) + addXFill = floatingWidth / count; + } + + for (NSInteger j = startIndex - count; j < startIndex; j++) + { + UIView *sbv = sbs[j]; + + MyFrame *sbvmyFrame = sbv.myFrame; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + + if (sbvsc.weight != 0.0 && totalWeight != 0.0) + { + CGFloat tempWidth = _myCGFloatRound((floatingWidth * sbvsc.weight / totalWeight)); + if (sbvsc.widthSizeInner != nil && sbvsc.widthSizeInner.dimeVal == nil) + tempWidth = [sbvsc.widthSizeInner measureWith:tempWidth]; + + sbvmyFrame.width = tempWidth + sbvmyFrame.width; + } + + //添加拉伸的尺寸。 + if (addXFill != 0.0) + sbvmyFrame.width += addXFill; + } + +} - (void)myCalcVertLayoutSinglelineWidthShrink:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalShrink:(CGFloat)totalShrink sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count { @@ -978,10 +1023,11 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab } + //每行行首的索引位置。 NSMutableIndexSet *arrangeIndexSet = [NSMutableIndexSet new]; - NSInteger rowIndex = 0; //行的索引。 - NSInteger arrangedIndex = 0; + NSInteger arrangedIndex = 0; //行内子视图的索引 CGFloat rowTotalWeight = 0.0; + NSInteger rowIndex = 0; //行的索引。 NSInteger i = 0; for (; i < sbs.count; i++) { @@ -989,10 +1035,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - - CGFloat topSpace = sbvsc.topPosInner.absVal; + CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; - CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; @@ -1014,20 +1058,105 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab else { //如果过了,则表示当前的剩余空间为0了,所以就按新的一行来算。。 - CGFloat floatWidth = selfSize.width - paddingHorz - rowMaxWidth; - if (_myCGFloatLessOrEqual(floatWidth, 0)) + CGFloat floatingWidth = selfSize.width - paddingHorz - rowMaxWidth; + if (_myCGFloatLessOrEqual(floatingWidth, 0)) { - floatWidth += rowMaxWidth; + floatingWidth += rowMaxWidth; arrangedIndex = 0; } if (arrangedIndex != 0) - floatWidth -= horzSpace; + floatingWidth -= horzSpace; - rect.size.width = (floatWidth + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace; + rect.size.width = (floatingWidth + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace; + } + } + + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + + //计算子视图的高度。 + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + + + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + } + + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + + + //计算xPos的值加上leadingSpace + rect.size.width + trailingSpace 的值要小于整体的宽度。 + CGFloat place = xPos + leadingSpace + rect.size.width + trailingSpace; + if (arrangedIndex != 0) + place += horzSpace; + place += paddingTrailing; + + //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的宽度和布局视图保持一致。 + if (!lsc.widthSizeInner.dimeWrapVal && (place - selfSize.width > 0.0001)) + { + [arrangeIndexSet addIndex:i - arrangedIndex]; + + //拉伸以及调整行内子视图的宽度。 + [self myAdjustVertLayoutSinglelineWidth:selfSize rowIndex:rowIndex floatingWidth:selfSize.width - paddingTrailing - xPos totalWeight:rowTotalWeight horzGravity:horzGravity sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; + + + xPos = paddingLeading; + + //计算单独的sbv的宽度是否大于整体的宽度。如果大于则缩小宽度。 + if (_myCGFloatGreat(leadingSpace + trailingSpace + rect.size.width, selfSize.width - paddingHorz)) + { + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:selfSize.width - paddingHorz - leadingSpace - trailingSpace sbvSize:rect.size selfLayoutSize:selfSize]; } + + rowMaxWidth = 0; + rowTotalWeight = 0; + rowIndex++; + arrangedIndex = 0; } + if (arrangedIndex != 0) + xPos += horzSpace; + + + rect.origin.x = xPos + leadingSpace; + xPos += leadingSpace + rect.size.width + trailingSpace; + + if (_myCGFloatLess(rowMaxWidth, (xPos - paddingLeading))) + rowMaxWidth = (xPos - paddingLeading); + + if (lsc.isFlex && sbvsc.weight != 0) + rowTotalWeight += sbvsc.weight; + + sbvmyFrame.frame = rect; + arrangedIndex++; + } + + //最后一行的开始索引。 + [arrangeIndexSet addIndex:i - arrangedIndex]; + + [self myAdjustVertLayoutSinglelineWidth:selfSize rowIndex:rowIndex floatingWidth:selfSize.width - paddingTrailing - xPos totalWeight:rowTotalWeight horzGravity:horzGravity sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; + +///////////////////////////// + //每行行首的索引位置。 + rowIndex = 0; //行的索引。 + arrangedIndex = 0; + NSInteger lineFirstIndex = 0; + i = 0; + for (; i < sbs.count; i++) + { + UIView *sbv = sbs[i]; + + MyFrame *sbvmyFrame = sbv.myFrame; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + + CGFloat topSpace = sbvsc.topPosInner.absVal; + CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; + CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; + CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; + CGRect rect = sbvmyFrame.frame; + + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; //计算子视图的高度。 @@ -1040,14 +1169,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - {//特殊处理宽度等于高度的情况 - rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - } - - //计算xPos的值加上leadingSpace + rect.size.width + trailingSpace 的值要小于整体的宽度。 CGFloat place = xPos + leadingSpace + rect.size.width + trailingSpace; if (arrangedIndex != 0) @@ -1056,43 +1177,17 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab maxWidth = place; + NSUInteger index = [arrangeIndexSet indexLessThanOrEqualToIndex:i]; //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的宽度和布局视图保持一致。 - if (!lsc.widthSizeInner.dimeWrapVal && (place - selfSize.width > 0.0001)) + if (!lsc.widthSizeInner.dimeWrapVal && lineFirstIndex != index) { - [arrangeIndexSet addIndex:i - arrangedIndex]; + lineFirstIndex = index; - //如果是flex并且比重不为0则拉伸所有子视图。 - if (lsc.isFlex && rowTotalWeight != 0.0) - { - //这里只减paddingTrailing的原因是xPos中已经带有paddingLeading了,所以不需要再次减paddingLeading. - [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingTrailing - xPos totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; - } - xPos = paddingLeading; yPos += vertSpace; yPos += [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - //计算单独的sbv的宽度是否大于整体的宽度。如果大于则缩小宽度。 - if (_myCGFloatGreat(leadingSpace + trailingSpace + rect.size.width, selfSize.width - paddingHorz)) - { - - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:selfSize.width - paddingHorz - leadingSpace - trailingSpace sbvSize:rect.size selfLayoutSize:selfSize]; - - //特殊处理高度包裹。 - if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) - { - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - } - - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) - {//特殊处理高度等于宽度的情况 - rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - } - - } - + rowMaxHeight = 0; rowMaxWidth = 0; rowTotalWeight = 0; @@ -1127,8 +1222,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab selfSize.width = maxWidth; //最后一行 - [arrangeIndexSet addIndex:i - arrangedIndex]; - if (lsc.isFlex && rowTotalWeight != 0.0) { //这里只减paddingTrailing的原因是xPos中已经带有paddingLeading了,所以不需要再次减paddingLeading. @@ -1137,6 +1230,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab rowMaxHeight = [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + //////////////////////////////////// + if (lsc.heightSizeInner.dimeWrapVal) { selfSize.height = yPos + paddingBottom + rowMaxHeight; From 303a5634ddc0780314df57c46980eca3d6421b6d Mon Sep 17 00:00:00 2001 From: youngsoft Date: Fri, 18 Oct 2019 00:15:09 +0800 Subject: [PATCH 055/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlowLayout.m | 463 ++++++++++++++++++------------------ 1 file changed, 231 insertions(+), 232 deletions(-) diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index d53c69c..c68422d 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -223,16 +223,16 @@ -(id)createSizeClassInstance #pragma mark -- Private Methods -- (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalWeight:(CGFloat)totalWeight sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count +- (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalWeight:(CGFloat)totalWeight sbs:(NSArray *)sbs nextLineFirstItemIndex:(NSInteger)nextLineFirstItemIndex count:(NSInteger)count { //如果浮动宽度都是小于等于0因为没有拉升必要,所以直接返回 if (totalFloatWidth <= 0.0) return; - CGFloat incOffset = 0; - for (NSInteger j = startIndex - count; j < startIndex; j++) + CGFloat incOffset = 0.0; + for (NSInteger itemIndex = nextLineFirstItemIndex - count; itemIndex < nextLineFirstItemIndex; itemIndex++) { - UIView *sbv = sbs[j]; + UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; @@ -250,7 +250,7 @@ - (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFlo } //第一个子视图不偏移。 - if (j != startIndex - count) + if (itemIndex != nextLineFirstItemIndex - count) sbvmyFrame.leading += incOffset; sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; incOffset += (sbvmyFrame.width - oldWidth); @@ -292,7 +292,7 @@ - (void)myCalcHorzLayoutSinglelineWeight:(CGSize)selfSize totalFloatHeight:(CGFl } } -- (void)myAdjustVertLayoutSinglelineWidth:(CGSize)selfSize rowIndex:(NSInteger)rowIndex floatingWidth:(CGFloat)floatingWidth totalWeight:(CGFloat)totalWeight horzGravity:(MyGravity)horzGravity sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc +- (void)myAdjustVertLayoutSinglelineWidth:(CGSize)selfSize lineIndex:(NSInteger)lineIndex floatingWidth:(CGFloat)floatingWidth totalWeight:(CGFloat)totalWeight horzGravity:(MyGravity)horzGravity sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc { if (floatingWidth <= 0.0) return; @@ -300,15 +300,13 @@ - (void)myAdjustVertLayoutSinglelineWidth:(CGSize)selfSize rowIndex:(NSInteger)r MyGravity lineHorzGravity = horzGravity; if (self.lineGravity != nil) { - lineHorzGravity = self.lineGravity(self, rowIndex); + lineHorzGravity = self.lineGravity(self, lineIndex); if (lineHorzGravity == MyGravity_None) lineHorzGravity = horzGravity; - else - lineHorzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lineHorzGravity]; } CGFloat addXFill = 0; - if (lineHorzGravity == MyGravity_Horz_Fill && totalWeight != 0.0) + if (lineHorzGravity == MyGravity_Horz_Fill && totalWeight == 0.0) { //流式布局中最后一行不会进行拉伸处理。 if (lsc.isFlex || startIndex != sbs.count) @@ -318,7 +316,6 @@ - (void)myAdjustVertLayoutSinglelineWidth:(CGSize)selfSize rowIndex:(NSInteger)r for (NSInteger j = startIndex - count; j < startIndex; j++) { UIView *sbv = sbs[j]; - MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; @@ -328,7 +325,7 @@ - (void)myAdjustVertLayoutSinglelineWidth:(CGSize)selfSize rowIndex:(NSInteger)r if (sbvsc.widthSizeInner != nil && sbvsc.widthSizeInner.dimeVal == nil) tempWidth = [sbvsc.widthSizeInner measureWith:tempWidth]; - sbvmyFrame.width = tempWidth + sbvmyFrame.width; + sbvmyFrame.width += tempWidth; } //添加拉伸的尺寸。 @@ -338,6 +335,49 @@ - (void)myAdjustVertLayoutSinglelineWidth:(CGSize)selfSize rowIndex:(NSInteger)r } +- (void)myAdjustHorzLayoutSinglelineHeight:(CGSize)selfSize lineIndex:(NSInteger)lineIndex floatingHeight:(CGFloat)floatingHeight totalWeight:(CGFloat)totalWeight vertGravity:(MyGravity)vertGravity sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc +{ + if (floatingHeight <= 0.0) + return; + + MyGravity lineVertGravity = vertGravity; + if (self.lineGravity != nil) + { + lineVertGravity = self.lineGravity(self, lineIndex); + if (lineVertGravity == MyGravity_None) + lineVertGravity = vertGravity; + } + + CGFloat addYFill = 0; + if (lineVertGravity == MyGravity_Vert_Fill && totalWeight == 0.0) + { + //流式布局中最后一行不会进行拉伸处理。 + if (lsc.isFlex || startIndex != sbs.count) + addYFill = floatingHeight / count; + } + + for (NSInteger j = startIndex - count; j < startIndex; j++) + { + UIView *sbv = sbs[j]; + MyFrame *sbvmyFrame = sbv.myFrame; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + + if (sbvsc.weight != 0.0 && totalWeight != 0.0) + { + CGFloat tempHeight = _myCGFloatRound((floatingHeight * sbvsc.weight / totalWeight)); + if (sbvsc.heightSizeInner != nil && sbvsc.heightSizeInner.dimeVal == nil) + tempHeight = [sbvsc.heightSizeInner measureWith:tempHeight]; + + sbvmyFrame.height += tempHeight; + } + + //添加拉伸的尺寸。 + if (addYFill != 0.0) + sbvmyFrame.height += addYFill; + } + +} + - (void)myCalcVertLayoutSinglelineWidthShrink:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalShrink:(CGFloat)totalShrink sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count { if (_myCGFloatGreatOrEqual(totalFloatWidth, 0.0)) @@ -387,7 +427,7 @@ - (void)myCalcHorzLayoutSinglelineHeightShrink:(CGSize)selfSize totalFloatHeight } -- (CGFloat)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger)rowIndex rowMaxHeight:(CGFloat)rowMaxHeight rowMaxWidth:(CGFloat)rowMaxWidth rowTotalShrink:(CGFloat)rowTotalShrink horzGravity:(MyGravity)horzGravity vertAlignment:(MyGravity)vertAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +- (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger)rowIndex rowMaxHeight:(CGFloat)rowMaxHeight rowMaxWidth:(CGFloat)rowMaxWidth rowTotalShrink:(CGFloat)rowTotalShrink horzGravity:(MyGravity)horzGravity vertAlignment:(MyGravity)vertAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc { CGFloat lineMaxHeight = rowMaxHeight; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; @@ -454,14 +494,6 @@ - (CGFloat)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInte break; } - //处理内容拉伸的情况。这里是只有内容约束布局才支持尺寸拉伸。 - if (lsc.arrangedCount == 0 && lineHorzGravity == MyGravity_Horz_Fill) - { - //不是最后一行。。 - if (lsc.isFlex || startIndex != sbs.count) - addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / count; - } - //压缩减少的尺寸汇总。 CGFloat totalShrinkSize = 0.0; //基线位置 @@ -543,37 +575,7 @@ - (CGFloat)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInte //内容约束布局并且是填充尺寸或者拉升尺寸。 if (addXFill != 0.0) { - if (lsc.arrangedCount == 0 && lineHorzGravity == MyGravity_Horz_Fill) - { - sbvmyFrame.width += addXFill; - if (j != startIndex - count) - sbvmyFrame.leading += addXFill * (j - (startIndex - count)); - - //特殊处理一下高度依赖宽度,以及宽度是固定但是高度自适应的情况,但这里有可能引起当前行的最高值的变化。 - - BOOL hasHeightChange = NO; - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) - {//特殊处理高度等于宽度的情况 - sbvmyFrame.height = [sbvsc.heightSizeInner measureWith:sbvmyFrame.width]; - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - hasHeightChange = YES; - } - - if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) - {//特殊处理高度自适应的情况。 - sbvmyFrame.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:sbvmyFrame.width]; - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - hasHeightChange = YES; - } - - if (hasHeightChange) - { - //得到最大的行高, - if (_myCGFloatLess(lineMaxHeight, sbvmyFrame.top + sbvmyFrame.height + sbvsc.bottomPosInner.absVal)) - lineMaxHeight = sbvmyFrame.top + sbvmyFrame.height + sbvsc.bottomPosInner.absVal; - } - } - else + if ( lineHorzGravity != MyGravity_Horz_Fill) { //其他的只拉伸间距 sbvmyFrame.leading += addXFill * (j - (startIndex - count)); @@ -618,10 +620,9 @@ - (CGFloat)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInte } } - return lineMaxHeight; } -- (CGFloat)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger)colIndex colMaxWidth:(CGFloat)colMaxWidth colMaxHeight:(CGFloat)colMaxHeight colTotalShrink:(CGFloat)colTotalShrink vertGravity:(MyGravity)vertGravity horzAlignment:(MyGravity)horzAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +- (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger)colIndex colMaxWidth:(CGFloat)colMaxWidth colMaxHeight:(CGFloat)colMaxHeight colTotalShrink:(CGFloat)colTotalShrink vertGravity:(MyGravity)vertGravity horzAlignment:(MyGravity)horzAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc { CGFloat lineMaxWidth = colMaxWidth; CGFloat paddingTop = lsc.myLayoutTopPadding; @@ -684,13 +685,7 @@ - (CGFloat)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInte break; } - //处理内容拉伸的情况。 - if (lsc.arrangedCount == 0 && lineVertGravity == MyGravity_Vert_Fill) - { - if (lsc.isFlex || startIndex != sbs.count) - addYFill = (selfSize.height - paddingVert - colMaxHeight) / count; - } - + //压缩减少的尺寸汇总。 CGFloat totalShrinkSize = 0; //将整行的位置进行调整。 @@ -763,24 +758,7 @@ - (CGFloat)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInte //内容约束布局并且是填充尺寸或者拉升尺寸。 if (addYFill != 0.0) { - if (lsc.arrangedCount == 0 && lineVertGravity == MyGravity_Vert_Fill) - { - sbvmyFrame.height += addYFill; - if (j != startIndex - count) - sbvmyFrame.top += addYFill * (j - (startIndex - count)); - - //特殊考虑一下高度等于宽度的问题 - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - {//特殊处理宽度等于高度的情况 - sbvmyFrame.width = [sbvsc.widthSizeInner measureWith:sbvmyFrame.height]; - sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - - //得到最大的行宽, - if (_myCGFloatLess(lineMaxWidth, sbvmyFrame.leading + sbvmyFrame.width + sbvsc.trailingPosInner.absVal)) - lineMaxWidth = sbvmyFrame.top + sbvmyFrame.leading + sbvmyFrame.width + sbvsc.trailingPosInner.absVal; - } - } - else + if (lineVertGravity != MyGravity_Vert_Fill) { //只拉伸间距 sbvmyFrame.top += addYFill * (j - (startIndex - count)); @@ -817,7 +795,6 @@ - (CGFloat)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInte } } - return lineMaxWidth; } @@ -1012,7 +989,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - //暂时把宽度存放sbv.myFrame.trailing上。因为浮动布局来说这个属性无用。 + //暂时把宽度存放sbv.myFrame.trailing上。因为流式布局来说这个属性无用。 sbvmyFrame.trailing = leadingSpace + rect.size.width + trailingSpace; if (_myCGFloatGreat(sbvmyFrame.trailing, selfSize.width - paddingHorz)) sbvmyFrame.trailing = selfSize.width - paddingHorz; @@ -1023,16 +1000,15 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab } - //每行行首的索引位置。 - NSMutableIndexSet *arrangeIndexSet = [NSMutableIndexSet new]; + //每行行首子视图的索引位置。 + NSMutableIndexSet *lineFirstSubviewIndexSet = [NSMutableIndexSet new]; + NSInteger lineIndex = 0; //行的索引。 NSInteger arrangedIndex = 0; //行内子视图的索引 - CGFloat rowTotalWeight = 0.0; - NSInteger rowIndex = 0; //行的索引。 + CGFloat lineTotalWeight = 0.0; NSInteger i = 0; for (; i < sbs.count; i++) { UIView *sbv = sbs[i]; - MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; @@ -1048,6 +1024,15 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab else if (sbvsc.widthSizeInner.dimeVal != nil) { rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + + //计算子视图的高度。 + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + } } else if (sbvsc.weight != 0) { @@ -1057,96 +1042,79 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab } else { - //如果过了,则表示当前的剩余空间为0了,所以就按新的一行来算。。 - CGFloat floatingWidth = selfSize.width - paddingHorz - rowMaxWidth; + CGFloat floatingWidth = selfSize.width - paddingTrailing - xPos; if (_myCGFloatLessOrEqual(floatingWidth, 0)) { - floatingWidth += rowMaxWidth; - arrangedIndex = 0; + //如果当前行的剩余空间不够,则需要换行来计算相对的宽度占比,这时候剩余空间就是按整行来算,并且将行索引设置为0 + floatingWidth = selfSize.width - paddingHorz; + } + else + { + if (arrangedIndex != 0) + floatingWidth -= horzSpace; } - - if (arrangedIndex != 0) - floatingWidth -= horzSpace; rect.size.width = (floatingWidth + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace; } } - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - {//特殊处理宽度等于高度的情况 - - //计算子视图的高度。 - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - - - rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; - } - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - //计算xPos的值加上leadingSpace + rect.size.width + trailingSpace 的值要小于整体的宽度。 CGFloat place = xPos + leadingSpace + rect.size.width + trailingSpace; if (arrangedIndex != 0) place += horzSpace; place += paddingTrailing; - //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的宽度和布局视图保持一致。 + //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。 if (!lsc.widthSizeInner.dimeWrapVal && (place - selfSize.width > 0.0001)) { - [arrangeIndexSet addIndex:i - arrangedIndex]; + //保存行首子视图的索引 + [lineFirstSubviewIndexSet addIndex:i - arrangedIndex]; //拉伸以及调整行内子视图的宽度。 - [self myAdjustVertLayoutSinglelineWidth:selfSize rowIndex:rowIndex floatingWidth:selfSize.width - paddingTrailing - xPos totalWeight:rowTotalWeight horzGravity:horzGravity sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; + [self myAdjustVertLayoutSinglelineWidth:selfSize lineIndex:lineIndex floatingWidth:selfSize.width - paddingTrailing - xPos totalWeight:lineTotalWeight horzGravity:horzGravity sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; xPos = paddingLeading; - //计算单独的sbv的宽度是否大于整体的宽度。如果大于则缩小宽度。 + //如何这个sbv的宽度大于整体布局视图的宽度。则将子视图的宽度缩小变为和布局视图一样宽 if (_myCGFloatGreat(leadingSpace + trailingSpace + rect.size.width, selfSize.width - paddingHorz)) { rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:selfSize.width - paddingHorz - leadingSpace - trailingSpace sbvSize:rect.size selfLayoutSize:selfSize]; } - rowMaxWidth = 0; - rowTotalWeight = 0; - rowIndex++; + lineTotalWeight = 0; + lineIndex++; arrangedIndex = 0; } if (arrangedIndex != 0) xPos += horzSpace; - rect.origin.x = xPos + leadingSpace; xPos += leadingSpace + rect.size.width + trailingSpace; - if (_myCGFloatLess(rowMaxWidth, (xPos - paddingLeading))) - rowMaxWidth = (xPos - paddingLeading); - - if (lsc.isFlex && sbvsc.weight != 0) - rowTotalWeight += sbvsc.weight; + if (lsc.isFlex && sbvsc.weight != 0.0) + lineTotalWeight += sbvsc.weight; sbvmyFrame.frame = rect; arrangedIndex++; } - //最后一行的开始索引。 - [arrangeIndexSet addIndex:i - arrangedIndex]; + //最后一行的行首索引 + [lineFirstSubviewIndexSet addIndex:i - arrangedIndex]; - [self myAdjustVertLayoutSinglelineWidth:selfSize rowIndex:rowIndex floatingWidth:selfSize.width - paddingTrailing - xPos totalWeight:rowTotalWeight horzGravity:horzGravity sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; + [self myAdjustVertLayoutSinglelineWidth:selfSize lineIndex:lineIndex floatingWidth:selfSize.width - paddingTrailing - xPos totalWeight:lineTotalWeight horzGravity:horzGravity sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; -///////////////////////////// - //每行行首的索引位置。 - rowIndex = 0; //行的索引。 - arrangedIndex = 0; - NSInteger lineFirstIndex = 0; + xPos = paddingLeading; + lineIndex = 0; //行的索引。 + arrangedIndex = 0; //行内的子视图索引 + NSInteger oldLineFirstIndex = 0; i = 0; for (; i < sbs.count; i++) { UIView *sbv = sbs[i]; - MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; @@ -1170,29 +1138,27 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab } //计算xPos的值加上leadingSpace + rect.size.width + trailingSpace 的值要小于整体的宽度。 - CGFloat place = xPos + leadingSpace + rect.size.width + trailingSpace; + maxWidth= xPos + leadingSpace + rect.size.width + trailingSpace; if (arrangedIndex != 0) - place += horzSpace; - place += paddingTrailing; - - maxWidth = place; + maxWidth += horzSpace; + maxWidth += paddingTrailing; - NSUInteger index = [arrangeIndexSet indexLessThanOrEqualToIndex:i]; - //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的宽度和布局视图保持一致。 - if (!lsc.widthSizeInner.dimeWrapVal && lineFirstIndex != index) + NSUInteger lineFirstIndex = [lineFirstSubviewIndexSet indexLessThanOrEqualToIndex:i]; + if (!lsc.widthSizeInner.dimeWrapVal && oldLineFirstIndex != lineFirstIndex) { - lineFirstIndex = index; + oldLineFirstIndex = lineFirstIndex; xPos = paddingLeading; yPos += vertSpace; - yPos += [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + yPos += rowMaxHeight; + + [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:lineIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; rowMaxHeight = 0; rowMaxWidth = 0; - rowTotalWeight = 0; arrangedIndex = 0; - rowIndex++; + lineIndex++; } @@ -1210,9 +1176,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab if (_myCGFloatLess(rowMaxWidth, (xPos - paddingLeading))) rowMaxWidth = (xPos - paddingLeading); - if (lsc.isFlex && sbvsc.weight != 0) - rowTotalWeight += sbvsc.weight; - sbvmyFrame.frame = rect; arrangedIndex++; } @@ -1222,15 +1185,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab selfSize.width = maxWidth; //最后一行 - if (lsc.isFlex && rowTotalWeight != 0.0) - { - //这里只减paddingTrailing的原因是xPos中已经带有paddingLeading了,所以不需要再次减paddingLeading. - [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingTrailing - xPos totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; - } - - rowMaxHeight = [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - - //////////////////////////////////// + [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:lineIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; if (lsc.heightSizeInner.dimeWrapVal) { @@ -1252,8 +1207,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab } else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) { - if (arrangeIndexSet.count > 0) - fill = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / arrangeIndexSet.count; + if (lineFirstSubviewIndexSet.count > 0) + fill = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / lineFirstSubviewIndexSet.count; //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' if (fill < 0 && vertGravity == MyGravity_Vert_Stretch) @@ -1261,13 +1216,13 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab } else if (vertGravity == MyGravity_Vert_Between) { - if (arrangeIndexSet.count > 1) - between = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / (arrangeIndexSet.count - 1); + if (lineFirstSubviewIndexSet.count > 1) + between = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / (lineFirstSubviewIndexSet.count - 1); } else if (vertGravity == MyGravity_Vert_Around) { - if (arrangeIndexSet.count > 1) - between = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / arrangeIndexSet.count; + if (lineFirstSubviewIndexSet.count > 1) + between = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / lineFirstSubviewIndexSet.count; } if (addYPos != 0 || between != 0 || fill != 0) @@ -1283,7 +1238,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab sbvmyFrame.top += addYPos; //找到行的最初索引。 - NSUInteger index = [arrangeIndexSet indexLessThanOrEqualToIndex:i]; + NSUInteger index = [lineFirstSubviewIndexSet indexLessThanOrEqualToIndex:i]; if (lastIndex != index) { lastIndex = index; @@ -1405,7 +1360,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (rowTotalWeight != 0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedCount]; + [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs nextLineFirstItemIndex:i count:arrangedCount]; } if (rowTotalShrink != 0 && horzGravity != MyGravity_Horz_Fill) @@ -1487,7 +1442,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (rowTotalWeight != 0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; + [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs nextLineFirstItemIndex:i count:arrangedIndex]; } //如果有压缩子视图的处理则需要压缩子视图。 @@ -1523,7 +1478,9 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray { arrangedIndex = 0; yPos += vertSpace; - yPos += [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + yPos += rowMaxHeight; + + [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; //分别处理水平分页和垂直分页。 if (isHorzPaging) @@ -1679,9 +1636,9 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray } //最后一行,有可能因为行宽的压缩导致那些高度依赖宽度以及高度自适应的视图会增加高度,从而使得行高被调整。 - CGFloat lastlineRowMaxHeight = [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - //在计算总体行高时,需要考虑这种高度出现变化的情况。 - maxHeight += paddingBottom + (lastlineRowMaxHeight - rowMaxHeight); + [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + + maxHeight += paddingBottom; if (lsc.heightSizeInner.dimeWrapVal) { @@ -1830,7 +1787,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - //暂时把宽度存放sbv.myFrame.trailing上。因为浮动布局来说这个属性无用。 + //暂时把宽度存放sbv.myFrame.trailing上。因为流式布局来说这个属性无用。 sbvmyFrame.trailing = topSpace + rect.size.height + bottomSpace; if (_myCGFloatGreat(sbvmyFrame.trailing, selfSize.height - paddingVert)) sbvmyFrame.trailing = selfSize.height - paddingVert; @@ -1839,24 +1796,22 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab [sbs setArray:[self myGetAutoArrangeSubviews:sbs selfSize:selfSize.height - paddingVert space:vertSpace]]; } - NSMutableIndexSet *arrangeIndexSet = [NSMutableIndexSet new]; - NSInteger colIndex = 0; + NSMutableIndexSet *lineFirstSubviewIndexSet = [NSMutableIndexSet new]; + NSInteger lineIndex = 0; NSInteger arrangedIndex = 0; - CGFloat colTotalWeight = 0.0; + CGFloat lineTotalWeight = 0.0; NSInteger i = 0; for (; i < sbs.count; i++) { UIView *sbv = sbs[i]; - MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.absVal; - CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; - CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; - + + //这里先计算一下宽度,因为有可能有宽度固定,高度自适应的情况。 rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; @@ -1867,6 +1822,12 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab else if (sbvsc.heightSizeInner.dimeVal != nil) { rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + {//特殊处理高度等于宽度的情况 + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } } else if (sbvsc.weight != 0) { @@ -1877,33 +1838,23 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab else { //如果过了,则表示当前的剩余空间为0了,所以就按新的一行来算。。 - CGFloat floatHeight = selfSize.height - paddingVert - colMaxHeight; - if (_myCGFloatLessOrEqual(floatHeight, 0)) + CGFloat floatingHeight = selfSize.height - paddingBottom - yPos; + if (_myCGFloatLessOrEqual(floatingHeight, 0)) { - floatHeight += colMaxHeight; - arrangedIndex = 0; + floatingHeight += selfSize.height - paddingVert; + } + else + { + if (arrangedIndex != 0) + floatingHeight -= vertSpace; } - if (arrangedIndex != 0) - floatHeight -= vertSpace; - - rect.size.height = (floatHeight + sbvsc.heightSizeInner.addVal) * sbvsc.weight - topSpace - bottomSpace; + rect.size.height = (floatingHeight + sbvsc.heightSizeInner.addVal) * sbvsc.weight - topSpace - bottomSpace; } } rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) - {//特殊处理高度等于宽度的情况 - rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - } - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - {//特殊处理宽度等于高度的情况 - rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - } //计算yPos的值加上topSpace + rect.size.height + bottomSpace的值要小于整体的高度。 CGFloat place = yPos + topSpace + rect.size.height + bottomSpace; @@ -1911,40 +1862,98 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab place += vertSpace; place += paddingBottom; - maxHeight = place; - //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的宽度和布局视图保持一致。 if (!lsc.heightSizeInner.dimeWrapVal && (place - selfSize.height > 0.0001)) { - [arrangeIndexSet addIndex:i - arrangedIndex]; + [lineFirstSubviewIndexSet addIndex:i - arrangedIndex]; - if (lsc.isFlex && colTotalWeight != 0) - { - //因为yPos中已经包含了paddingTop,所以这里不需要再减了。 - [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingBottom - yPos totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; - } + //拉伸以及调整行内子视图的高度。 + [self myAdjustHorzLayoutSinglelineHeight:selfSize lineIndex:lineIndex floatingHeight:selfSize.height - paddingBottom - yPos totalWeight:lineTotalWeight vertGravity:vertGravity sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; yPos = paddingTop; - xPos += horzSpace; - xPos += [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; //计算单独的sbv的高度是否大于整体的高度。如果大于则缩小高度。 if (_myCGFloatGreat(topSpace + bottomSpace + rect.size.height, selfSize.height - paddingVert)) { rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:selfSize.height - paddingVert - topSpace - bottomSpace sbvSize:rect.size selfLayoutSize:selfSize]; - - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - {//特殊处理宽度等于高度的情况 - rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - } } + lineTotalWeight = 0; + lineIndex++; + arrangedIndex = 0; + } + + if (arrangedIndex != 0) + yPos += vertSpace; + + + rect.origin.y = yPos + topSpace; + yPos += topSpace + rect.size.height + bottomSpace; + + if (lsc.isFlex && sbvsc.weight != 0) + lineTotalWeight += sbvsc.weight; + + sbvmyFrame.frame = rect; + arrangedIndex++; + + } + + //最后一行的行首索引 + [lineFirstSubviewIndexSet addIndex:i - arrangedIndex]; + + [self myAdjustHorzLayoutSinglelineHeight:selfSize lineIndex:lineIndex floatingHeight:selfSize.height - paddingBottom - yPos totalWeight:lineTotalWeight vertGravity:vertGravity sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; + + + yPos = paddingTop; + lineIndex = 0; //行的索引。 + arrangedIndex = 0; //行内的子视图索引 + NSInteger oldLineFirstIndex = 0; + i = 0; + for (; i < sbs.count; i++) + { + UIView *sbv = sbs[i]; + MyFrame *sbvmyFrame = sbv.myFrame; + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + + CGFloat topSpace = sbvsc.topPosInner.absVal; + CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; + CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; + CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; + CGRect rect = sbvmyFrame.frame; + + + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + + + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + } + + //计算yPos的值加上topSpace + rect.size.height + bottomSpace 的值要小于整体的高度。 + maxHeight= yPos + topSpace + rect.size.height + bottomSpace; + if (arrangedIndex != 0) + maxHeight += vertSpace; + maxHeight += paddingBottom; + + NSUInteger lineFirstIndex = [lineFirstSubviewIndexSet indexLessThanOrEqualToIndex:i]; + if (!lsc.widthSizeInner.dimeWrapVal && oldLineFirstIndex != lineFirstIndex) + { + oldLineFirstIndex = lineFirstIndex; + + yPos = paddingTop; + xPos += horzSpace; + xPos += colMaxWidth; + + [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:lineIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + + colMaxWidth = 0; colMaxHeight = 0; arrangedIndex = 0; - colTotalWeight = 0; - colIndex++; + lineIndex++; + } if (arrangedIndex != 0) @@ -1961,27 +1970,15 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab if (_myCGFloatLess(colMaxHeight, (yPos - paddingTop))) colMaxHeight = (yPos - paddingTop); - if (lsc.isFlex && sbvsc.weight != 0) - colTotalWeight += sbvsc.weight; - sbvmyFrame.frame = rect; arrangedIndex++; - } if (lsc.heightSizeInner.dimeWrapVal) selfSize.height = maxHeight; - //最后一行 - [arrangeIndexSet addIndex:i - arrangedIndex]; - - if (lsc.isFlex && colTotalWeight != 0) - { - //因为yPos中已经包含了paddingTop,所以这里不需要再减了。 - [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingBottom - yPos totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; - } - colMaxWidth = [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:lineIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; if (lsc.widthSizeInner.dimeWrapVal) { @@ -2003,8 +2000,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab } else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) { - if (arrangeIndexSet.count > 0) - fill = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / arrangeIndexSet.count; + if (lineFirstSubviewIndexSet.count > 0) + fill = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / lineFirstSubviewIndexSet.count; //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' if (fill < 0 && horzGravity == MyGravity_Horz_Stretch) @@ -2012,13 +2009,13 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab } else if (horzGravity == MyGravity_Horz_Between) { - if (arrangeIndexSet.count > 1) - between = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / (arrangeIndexSet.count - 1); + if (lineFirstSubviewIndexSet.count > 1) + between = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / (lineFirstSubviewIndexSet.count - 1); } else if (horzGravity == MyGravity_Horz_Around) { - if (arrangeIndexSet.count > 1) - between = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / arrangeIndexSet.count; + if (lineFirstSubviewIndexSet.count > 1) + between = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / lineFirstSubviewIndexSet.count; } if (addXPos != 0 || between != 0 || fill != 0) @@ -2033,7 +2030,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab sbvmyFrame.leading += addXPos; //找到行的最初索引。 - NSUInteger index = [arrangeIndexSet indexLessThanOrEqualToIndex:i]; + NSUInteger index = [lineFirstSubviewIndexSet indexLessThanOrEqualToIndex:i]; if (lastIndex != index) { lastIndex = index; @@ -2277,7 +2274,9 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray { arrangedIndex = 0; xPos += horzSpace; - xPos += [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc];; + xPos += colMaxWidth; + + [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc];; //分别处理水平分页和垂直分页。 if (isVertPaging) @@ -2409,9 +2408,9 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray } //最后一列 - CGFloat lastlineColMaxWidth = [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - maxWidth += paddingTrailing + (lastlineColMaxWidth - colMaxWidth); + maxWidth += paddingTrailing; if (lsc.widthSizeInner.dimeWrapVal) { From e39e19db9046f3bbc17d0d8c0033517a67768cc8 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Fri, 18 Oct 2019 00:27:49 +0800 Subject: [PATCH 056/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlowLayout.m | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index c68422d..8bc1246 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -1281,12 +1281,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray BOOL autoArrange = lsc.autoArrange; NSInteger arrangedCount = lsc.arrangedCount; - CGFloat xPos = paddingLeading; - CGFloat yPos = paddingTop; - CGFloat rowMaxHeight = 0; //某一行的最高值。 - CGFloat rowMaxWidth = 0; //某一行的最宽值 - CGFloat maxWidth = paddingLeading; //全部行的最宽值 - CGFloat maxHeight = paddingTop; //最大的高度 + MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; MyGravity vertAlign = lsc.arrangedGravity & MyGravity_Horz_Mask; @@ -1295,6 +1290,13 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray CGFloat horzSpace = lsc.subviewHSpace; CGFloat subviewSize = [self myCalcMaxMinSubviewSize:selfSize.width - paddingHorz lsc:(MyFlowLayoutViewSizeClass*)lsc arrangedCount:arrangedCount space:&horzSpace]; + CGFloat xPos = paddingLeading; + CGFloat yPos = paddingTop; + CGFloat rowMaxHeight = 0.0; //某一行的最高值。 + CGFloat rowMaxWidth = 0.0; //某一行的最宽值 + CGFloat maxWidth = paddingLeading; //全部行的最大宽度 + CGFloat maxHeight = paddingTop; //最大的高度 + #if TARGET_OS_IOS //判断父滚动视图是否分页滚动 BOOL isPagingScroll = (self.superview != nil && From 7ed485755abdd1b14d873b769f1311229e91b439 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Fri, 18 Oct 2019 09:30:36 +0800 Subject: [PATCH 057/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlowLayout.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 8bc1246..d694d75 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -2075,22 +2075,22 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray BOOL autoArrange = lsc.autoArrange; NSInteger arrangedCount = lsc.arrangedCount; - CGFloat xPos = paddingLeading; - CGFloat yPos = paddingTop; - CGFloat colMaxWidth = 0; //每列的最大宽度 - CGFloat colMaxHeight = 0; //每列的最大高度 - CGFloat maxHeight = paddingTop; - CGFloat maxWidth = paddingLeading; //最大的宽度。 MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; MyGravity horzAlign = [self myConvertLeftRightGravityToLeadingTrailing:lsc.arrangedGravity & MyGravity_Vert_Mask]; - CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; CGFloat subviewSize = [self myCalcMaxMinSubviewSize:selfSize.height - paddingVert lsc:(MyFlowLayoutViewSizeClass*)lsc arrangedCount:arrangedCount space:&vertSpace]; + CGFloat xPos = paddingLeading; + CGFloat yPos = paddingTop; + CGFloat colMaxWidth = 0; //每列的最大宽度 + CGFloat colMaxHeight = 0; //每列的最大高度 + CGFloat maxHeight = paddingTop; + CGFloat maxWidth = paddingLeading; //最大的宽度。 + //父滚动视图是否分页滚动。 #if TARGET_OS_IOS //判断父滚动视图是否分页滚动 From 2b653104802fd10194448a8da877d0fb591db348 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Fri, 18 Oct 2019 10:54:38 +0800 Subject: [PATCH 058/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayoutDemo/AllTestExampleViewController.m | 32 ++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/MyLayoutDemo/AllTestExampleViewController.m b/MyLayoutDemo/AllTestExampleViewController.m index 8693239..f9dd476 100644 --- a/MyLayoutDemo/AllTestExampleViewController.m +++ b/MyLayoutDemo/AllTestExampleViewController.m @@ -23,7 +23,8 @@ - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; - [self example1]; + // [self example1]; + [self example2]; } - (void)didReceiveMemoryWarning { @@ -95,6 +96,35 @@ -(void)example1 } +-(void)example2 +{ + MyFrameLayout *rootLayout = [MyFrameLayout new]; + rootLayout.myMargin = 0; + [self.view addSubview:rootLayout]; + + // B 视图 + UIScrollView *scrollview = [[UIScrollView alloc] init]; + scrollview.backgroundColor = [UIColor blueColor]; + scrollview.myHorzMargin = 0; + scrollview.wrapContentHeight = YES; + scrollview.heightSize.max(400).min(280); + [rootLayout addSubview:scrollview]; + + // 内容C视图 + MyLinearLayout * backLinear = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + backLinear.backgroundColor = [UIColor greenColor]; + backLinear.myHorzMargin = 0; + backLinear.heightSize.min(280); + backLinear.gravity = MyGravity_Vert_Bottom; + [scrollview addSubview:backLinear]; + + UIView *v = [UIView new]; + v.myHeight = 500; //调整不同的尺寸得到不同的结果。 + v.myWidth = 100; + v.backgroundColor = [UIColor redColor]; + [backLinear addSubview:v]; + +} @end From 821ed03c5c22bb6247a69df7f571deea0eb5e148 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Sun, 20 Oct 2019 14:02:36 +0800 Subject: [PATCH 059/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFloatLayout.m | 82 +++-- MyLayout/Lib/MyFlowLayout.m | 314 ++++++++-------- MyLayoutDemo/AllTestExampleViewController.m | 2 +- MyLayoutTests/MyFloatLayoutTestCase.m | 124 +++++++ MyLayoutTests/MyFlowLayoutTestCase.m | 381 +++++++++++++++++--- MyLayoutTests/MyLayoutTestCaseBase.h | 5 + MyLayoutTests/MyLayoutTestCaseBase.m | 2 + MyLayoutTests/MyLinearLayoutTestCase.m | 58 ++- 8 files changed, 719 insertions(+), 249 deletions(-) diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 3663c5f..87392da 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -821,27 +821,32 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i maxHeight += paddingBottom; if (lsc.heightSizeInner.dimeWrapVal) - selfSize.height = maxHeight; - else { - CGFloat addYPos = 0; - MyGravity mgvert = lsc.gravity & MyGravity_Horz_Mask; - if (mgvert == MyGravity_Vert_Center) - { - addYPos = (selfSize.height - maxHeight) / 2; - } - else if (mgvert == MyGravity_Vert_Bottom) - { - addYPos = selfSize.height - maxHeight; - } - - if (addYPos != 0) + selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:maxHeight sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + } + + if (selfSize.height != maxHeight) + { + MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; + if (vertGravity != MyGravity_None) { - for (int i = 0; i < sbs.count; i++) + CGFloat addYPos = 0; + if (vertGravity == MyGravity_Vert_Center) { - UIView *sbv = sbs[i]; - - sbv.myFrame.top += addYPos; + addYPos = (selfSize.height - maxHeight) / 2; + } + else if (vertGravity == MyGravity_Vert_Bottom) + { + addYPos = selfSize.height - maxHeight; + } + + if (addYPos != 0) + { + for (int i = 0; i < sbs.count; i++) + { + UIView *sbv = sbs[i]; + sbv.myFrame.top += addYPos; + } } } } @@ -1281,31 +1286,34 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i maxWidth += paddingTrailing; if (lsc.widthSizeInner.dimeWrapVal) - selfSize.width = maxWidth; - else { - CGFloat addXPos = 0; + selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:maxWidth sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + } + + if (selfSize.width != maxWidth) + { MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; - - if (horzGravity == MyGravity_Horz_Center) + if (horzGravity != MyGravity_None) { - addXPos = (selfSize.width - maxWidth) / 2; - } - else if (horzGravity == MyGravity_Horz_Trailing) - { - addXPos = selfSize.width - maxWidth; - } - - if (addXPos != 0) - { - for (int i = 0; i < sbs.count; i++) + CGFloat addXPos = 0; + if (horzGravity == MyGravity_Horz_Center) { - UIView *sbv = sbs[i]; - - sbv.myFrame.leading += addXPos; + addXPos = (selfSize.width - maxWidth) / 2; + } + else if (horzGravity == MyGravity_Horz_Trailing) + { + addXPos = selfSize.width - maxWidth; + } + + if (addXPos != 0) + { + for (int i = 0; i < sbs.count; i++) + { + UIView *sbv = sbs[i]; + sbv.myFrame.leading += addXPos; + } } } - } //如果有子视图设置了对齐属性,那么就要对处在同一列内的子视图进行对齐设置。 diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index d694d75..fb8bcb0 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -955,12 +955,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; CGFloat paddingHorz = paddingLeading + paddingTrailing; - CGFloat xPos = paddingLeading; - CGFloat yPos = paddingTop; - CGFloat rowMaxHeight = 0; //某一行的最高值。 - CGFloat rowMaxWidth = 0; //某一行的最宽值。 - CGFloat maxWidth = 0; //所有行中最宽的值。 - MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; MyGravity vertAlign = lsc.arrangedGravity & MyGravity_Horz_Mask; @@ -970,6 +964,12 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab CGFloat horzSpace = lsc.subviewHSpace; CGFloat subviewSize = [self myCalcMaxMinSubviewSizeForContent:selfSize.width - paddingHorz lsc:(MyFlowLayoutViewSizeClass*)lsc space:&horzSpace]; + CGFloat xPos = paddingLeading; + CGFloat yPos = paddingTop; + CGFloat rowMaxHeight = 0.0; //某一行的最高值。 + CGFloat rowMaxWidth = 0.0; //某一行的最宽值。 + CGFloat maxWidth = 0.0; //所有行中最宽的值。 + if (lsc.autoArrange) { //计算出每个子视图的宽度。 @@ -1016,8 +1016,15 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; + //这里先算一下那些有约束的高度,因为有可能有一些子视图的宽度等于这个子视图的高度。 + if (sbvsc.heightSizeInner.dimeVal != nil) + { + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } + //计算子视图的宽度。 - if (subviewSize != 0) + if (subviewSize != 0.0) { rect.size.width = subviewSize - leadingSpace - trailingSpace; } @@ -1027,32 +1034,26 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) {//特殊处理宽度等于高度的情况 - - //计算子视图的高度。 - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; } } - else if (sbvsc.weight != 0) + else if (sbvsc.weight != 0.0) { if (lsc.isFlex) { - rect.size.width = 0; + rect.size.width = 0.0; } else { - CGFloat floatingWidth = selfSize.width - paddingTrailing - xPos; - if (_myCGFloatLessOrEqual(floatingWidth, 0)) + CGFloat floatingWidth = selfSize.width - paddingTrailing - xPos - leadingSpace - trailingSpace; + if (arrangedIndex != 0) + floatingWidth -= horzSpace; + + if (_myCGFloatLessOrEqual(floatingWidth, 0.0)) { //如果当前行的剩余空间不够,则需要换行来计算相对的宽度占比,这时候剩余空间就是按整行来算,并且将行索引设置为0 floatingWidth = selfSize.width - paddingHorz; } - else - { - if (arrangedIndex != 0) - floatingWidth -= horzSpace; - } rect.size.width = (floatingWidth + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace; } @@ -1060,6 +1061,13 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + //特殊处理自身高度等于自身宽度的情况。 + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + {//特殊处理高度等于宽度的情况 + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } + //计算xPos的值加上leadingSpace + rect.size.width + trailingSpace 的值要小于整体的宽度。 CGFloat place = xPos + leadingSpace + rect.size.width + trailingSpace; if (arrangedIndex != 0) @@ -1075,7 +1083,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab //拉伸以及调整行内子视图的宽度。 [self myAdjustVertLayoutSinglelineWidth:selfSize lineIndex:lineIndex floatingWidth:selfSize.width - paddingTrailing - xPos totalWeight:lineTotalWeight horzGravity:horzGravity sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; - xPos = paddingLeading; //如何这个sbv的宽度大于整体布局视图的宽度。则将子视图的宽度缩小变为和布局视图一样宽 @@ -1084,7 +1091,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:selfSize.width - paddingHorz - leadingSpace - trailingSpace sbvSize:rect.size selfLayoutSize:selfSize]; } - lineTotalWeight = 0; + lineTotalWeight = 0.0; lineIndex++; arrangedIndex = 0; } @@ -1155,8 +1162,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:lineIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - rowMaxHeight = 0; - rowMaxWidth = 0; + rowMaxHeight = 0.0; + rowMaxWidth = 0.0; arrangedIndex = 0; lineIndex++; @@ -1187,45 +1194,46 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab //最后一行 [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:lineIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + yPos += rowMaxHeight + paddingBottom; + if (lsc.heightSizeInner.dimeWrapVal) + selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:yPos sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + + if (vertGravity != MyGravity_None && selfSize.height != yPos) { - selfSize.height = yPos + paddingBottom + rowMaxHeight; - } - else - { - CGFloat addYPos = 0; - CGFloat between = 0; - CGFloat fill = 0; + CGFloat addYPos = 0.0; + CGFloat between = 0.0; + CGFloat fill = 0.0; if (vertGravity == MyGravity_Vert_Center) { - addYPos = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / 2; + addYPos = (selfSize.height - yPos) / 2; } else if (vertGravity == MyGravity_Vert_Bottom) { - addYPos = selfSize.height - paddingBottom - rowMaxHeight - yPos; + addYPos = selfSize.height - yPos; } else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) { if (lineFirstSubviewIndexSet.count > 0) - fill = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / lineFirstSubviewIndexSet.count; + fill = (selfSize.height - yPos) / lineFirstSubviewIndexSet.count; //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' - if (fill < 0 && vertGravity == MyGravity_Vert_Stretch) - fill = 0; + if (fill < 0.0 && vertGravity == MyGravity_Vert_Stretch) + fill = 0.0; } else if (vertGravity == MyGravity_Vert_Between) { if (lineFirstSubviewIndexSet.count > 1) - between = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / (lineFirstSubviewIndexSet.count - 1); + between = (selfSize.height - yPos) / (lineFirstSubviewIndexSet.count - 1); } else if (vertGravity == MyGravity_Vert_Around) { if (lineFirstSubviewIndexSet.count > 1) - between = (selfSize.height - paddingBottom - rowMaxHeight - yPos) / lineFirstSubviewIndexSet.count; + between = (selfSize.height - yPos) / lineFirstSubviewIndexSet.count; } - if (addYPos != 0 || between != 0 || fill != 0) + if (addYPos != 0.0 || between != 0.0 || fill != 0.0) { int lineidx = 0; NSUInteger lastIndex = 0; @@ -1259,7 +1267,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab sbvmyFrame.top += between * lineidx; - if (vertGravity == MyGravity_Vert_Around && lineidx == 0) + if (vertGravity == MyGravity_Vert_Around) sbvmyFrame.top += (between / 2.0); } } @@ -1305,8 +1313,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray BOOL isPagingScroll = NO; #endif - CGFloat pagingItemHeight = 0; - CGFloat pagingItemWidth = 0; + CGFloat pagingItemHeight = 0.0; + CGFloat pagingItemWidth = 0.0; BOOL isVertPaging = NO; BOOL isHorzPaging = NO; if (lsc.pagedCount > 0 && self.superview != nil) @@ -1352,7 +1360,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray for (; i < sbs.count; i++) { UIView *sbv = sbs[i]; - MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; @@ -1370,9 +1377,9 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray [self myCalcVertLayoutSinglelineWidthShrink:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalShrink:rowTotalShrink sbs:sbs startIndex:i count:arrangedCount]; } - rowTotalWeight = 0; - rowTotalFixedWidth = 0; - rowTotalShrink = 0; + rowTotalWeight = 0.0; + rowTotalFixedWidth = 0.0; + rowTotalShrink = 0.0; } CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; @@ -1399,7 +1406,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) {//特殊处理宽度等于高度的情况 - if (pagingItemHeight != 0) + if (pagingItemHeight != 0.0) rect.size.height = pagingItemHeight - topSpace - bottomSpace; else rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; @@ -1429,7 +1436,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray rowTotalFixedWidth += rect.size.width; rowTotalFixedWidth += leadingSpace + trailingSpace; - if (arrangedIndex != (arrangedCount - 1)) rowTotalFixedWidth += horzSpace; @@ -1442,18 +1448,18 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (arrangedIndex < arrangedCount) rowTotalFixedWidth -= horzSpace; - if (rowTotalWeight != 0 && horzGravity != MyGravity_Horz_Fill) + if (rowTotalWeight != 0.0 && horzGravity != MyGravity_Horz_Fill) { [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs nextLineFirstItemIndex:i count:arrangedIndex]; } //如果有压缩子视图的处理则需要压缩子视图。 - if (rowTotalShrink != 0 && horzGravity != MyGravity_Horz_Fill) + if (rowTotalShrink != 0.0 && horzGravity != MyGravity_Horz_Fill) { [self myCalcVertLayoutSinglelineWidthShrink:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalShrink:rowTotalShrink sbs:sbs startIndex:i count:arrangedIndex]; } - //每列的下一个位置。 + //初始化每行的下一个子视图的位置。 NSMutableArray *nextPointOfRows = nil; if (autoArrange) { @@ -1465,9 +1471,9 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray } NSInteger rowIndex = 0; //行索引 - CGFloat pageWidth = 0; //页宽。 + CGFloat pageWidth = 0.0; //页宽。 arrangedIndex = 0; - rowTotalShrink = 0; + rowTotalShrink = 0.0; i = 0; for (; i < sbs.count; i++) { @@ -1514,9 +1520,9 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray xPos = paddingLeading + pageWidth; - rowMaxHeight = 0; - rowMaxWidth = 0; - rowTotalShrink = 0; + rowMaxHeight = 0.0; + rowMaxWidth = 0.0; + rowTotalShrink = 0.0; rowIndex++; } @@ -1646,21 +1652,23 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray { selfSize.height = maxHeight; - //只有在父视图为滚动视图,且开启了分页滚动时才会扩充具有包裹设置的布局视图的宽度。 + //只有在父视图为滚动视图,且开启了分页滚动时才会扩充具有包裹设置的布局视图的高度。 if (isVertPaging && isPagingScroll) { - //算出页数来。如果包裹计算出来的宽度小于指定页数的宽度,因为要分页滚动所以这里会扩充布局的宽度。 + //算出页数来。如果包裹计算出来的高度小于指定页数的高度,因为要分页滚动所以这里会扩充布局的高度。 NSInteger totalPages = floor((sbs.count + lsc.pagedCount - 1.0 ) / lsc.pagedCount); if (_myCGFloatLess(selfSize.height, totalPages * CGRectGetHeight(self.superview.bounds))) selfSize.height = totalPages * CGRectGetHeight(self.superview.bounds); } + selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:selfSize.height sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; } - else + + if (vertGravity != MyGravity_None && selfSize.height != maxHeight && !(isVertPaging && isPagingScroll)) { - CGFloat addYPos = 0; - CGFloat between = 0; - CGFloat fill = 0; + CGFloat addYPos = 0.0; + CGFloat between = 0.0; + CGFloat fill = 0.0; int arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); //行数 if (vertGravity == MyGravity_Vert_Center) @@ -1677,8 +1685,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray fill = (selfSize.height - maxHeight) / arranges; //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' - if (fill < 0 && vertGravity == MyGravity_Vert_Stretch) - fill = 0; + if (fill < 0.0 && vertGravity == MyGravity_Vert_Stretch) + fill = 0.0; } else if (vertGravity == MyGravity_Vert_Between) { @@ -1691,7 +1699,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray between = (selfSize.height - maxHeight) / arranges; } - if (addYPos != 0 || between != 0 || fill != 0) + if (addYPos != 0.0 || between != 0.0 || fill != 0.0) { for (int i = 0; i < sbs.count; i++) { @@ -1716,8 +1724,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray sbvmyFrame.top += between * lineidx; - //如果是vert_around那么第0行应该添加一半的between值。 - if (vertGravity == MyGravity_Vert_Around && lineidx == 0) + //如果是vert_around那么所有行都应该添加一半的between值。 + if (vertGravity == MyGravity_Vert_Around) sbvmyFrame.top += (between / 2.0); } } @@ -1749,12 +1757,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; CGFloat paddingVert = paddingTop + paddingBottom; - CGFloat xPos = paddingLeading; - CGFloat yPos = paddingTop; - CGFloat colMaxWidth = 0; //某一列的最宽值。 - CGFloat colMaxHeight = 0; //某一列的最高值 - CGFloat maxHeight = 0; //所有列的最宽行 - MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; MyGravity horzAlign = [self myConvertLeftRightGravityToLeadingTrailing:lsc.arrangedGravity & MyGravity_Vert_Mask]; @@ -1765,6 +1767,12 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab CGFloat horzSpace = lsc.subviewHSpace; CGFloat subviewSize = [self myCalcMaxMinSubviewSizeForContent:selfSize.height - paddingVert lsc:(MyFlowLayoutViewSizeClass*)lsc space:&vertSpace]; + CGFloat xPos = paddingLeading; + CGFloat yPos = paddingTop; + CGFloat colMaxWidth = 0.0; //某一列的最宽值。 + CGFloat colMaxHeight = 0.0; //某一列的最高值 + CGFloat maxHeight = 0.0; //所有列的最宽行 + if (lsc.autoArrange) { //计算出每个子视图的宽度。 @@ -1814,10 +1822,13 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab CGRect rect = sbvmyFrame.frame; //这里先计算一下宽度,因为有可能有宽度固定,高度自适应的情况。 - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + if (sbvsc.widthSizeInner.dimeVal != nil) + { + rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + } - if (subviewSize != 0) + if (subviewSize != 0.0) { rect.size.height = subviewSize - topSpace - bottomSpace; } @@ -1831,32 +1842,36 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } } - else if (sbvsc.weight != 0) + else if (sbvsc.weight != 0.0) { if (lsc.isFlex) { - rect.size.height = 0; + rect.size.height = 0.0; } else { - //如果过了,则表示当前的剩余空间为0了,所以就按新的一行来算。。 - CGFloat floatingHeight = selfSize.height - paddingBottom - yPos; - if (_myCGFloatLessOrEqual(floatingHeight, 0)) - { - floatingHeight += selfSize.height - paddingVert; - } - else + //如果超过了布局尺寸,则表示当前的剩余空间为0了,所以就按新的一行来算。。 + CGFloat floatingHeight = selfSize.height - paddingBottom - yPos - topSpace - bottomSpace; + if (arrangedIndex != 0) + floatingHeight -= vertSpace; + if (_myCGFloatLessOrEqual(floatingHeight, 0.0)) { - if (arrangedIndex != 0) - floatingHeight -= vertSpace; + floatingHeight = selfSize.height - paddingVert; } - + rect.size.height = (floatingHeight + sbvsc.heightSizeInner.addVal) * sbvsc.weight - topSpace - bottomSpace; } } rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + //特殊处理宽度依赖高度的子视图。 + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + {//特殊处理宽度等于高度的情况 + rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + } + //计算yPos的值加上topSpace + rect.size.height + bottomSpace的值要小于整体的高度。 CGFloat place = yPos + topSpace + rect.size.height + bottomSpace; @@ -1880,7 +1895,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:selfSize.height - paddingVert - topSpace - bottomSpace sbvSize:rect.size selfLayoutSize:selfSize]; } - lineTotalWeight = 0; + lineTotalWeight = 0.0; lineIndex++; arrangedIndex = 0; } @@ -1897,7 +1912,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab sbvmyFrame.frame = rect; arrangedIndex++; - } //最后一行的行首索引 @@ -1940,7 +1954,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab maxHeight += paddingBottom; NSUInteger lineFirstIndex = [lineFirstSubviewIndexSet indexLessThanOrEqualToIndex:i]; - if (!lsc.widthSizeInner.dimeWrapVal && oldLineFirstIndex != lineFirstIndex) + if (!lsc.heightSizeInner.dimeWrapVal && oldLineFirstIndex != lineFirstIndex) { oldLineFirstIndex = lineFirstIndex; @@ -1951,8 +1965,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:lineIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - colMaxWidth = 0; - colMaxHeight = 0; + colMaxWidth = 0.0; + colMaxHeight = 0.0; arrangedIndex = 0; lineIndex++; @@ -1982,45 +1996,47 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:lineIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + + xPos += colMaxWidth + paddingTrailing; + if (lsc.widthSizeInner.dimeWrapVal) + selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:xPos sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + + if (horzGravity != MyGravity_None && selfSize.width != xPos) { - selfSize.width = xPos + paddingTrailing + colMaxWidth; - } - else - { - CGFloat addXPos = 0; - CGFloat fill = 0; - CGFloat between = 0; + CGFloat addXPos = 0.0; + CGFloat fill = 0.0; + CGFloat between = 0.0; if (horzGravity == MyGravity_Horz_Center) { - addXPos = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / 2; + addXPos = (selfSize.width - xPos) / 2; } else if (horzGravity == MyGravity_Horz_Trailing) { - addXPos = selfSize.width - paddingTrailing - colMaxWidth - xPos; + addXPos = selfSize.width - xPos; } else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) { if (lineFirstSubviewIndexSet.count > 0) - fill = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / lineFirstSubviewIndexSet.count; + fill = (selfSize.width - xPos) / lineFirstSubviewIndexSet.count; //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' - if (fill < 0 && horzGravity == MyGravity_Horz_Stretch) - fill = 0; + if (fill < 0.0 && horzGravity == MyGravity_Horz_Stretch) + fill = 0.0; } else if (horzGravity == MyGravity_Horz_Between) { if (lineFirstSubviewIndexSet.count > 1) - between = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / (lineFirstSubviewIndexSet.count - 1); + between = (selfSize.width - xPos) / (lineFirstSubviewIndexSet.count - 1); } else if (horzGravity == MyGravity_Horz_Around) { if (lineFirstSubviewIndexSet.count > 1) - between = (selfSize.width - paddingTrailing - colMaxWidth - xPos) / lineFirstSubviewIndexSet.count; + between = (selfSize.width - xPos) / lineFirstSubviewIndexSet.count; } - if (addXPos != 0 || between != 0 || fill != 0) + if (addXPos != 0.0 || between != 0.0 || fill != 0.0) { int lineidx = 0; NSUInteger lastIndex = 0; @@ -2053,7 +2069,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab sbvmyFrame.leading += between * lineidx; - if (horzGravity == MyGravity_Horz_Around && lineidx == 0) + if (horzGravity == MyGravity_Horz_Around) sbvmyFrame.leading += (between / 2.0); } } @@ -2086,9 +2102,9 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; - CGFloat colMaxWidth = 0; //每列的最大宽度 - CGFloat colMaxHeight = 0; //每列的最大高度 - CGFloat maxHeight = paddingTop; + CGFloat colMaxWidth = 0.0; //每一列的最大宽度 + CGFloat colMaxHeight = 0.0; //每一列的最大高度 + CGFloat maxHeight = paddingTop; //全列的最大高度 CGFloat maxWidth = paddingLeading; //最大的宽度。 //父滚动视图是否分页滚动。 @@ -2100,8 +2116,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray BOOL isPagingScroll = NO; #endif - CGFloat pagingItemHeight = 0; - CGFloat pagingItemWidth = 0; + CGFloat pagingItemHeight = 0.0; + CGFloat pagingItemWidth = 0.0; BOOL isVertPaging = NO; BOOL isHorzPaging = NO; if (lsc.pagedCount > 0 && self.superview != nil) @@ -2140,9 +2156,9 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray NSInteger arrangedIndex = 0; NSInteger i = 0; + CGFloat colTotalShrink = 0.0; //某一行的总压缩比重。 CGFloat colTotalWeight = 0.0; CGFloat colTotalFixedHeight = 0.0; - CGFloat colTotalShrink = 0.0; //某一行的总压缩比重。 for (; i < sbs.count; i++) { UIView *sbv = sbs[i]; @@ -2163,9 +2179,9 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray [self myCalcHorzLayoutSinglelineHeightShrink:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalShrink:colTotalShrink sbs:sbs startIndex:i count:arrangedCount]; } - colTotalWeight = 0; - colTotalFixedHeight = 0; - colTotalShrink = 0; + colTotalWeight = 0.0; + colTotalFixedHeight = 0.0; + colTotalShrink = 0.0; } @@ -2175,7 +2191,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; - if (pagingItemWidth != 0) + //水平流式布局因为高度依赖宽度自适应的情况比较少,所以这里直接先计算宽度 + if (pagingItemWidth != 0.0) rect.size.width = pagingItemWidth - leadingSpace - trailingSpace; else rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; @@ -2186,11 +2203,11 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray { rect.size.height = averageHeight - topSpace - bottomSpace; } - else if (subviewSize != 0) + else if (subviewSize != 0.0) { rect.size.height = subviewSize - topSpace - bottomSpace; } - else if (pagingItemHeight != 0) + else if (pagingItemHeight != 0.0) { rect.size.height = pagingItemHeight - topSpace - bottomSpace; } @@ -2207,7 +2224,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray } else if (sbvsc.weight != 0.0) { - rect.size.height = 0; + rect.size.height = 0.0; } rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; @@ -2236,35 +2253,34 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray } //最后一行。 - if (arrangedIndex < arrangedCount) colTotalFixedHeight -= vertSpace; - if (colTotalWeight != 0 && vertGravity != MyGravity_Vert_Fill) + if (colTotalWeight != 0.0 && vertGravity != MyGravity_Vert_Fill) { [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; } - if (colTotalShrink != 0 && vertGravity != MyGravity_Vert_Fill) + if (colTotalShrink != 0.0 && vertGravity != MyGravity_Vert_Fill) { [self myCalcHorzLayoutSinglelineHeightShrink:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalShrink:colTotalShrink sbs:sbs startIndex:i count:arrangedIndex]; } - //每行的下一个位置。 - NSMutableArray *nextPointOfRows = nil; + //初始化每行的下一个子视图的位置。 + NSMutableArray *nextPointOfCols = nil; if (autoArrange) { - nextPointOfRows = [NSMutableArray arrayWithCapacity:arrangedCount]; + nextPointOfCols = [NSMutableArray arrayWithCapacity:arrangedCount]; for (NSInteger idx = 0; idx < arrangedCount; idx++) { - [nextPointOfRows addObject:[NSValue valueWithCGPoint:CGPointMake(paddingLeading, paddingTop)]]; + [nextPointOfCols addObject:[NSValue valueWithCGPoint:CGPointMake(paddingLeading, paddingTop)]]; } } NSInteger colIndex = 0; - CGFloat pageHeight = 0; //页高 + CGFloat pageHeight = 0.0; //页高 arrangedIndex = 0; - colTotalShrink = 0; + colTotalShrink = 0.0; i = 0; for (; i < sbs.count; i++) { @@ -2302,8 +2318,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray if (isPagingScroll) { xPos -= horzSpace; - xPos += paddingTrailing; - xPos += paddingLeading; + xPos += paddingHorz; } } } @@ -2311,9 +2326,9 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray yPos = paddingTop + pageHeight; - colMaxWidth = 0; - colMaxHeight = 0; - colTotalShrink = 0; + colMaxWidth = 0.0; + colMaxHeight = 0.0; + colTotalShrink = 0.0; colIndex++; } @@ -2335,7 +2350,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray NSInteger minNextPointIndex = 0; for (int idx = 0; idx < arrangedCount; idx++) { - CGPoint pt = nextPointOfRows[idx].CGPointValue; + CGPoint pt = nextPointOfCols[idx].CGPointValue; if (minPt.x > pt.x) { minPt = pt; @@ -2348,12 +2363,12 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray yPos = minPt.y; minPt.x = minPt.x + leadingSpace + rect.size.width + trailingSpace + horzSpace; - nextPointOfRows[minNextPointIndex] = [NSValue valueWithCGPoint:minPt]; + nextPointOfCols[minNextPointIndex] = [NSValue valueWithCGPoint:minPt]; if (minNextPointIndex + 1 <= arrangedCount - 1) { - minPt = nextPointOfRows[minNextPointIndex + 1].CGPointValue; + minPt = nextPointOfCols[minNextPointIndex + 1].CGPointValue; minPt.y = yPos + topSpace + rect.size.height + bottomSpace + vertSpace; - nextPointOfRows[minNextPointIndex + 1] = [NSValue valueWithCGPoint:minPt]; + nextPointOfCols[minNextPointIndex + 1] = [NSValue valueWithCGPoint:minPt]; } if (_myCGFloatLess(maxWidth, xPos + leadingSpace + rect.size.width + trailingSpace)) @@ -2427,13 +2442,15 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray selfSize.width = totalPages * CGRectGetWidth(self.superview.bounds); } + selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:selfSize.width sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; } - else + + if (horzGravity != MyGravity_None && selfSize.width != maxWidth && !(isHorzPaging && isPagingScroll)) { - CGFloat addXPos = 0; - CGFloat between = 0; - CGFloat fill = 0; + CGFloat addXPos = 0.0; + CGFloat between = 0.0; + CGFloat fill = 0.0; int arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); //列数 if (horzGravity == MyGravity_Horz_Center) @@ -2450,8 +2467,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray fill = (selfSize.width - maxWidth) / arranges; //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' - if (fill < 0 && horzGravity == MyGravity_Horz_Stretch) - fill = 0; + if (fill < 0.0 && horzGravity == MyGravity_Horz_Stretch) + fill = 0.0; } else if (horzGravity == MyGravity_Horz_Between) { @@ -2464,7 +2481,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray between = (selfSize.width - maxWidth) / arranges; } - if (addXPos != 0 || between != 0 || fill != 0) + if (addXPos != 0.0 || between != 0.0 || fill != 0.0) { for (int i = 0; i < sbs.count; i++) { @@ -2489,8 +2506,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray sbvmyFrame.leading += between * lineidx; - //如果是horz_around那么第0行应该添加一半的between值。 - if (horzGravity == MyGravity_Horz_Around && lineidx == 0) + if (horzGravity == MyGravity_Horz_Around) sbvmyFrame.leading += (between / 2.0); } } diff --git a/MyLayoutDemo/AllTestExampleViewController.m b/MyLayoutDemo/AllTestExampleViewController.m index f9dd476..4330f15 100644 --- a/MyLayoutDemo/AllTestExampleViewController.m +++ b/MyLayoutDemo/AllTestExampleViewController.m @@ -119,7 +119,7 @@ -(void)example2 [scrollview addSubview:backLinear]; UIView *v = [UIView new]; - v.myHeight = 500; //调整不同的尺寸得到不同的结果。 + v.myHeight = 500; //调整不同的尺寸得到不同的结果。分别设置为100, 350, 500 v.myWidth = 100; v.backgroundColor = [UIColor redColor]; [backLinear addSubview:v]; diff --git a/MyLayoutTests/MyFloatLayoutTestCase.m b/MyLayoutTests/MyFloatLayoutTestCase.m index ab0b8e9..5c6380e 100644 --- a/MyLayoutTests/MyFloatLayoutTestCase.m +++ b/MyLayoutTests/MyFloatLayoutTestCase.m @@ -265,6 +265,130 @@ -(void)testExample3 } +-(void)testWrapAndGravity +{ + //测试尺寸自适应,但是又设置了停靠的例子。 + { + MyFloatLayout *rootLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; + rootLayout.mySize = CGSizeMake(100, MyLayoutSize.wrap); + rootLayout.frame = CGRectMake(0, 0, 100, 0); + rootLayout.gravity = MyGravity_Vert_Center; + rootLayout.heightSize.min(90); + + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(40, 40); + [rootLayout addSubview:v1]; + + UIView *v2 = [UIView new]; + v2.reverseFloat = YES; + v2.mySize = CGSizeMake(50, 50); + [rootLayout addSubview:v2]; + + UIView *v3 = [UIView new]; + v3.mySize = CGSizeMake(10, 10); + [rootLayout addSubview:v3]; + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + MyRectAssert(rootLayout, CGRectMake(0, 0, 100, 90)); + MyRectAssert(v1, CGRectMake(0, 20, 40, 40)); + MyRectAssert(v2, CGRectMake(50, 20, 50, 50)); + MyRectAssert(v3, CGRectMake(40, 20, 10, 10)); + + + v3.mySize = CGSizeMake(20, 20); + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + MyRectAssert(rootLayout, CGRectMake(0, 0, 100, 90)); + MyRectAssert(v1, CGRectMake(0, 15, 40, 40)); + MyRectAssert(v2, CGRectMake(50, 15, 50, 50)); + MyRectAssert(v3, CGRectMake(0, 55, 20, 20)); + + + + v3.mySize = CGSizeMake(60, 60); + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + MyRectAssert(rootLayout, CGRectMake(0, 0, 100, 110)); + MyRectAssert(v1, CGRectMake(0, 0, 40, 40)); + MyRectAssert(v2, CGRectMake(50, 0, 50, 50)); + MyRectAssert(v3, CGRectMake(0, 50, 60, 60)); + + rootLayout.gravity = MyGravity_Vert_Bottom; + v3.mySize = CGSizeMake(10, 10); + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + MyRectAssert(rootLayout, CGRectMake(0, 0, 100, 90)); + MyRectAssert(v1, CGRectMake(0, 40, 40, 40)); + MyRectAssert(v2, CGRectMake(50, 40, 50, 50)); + MyRectAssert(v3, CGRectMake(40,40,10,10)); + } + + { + MyFloatLayout *rootLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Horz]; + rootLayout.mySize = CGSizeMake(MyLayoutSize.wrap,100); + rootLayout.frame = CGRectMake(0, 0, 0,100); + rootLayout.gravity = MyGravity_Horz_Center; + rootLayout.widthSize.min(90); + + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(40, 40); + [rootLayout addSubview:v1]; + + UIView *v2 = [UIView new]; + v2.reverseFloat = YES; + v2.mySize = CGSizeMake(50, 50); + [rootLayout addSubview:v2]; + + UIView *v3 = [UIView new]; + v3.mySize = CGSizeMake(10, 10); + [rootLayout addSubview:v3]; + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + MyRectAssert(rootLayout, CGRectMake(0, 0, 90, 100)); + MyRectAssert(v1, CGRectMake(20,0, 40, 40)); + MyRectAssert(v2, CGRectMake(20,50, 50, 50)); + MyRectAssert(v3, CGRectMake(20,40, 10, 10)); + + + v3.mySize = CGSizeMake(20, 20); + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + MyRectAssert(rootLayout, CGRectMake(0, 0, 90, 100)); + MyRectAssert(v1, CGRectMake(15,0, 40, 40)); + MyRectAssert(v2, CGRectMake(15,50, 50, 50)); + MyRectAssert(v3, CGRectMake(55, 0,20, 20)); + + + + v3.mySize = CGSizeMake(60, 60); + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + MyRectAssert(rootLayout, CGRectMake(0, 0, 110, 100)); + MyRectAssert(v1, CGRectMake(0, 0, 40, 40)); + MyRectAssert(v2, CGRectMake(0,50, 50, 50)); + MyRectAssert(v3, CGRectMake(50,0, 60, 60)); + + rootLayout.gravity = MyGravity_Horz_Trailing; + v3.mySize = CGSizeMake(10, 10); + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + MyRectAssert(rootLayout, CGRectMake(0, 0, 90, 100)); + MyRectAssert(v1, CGRectMake(40,0, 40, 40)); + MyRectAssert(v2, CGRectMake(40,50, 50, 50)); + MyRectAssert(v3, CGRectMake(40,40,10,10)); + } +} + - (void)testPerformanceExample { // This is an example of a performance test case. diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index 755a601..7bc75ed 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -313,72 +313,333 @@ -(void)testSubviewSizeDependent -(void)testWrapContentSize2 { //测试一个布局宽度固定,高度包裹,然后子视图的高度依赖宽度,或者子视图高度自适应,然后又有压缩的场景,看是否会导致行高不对,或者整个行高不对。 + { + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; + rootLayout.frame = CGRectMake(0, 0, 110, 0); + rootLayout.padding = UIEdgeInsetsMake(10, 10, 5, 5); + rootLayout.mySize = CGSizeMake(110, MyLayoutSize.wrap); + rootLayout.subviewSpace = 6; + rootLayout.gravity = MyGravity_Horz_Fill; + + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(10, 20); + v1.myMargin = 5; + [rootLayout addSubview:v1]; + + UIView *v2 = [UIView new]; + v2.myWidth = 30; + v2.heightSize.equalTo(v2.widthSize); + v2.myMargin = 6; + [rootLayout addSubview:v2]; + + + UIView *v3 = [UIView new]; + v3.mySize = CGSizeMake(10, 50); + v3.myMargin = 2; + [rootLayout addSubview:v3]; + + UIView *v4 = [UIView new]; + v4.myWidth = 20; + v4.heightSize.equalTo(v4.widthSize).multiply(0.5).add(10); + v4.myMargin = 3; + [rootLayout addSubview:v4]; + + UILabel *v5 = [UILabel new]; + v5.text = @"测试测试测试"; + v5.frame = CGRectMake(0, 0, 20, 0); + v5.heightSize.equalTo(@(MyLayoutSize.wrap)); + [rootLayout addSubview:v5]; + + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,110,197)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(15,15,12.5,20)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(44.5,16,32.5,32.5)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(90.5,12,12.5,50)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(13,73,20,20)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(42,70,20,122)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + + rootLayout.isFlex = YES; + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,110,136)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(15,15,12.5,20)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(44.5,16,32.5,32.5)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(90.5,12,12.5,50)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(13,73,41.5,31)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(63.5,70,41.5,61)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + } - MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; - rootLayout.frame = CGRectMake(0, 0, 110, 0); - rootLayout.padding = UIEdgeInsetsMake(10, 10, 5, 5); - rootLayout.mySize = CGSizeMake(110, MyLayoutSize.wrap); - rootLayout.subviewSpace = 6; - rootLayout.gravity = MyGravity_Horz_Fill; - - UIView *v1 = [UIView new]; - v1.mySize = CGSizeMake(10, 20); - v1.myMargin = 5; - [rootLayout addSubview:v1]; - - UIView *v2 = [UIView new]; - v2.myWidth = 30; - v2.heightSize.equalTo(v2.widthSize); - v2.myMargin = 6; - [rootLayout addSubview:v2]; + { + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:0]; + rootLayout.frame = CGRectMake(0, 0, 0, 110); + rootLayout.padding = UIEdgeInsetsMake(10, 10, 5, 5); + rootLayout.mySize = CGSizeMake(MyLayoutSize.wrap, 110); + rootLayout.subviewSpace = 6; + rootLayout.gravity = MyGravity_Vert_Fill; + + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(20, 10); + v1.myMargin = 5; + [rootLayout addSubview:v1]; + + UIView *v2 = [UIView new]; + v2.myHeight = 30; + v2.widthSize.equalTo(v2.heightSize); + v2.myMargin = 6; + [rootLayout addSubview:v2]; + + + UIView *v3 = [UIView new]; + v3.mySize = CGSizeMake(50, 10); + v3.myMargin = 2; + [rootLayout addSubview:v3]; + + UIView *v4 = [UIView new]; + v4.myHeight = 20; + v4.widthSize.equalTo(v4.heightSize).multiply(0.5).add(10); + v4.myMargin = 3; + [rootLayout addSubview:v4]; + + UILabel *v5 = [UILabel new]; + v5.text = @"测试测试测试"; + v5.frame = CGRectMake(0, 0, 0, 20); + v5.widthSize.equalTo(@(MyLayoutSize.wrap)); + [rootLayout addSubview:v5]; + + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,179,110)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(15,15,20,12.5)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(16,44.5,32.5,32.5)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(12,90.5,50,12.5)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(73,13,20,20)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(70,42,104,20)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + + rootLayout.isFlex = YES; + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,179,110)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(15,15,20,12.5)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(16,44.5,32.5,32.5)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(12,90.5,50,12.5)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(73,13,31,41.5)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(70,63.5,104,41.5)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); - - UIView *v3 = [UIView new]; - v3.mySize = CGSizeMake(10, 50); - v3.myMargin = 2; - [rootLayout addSubview:v3]; - - UIView *v4 = [UIView new]; - v4.myWidth = 20; - v4.heightSize.equalTo(v4.widthSize).multiply(0.5).add(10); - v4.myMargin = 3; - [rootLayout addSubview:v4]; - - UILabel *v5 = [UILabel new]; - v5.text = @"测试测试测试"; - v5.frame = CGRectMake(0, 0, 20, 0); - v5.heightSize.equalTo(@(MyLayoutSize.wrap)); - [rootLayout addSubview:v5]; + } +} +-(void)testWeight +{ + //测试内容约束布局中weight刚好在边界的情况。 + { + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; + rootLayout.frame = CGRectMake(0, 0, 152, 100); + rootLayout.padding = UIEdgeInsetsMake(10, 10, 5, 5); + rootLayout.subviewSpace = 6; + rootLayout.myHeight = MyLayoutSize.wrap; + + UIView *v1 = [UIView new]; + v1.myHorzMargin = 4; + v1.mySize = CGSizeMake(20, 20); + [rootLayout addSubview:v1]; // 10+4+20+4+6 = 44 + + UIView *v2 = [UIView new]; + v2.myHorzMargin = 5; + v2.mySize = CGSizeMake(30, 30); + [rootLayout addSubview:v2]; //10+4+20+4+6+5+30+5+6 = 90 + + UIView *v3 = [UIView new]; + v3.myHorzMargin = 6; + v3.mySize = CGSizeMake(40, 40); + [rootLayout addSubview:v3]; //10+4+20+4+6+5+30+5+6+ 6+40+6+ 6 + 5 = 153 + + UIView *v4 = [UIView new]; + v4.myHeight = 50; + v4.weight = 0.6; + [rootLayout addSubview:v4]; + + UIView *v5 = [UIView new]; + v5.mySize = CGSizeMake(20, 20); + [rootLayout addSubview:v5]; + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(10,56,82,50)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(98,56,20,20)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,152,111)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + rootLayout.frame = CGRectMake(0, 0, 153, 0); + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(10,56,83,50)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(99,56,20,20)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,153,111)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + + rootLayout.frame = CGRectMake(0, 0, 154, 100); + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(148,10,0.5,50)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(10,66,20,20)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,154,91)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + rootLayout.frame = CGRectMake(0, 0, 152, 100); + v4.weight = 1; + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(10,56,137,50)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(10,112,20,20)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,152,137)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + rootLayout.isFlex = YES; + v4.weight = 1; + v5.weight = 1; + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(10,56,55.5,50)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(71.5,56,75.5,20)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,152,111)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + } - [rootLayout setNeedsLayout]; - [rootLayout layoutIfNeeded]; - - XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,110,197.5)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); - - XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(15,15,12.5,20)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); - - XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(44.5,16,32.5,32.5)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); - - XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(90.5,12,12.5,50)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); - - XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(13,73.5,20,20)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); - - XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(42,70.5,20,122)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); - - rootLayout.isFlex = YES; - [rootLayout setNeedsLayout]; - [rootLayout layoutIfNeeded]; + //测试内容约束布局中weight刚好在边界的情况。 + { + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:0]; + rootLayout.frame = CGRectMake(0, 0, 100, 152); + rootLayout.padding = UIEdgeInsetsMake(10, 10, 5, 5); + rootLayout.subviewSpace = 6; + rootLayout.myWidth = MyLayoutSize.wrap; + + UIView *v1 = [UIView new]; + v1.myVertMargin = 4; + v1.mySize = CGSizeMake(20, 20); + [rootLayout addSubview:v1]; // 10+4+20+4+6 = 44 + + UIView *v2 = [UIView new]; + v2.myVertMargin = 5; + v2.mySize = CGSizeMake(30, 30); + [rootLayout addSubview:v2]; //10+4+20+4+6+5+30+5+6 = 90 + + UIView *v3 = [UIView new]; + v3.myVertMargin = 6; + v3.mySize = CGSizeMake(40, 40); + [rootLayout addSubview:v3]; //10+4+20+4+6+5+30+5+6+ 6+40+6+ 6 + 5 = 153 + + UIView *v4 = [UIView new]; + v4.myWidth = 50; + v4.weight = 0.6; + [rootLayout addSubview:v4]; + + UIView *v5 = [UIView new]; + v5.mySize = CGSizeMake(20, 20); + [rootLayout addSubview:v5]; + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(56,10,50,82)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(56,98,20,20)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,111,152)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + rootLayout.frame = CGRectMake(0, 0, 0, 153); + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(56,10,50,83)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(56,99,20,20)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,111,153)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + + rootLayout.frame = CGRectMake(0, 0, 100, 154); + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(10,148,50,0.5)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(66,10,20,20)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,91,154)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + rootLayout.frame = CGRectMake(0, 0, 100, 152); + v4.weight = 1; + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(56,10,50,137)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(112,10,20,20)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,137,152)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + + rootLayout.isFlex = YES; + v4.weight = 1; + v5.weight = 1; + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(56,10,50,55.5)), @"the v4.frame = %@",NSStringFromCGRect(v4.frame)); + + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(56,71.5,20,75.5)), @"the v5.frame = %@",NSStringFromCGRect(v5.frame)); + + XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,111,152)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); + } - - NSLog(@""); - //> -// <__NSArrayM 0x600002d2db00>( -// >, -// >, -// >, -// > } +-(void)testWrapAndGravity +{ + +} @end diff --git a/MyLayoutTests/MyLayoutTestCaseBase.h b/MyLayoutTests/MyLayoutTestCaseBase.h index 3243aff..f43db7c 100644 --- a/MyLayoutTests/MyLayoutTestCaseBase.h +++ b/MyLayoutTests/MyLayoutTestCaseBase.h @@ -9,11 +9,16 @@ #import #import "MyLayout.h" + +#define MyRectAssert(v, rc) XCTAssert(CGRectEqualToRect(v.frame, rc), @"the real frame = %@",NSStringFromCGRect(v.frame)); + + @interface MyLayoutTestCaseBase : XCTestCase -(void)startClock; -(void)endClock:(NSString*)text; + @end diff --git a/MyLayoutTests/MyLayoutTestCaseBase.m b/MyLayoutTests/MyLayoutTestCaseBase.m index a5fbdd1..26e57b4 100644 --- a/MyLayoutTests/MyLayoutTestCaseBase.m +++ b/MyLayoutTests/MyLayoutTestCaseBase.m @@ -26,6 +26,8 @@ -(void)endClock:(NSString*)text } + + - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. diff --git a/MyLayoutTests/MyLinearLayoutTestCase.m b/MyLayoutTests/MyLinearLayoutTestCase.m index 2a17f56..0ba093d 100644 --- a/MyLayoutTests/MyLinearLayoutTestCase.m +++ b/MyLayoutTests/MyLinearLayoutTestCase.m @@ -824,8 +824,62 @@ -(void)testequalizeSubviews XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(207,0,93.5,100)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); } - - +} + +-(void)testMaxAndMin +{ + MyFrameLayout *rootLayout = [MyFrameLayout new]; + rootLayout.frame = CGRectMake(0, 0, 375, 667); + + // B 视图 + UIScrollView *scrollview = [[UIScrollView alloc] init]; + scrollview.backgroundColor = [UIColor blueColor]; + scrollview.myHorzMargin = 0; + scrollview.heightSize.equalTo(@(MyLayoutSize.wrap)).min(280).uBound(rootLayout.heightSize, 66.5, 0.5); + [rootLayout addSubview:scrollview]; + + // 内容C视图 + MyLinearLayout * backLinear = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + backLinear.backgroundColor = [UIColor greenColor]; + backLinear.myHorzMargin = 0; + backLinear.heightSize.equalTo(@(MyLayoutSize.wrap)).min(280); + backLinear.gravity = MyGravity_Vert_Bottom; + [scrollview addSubview:backLinear]; + + UIView *v = [UIView new]; + v.myHeight = 100; + v.myWidth = 100; + v.backgroundColor = [UIColor redColor]; + [backLinear addSubview:v]; + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(scrollview.frame, CGRectMake(0,0,375,280)), @"the scrollview.frame = %@",NSStringFromCGRect(scrollview.frame)); + XCTAssertTrue(CGSizeEqualToSize(scrollview.contentSize, CGSizeMake(375, 280)), @"the scrollview.contentSize = %@",NSStringFromCGSize(scrollview.contentSize)); + XCTAssertTrue(CGRectEqualToRect(backLinear.frame, CGRectMake(0,0,375,280)), @"the backLinear.frame = %@",NSStringFromCGRect(backLinear.frame)); + XCTAssertTrue(CGRectEqualToRect(v.frame, CGRectMake(0,180,100,100)), @"the v.frame = %@",NSStringFromCGRect(v.frame)); + + + v.myHeight = 350; + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + XCTAssertTrue(CGRectEqualToRect(scrollview.frame, CGRectMake(0,0,375,350)), @"the scrollview.frame = %@",NSStringFromCGRect(scrollview.frame)); + XCTAssertTrue(CGSizeEqualToSize(scrollview.contentSize, CGSizeMake(375, 350)), @"the scrollview.contentSize = %@",NSStringFromCGSize(scrollview.contentSize)); + XCTAssertTrue(CGRectEqualToRect(backLinear.frame, CGRectMake(0,0,375,350)), @"the backLinear.frame = %@",NSStringFromCGRect(backLinear.frame)); + XCTAssertTrue(CGRectEqualToRect(v.frame, CGRectMake(0,0,100,350)), @"the v.frame = %@",NSStringFromCGRect(v.frame)); + + v.myHeight = 500; + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + + + XCTAssertTrue(CGRectEqualToRect(scrollview.frame, CGRectMake(0,0,375,400)), @"the scrollview.frame = %@",NSStringFromCGRect(scrollview.frame)); + XCTAssertTrue(CGSizeEqualToSize(scrollview.contentSize, CGSizeMake(375, 500)), @"the scrollview.contentSize = %@",NSStringFromCGSize(scrollview.contentSize)); + XCTAssertTrue(CGRectEqualToRect(backLinear.frame, CGRectMake(0,0,375,500)), @"the backLinear.frame = %@",NSStringFromCGRect(backLinear.frame)); + XCTAssertTrue(CGRectEqualToRect(v.frame, CGRectMake(0,0,100,500)), @"the v.frame = %@",NSStringFromCGRect(v.frame)); + } - (void)testPerformanceExample { From 26e433c24f0eb112db57efca7cb25ed75fc2763a Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Sun, 20 Oct 2019 22:24:28 +0800 Subject: [PATCH 060/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 68 +++++++++++++++++++------- MyLayout/Lib/MyFlowLayout.m | 56 ++++++++++----------- MyLayout/Lib/MyLinearLayout.m | 91 +++++++++++++++-------------------- 3 files changed, 117 insertions(+), 98 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bcf479..9f7b006 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,56 @@ # 版本变更日志 **MyLayout**的所有版本的变更日志都将会在这里记录. -1.添加新的布局MyFlexbox -2.添加新的停靠和对齐属性Around, Stretch -3.添加和抽象对拖动的支持。 -4.添加对iOS13的黑白模式的支持。 -5.流式布局添加单独设置行内停靠对齐的支持。 -6.流式布局添加让所有行都受到对齐停靠影响的属性。 -7.添加对最值约束的设置。 -8.添加对视图尺寸和位置进行压缩的设置。 -9.流式布局和浮动布局增加对基线对齐的支持。 -10.浮动布局添加对尺寸自适应的支持。 - -修改: -1.修改对wrapConentSize的支持。 -2. - -BUG修复: -1.修复在使用sizeclass时对位置对象进行克隆的一个BUG。导致无法。。。 -2.修复相对布局下的一个尺寸自适应计算的一个BUG。 +--- +## [V1.9.0](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.9.0)(2019/10/21) + +### Added + +1. 添加新的布局:**MyFlexLayout**。 MyFlexLayout布局是从MyFlowLayout派生的布局,它兼容flexbox的所有特性,以及提供了和flexbox相同的设置语法。您可以通过MyFlexLayout中提供的flex属性并用链式语法的形式来设置布局特性,同时还可以通过视图提供的扩展分类flexItem属性来设置布局内子视图的布局特性。具体可以参考:[FLXTest1ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/FLXTest1ViewController.m) 中的介绍和使用方法 + +2. 添加尺寸对象MyLayoutSize和位置对象MyLayoutPos的最值约束的设置。您可以将视图的尺寸设置为某一个尺寸集合中的最大值或者最小值。在相对布局中您也可以将视图的位置设置为某一个位置集合中的最大值和最小值。比如A的宽度是B,C,D三个视图宽度中的最大值,则可以设置为:`A.widthSize.equalTo(@[B.widthSize,C.widthSize,D.widthSize].myMaxSize)` 具体实例请参考:[RLTest6ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/RLTest6ViewController.m) + +3. 添加对视图尺寸和位置进行压缩的设置。在线性布局和流式布局以及框架布局中当子视图的尺寸和间距总和大于布局视图的尺寸时,您可以通过MyLayoutSize以及MyLayoutPos中提供的新属性**shrink**来设置压缩的比重,默认情况下压缩比重的值是0表示不压缩,比重越大压缩度越大。具体的使用方法可以参考:[AllTest7ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/AllTest7ViewController.m) 中的第12个demo。 + + +4. 针对线性布局、流式布局中的gravity属性添加了Around和Stretch两种停靠和对齐能力,其中的Around和Between的区别是前者的首行和尾行的拉伸间距是其他行之间间距的一半,而后者则首行和尾行的间距不会被拉伸。Stretch和Fill的区别是前者对明确设置了尺寸的视图不进行尺寸拉伸,而后者则是对所有视图都进行尺寸拉伸 + + +5. 添加和抽象对拖动的支持,系统提供了一个新的类**MyLayoutDragger**,你可以用这个类中提供的方法就可以很轻易的实现对布局视图中的子视图进行拖放操作。具体使用方法可以参考:[FLLTest3ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/FLLTest3ViewController.m) + +6. 添加对iOS13的黑白模式适配的支持,解决了边界线的黑白模式适配的问题。 + +7. 流式布局MyFlowLayout中添加单独设置行内停靠对齐的支持属性:**lineGravity**,这个属性是一个block类型的对象,我们可以借助这个属性来实现对布局内每行的停靠对齐操作。具体实例可以参考:[FLLTest4ViewController](https://github.com/youngsoft/MyLinearLayout/blob/master/MyLayoutDemo/FLLTest4ViewController.m) + + + +8. 流式布局MyFlowLayout添加属性**isFlex**,这个属性默认是NO,当设置为YES时则表明让流式布局来兼容flexbox的特性。具体兼容可以参考属性中的注释。 + + +9. 流式布局和浮动布局添加了行内的基线对齐的功能。您可以将gravity或者arrangedGravity的值设置为MyGravity_Baseline。 + +10. 浮动布局添加对尺寸自适应的支持。您可以在垂直浮动布局中将布局视图的宽度设置为自适应,同时可以在水平浮动布局中将布局视图的高度设置为自适应。 + + +11. 在线性布局、流式布局、浮动布局中实现了可以在尺寸自适应的模式下gravity的停靠属性生效的能力。解决了[issue#102](https://github.com/youngsoft/MyLinearLayout/issues/102) + +### Update +1. 更新了对尺寸自适应属性的设置方式。不再建议使用wrapContentWidth进行宽度自适应设置,而是改为`myWidth = MyLayoutSize.wrap`或者`widthSize.equalTo(@(MyLayoutSize.wrap))`进行宽度自适应设置。不再建议使用wrapContentHeight进行高度尺寸自适应设置,而是改为`myHeight= MyLayoutSize.wrap`或者`heightSize.equalTo(@(MyLayoutSize.wrap))`进行高度自适应设置。 对于宽度是否自适应的判断则可以用`myWidth == MyLayoutSize.wrap`或widthSize.iswrap进行判断,高度也是一样的。 +2. 在框架布局、线性布局、相对布局中子视图如果同时设置了上下边距或者左右边距,并且同时设置了高度或者宽度约束时则子视图的高度或者宽度不再是由布局视图决定而是由自身设置的高度或者宽度约束决定。解决了[issue#100](https://github.com/youngsoft/MyLinearLayout/issues/100) + +2. 将浮动布局的noBoundaryLimit属性设置为过期,这个属性将不再生效,而是直接将布局的宽度或者高度设置为自适应即可实现相同的功能。 + +3. 线性布局中的shrinkType属性用于控制所有子视图的压缩特性,如果子视图的尺寸设置shrink属性值则以子视图的设置优先,布局视图的shrinkType将不再起作用。 + + +### Fixed + +1. 修复在使用sizeclass时对位置对象进行克隆的一个BUG。这个BUG可能导致在不同sizeclass下位置设置被覆盖的问题。 +2. 修复相对布局下一组视图在高度或者宽度自适应下无法垂直居中或者水平居中的[BUG#103](https://github.com/youngsoft/MyLinearLayout/issues/103) +3. 修复框架布局MyFrameLayout设置高度自适应时,当其中的子视图隐藏或者恢复隐藏时自适应高度无法更新的[BUG#99](https://github.com/youngsoft/MyLinearLayout/issues/99) + + + diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index fb8bcb0..3369b19 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -223,14 +223,14 @@ -(id)createSizeClassInstance #pragma mark -- Private Methods -- (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalWeight:(CGFloat)totalWeight sbs:(NSArray *)sbs nextLineFirstItemIndex:(NSInteger)nextLineFirstItemIndex count:(NSInteger)count +- (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalWeight:(CGFloat)totalWeight sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count { //如果浮动宽度都是小于等于0因为没有拉升必要,所以直接返回 if (totalFloatWidth <= 0.0) return; CGFloat incOffset = 0.0; - for (NSInteger itemIndex = nextLineFirstItemIndex - count; itemIndex < nextLineFirstItemIndex; itemIndex++) + for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; @@ -250,7 +250,7 @@ - (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFlo } //第一个子视图不偏移。 - if (itemIndex != nextLineFirstItemIndex - count) + if (itemIndex != startIndex - count) sbvmyFrame.leading += incOffset; sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; incOffset += (sbvmyFrame.width - oldWidth); @@ -263,9 +263,9 @@ - (void)myCalcHorzLayoutSinglelineWeight:(CGSize)selfSize totalFloatHeight:(CGFl return; CGFloat incOffset = 0.0; - for (NSInteger j = startIndex - count; j < startIndex; j++) + for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { - UIView *sbv = sbs[j]; + UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; @@ -285,7 +285,7 @@ - (void)myCalcHorzLayoutSinglelineWeight:(CGSize)selfSize totalFloatHeight:(CGFl sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:[sbvsc.widthSizeInner measureWith: sbvmyFrame.height ] sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } - if (j != startIndex - count) + if (itemIndex != startIndex - count) sbvmyFrame.top += incOffset; sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; incOffset += (sbvmyFrame.height - oldHeight); @@ -313,9 +313,9 @@ - (void)myAdjustVertLayoutSinglelineWidth:(CGSize)selfSize lineIndex:(NSInteger) addXFill = floatingWidth / count; } - for (NSInteger j = startIndex - count; j < startIndex; j++) + for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { - UIView *sbv = sbs[j]; + UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; @@ -356,9 +356,9 @@ - (void)myAdjustHorzLayoutSinglelineHeight:(CGSize)selfSize lineIndex:(NSInteger addYFill = floatingHeight / count; } - for (NSInteger j = startIndex - count; j < startIndex; j++) + for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { - UIView *sbv = sbs[j]; + UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; @@ -387,9 +387,9 @@ - (void)myCalcVertLayoutSinglelineWidthShrink:(CGSize)selfSize totalFloatWidth:( return; //如果有压缩则调整子视图的宽度。 - for (NSInteger j = startIndex - count; j < startIndex; j++) + for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { - UIView *sbv = sbs[j]; + UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; @@ -411,9 +411,9 @@ - (void)myCalcHorzLayoutSinglelineHeightShrink:(CGSize)selfSize totalFloatHeight return; //如果有压缩则调整子视图的高度。 - for (NSInteger j = startIndex - count; j < startIndex; j++) + for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { - UIView *sbv = sbs[j]; + UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; @@ -499,9 +499,9 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger //基线位置 CGFloat baselinePos = CGFLOAT_MAX; //将整行的位置进行调整。 - for (NSInteger j = startIndex - count; j < startIndex; j++) + for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { - UIView *sbv = sbs[j]; + UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; @@ -523,11 +523,11 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger sbvl.bottomBorderline = self.intelligentBorderline; //如果不是最后一列就画右边, - if (j < startIndex - 1) + if (itemIndex < startIndex - 1) sbvl.trailingBorderline = self.intelligentBorderline; //如果最后一行的最后一个没有满列数时 - if (j == sbs.count - 1 && lsc.arrangedCount != count ) + if (itemIndex == sbs.count - 1 && lsc.arrangedCount != count ) sbvl.trailingBorderline = self.intelligentBorderline; //如果有垂直间距则不是第一行就画上 @@ -535,7 +535,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger sbvl.topBorderline = self.intelligentBorderline; //如果有水平间距则不是第一列就画左 - if (horzSpace != 0 && j != startIndex - count) + if (horzSpace != 0 && itemIndex != startIndex - count) sbvl.leadingBorderline = self.intelligentBorderline; } } @@ -578,7 +578,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger if ( lineHorzGravity != MyGravity_Horz_Fill) { //其他的只拉伸间距 - sbvmyFrame.leading += addXFill * (j - (startIndex - count)); + sbvmyFrame.leading += addXFill * (itemIndex - (startIndex - count)); } } @@ -689,9 +689,9 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger //压缩减少的尺寸汇总。 CGFloat totalShrinkSize = 0; //将整行的位置进行调整。 - for (NSInteger j = startIndex - count; j < startIndex; j++) + for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { - UIView *sbv = sbs[j]; + UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; @@ -710,7 +710,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger //如果不是最后一行就画下面, - if (j < startIndex - 1) + if (itemIndex < startIndex - 1) sbvl.bottomBorderline = self.intelligentBorderline; //如果不是最后一列就画右边, @@ -718,11 +718,11 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger sbvl.trailingBorderline = self.intelligentBorderline; //如果最后一行的最后一个没有满列数时 - if (j == sbs.count - 1 && lsc.arrangedCount != count ) + if (itemIndex == sbs.count - 1 && lsc.arrangedCount != count ) sbvl.bottomBorderline = self.intelligentBorderline; //如果有垂直间距则不是第一行就画上 - if (vertSpace != 0 && j != startIndex - count) + if (vertSpace != 0 && itemIndex != startIndex - count) sbvl.topBorderline = self.intelligentBorderline; //如果有水平间距则不是第一列就画左 @@ -761,7 +761,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger if (lineVertGravity != MyGravity_Vert_Fill) { //只拉伸间距 - sbvmyFrame.top += addYFill * (j - (startIndex - count)); + sbvmyFrame.top += addYFill * (itemIndex - (startIndex - count)); } } @@ -1369,7 +1369,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (rowTotalWeight != 0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs nextLineFirstItemIndex:i count:arrangedCount]; + [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedCount]; } if (rowTotalShrink != 0 && horzGravity != MyGravity_Horz_Fill) @@ -1450,7 +1450,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (rowTotalWeight != 0.0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs nextLineFirstItemIndex:i count:arrangedIndex]; + [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; } //如果有压缩子视图的处理则需要压缩子视图。 diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 8813c93..5170d43 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -320,19 +320,19 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; - CGFloat fixedHeight = 0; //计算固定部分的高度 - CGFloat totalWeight = 0; //剩余部分的总比重 - CGFloat totalShrink = 0; //总的压缩比重 - CGFloat addSpace = 0; //用于压缩时的间距压缩增量。 - CGFloat maxSelfWidth = 0; + CGFloat fixedHeight = 0.0; //计算固定部分的高度 + CGFloat totalWeight = 0.0; //剩余部分的总比重 + CGFloat totalShrink = 0.0; //总的压缩比重 + CGFloat addSpace = 0.0; //用于压缩时的间距压缩增量。 + CGFloat maxSelfWidth = 0.0; //高度不是包裹的子视图集合 NSMutableSet *noWrapsbsSet = [NSMutableSet new]; //固定高度尺寸的子视图集合 NSMutableArray *fixedSizeSbs = [NSMutableArray new]; - CGFloat fixedSizeHeight = 0; - NSInteger fixedSpaceCount = 0; //固定间距的子视图数量。 - CGFloat fixedSpaceHeight = 0; //固定间距的子视图的高度。 + CGFloat fixedSizeHeight = 0.0; + NSInteger fixedSpaceCount = 0.0; //固定间距的子视图数量。 + CGFloat fixedSpaceHeight = 0.0; //固定间距的子视图的高度。 CGFloat pos = paddingTop; for (UIView *sbv in sbs) { @@ -345,7 +345,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l { BOOL canAddToNoWrapSbs = YES; - if (sbvsc.weight != 0) + if (sbvsc.weight != 0.0) canAddToNoWrapSbs = NO; //判断是否是添加到参与布局视图包裹计算的子视图。 @@ -384,10 +384,9 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l sbvSize:rect.size]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + //特殊处理宽度等于高度的情况 if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) - {//特殊处理宽度等于高度的情况 rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; - } //计算子视图宽度以及对齐, 先计算宽度的原因是处理那些高度依赖宽度并且是wrap的情况。 CGFloat tempSelfWidth = [self myCalcSubviewLeadingTrailingRect:horzGravity @@ -427,14 +426,13 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l if (sbvsc.topPosInner.isRelativePos) { totalWeight += sbvsc.topPosInner.posNumVal.doubleValue; - fixedHeight += sbvsc.topPosInner.offsetVal; } else { fixedHeight += sbvsc.topPosInner.absVal; - if (sbvsc.topPosInner.absVal != 0) + if (sbvsc.topPosInner.absVal != 0.0) { fixedSpaceCount += 1; fixedSpaceHeight += sbvsc.topPosInner.absVal; @@ -446,7 +444,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l pos += sbvsc.topPosInner.absVal; rect.origin.y = pos; - if (sbvsc.weight != 0.0) { totalWeight += sbvsc.weight; @@ -475,7 +472,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l { fixedHeight += sbvsc.bottomPosInner.absVal; - if (sbvsc.bottomPosInner.absVal != 0) + if (sbvsc.bottomPosInner.absVal != 0.0) { fixedSpaceCount += 1; fixedSpaceHeight += sbvsc.bottomPosInner.absVal; @@ -491,7 +488,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l pos += subviewSpace; - if (subviewSpace != 0) + if (subviewSpace != 0.0) { fixedSpaceCount += 1; fixedSpaceHeight += subviewSpace; @@ -503,7 +500,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l if (lsc.heightSizeInner.dimeWrapVal) { - if (totalWeight != 0) + if (totalWeight != 0.0) { //在包裹高度且总体比重不为0时则,则需要还原最小的高度,这样就不会使得高度在横竖屏或者多次计算后越来高。 CGFloat tempSelfHeight = paddingVert; if (sbs.count > 1) @@ -518,7 +515,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l //如果是高度自适应则不需要压缩。 totalShrink = 0.0; - } if (lsc.widthSizeInner.dimeWrapVal) @@ -590,7 +586,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } if (totalShrink == 0.0) - floatingHeight = 0; + floatingHeight = 0.0; } else { @@ -607,9 +603,9 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l //如果有浮动尺寸或者有压缩模式 if (totalWeight != 0.0 || totalShrink != 0.0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingHeight, 0)) || vertGravity != MyGravity_None || lsc.widthSizeInner.dimeWrapVal) { - maxSelfWidth = 0; - CGFloat between = 0; //间距扩充 - CGFloat fill = 0; //尺寸扩充 + maxSelfWidth = 0.0; + CGFloat between = 0.0; //间距扩充 + CGFloat fill = 0.0; //尺寸扩充 if (vertGravity == MyGravity_Vert_Center) { pos = (selfSize.height - fixedHeight - paddingVert)/2.0 + paddingTop; @@ -794,7 +790,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l sbvmyFrame.frame = rect; } - } pos += paddingBottom; @@ -819,10 +814,10 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; - CGFloat fixedWidth = 0; //计算固定部分的宽度 - CGFloat totalWeight = 0; //剩余部分的总比重 - CGFloat totalShrink = 0; //总的压缩比重 - CGFloat addSpace = 0; //用于压缩时的间距压缩增量。 + CGFloat fixedWidth = 0.0; //计算固定部分的宽度 + CGFloat totalWeight = 0.0; //剩余部分的总比重 + CGFloat totalShrink = 0.0; //总的压缩比重 + CGFloat addSpace = 0.0; //用于压缩时的间距压缩增量。 //宽度不是包裹的子视图集合 NSMutableSet *noWrapsbsSet = [NSMutableSet new]; @@ -830,12 +825,12 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l NSMutableArray *fixedSizeSbs = [NSMutableArray new]; //浮动宽度尺寸的子视图集合 NSMutableArray *flexedSizeSbs = [NSMutableArray new]; - CGFloat fixedSizeWidth = 0; //固定尺寸视图的宽度 - NSInteger fixedSpaceCount = 0; //固定间距的子视图数量。 - CGFloat fixedSpaceWidth = 0; //固定间距的子视图的宽度。 + CGFloat fixedSizeWidth = 0.0; //固定尺寸视图的宽度 + NSInteger fixedSpaceCount = 0.0; //固定间距的子视图数量。 + CGFloat fixedSpaceWidth = 0.0; //固定间距的子视图的宽度。 CGFloat baselinePos = CGFLOAT_MAX; //保存基线的值。 CGFloat pos = paddingLeading; - CGFloat maxSelfHeight = 0; + CGFloat maxSelfHeight = 0.0; for (UIView *sbv in sbs) { //计算出固定宽度部分以及weight部分。这里的宽度可能依赖高度。如果不是高度包裹则计算出所有高度。 @@ -848,7 +843,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l { BOOL canAddToNoWrapSbs = YES; - if (sbvsc.weight != 0) + if (sbvsc.weight != 0.0) canAddToNoWrapSbs = NO; //判断是否是添加到参与布局视图包裹计算的子视图。 @@ -871,7 +866,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l //在计算拉伸时,如果没有设置宽度约束则将宽度设置为0 if (sbvsc.widthSizeInner.dimeVal == nil && !sbvsc.widthSizeInner.lBoundValInner.dimeWrapVal) - rect.size.width = 0; + rect.size.width = 0.0; } //计算子视图的宽度,这里不管是否设置约束以及是否宽度是weight的都是进行计算。 @@ -939,7 +934,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l { fixedWidth += sbvsc.leadingPosInner.absVal; - if (sbvsc.leadingPosInner.absVal != 0) + if (sbvsc.leadingPosInner.absVal != 0.0) { fixedSpaceCount += 1; fixedSpaceWidth += sbvsc.leadingPosInner.absVal; @@ -951,7 +946,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l pos += sbvsc.leadingPosInner.absVal; rect.origin.x = pos; - if (sbvsc.weight != 0.0) { totalWeight += sbvsc.weight; @@ -985,7 +979,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l { fixedWidth += sbvsc.trailingPosInner.absVal; - if (sbvsc.trailingPosInner.absVal != 0) + if (sbvsc.trailingPosInner.absVal != 0.0) { fixedSpaceCount += 1; fixedSpaceWidth += sbvsc.trailingPosInner.absVal; @@ -1001,7 +995,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l pos += subviewSpace; - if (subviewSpace != 0) + if (subviewSpace != 0.0) { fixedSpaceCount += 1; fixedSpaceWidth += subviewSpace; @@ -1014,7 +1008,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l //在包裹宽度且总体比重不为0时则,则需要还原最小的宽度,这样就不会使得宽度在横竖屏或者多次计算后越来越宽。 if (lsc.widthSizeInner.dimeWrapVal) { - if (totalWeight != 0) + if (totalWeight != 0.0) { CGFloat tempSelfWidth = paddingHorz; if (sbs.count > 1) @@ -1040,7 +1034,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l //这里需要特殊处理当子视图的尺寸宽度大于布局视图的宽度的情况. //剩余的可浮动的宽度,那些weight不为0的从这个宽度来进行分发 BOOL isWeightShrinkSpace = NO; //是否按比重缩小间距。。。 - CGFloat weightShrinkSpaceTotalWidth = 0; + CGFloat weightShrinkSpaceTotalWidth = 0.0; CGFloat floatingWidth = selfSize.width - fixedWidth - paddingHorz; //取出shrinkType中的模式和内容类型: MySubviewsShrinkType sstMode = lsc.shrinkType & 0x0F; //压缩的模式 @@ -1050,7 +1044,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l if (totalShrink != 0.0) sstMode = MySubviewsShrink_None; - if (_myCGFloatLessOrEqual(floatingWidth, 0)) + if (_myCGFloatLessOrEqual(floatingWidth, 0.0)) { //如果压缩方式为自动,但是浮动宽度子视图数量不为2则压缩类型无效。 if (sstMode == MySubviewsShrink_Auto && flexedSizeSbs.count != 2) @@ -1106,11 +1100,9 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l leadingView.myFrame.width = leadingWidth; trailingView.myFrame.width = layoutWidth - leadingWidth; } - } else ; - } else if (_myCGFloatNotEqual(fixedSizeWidth, 0)) {//按比例分配。 @@ -1118,7 +1110,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l { fsbv.myFrame.width += floatingWidth * (fsbv.myFrame.width / fixedSizeWidth); } - } } } @@ -1154,16 +1145,14 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l //如果是总的压缩比重不为0则认为固定宽度和布局视图宽度保持一致。 if (totalShrink != 0.0) - { fixedWidth = selfSize.width - paddingHorz; - } //如果有浮动尺寸或者有压缩模式 if (totalWeight != 0.0 || totalShrink != 0.0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingWidth, 0)) || horzGravity != MyGravity_None || lsc.heightSizeInner.dimeWrapVal) { - maxSelfHeight = 0; - CGFloat between = 0; //间距扩充 - CGFloat fill = 0; //尺寸扩充 + maxSelfHeight = 0.0; + CGFloat between = 0.0; //间距扩充 + CGFloat fill = 0.0; //尺寸扩充 if (horzGravity == MyGravity_Horz_Center) { pos = (selfSize.width - fixedWidth - paddingHorz)/2.0 + paddingLeading; @@ -1218,7 +1207,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - CGFloat leadingSpace = sbvsc.leadingPosInner.posNumVal.doubleValue; CGFloat trailingSpace = sbvsc.trailingPosInner.posNumVal.doubleValue; CGFloat weight = sbvsc.weight; @@ -1255,7 +1243,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l rect.origin.x = pos; //分别处理相对高度和绝对高度 - if (weight != 0) + if (weight != 0.0) { CGFloat w = _myCGFloatRound((weight / totalWeight) * floatingWidth); if (_myCGFloatLessOrEqual(w, 0)) @@ -1265,7 +1253,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } //加上扩充的宽度。 - if (fill != 0 && [noWrapsbsSet containsObject:sbv]) + if (fill != 0.0 && [noWrapsbsSet containsObject:sbv]) rect.size.width += fill; if (totalShrink != 0.0 && sbvsc.widthSizeInner.shrink != 0.0) @@ -1348,7 +1336,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l sbvmyFrame.frame = rect; } - } pos += paddingTrailing; From 7dd0a66c2f5c1346b3e608dc0d77507f3c7d1a46 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Thu, 24 Oct 2019 09:34:05 +0800 Subject: [PATCH 061/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlowLayout.m | 619 ++++++++++++++++++++---------------- 1 file changed, 340 insertions(+), 279 deletions(-) diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 3369b19..9aff4e2 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -223,53 +223,48 @@ -(id)createSizeClassInstance #pragma mark -- Private Methods -- (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalWeight:(CGFloat)totalWeight sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count +- (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalWeight:(CGFloat)totalWeight sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc { //如果浮动宽度都是小于等于0因为没有拉升必要,所以直接返回 if (totalFloatWidth <= 0.0) return; - CGFloat incOffset = 0.0; + //按照flex规约,如果总的比重小于1则只会将剩余宽度的总比重部分来进行按比例拉伸。 + if (lsc.isFlex && totalWeight < 1.0) + totalFloatWidth *= totalWeight; + + for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - CGFloat oldWidth = sbvmyFrame.width; if (sbvsc.weight != 0) { CGFloat tempWidth = _myCGFloatRound((totalFloatWidth * sbvsc.weight / totalWeight)); if (sbvsc.widthSizeInner != nil && sbvsc.widthSizeInner.dimeVal == nil) tempWidth = [sbvsc.widthSizeInner measureWith:tempWidth]; - totalFloatWidth -= tempWidth; - totalWeight -= sbvsc.weight; - sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:tempWidth + sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } - - //第一个子视图不偏移。 - if (itemIndex != startIndex - count) - sbvmyFrame.leading += incOffset; - sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; - incOffset += (sbvmyFrame.width - oldWidth); - } + } } -- (void)myCalcHorzLayoutSinglelineWeight:(CGSize)selfSize totalFloatHeight:(CGFloat)totalFloatHeight totalWeight:(CGFloat)totalWeight sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count +- (void)myCalcHorzLayoutSinglelineWeight:(CGSize)selfSize totalFloatHeight:(CGFloat)totalFloatHeight totalWeight:(CGFloat)totalWeight sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc { if (totalFloatHeight <= 0.0) return; - CGFloat incOffset = 0.0; + if (lsc.isFlex && totalWeight < 1.0) + totalFloatHeight *= totalWeight; + for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - CGFloat oldHeight = sbvmyFrame.height; if (sbvsc.weight != 0) { CGFloat tempHeight = _myCGFloatRound((totalFloatHeight * sbvsc.weight / totalWeight)); @@ -284,11 +279,6 @@ - (void)myCalcHorzLayoutSinglelineWeight:(CGSize)selfSize totalFloatHeight:(CGFl if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:[sbvsc.widthSizeInner measureWith: sbvmyFrame.height ] sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } - - if (itemIndex != startIndex - count) - sbvmyFrame.top += incOffset; - sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; - incOffset += (sbvmyFrame.height - oldHeight); } } @@ -312,6 +302,12 @@ - (void)myAdjustVertLayoutSinglelineWidth:(CGSize)selfSize lineIndex:(NSInteger) if (lsc.isFlex || startIndex != sbs.count) addXFill = floatingWidth / count; } + else + { + //flex规则:当总的比重小于1时,剩余的宽度要乘以这个比重值再进行分配。 + if (lsc.isFlex && totalWeight < 1.0) + floatingWidth *= totalWeight; + } for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { @@ -355,6 +351,12 @@ - (void)myAdjustHorzLayoutSinglelineHeight:(CGSize)selfSize lineIndex:(NSInteger if (lsc.isFlex || startIndex != sbs.count) addYFill = floatingHeight / count; } + else + { + //flex规则:当总的比重小于1时,剩余的高度要乘以这个比重值再进行分配。 + if (lsc.isFlex && totalWeight < 1.0) + floatingHeight *= totalWeight; + } for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { @@ -378,7 +380,7 @@ - (void)myAdjustHorzLayoutSinglelineHeight:(CGSize)selfSize lineIndex:(NSInteger } -- (void)myCalcVertLayoutSinglelineWidthShrink:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalShrink:(CGFloat)totalShrink sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count +- (void)myCalcVertLayoutSinglelineWidthShrink:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalShrink:(CGFloat)totalShrink sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc { if (_myCGFloatGreatOrEqual(totalFloatWidth, 0.0)) totalShrink = 0.0; @@ -386,6 +388,10 @@ - (void)myCalcVertLayoutSinglelineWidthShrink:(CGSize)selfSize totalFloatWidth:( if (totalShrink == 0.0) return; + //根据flex规约:如果总的压缩比重小于1则超出部分会乘以这个压缩比再进行压缩。 + if (lsc.isFlex && totalShrink < 1.0) + totalFloatWidth *= totalShrink; + //如果有压缩则调整子视图的宽度。 for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { @@ -402,7 +408,7 @@ - (void)myCalcVertLayoutSinglelineWidthShrink:(CGSize)selfSize totalFloatWidth:( } } -- (void)myCalcHorzLayoutSinglelineHeightShrink:(CGSize)selfSize totalFloatHeight:(CGFloat)totalFloatHeight totalShrink:(CGFloat)totalShrink sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count +- (void)myCalcHorzLayoutSinglelineHeightShrink:(CGSize)selfSize totalFloatHeight:(CGFloat)totalFloatHeight totalShrink:(CGFloat)totalShrink sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout *)lsc { if (_myCGFloatGreatOrEqual(totalFloatHeight, 0.0)) totalShrink = 0.0; @@ -410,6 +416,10 @@ - (void)myCalcHorzLayoutSinglelineHeightShrink:(CGSize)selfSize totalFloatHeight if (totalShrink == 0.0) return; + //根据flex规约:如果总的压缩比重小于1则超出部分会乘以这个压缩比再进行压缩。 + if (lsc.isFlex && totalShrink < 1.0) + totalFloatHeight *= totalShrink; + //如果有压缩则调整子视图的高度。 for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) { @@ -954,6 +964,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; CGFloat paddingHorz = paddingLeading + paddingTrailing; + CGFloat paddingVert = paddingTop + paddingBottom; + MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; @@ -1187,91 +1199,101 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab arrangedIndex++; } + yPos += rowMaxHeight + paddingBottom; + + //内容填充约束布局的宽度包裹计算。 if (lsc.widthSizeInner.dimeWrapVal) selfSize.width = maxWidth; - //最后一行 - [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:lineIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - - yPos += rowMaxHeight + paddingBottom; - if (lsc.heightSizeInner.dimeWrapVal) selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:yPos sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + NSInteger arranges = lineFirstSubviewIndexSet.count; + //根据flex规则:如果只有一行则整个高度都作为子视图的拉伸和停靠区域。 + if (lsc.isFlex && arranges == 1) + rowMaxHeight = selfSize.height - paddingVert; + + //最后一行 + [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:lineIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + + //整体的停靠 if (vertGravity != MyGravity_None && selfSize.height != yPos) { - CGFloat addYPos = 0.0; - CGFloat between = 0.0; - CGFloat fill = 0.0; - - if (vertGravity == MyGravity_Vert_Center) - { - addYPos = (selfSize.height - yPos) / 2; - } - else if (vertGravity == MyGravity_Vert_Bottom) - { - addYPos = selfSize.height - yPos; - } - else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) + //根据flex标准:只有在多行下vertGravity才有意义。非flex标准则不受这个条件约束。 + if (arranges > 1 || !lsc.isFlex) { - if (lineFirstSubviewIndexSet.count > 0) - fill = (selfSize.height - yPos) / lineFirstSubviewIndexSet.count; + CGFloat addYPos = 0.0; + CGFloat between = 0.0; + CGFloat fill = 0.0; - //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' - if (fill < 0.0 && vertGravity == MyGravity_Vert_Stretch) - fill = 0.0; - } - else if (vertGravity == MyGravity_Vert_Between) - { - if (lineFirstSubviewIndexSet.count > 1) - between = (selfSize.height - yPos) / (lineFirstSubviewIndexSet.count - 1); - } - else if (vertGravity == MyGravity_Vert_Around) - { - if (lineFirstSubviewIndexSet.count > 1) - between = (selfSize.height - yPos) / lineFirstSubviewIndexSet.count; - } - - if (addYPos != 0.0 || between != 0.0 || fill != 0.0) - { - int lineidx = 0; - NSUInteger lastIndex = 0; - for (int i = 0; i < sbs.count; i++) + if (vertGravity == MyGravity_Vert_Center) { - UIView *sbv = sbs[i]; - - MyFrame *sbvmyFrame = sbv.myFrame; - - sbvmyFrame.top += addYPos; - - //找到行的最初索引。 - NSUInteger index = [lineFirstSubviewIndexSet indexLessThanOrEqualToIndex:i]; - if (lastIndex != index) - { - lastIndex = index; - lineidx ++; - } + addYPos = (selfSize.height - yPos) / 2; + } + else if (vertGravity == MyGravity_Vert_Bottom) + { + addYPos = selfSize.height - yPos; + } + else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) + { + if (lineFirstSubviewIndexSet.count > 0) + fill = (selfSize.height - yPos) / arranges; - if (vertGravity == MyGravity_Vert_Stretch) + //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' + if (fill < 0.0 && vertGravity == MyGravity_Vert_Stretch) + fill = 0.0; + } + else if (vertGravity == MyGravity_Vert_Between) + { + if (lineFirstSubviewIndexSet.count > 1) + between = (selfSize.height - yPos) / (arranges - 1); + } + else if (vertGravity == MyGravity_Vert_Around) + { + if (lineFirstSubviewIndexSet.count > 1) + between = (selfSize.height - yPos) / arranges; + } + + if (addYPos != 0.0 || between != 0.0 || fill != 0.0) + { + int lineidx = 0; + NSUInteger lastIndex = 0; + for (int i = 0; i < sbs.count; i++) { - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.heightSizeInner.dimeVal == nil) + UIView *sbv = sbs[i]; + + MyFrame *sbvmyFrame = sbv.myFrame; + + sbvmyFrame.top += addYPos; + + //找到行的最初索引。 + NSUInteger index = [lineFirstSubviewIndexSet indexLessThanOrEqualToIndex:i]; + if (lastIndex != index) + { + lastIndex = index; + lineidx ++; + } + + if (vertGravity == MyGravity_Vert_Stretch) + { + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + if (sbvsc.heightSizeInner.dimeVal == nil) + sbvmyFrame.height += fill; + } + else + { sbvmyFrame.height += fill; + } + sbvmyFrame.top += fill * lineidx; + + sbvmyFrame.top += between * lineidx; + + if (vertGravity == MyGravity_Vert_Around) + sbvmyFrame.top += (between / 2.0); } - else - { - sbvmyFrame.height += fill; - } - sbvmyFrame.top += fill * lineidx; - - sbvmyFrame.top += between * lineidx; - - if (vertGravity == MyGravity_Vert_Around) - sbvmyFrame.top += (between / 2.0); } } - } return selfSize; @@ -1369,12 +1391,12 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (rowTotalWeight != 0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedCount]; + [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedCount lsc:lsc]; } if (rowTotalShrink != 0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWidthShrink:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalShrink:rowTotalShrink sbs:sbs startIndex:i count:arrangedCount]; + [self myCalcVertLayoutSinglelineWidthShrink:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalShrink:rowTotalShrink sbs:sbs startIndex:i count:arrangedCount lsc:lsc]; } rowTotalWeight = 0.0; @@ -1450,13 +1472,13 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (rowTotalWeight != 0.0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; + [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; } //如果有压缩子视图的处理则需要压缩子视图。 if (rowTotalShrink != 0.0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWidthShrink:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalShrink:rowTotalShrink sbs:sbs startIndex:i count:arrangedIndex]; + [self myCalcVertLayoutSinglelineWidthShrink:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalShrink:rowTotalShrink sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; } //初始化每行的下一个子视图的位置。 @@ -1642,9 +1664,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray //这里只对间距进行压缩比重的计算,因为前面压缩了宽度,这里只需要压缩间距了。 rowTotalShrink += sbvsc.leadingPosInner.shrink + sbvsc.trailingPosInner.shrink; } - - //最后一行,有可能因为行宽的压缩导致那些高度依赖宽度以及高度自适应的视图会增加高度,从而使得行高被调整。 - [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; maxHeight += paddingBottom; @@ -1664,69 +1683,90 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:selfSize.height sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; } + //得到行数 + NSInteger arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); //行数 + //根据flex规则:如果只有一行则整个高度都作为子视图的拉伸和停靠区域。 + if (lsc.isFlex && arranges == 1) + rowMaxHeight = selfSize.height - paddingVert; + + //最后一行,有可能因为行宽的压缩导致那些高度依赖宽度以及高度自适应的视图会增加高度,从而使得行高被调整。 + [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + + //整体的停靠 if (vertGravity != MyGravity_None && selfSize.height != maxHeight && !(isVertPaging && isPagingScroll)) { - CGFloat addYPos = 0.0; - CGFloat between = 0.0; - CGFloat fill = 0.0; - int arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); //行数 - - if (vertGravity == MyGravity_Vert_Center) + //根据flex标准:只有在多行下vertGravity才有意义。非flex标准则不受这个条件约束。 + if (arranges > 1 || !lsc.isFlex) { - addYPos = (selfSize.height - maxHeight) / 2; - } - else if (vertGravity == MyGravity_Vert_Bottom) - { - addYPos = selfSize.height - maxHeight; - } - else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) - { - if (arranges > 0) - fill = (selfSize.height - maxHeight) / arranges; + CGFloat addYPos = 0.0; + CGFloat between = 0.0; + CGFloat fill = 0.0; - //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' - if (fill < 0.0 && vertGravity == MyGravity_Vert_Stretch) - fill = 0.0; - } - else if (vertGravity == MyGravity_Vert_Between) - { - if (arranges > 1) - between = (selfSize.height - maxHeight) / (arranges - 1); - } - else if (vertGravity == MyGravity_Vert_Around) - { - if (arranges > 1) - between = (selfSize.height - maxHeight) / arranges; - } - - if (addYPos != 0.0 || between != 0.0 || fill != 0.0) - { - for (int i = 0; i < sbs.count; i++) + if (vertGravity == MyGravity_Vert_Center) { - UIView *sbv = sbs[i]; - - MyFrame *sbvmyFrame = sbv.myFrame; + addYPos = (selfSize.height - maxHeight) / 2; + } + else if (vertGravity == MyGravity_Vert_Bottom) + { + addYPos = selfSize.height - maxHeight; + } + else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) + { + if (arranges > 0) + fill = (selfSize.height - maxHeight) / arranges; - int lineidx = i / arrangedCount; - if (vertGravity == MyGravity_Vert_Stretch) + //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' + if (fill < 0.0 && vertGravity == MyGravity_Vert_Stretch) + fill = 0.0; + } + else if (vertGravity == MyGravity_Vert_Between) + { + if (arranges > 1) + between = (selfSize.height - maxHeight) / (arranges - 1); + } + else if (vertGravity == MyGravity_Vert_Around) + { + if (arranges > 1) + between = (selfSize.height - maxHeight) / arranges; + } + + if (addYPos != 0.0 || between != 0.0 || fill != 0.0) + { + for (int i = 0; i < sbs.count; i++) { - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.heightSizeInner.dimeVal == nil) + UIView *sbv = sbs[i]; + + MyFrame *sbvmyFrame = sbv.myFrame; + + int lineidx = i / arrangedCount; + if (vertGravity == MyGravity_Vert_Stretch) + { + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + if (sbvsc.heightSizeInner.dimeVal == nil) + sbvmyFrame.height += fill; + +// //因为每行都增加了fill。所以如果有行内对齐则需要这里调整。 +// MyGravity sbvVertAlignment = sbvsc.alignment & MyGravity_Horz_Mask; +// if (sbvVertAlignment == MyGravity_None) +// sbvVertAlignment = vertAlign; +// if (vertAlignment == MyGravity_Vert_Between) +// sbvVertAlignment = MyGravity_Vert_Between; + + } + else + { sbvmyFrame.height += fill; + } + sbvmyFrame.top += fill * lineidx; + + sbvmyFrame.top += addYPos; + + sbvmyFrame.top += between * lineidx; + + //如果是vert_around那么所有行都应该添加一半的between值。 + if (vertGravity == MyGravity_Vert_Around) + sbvmyFrame.top += (between / 2.0); } - else - { - sbvmyFrame.height += fill; - } - sbvmyFrame.top += fill * lineidx; - - sbvmyFrame.top += addYPos; - - sbvmyFrame.top += between * lineidx; - - //如果是vert_around那么所有行都应该添加一半的between值。 - if (vertGravity == MyGravity_Vert_Around) - sbvmyFrame.top += (between / 2.0); } } } @@ -1756,6 +1796,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; CGFloat paddingVert = paddingTop + paddingBottom; + CGFloat paddingHorz = paddingLeading + paddingTrailing; MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; @@ -1990,87 +2031,96 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab arrangedIndex++; } + xPos += colMaxWidth + paddingTrailing; + if (lsc.heightSizeInner.dimeWrapVal) selfSize.height = maxHeight; - - - [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:lineIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; - - - xPos += colMaxWidth + paddingTrailing; - + + if (lsc.widthSizeInner.dimeWrapVal) selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:xPos sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + NSInteger arranges = lineFirstSubviewIndexSet.count; + //根据flex规则:如果只有一列则整个宽度都作为子视图的拉伸和停靠区域。 + if (lsc.isFlex && arranges == 1) + colMaxWidth = selfSize.width - paddingHorz; + + //最后一列 + [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:lineIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + + //整体的停靠 if (horzGravity != MyGravity_None && selfSize.width != xPos) { - CGFloat addXPos = 0.0; - CGFloat fill = 0.0; - CGFloat between = 0.0; - - if (horzGravity == MyGravity_Horz_Center) - { - addXPos = (selfSize.width - xPos) / 2; - } - else if (horzGravity == MyGravity_Horz_Trailing) - { - addXPos = selfSize.width - xPos; - } - else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) + //根据flex标准:只有在多行下horzGravity才有意义。非flex标准则不受这个条件约束。 + if (arranges > 1 || !lsc.isFlex) { - if (lineFirstSubviewIndexSet.count > 0) - fill = (selfSize.width - xPos) / lineFirstSubviewIndexSet.count; - - //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' - if (fill < 0.0 && horzGravity == MyGravity_Horz_Stretch) - fill = 0.0; - } - else if (horzGravity == MyGravity_Horz_Between) - { - if (lineFirstSubviewIndexSet.count > 1) - between = (selfSize.width - xPos) / (lineFirstSubviewIndexSet.count - 1); - } - else if (horzGravity == MyGravity_Horz_Around) - { - if (lineFirstSubviewIndexSet.count > 1) - between = (selfSize.width - xPos) / lineFirstSubviewIndexSet.count; - } - - if (addXPos != 0.0 || between != 0.0 || fill != 0.0) - { - int lineidx = 0; - NSUInteger lastIndex = 0; - for (int i = 0; i < sbs.count; i++) + CGFloat addXPos = 0.0; + CGFloat fill = 0.0; + CGFloat between = 0.0; + if (horzGravity == MyGravity_Horz_Center) { - UIView *sbv = sbs[i]; - MyFrame *sbvmyFrame = sbv.myFrame; - - sbvmyFrame.leading += addXPos; - - //找到行的最初索引。 - NSUInteger index = [lineFirstSubviewIndexSet indexLessThanOrEqualToIndex:i]; - if (lastIndex != index) - { - lastIndex = index; - lineidx ++; - } + addXPos = (selfSize.width - xPos) / 2; + } + else if (horzGravity == MyGravity_Horz_Trailing) + { + addXPos = selfSize.width - xPos; + } + else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) + { + if (lineFirstSubviewIndexSet.count > 0) + fill = (selfSize.width - xPos) / lineFirstSubviewIndexSet.count; - if (horzGravity == MyGravity_Horz_Stretch) + //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' + if (fill < 0.0 && horzGravity == MyGravity_Horz_Stretch) + fill = 0.0; + } + else if (horzGravity == MyGravity_Horz_Between) + { + if (lineFirstSubviewIndexSet.count > 1) + between = (selfSize.width - xPos) / (lineFirstSubviewIndexSet.count - 1); + } + else if (horzGravity == MyGravity_Horz_Around) + { + if (lineFirstSubviewIndexSet.count > 1) + between = (selfSize.width - xPos) / lineFirstSubviewIndexSet.count; + } + + if (addXPos != 0.0 || between != 0.0 || fill != 0.0) + { + int lineidx = 0; + NSUInteger lastIndex = 0; + for (int i = 0; i < sbs.count; i++) { - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.widthSizeInner.dimeVal == nil) + UIView *sbv = sbs[i]; + MyFrame *sbvmyFrame = sbv.myFrame; + + sbvmyFrame.leading += addXPos; + + //找到行的最初索引。 + NSUInteger index = [lineFirstSubviewIndexSet indexLessThanOrEqualToIndex:i]; + if (lastIndex != index) + { + lastIndex = index; + lineidx ++; + } + + if (horzGravity == MyGravity_Horz_Stretch) + { + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + if (sbvsc.widthSizeInner.dimeVal == nil) + sbvmyFrame.width += fill; + } + else + { sbvmyFrame.width += fill; + } + sbvmyFrame.leading += fill * lineidx; + + sbvmyFrame.leading += between * lineidx; + + if (horzGravity == MyGravity_Horz_Around) + sbvmyFrame.leading += (between / 2.0); } - else - { - sbvmyFrame.width += fill; - } - sbvmyFrame.leading += fill * lineidx; - - sbvmyFrame.leading += between * lineidx; - - if (horzGravity == MyGravity_Horz_Around) - sbvmyFrame.leading += (between / 2.0); } } } @@ -2171,12 +2221,12 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray if (colTotalWeight != 0 && vertGravity != MyGravity_Vert_Fill) { - [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedCount]; + [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedCount lsc:lsc]; } if (colTotalShrink != 0 && vertGravity != MyGravity_Vert_Fill) { - [self myCalcHorzLayoutSinglelineHeightShrink:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalShrink:colTotalShrink sbs:sbs startIndex:i count:arrangedCount]; + [self myCalcHorzLayoutSinglelineHeightShrink:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalShrink:colTotalShrink sbs:sbs startIndex:i count:arrangedCount lsc:lsc]; } colTotalWeight = 0.0; @@ -2258,12 +2308,12 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray if (colTotalWeight != 0.0 && vertGravity != MyGravity_Vert_Fill) { - [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedIndex]; + [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; } if (colTotalShrink != 0.0 && vertGravity != MyGravity_Vert_Fill) { - [self myCalcHorzLayoutSinglelineHeightShrink:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalShrink:colTotalShrink sbs:sbs startIndex:i count:arrangedIndex]; + [self myCalcHorzLayoutSinglelineHeightShrink:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalShrink:colTotalShrink sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; } //初始化每行的下一个子视图的位置。 @@ -2424,8 +2474,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray colTotalShrink += sbvsc.topPosInner.shrink + sbvsc.bottomPosInner.shrink; } - //最后一列 - [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; maxWidth += paddingTrailing; @@ -2445,69 +2493,82 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:selfSize.width sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; } + //得到行数 + NSInteger arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); //行数 + //根据flex规则:如果只有一行则整个高度都作为子视图的拉伸和停靠区域。 + if (lsc.isFlex && arranges == 1) + colMaxWidth = selfSize.width - paddingHorz; + + //最后一列 + [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + + //整体的停靠。 if (horzGravity != MyGravity_None && selfSize.width != maxWidth && !(isHorzPaging && isPagingScroll)) { - - CGFloat addXPos = 0.0; - CGFloat between = 0.0; - CGFloat fill = 0.0; - int arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); //列数 - - if (horzGravity == MyGravity_Horz_Center) - { - addXPos = (selfSize.width - maxWidth) / 2; - } - else if (horzGravity == MyGravity_Horz_Trailing) - { - addXPos = selfSize.width - maxWidth; - } - else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) + + //根据flex标准:只有在多行下horzGravity才有意义。非flex标准则不受这个条件约束。 + if (arranges > 1 || !lsc.isFlex) { - if (arranges > 0) - fill = (selfSize.width - maxWidth) / arranges; + CGFloat addXPos = 0.0; + CGFloat between = 0.0; + CGFloat fill = 0.0; - //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' - if (fill < 0.0 && horzGravity == MyGravity_Horz_Stretch) - fill = 0.0; - } - else if (horzGravity == MyGravity_Horz_Between) - { - if (arranges > 1) - between = (selfSize.width - maxWidth) / (arranges - 1); - } - else if (horzGravity == MyGravity_Horz_Around) - { - if (arranges > 1) - between = (selfSize.width - maxWidth) / arranges; - } - - if (addXPos != 0.0 || between != 0.0 || fill != 0.0) - { - for (int i = 0; i < sbs.count; i++) + if (horzGravity == MyGravity_Horz_Center) { - UIView *sbv = sbs[i]; - - MyFrame *sbvmyFrame = sbv.myFrame; + addXPos = (selfSize.width - maxWidth) / 2; + } + else if (horzGravity == MyGravity_Horz_Trailing) + { + addXPos = selfSize.width - maxWidth; + } + else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) + { + if (arranges > 0) + fill = (selfSize.width - maxWidth) / arranges; - int lineidx = i / arrangedCount; - if (horzGravity == MyGravity_Horz_Stretch) + //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' + if (fill < 0.0 && horzGravity == MyGravity_Horz_Stretch) + fill = 0.0; + } + else if (horzGravity == MyGravity_Horz_Between) + { + if (arranges > 1) + between = (selfSize.width - maxWidth) / (arranges - 1); + } + else if (horzGravity == MyGravity_Horz_Around) + { + if (arranges > 1) + between = (selfSize.width - maxWidth) / arranges; + } + + if (addXPos != 0.0 || between != 0.0 || fill != 0.0) + { + for (int i = 0; i < sbs.count; i++) { - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.widthSizeInner.dimeVal == nil) + UIView *sbv = sbs[i]; + + MyFrame *sbvmyFrame = sbv.myFrame; + + int lineidx = i / arrangedCount; + if (horzGravity == MyGravity_Horz_Stretch) + { + UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + if (sbvsc.widthSizeInner.dimeVal == nil) + sbvmyFrame.width += fill; + } + else + { sbvmyFrame.width += fill; + } + sbvmyFrame.leading += fill * lineidx; + + sbvmyFrame.leading += addXPos; + + sbvmyFrame.leading += between * lineidx; + + if (horzGravity == MyGravity_Horz_Around) + sbvmyFrame.leading += (between / 2.0); } - else - { - sbvmyFrame.width += fill; - } - sbvmyFrame.leading += fill * lineidx; - - sbvmyFrame.leading += addXPos; - - sbvmyFrame.leading += between * lineidx; - - if (horzGravity == MyGravity_Horz_Around) - sbvmyFrame.leading += (between / 2.0); } } } From ef26c63ad42d536ca2b5676c8f849b20a59f9199 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Thu, 24 Oct 2019 18:46:42 +0800 Subject: [PATCH 062/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlowLayout.m | 68 ++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 9aff4e2..b4def57 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -1279,7 +1279,22 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab { UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.heightSizeInner.dimeVal == nil) + { sbvmyFrame.height += fill; + } + else + { + //因为每行都增加了fill。所以如果有行内对齐则需要这里调整。 + MyGravity sbvVertAlignment = sbvsc.alignment & MyGravity_Horz_Mask; + if (sbvVertAlignment == MyGravity_None) + sbvVertAlignment = vertAlign; + + if (sbvVertAlignment == MyGravity_Vert_Center) + sbvmyFrame.top += fill/2.0; + else if (sbvVertAlignment == MyGravity_Vert_Bottom) + sbvmyFrame.top += fill; + else; + } } else { @@ -1743,15 +1758,22 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray { UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.heightSizeInner.dimeVal == nil) + { sbvmyFrame.height += fill; - -// //因为每行都增加了fill。所以如果有行内对齐则需要这里调整。 -// MyGravity sbvVertAlignment = sbvsc.alignment & MyGravity_Horz_Mask; -// if (sbvVertAlignment == MyGravity_None) -// sbvVertAlignment = vertAlign; -// if (vertAlignment == MyGravity_Vert_Between) -// sbvVertAlignment = MyGravity_Vert_Between; - + } + else + { + //因为每行都增加了fill。所以如果有行内对齐则需要这里调整。 + MyGravity sbvVertAlignment = sbvsc.alignment & MyGravity_Horz_Mask; + if (sbvVertAlignment == MyGravity_None) + sbvVertAlignment = vertAlign; + + if (sbvVertAlignment == MyGravity_Vert_Center) + sbvmyFrame.top += fill/2.0; + else if (sbvVertAlignment == MyGravity_Vert_Bottom) + sbvmyFrame.top += fill; + else; + } } else { @@ -2108,7 +2130,22 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab { UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.widthSizeInner.dimeVal == nil) + { sbvmyFrame.width += fill; + } + else + { + //因为每行都增加了fill。所以如果有行内对齐则需要这里调整。 + MyGravity sbvHorzAlignment = [self myConvertLeftRightGravityToLeadingTrailing:sbvsc.alignment & MyGravity_Vert_Mask]; + if (sbvHorzAlignment == MyGravity_None) + sbvHorzAlignment = horzAlign; + + if (sbvHorzAlignment == MyGravity_Horz_Center) + sbvmyFrame.leading += fill/2.0; + else if (sbvHorzAlignment == MyGravity_Horz_Trailing) + sbvmyFrame.leading += fill; + else; + } } else { @@ -2554,7 +2591,22 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray { UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.widthSizeInner.dimeVal == nil) + { sbvmyFrame.width += fill; + } + else + { + //因为每行都增加了fill。所以如果有行内对齐则需要这里调整。 + MyGravity sbvHorzAlignment = [self myConvertLeftRightGravityToLeadingTrailing:sbvsc.alignment & MyGravity_Vert_Mask]; + if (sbvHorzAlignment == MyGravity_None) + sbvHorzAlignment = horzAlign; + + if (sbvHorzAlignment == MyGravity_Horz_Center) + sbvmyFrame.leading += fill/2.0; + else if (sbvHorzAlignment == MyGravity_Horz_Trailing) + sbvmyFrame.leading += fill; + else; + } } else { From 187d3f096ab98e7db20792b8f15938fd19e39054 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Thu, 24 Oct 2019 22:20:10 +0800 Subject: [PATCH 063/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7,BU?= =?UTF-8?q?G=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.h | 2 ++ MyLayout/Lib/MyFlexLayout.h | 13 +++++++---- MyLayout/Lib/MyFlowLayout.h | 3 ++- MyLayoutDemo/FLXTest1ViewController.m | 31 +++++++++++++++++---------- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index b2963ac..6f0febb 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -741,6 +741,8 @@ 8. MyGravity_Horz_Fill 表示布局会拉伸子视图的宽度,以便使里面的子视图水平方向填充满整个布局视图的宽度或者子视图平分布局视图的宽度。 (支持:框架布局,垂直线性布局,垂直表格布局,流式布局) 9. MyGravity_Vert_Baseline 表示布局里面的子视图都基线对齐,目前只支持水平线性布局。 + 10.MyGravity_Vert_Stretch 表示当布局中的子视图没有设置高度约束时,会拉伸子视图的高度。(支持:线性布局、流式布局) + 11.MyGravity_Horz_Stretch 表示当布局中的子视图没有设置宽度约束时,会拉伸子视图的宽度。(支持:线性布局、流式布局) */ @property(nonatomic, assign) IBInspectable MyGravity gravity; diff --git a/MyLayout/Lib/MyFlexLayout.h b/MyLayout/Lib/MyFlexLayout.h index b1d5c28..7068385 100644 --- a/MyLayout/Lib/MyFlexLayout.h +++ b/MyLayout/Lib/MyFlexLayout.h @@ -37,6 +37,9 @@ typedef enum : int { extern const int MyFlex_Auto; +/* + flexbox中项目的设置类。 + */ @interface MyFlexItem:NSObject //您可以用链式语法进行属性设置,也可以直接通过属性赋值进行设置和获取。 @@ -66,7 +69,7 @@ extern const int MyFlex_Auto; -(MyFlexItem* (^)(CGFloat))flex_basis; //行内条目自身的对齐方式。 -(MyFlexItem* (^)(MyFlexGravity))align_self; -//设置具体的宽度值,当宽度值大于0小于1是表明的是相对宽度,你也可以设置MyLayoutSize.wrap和MyLayoutSize.fill来设置特殊宽度。 +//设置具体的宽度或高度值,当宽度值大于0小于1是表明的是相对宽度或高度,你也可以设置MyLayoutSize.wrap和MyLayoutSize.fill来设置特殊宽度或高度。 -(MyFlexItem* (^)(CGFloat))width; -(MyFlexItem* (^)(CGFloat))min_width; -(MyFlexItem* (^)(CGFloat))max_width; @@ -87,7 +90,9 @@ extern const int MyFlex_Auto; @end - +/* + flexbox的设置类。 + */ @interface MyFlex:MyFlexItem @property(nonatomic, assign) MyFlexDirection flex_direction_val; @@ -118,10 +123,9 @@ extern const int MyFlex_Auto; -(MyFlex* (^)(CGFloat))vert_space; -(MyFlex* (^)(CGFloat))horz_space; - @end - +//视图在flexbox中的分类扩展,只有MyFlexLayout中的子视图才有用。 @interface UIView(MyFlexLayout) //我们可以借助视图的flexItem来设置当视图在flexbox中的一些属性。 @@ -136,6 +140,7 @@ extern const int MyFlex_Auto; */ @interface MyFlexLayout:MyFlowLayout +//用于flexbox约束的设置。 @property(nonatomic, readonly, strong, readonly) MyFlex *flex; @end diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index d79a605..cf56f5a 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -197,6 +197,7 @@ MyGravity_Vert_Center 垂直居中对齐 MyGravity_Vert_Bottom 底部对齐 MyGravity_Vert_Fill 两端对齐 + MyGravity_Vert_Stretch 如果子视图未设置约束则子视图高度被拉伸 MyGravity_Vert_Baseline 基线对齐,以每一行的第一个带有文字的视图作为基线进行对齐。 MyGravity_Vert_Between 数量约束垂直流式布局有效,子视图会紧凑进行排列,当设置为这个属性值时,子视图的y轴的位置总是从对应列的上一行的结尾开始,而不是上一行的最高位置开始。 MyGravity_Vert_Around 如果行内子视图没有设置高度约束,则子视图的高度填充整行,否则按子视图的高度是高度约束决定。 @@ -207,6 +208,7 @@ MyGravity_Horz_Center 水平居中对齐 MyGravity_Horz_Right 右边对齐 MyGravity_Horz_Fill 两端对齐 + MyGravity_Horz_Stretch 如果子视图未设置约束则子视图宽度被拉伸 MyGravity_Horz_Between 数量约束垂直流式布局有效,子视图会紧凑进行排列,当设置为这个属性值时,子视图的x轴的位置总是从对应行的上一列的结尾开始,而不是上一列的最宽位置开始。 MyGravity_Horz_Around 如果列内子视图没有设置宽度约束,则子视图的宽度填充整行,否则按子视图的宽度是宽度约束决定。 @endcode @@ -257,6 +259,5 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace inSizeClass:(MySizeClass)sizeClass; - @end diff --git a/MyLayoutDemo/FLXTest1ViewController.m b/MyLayoutDemo/FLXTest1ViewController.m index a6adcf9..dccdcd2 100644 --- a/MyLayoutDemo/FLXTest1ViewController.m +++ b/MyLayoutDemo/FLXTest1ViewController.m @@ -29,6 +29,7 @@ @implementation FLXTest1ViewController -(void)loadView { + //根视图为flexbox布局视图。 MyFlexLayout *rootLayout = MyFlexLayout.new.flex .flex_direction(MyFlexDirection_Column) .vert_space(10) @@ -194,11 +195,6 @@ -(void)loadView [button addTarget:self action:@selector(handleAddItem:) forControlEvents:UIControlEventTouchUpInside]; -// UIScrollView *scrollView = UIScrollView.new.flexItem -// .width(MyLayoutSize.fill) -// .flex_grow(1) -// .addTo(rootLayout); - MyFlexLayout *contentLayout = MyFlexLayout.new.flex .width(MyLayoutSize.fill) .flex_grow(1) @@ -376,6 +372,7 @@ -(void)editFlexItem:(UIView*)itemView widthTextField.tag = 100; widthTextField.borderStyle = UITextBorderStyleRoundedRect; + widthTextField.placeholder = @"数字|wrap|fill|空"; UILabel *heightLabel = UILabel.new.flexItem .width(MyLayoutSize.wrap) @@ -392,7 +389,8 @@ -(void)editFlexItem:(UIView*)itemView heightTextField.tag = 200; heightTextField.borderStyle = UITextBorderStyleRoundedRect; - + heightTextField.placeholder = @"数字|wrap|fill|空"; + UILabel *orderLabel = UILabel.new.flexItem .width(MyLayoutSize.wrap) @@ -409,7 +407,8 @@ -(void)editFlexItem:(UIView*)itemView orderTextField.tag = 300; orderTextField.borderStyle = UITextBorderStyleRoundedRect; - + orderTextField.placeholder = @"数字|空"; + UILabel *flex_growLabel = UILabel.new.flexItem .width(MyLayoutSize.wrap) @@ -426,7 +425,8 @@ -(void)editFlexItem:(UIView*)itemView flex_growTextField.tag = 400; flex_growTextField.borderStyle = UITextBorderStyleRoundedRect; - + flex_growTextField.placeholder = @"数字|空"; + UILabel *flex_shrinkLabel = UILabel.new.flexItem .width(MyLayoutSize.wrap) @@ -443,7 +443,8 @@ -(void)editFlexItem:(UIView*)itemView flex_shrinkTextField.tag = 500; flex_shrinkTextField.borderStyle = UITextBorderStyleRoundedRect; - + flex_shrinkTextField.placeholder = @"数字|空"; + UILabel *flex_basisLabel = UILabel.new.flexItem .width(MyLayoutSize.wrap) @@ -460,7 +461,8 @@ -(void)editFlexItem:(UIView*)itemView flex_basisTextField.tag = 600; flex_basisTextField.borderStyle = UITextBorderStyleRoundedRect; - + flex_basisTextField.placeholder = @"数字|空"; + UILabel *align_selfLabel = UILabel.new.flexItem .width(MyLayoutSize.wrap) @@ -477,7 +479,8 @@ -(void)editFlexItem:(UIView*)itemView align_selfTextField.tag = 700; align_selfTextField.borderStyle = UITextBorderStyleRoundedRect; - + align_selfTextField.placeholder = @"flex-start|flex-end|center|stretch|baseline|auto"; + UIButton *addButton = UIButton.new.flexItem .flex_grow(1) @@ -508,6 +511,12 @@ -(void)editFlexItem:(UIView*)itemView [closeButton addTarget:self action:@selector(handleCloseDialog:) forControlEvents:UIControlEventTouchUpInside]; + UILabel *tipLabel = UILabel.new.flexItem + .width(MyLayoutSize.fill) + .height(MyLayoutSize.wrap) + .addTo(dialogLayout); + + tipLabel.text = @"添加后单击修改,长按删除"; if (itemView != nil) { From d3e794f740d6fc3922495ba92c84ca1a036deba7 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Thu, 24 Oct 2019 22:34:09 +0800 Subject: [PATCH 064/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlexLayout.m | 97 ++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 55 deletions(-) diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index da42451..5e6c4b4 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -442,6 +442,9 @@ -(instancetype)init -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { + + //将flexbox中的属性映射为MyFlowLayout中的属性。 + MyFlexLayout *lsc = self.myCurrentSizeClass; //最先设置方向。 @@ -555,7 +558,6 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //设置主轴的水平对齐和拉伸 MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = lsc.gravity & MyGravity_Vert_Mask; - switch (self.flex.justify_content_val) { case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Vert) @@ -593,7 +595,6 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //次轴的对齐处理。 MyGravity vertArrangedGravity = lsc.arrangedGravity & MyGravity_Horz_Mask; MyGravity horzArrangedGravity = lsc.arrangedGravity & MyGravity_Vert_Mask; - switch (self.flex.align_items_val) { case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Vert) @@ -628,61 +629,47 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( break; } + //多行下的整体停靠处理。 vertGravity = lsc.gravity & MyGravity_Horz_Mask; horzGravity = lsc.gravity & MyGravity_Vert_Mask; - //只有换行才有用,单行不起作用。 - if (lsc.arrangedCount == 0) - { - switch (self.flex.align_content_val) { - case MyFlexGravity_Flex_End: - if (lsc.orientation == MyOrientation_Horz) - lsc.gravity = MyGravity_Horz_Trailing | vertGravity; - else - lsc.gravity = MyGravity_Vert_Bottom | horzGravity; - break; - case MyFlexGravity_Center: - if (lsc.orientation == MyOrientation_Horz) - lsc.gravity = MyGravity_Horz_Center | vertGravity; - else - lsc.gravity = MyGravity_Vert_Center | horzGravity; - break; - case MyFlexGravity_Space_Between: - if (lsc.orientation == MyOrientation_Horz) - lsc.gravity = MyGravity_Horz_Between | vertGravity; - else - lsc.gravity = MyGravity_Vert_Between | horzGravity; - break; - case MyFlexGravity_Space_Around: - if (lsc.orientation == MyOrientation_Horz) - lsc.gravity = MyGravity_Horz_Around | vertGravity; - else - lsc.gravity = MyGravity_Vert_Around | horzGravity; - break; - case MyFlexGravity_Flex_Start: - if (lsc.orientation == MyOrientation_Horz) - lsc.gravity = MyGravity_Horz_Leading | vertGravity; - else - lsc.gravity = MyGravity_Vert_Top | horzGravity; - break; - case MyFlexGravity_Stretch: - default: - if (lsc.orientation == MyOrientation_Horz) - lsc.gravity = MyGravity_Horz_Stretch | vertGravity; - else - lsc.gravity = MyGravity_Vert_Stretch | horzGravity; - break; - } - } - else - { - if (lsc.orientation == MyOrientation_Horz) - { - lsc.gravity = vertGravity; - } - else - { - lsc.gravity = horzGravity; - } + switch (self.flex.align_content_val) { + case MyFlexGravity_Flex_End: + if (lsc.orientation == MyOrientation_Horz) + lsc.gravity = MyGravity_Horz_Trailing | vertGravity; + else + lsc.gravity = MyGravity_Vert_Bottom | horzGravity; + break; + case MyFlexGravity_Center: + if (lsc.orientation == MyOrientation_Horz) + lsc.gravity = MyGravity_Horz_Center | vertGravity; + else + lsc.gravity = MyGravity_Vert_Center | horzGravity; + break; + case MyFlexGravity_Space_Between: + if (lsc.orientation == MyOrientation_Horz) + lsc.gravity = MyGravity_Horz_Between | vertGravity; + else + lsc.gravity = MyGravity_Vert_Between | horzGravity; + break; + case MyFlexGravity_Space_Around: + if (lsc.orientation == MyOrientation_Horz) + lsc.gravity = MyGravity_Horz_Around | vertGravity; + else + lsc.gravity = MyGravity_Vert_Around | horzGravity; + break; + case MyFlexGravity_Flex_Start: + if (lsc.orientation == MyOrientation_Horz) + lsc.gravity = MyGravity_Horz_Leading | vertGravity; + else + lsc.gravity = MyGravity_Vert_Top | horzGravity; + break; + case MyFlexGravity_Stretch: + default: + if (lsc.orientation == MyOrientation_Horz) + lsc.gravity = MyGravity_Horz_Stretch | vertGravity; + else + lsc.gravity = MyGravity_Vert_Stretch | horzGravity; + break; } return [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; From 0d5493ff2936e9532feef1ae3775eaeefbb35754 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Tue, 29 Oct 2019 00:38:47 +0800 Subject: [PATCH 065/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout.xcodeproj/project.pbxproj | 6 + MyLayout/Lib/MyFlexLayout.h | 9 +- MyLayout/Lib/MyFlowLayout.h | 11 +- MyLayout/Lib/MyFlowLayout.m | 85 ++++++-- MyLayout/Lib/MyLayoutPos.h | 4 +- MyLayout/Lib/MyLayoutSize.h | 2 +- MyLayoutDemo/AllTestExampleViewController.m | 53 ++++- MyLayoutDemo/FLLTest4ViewController.m | 2 +- MyLayoutDemo/FLLTest9ViewController.h | 14 ++ MyLayoutDemo/FLLTest9ViewController.m | 184 ++++++++++++++++++ MyLayoutDemo/RLTest6ViewController.m | 4 +- MyLayoutDemo/ViewController.m | 4 + .../zh-Hans.lproj/Localizable.strings | 1 + 13 files changed, 349 insertions(+), 30 deletions(-) create mode 100644 MyLayoutDemo/FLLTest9ViewController.h create mode 100644 MyLayoutDemo/FLLTest9ViewController.m diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index d45c2c0..ce750b5 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -181,6 +181,7 @@ 4689881D23430A8400BFE829 /* MyPathLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 4689881C23430A8400BFE829 /* MyPathLayoutTestCase.m */; }; 4689881F23430AA000BFE829 /* MyGridLayoutTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 4689881E23430AA000BFE829 /* MyGridLayoutTestCase.m */; }; 4689882223449E8300BFE829 /* RLTest6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4689882123449E8300BFE829 /* RLTest6ViewController.m */; }; + 46898847236733AC00BFE829 /* FLLTest9ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 46898846236733AC00BFE829 /* FLLTest9ViewController.m */; }; 6740E1F820A52D9E00AFBC5A /* AllTest10ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */; }; 6740E1FB20A52DA900AFBC5A /* AllTest10Model.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */; }; 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6740E1FC20A52DB000AFBC5A /* AllTest10HeaderView.m */; }; @@ -441,6 +442,8 @@ 4689881E23430AA000BFE829 /* MyGridLayoutTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyGridLayoutTestCase.m; sourceTree = ""; }; 4689882023449E7900BFE829 /* RLTest6ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLTest6ViewController.h; sourceTree = ""; }; 4689882123449E8300BFE829 /* RLTest6ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RLTest6ViewController.m; sourceTree = ""; }; + 468988452367339C00BFE829 /* FLLTest9ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLLTest9ViewController.h; sourceTree = ""; }; + 46898846236733AC00BFE829 /* FLLTest9ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLLTest9ViewController.m; sourceTree = ""; }; 6740E1F520A52D9D00AFBC5A /* AllTest10ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllTest10ViewController.h; sourceTree = ""; }; 6740E1F620A52D9E00AFBC5A /* AllTest10ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10ViewController.m; sourceTree = ""; }; 6740E1F920A52DA900AFBC5A /* AllTest10Model.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AllTest10Model.m; sourceTree = ""; }; @@ -616,6 +619,8 @@ 2075CC3120A0B2A400BA6F65 /* FLLTest7ViewController.m */, 20F0DFFE21120A8D00CFCE8C /* FLLTest8ViewController.h */, 20F0DFFF21120A8D00CFCE8C /* FLLTest8ViewController.m */, + 468988452367339C00BFE829 /* FLLTest9ViewController.h */, + 46898846236733AC00BFE829 /* FLLTest9ViewController.m */, ); name = FlowLayoutDemo; sourceTree = ""; @@ -1204,6 +1209,7 @@ 18D3C9941EDF08F800D3DE43 /* YYFPSLabel.m in Sources */, 18D3C91D1EDF078200D3DE43 /* FLTest2ViewController.m in Sources */, 18D3C9661EDF080800D3DE43 /* TLTest1ViewController.m in Sources */, + 46898847236733AC00BFE829 /* FLLTest9ViewController.m in Sources */, 467E63CC228C4D6F0065D080 /* AllTest12ViewController.m in Sources */, 6740E1FE20A52DB100AFBC5A /* AllTest10HeaderView.m in Sources */, 18D3C94A1EDF07E700D3DE43 /* PLTest2ViewController.m in Sources */, diff --git a/MyLayout/Lib/MyFlexLayout.h b/MyLayout/Lib/MyFlexLayout.h index 7068385..7ec041f 100644 --- a/MyLayout/Lib/MyFlexLayout.h +++ b/MyLayout/Lib/MyFlexLayout.h @@ -58,14 +58,13 @@ extern const int MyFlex_Auto; @property(nonatomic, assign) MyVisibility visibility_val; - //条目的顺序设置 -(MyFlexItem* (^)(NSInteger))order; //条目的尺寸比重设置,默认为0表示不按比重 -(MyFlexItem* (^)(CGFloat))flex_grow; //条目的压缩比重设置,默认为1,表示当会进行压缩 -(MyFlexItem* (^)(CGFloat))flex_shrink; -//条目的尺寸设置,可以设置为_auto,固定值,相对值。你可以使用这个属性也可以通过width/height来设置。 +//条目的尺寸设置,可以设置为MyFlex_Auto,固定值,相对值。你可以使用这个属性也可以通过width/height来设置。 -(MyFlexItem* (^)(CGFloat))flex_basis; //行内条目自身的对齐方式。 -(MyFlexItem* (^)(MyFlexGravity))align_self; @@ -125,17 +124,17 @@ extern const int MyFlex_Auto; @end -//视图在flexbox中的分类扩展,只有MyFlexLayout中的子视图才有用。 +//条目视图在应用flexbox时的分类扩展,只有MyFlexLayout中的子视图才有用。 @interface UIView(MyFlexLayout) -//我们可以借助视图的flexItem来设置当视图在flexbox中的一些属性。 +//我们可以借助视图的flexItem来设置条目视图在弹性布局视图中的一些属性。 @property(nonatomic, readonly, strong) MyFlexItem *flexItem; @end /* - * FlexLayout布局是为了兼容flexbox语法而建立了一个布局,它是从MyFlowLayout派生。在MyFlowLayout中也是支持类似flexbox的一些特性的 + * 弹性布局是为了兼容flexbox语法而建立了一个布局,它是从MyFlowLayout派生。在MyFlowLayout中也是支持类似flexbox的一些特性的 * 但是它的属性和flexbox不兼容和一致,因此提供一个新的类MyFlexLayout来完全支持flexbox. */ @interface MyFlexLayout:MyFlowLayout diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index cf56f5a..03d6749 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -137,7 +137,7 @@ /** - 为流式布局提供分页展示的能力,默认是0表不支持分页展示。当设置为非0时则要求必须是arrangedCount的整数倍数,表示每页的子视图的数量。而arrangedCount则表示每排内的子视图的数量。当启用pagedCount时要求将流式布局加入到UIScrollView或者其派生类中才能生效。只有数量约束流式布局才支持分页展示的功能,通过pagedCount和设置尺寸的高度或者宽度自适应配合使用能实现不同的分页展示能力: + 为流式布局提供分页展示的能力,默认是0表不支持分页展示。当设置为非0时则要求必须是arrangedCount的整数倍数,表示每页的子视图的数量。而arrangedCount则表示每排内的子视图的数量。当启用pagedCount时如果流式布局的父视图是UIScrollView或者其派生类就会有分页滚动的效果。只有数量约束流式布局才支持分页展示的功能,通过pagedCount和设置尺寸的高度或者宽度自适应配合使用能实现不同的分页展示能力: @note 1. 垂直数量约束流式布局的高度设置为自适应时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一排的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的宽度你也可以自定义),整体的分页滚动是从上到下滚动。(每页布局时从左到右再从上到下排列,新页往下滚动继续排列): @code @@ -232,11 +232,12 @@ /** - 单独为某一行或者一列定制gravity停靠对齐属性,默认情况下布局视图的gravity作用于所有行或者列的停靠对齐。如果你想单独定制某一行或者某一列的停靠对齐方式时 - 可以通过设置这个block属性。lineGravity的入参是布局对象和当前行列的索引值,索引值以0开始,返回的是此行的停靠对齐方式,如果返回MyGravity_None则表示使用 - 布局默认的gravity停靠对齐属性。如果您的gravity属性设置的是Fill的话则有可能通过这个进行定制化会出现一些异常。 + 单独为某一行或者一列定制的水平和垂直停靠对齐属性,默认情况下布局视图的gravity和arrangedGravity作用于所有行或者列的停靠对齐。如果你想单独定制某一行或者某一列的停靠对齐方式时 + 可以通过设置这个block属性。 + lineGravity的入参分别是布局对象、当前行的索引(0开始)、当前行的条目视图数量、是否是最后一行四个参数。 + 函数返回的是此行的停靠对齐方式,如果返回MyGravity_None则表示使用布局默认的gravity和arrangedGravity停靠对齐属性。 */ -@property(nonatomic, copy) MyGravity (^lineGravity)(MyFlowLayout *layout, NSInteger lineIndex); +@property(nonatomic, copy) MyGravity (^lineGravity)(MyFlowLayout *layout, NSInteger lineIndex, NSInteger itemCount, BOOL isLastLine); diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index b4def57..e1f1760 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -290,7 +290,7 @@ - (void)myAdjustVertLayoutSinglelineWidth:(CGSize)selfSize lineIndex:(NSInteger) MyGravity lineHorzGravity = horzGravity; if (self.lineGravity != nil) { - lineHorzGravity = self.lineGravity(self, lineIndex); + lineHorzGravity = self.lineGravity(self, lineIndex, count, startIndex == sbs.count) & MyGravity_Vert_Mask; if (lineHorzGravity == MyGravity_None) lineHorzGravity = horzGravity; } @@ -339,7 +339,7 @@ - (void)myAdjustHorzLayoutSinglelineHeight:(CGSize)selfSize lineIndex:(NSInteger MyGravity lineVertGravity = vertGravity; if (self.lineGravity != nil) { - lineVertGravity = self.lineGravity(self, lineIndex); + lineVertGravity = self.lineGravity(self, lineIndex, count, startIndex == sbs.count) & MyGravity_Horz_Mask; if (lineVertGravity == MyGravity_None) lineVertGravity = vertGravity; } @@ -456,13 +456,19 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger CGFloat addXFill = 0; //多出来的平均区域,用于拉伸间距或者尺寸 MyGravity lineHorzGravity = horzGravity; + MyGravity lineVertAlignment = vertAlignment; if (self.lineGravity != nil) { - lineHorzGravity = self.lineGravity(self, rowIndex); + MyGravity lineGravity = self.lineGravity(self, rowIndex, count, startIndex == sbs.count); + lineHorzGravity = lineGravity & MyGravity_Vert_Mask; if (lineHorzGravity == MyGravity_None) lineHorzGravity = horzGravity; else lineHorzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lineHorzGravity]; + + lineVertAlignment = lineGravity & MyGravity_Horz_Mask; + if (lineVertAlignment == MyGravity_None) + lineVertAlignment = vertAlignment; } switch (lineHorzGravity) @@ -553,9 +559,10 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger MyGravity sbvVertAlignment = sbvsc.alignment & MyGravity_Horz_Mask; if (sbvVertAlignment == MyGravity_None) - sbvVertAlignment = vertAlignment; + sbvVertAlignment = lineVertAlignment; + //因为单行内的垂直间距拉伸被赋予紧凑排列,所以这里的定制化将不起作用。 if (vertAlignment == MyGravity_Vert_Between) - sbvVertAlignment = MyGravity_Vert_Between; + sbvVertAlignment = MyGravity_None; UIFont *sbvFont = nil; if (sbvVertAlignment == MyGravity_Vert_Baseline) @@ -649,10 +656,18 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger //计算每行的gravity情况。 CGFloat addYPos = 0; CGFloat addYFill = 0; + MyGravity lineHorzAlignment = horzAlignment; MyGravity lineVertGravity = vertGravity; if (self.lineGravity != nil) { - lineVertGravity = self.lineGravity(self, colIndex); + MyGravity lineGravity = self.lineGravity(self, colIndex, count, startIndex == sbs.count); + lineHorzAlignment = lineGravity & MyGravity_Vert_Mask; + if (lineHorzAlignment == MyGravity_None) + lineHorzAlignment = horzAlignment; + else + lineHorzAlignment = [self myConvertLeftRightGravityToLeadingTrailing:lineHorzAlignment]; + + lineVertGravity = lineGravity & MyGravity_Horz_Mask; if (lineVertGravity == MyGravity_None) lineVertGravity = vertGravity; } @@ -745,9 +760,10 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger MyGravity sbvHorzAlignment = [self myConvertLeftRightGravityToLeadingTrailing:sbvsc.alignment & MyGravity_Vert_Mask]; if (sbvHorzAlignment == MyGravity_None) - sbvHorzAlignment = horzAlignment; + sbvHorzAlignment = lineHorzAlignment; + //因为单行内的水平间距拉伸被赋予紧凑排列,所以这里的定制化将不起作用。 if (horzAlignment == MyGravity_Horz_Between) - sbvHorzAlignment = MyGravity_Horz_Between; + sbvHorzAlignment = MyGravity_None; if ((sbvHorzAlignment != MyGravity_None && sbvHorzAlignment != MyGravity_Horz_Leading) || _myCGFloatNotEqual(addYPos, 0.0) || _myCGFloatNotEqual(addYFill, 0.0) || colTotalShrink != 0.0) { @@ -1147,7 +1163,17 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; //计算子视图的高度。 - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + if (sbvsc.heightSizeInner.dimeVal != nil) + { + rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + } + else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) + { + rect.size.height = 0; + } + + + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) @@ -1375,9 +1401,16 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray pagingItemWidth = (selfSize.width - paddingHorz - (arrangedCount - 1) * horzSpace) / arrangedCount; //分页滚动时和非分页滚动时的高度计算是不一样的。 if (isPagingScroll) + { pagingItemHeight = (CGRectGetHeight(self.superview.bounds) - paddingVert - (rows - 1) * vertSpace) / rows; + } else - pagingItemHeight = (CGRectGetHeight(self.superview.bounds) - paddingTop - rows * vertSpace) / rows; + { + if ([self.superview isKindOfClass:[UIScrollView class]]) + pagingItemHeight = (CGRectGetHeight(self.superview.bounds) - paddingTop - rows * vertSpace) / rows; + else + pagingItemHeight = (selfSize.height - paddingVert - (rows - 1) * vertSpace) / rows; + } } @@ -1571,9 +1604,18 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray CGRect rect = sbvmyFrame.frame; if (pagingItemHeight != 0) + { rect.size.height = pagingItemHeight - topSpace - bottomSpace; - else + } + else if (sbvsc.heightSizeInner.dimeVal != nil) + { rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + } + else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) + {//如果没有设置高度约束但是又是垂直拉伸则将高度设置为0. + rect.size.height = 0; + } + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; @@ -1890,6 +1932,10 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; } + else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) + { + rect.size.width = 0.0; + } if (subviewSize != 0.0) { @@ -2228,9 +2274,16 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray pagingItemHeight = (selfSize.height - paddingVert - (arrangedCount - 1) * vertSpace) / arrangedCount; //分页滚动时和非分页滚动时的宽度计算是不一样的。 if (isPagingScroll) + { pagingItemWidth = (CGRectGetWidth(self.superview.bounds) - paddingHorz - (cols - 1) * horzSpace) / cols; + } else - pagingItemWidth = (CGRectGetWidth(self.superview.bounds) - paddingLeading - cols * horzSpace) / cols; + { + if ([self.superview isKindOfClass:[UIScrollView class]]) + pagingItemWidth = (CGRectGetWidth(self.superview.bounds) - paddingLeading - cols * horzSpace) / cols; + else + pagingItemWidth = (selfSize.width - paddingHorz - (cols - 1) * horzSpace) / cols; + } } @@ -2281,8 +2334,14 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray //水平流式布局因为高度依赖宽度自适应的情况比较少,所以这里直接先计算宽度 if (pagingItemWidth != 0.0) rect.size.width = pagingItemWidth - leadingSpace - trailingSpace; - else + else if (sbvsc.widthSizeInner.dimeVal != nil) + { rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + } + else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) + { + rect.size.width = 0; + } rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; diff --git a/MyLayout/Lib/MyLayoutPos.h b/MyLayout/Lib/MyLayoutPos.h index 3f5a7c9..512b55e 100644 --- a/MyLayout/Lib/MyLayoutPos.h +++ b/MyLayout/Lib/MyLayoutPos.h @@ -271,9 +271,9 @@ */ @interface NSArray(MyLayoutMostPos) -//从数组中得到最小的尺寸值。要求数组的元素必须是MyLayoutPos或者NSNumber类型 +//从数组中得到最大的位置值。要求数组的元素必须是MyLayoutPos或者NSNumber类型 @property(nonatomic, readonly) MyLayoutMostPos *myMinPos; -//从数组中得到最小的尺寸值。要求数组的元素必须是MyLayoutPos或者NSNumber类型 +//从数组中得到最小的位置值。要求数组的元素必须是MyLayoutPos或者NSNumber类型 @property(nonatomic, readonly) MyLayoutMostPos *myMaxPos; @end diff --git a/MyLayout/Lib/MyLayoutSize.h b/MyLayout/Lib/MyLayoutSize.h index 748eba2..b9ceac6 100644 --- a/MyLayout/Lib/MyLayoutSize.h +++ b/MyLayout/Lib/MyLayoutSize.h @@ -238,7 +238,7 @@ //从数组中得到最小的尺寸值。要求数组的元素必须是MyLayoutSize类型 @property(nonatomic, readonly) MyLayoutMostSize *myMinSize; -//从数组中得到最小的尺寸值。要求数组的元素必须是MyLayoutSize类型 +//从数组中得到最大的尺寸值。要求数组的元素必须是MyLayoutSize类型 @property(nonatomic, readonly) MyLayoutMostSize *myMaxSize; @end diff --git a/MyLayoutDemo/AllTestExampleViewController.m b/MyLayoutDemo/AllTestExampleViewController.m index 4330f15..53f8f62 100644 --- a/MyLayoutDemo/AllTestExampleViewController.m +++ b/MyLayoutDemo/AllTestExampleViewController.m @@ -24,7 +24,8 @@ - (void)viewDidLoad { self.view.backgroundColor = [UIColor whiteColor]; // [self example1]; - [self example2]; + // [self example2]; + [self example3]; } - (void)didReceiveMemoryWarning { @@ -126,5 +127,55 @@ -(void)example2 } +-(void)example3 +{ + //用链式语法创建一个弹性布局,宽度和父视图一致,高度为100 + MyFlexLayout *layout = MyFlexLayout.new.flex + .flex_direction(MyFlexDirection_Row) + .flex_wrap(MyFlexWrap_Wrap) + .align_content(MyFlexGravity_Center) + .align_items(MyFlexGravity_Flex_End) + .vert_space(10) + .horz_space(10) + .padding(UIEdgeInsetsMake(10, 10, 10, 10)) + .margin_top(50) + .width(MyLayoutSize.fill) + .height(MyLayoutSize.wrap) + .addTo(self.view); + + + UILabel *itemA = UILabel.new.flexItem + .width(MyLayoutSize.fill) + .height(30) + .addTo(layout); + + UILabel *itemB = UILabel.new.flexItem + .flex_grow(1) + .align_self(MyFlexGravity_Flex_Start) + .height(30) + .addTo(layout); + + UILabel *itemC = UILabel.new.flexItem + .flex_grow(1) + .height(40) + .addTo(layout); + + UILabel *itemD = UILabel.new.flexItem + .flex_grow(1) + .height(50) + .addTo(layout); + + + layout.backgroundColor = [UIColor grayColor]; + itemA.text = @"A"; + itemA.backgroundColor = [UIColor redColor]; + itemB.text = @"B"; + itemB.backgroundColor = [UIColor greenColor]; + itemC.text = @"C"; + itemC.backgroundColor = [UIColor blueColor]; + itemD.text = @"D"; + itemD.backgroundColor = [UIColor yellowColor]; + +} @end diff --git a/MyLayoutDemo/FLLTest4ViewController.m b/MyLayoutDemo/FLLTest4ViewController.m index 4632e27..e3a27b3 100644 --- a/MyLayoutDemo/FLLTest4ViewController.m +++ b/MyLayoutDemo/FLLTest4ViewController.m @@ -166,7 +166,7 @@ -(void)createFlowLayout1:(MyLinearLayout*)rootLayout //第六行因为最后只有一个按钮,所以这里不需要建立占位视图。 //我们可以通过lineGravity属性来实现为每一行进行不同的对齐方式定制,如果返回MyGravity_None则表示用gravity属性设置的对齐方式来进行处理。 - flowLayout.lineGravity = ^MyGravity(MyFlowLayout *layout, NSInteger lineIndex) { + flowLayout.lineGravity = ^MyGravity(MyFlowLayout *layout, NSInteger lineIndex, NSInteger itemCount, BOOL isLastLine) { switch (lineIndex) { case 3: diff --git a/MyLayoutDemo/FLLTest9ViewController.h b/MyLayoutDemo/FLLTest9ViewController.h new file mode 100644 index 0000000..5582105 --- /dev/null +++ b/MyLayoutDemo/FLLTest9ViewController.h @@ -0,0 +1,14 @@ +// +// FLLTest9ViewController.h +// MyLayoutDemo +// +// Created by oubaiquan on 2018/8/1. +// Copyright © 2018年 YoungSoft. All rights reserved. +// + +#import + +/*9.FlowLayout - line gravity*/ +@interface FLLTest9ViewController : UIViewController + +@end diff --git a/MyLayoutDemo/FLLTest9ViewController.m b/MyLayoutDemo/FLLTest9ViewController.m new file mode 100644 index 0000000..5557b92 --- /dev/null +++ b/MyLayoutDemo/FLLTest9ViewController.m @@ -0,0 +1,184 @@ +// +// FLLTest9ViewController.m +// MyLayoutDemo +// +// Created by oubaiquan on 2018/8/1. +// Copyright © 2018年 YoungSoft. All rights reserved. +// + +#import "FLLTest9ViewController.h" +#import "MyLayout.h" +#import "CFTool.h" + +@interface FLLTest9ViewController () + +@property(nonatomic, strong) MyFlowLayout *vertContentLayout; +@property(nonatomic, strong) MyFlowLayout *horzContentLayout; + +@end + +@implementation FLLTest9ViewController + +-(void)loadView +{ + /* + 这个例子主要演示流式布局中进行行内的自定义停靠对齐属性lineGravity的使用方法。一般情况下我们可以通过gravity来设置布局内所有行的停靠特性,而通过arrangedGravity来设置行内的对齐特性。而如果我们想自定义某行的停靠和对齐特性时则需要实现lineGravity这个block。 + + */ + + self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; + rootLayout.isFlex = YES; + rootLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); + rootLayout.subviewSpace = 5; + self.view = rootLayout; + + [self createVertContentLayout:rootLayout]; + + [self createHorzContentLayout:rootLayout]; + +} + +-(void)createVertContentLayout:(MyFlowLayout*)rootLayout +{ + UIButton *vertLayoutItemAddButon = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [vertLayoutItemAddButon addTarget:self action:@selector(handleVertLayoutItemAdd:) forControlEvents:UIControlEventTouchUpInside]; + [vertLayoutItemAddButon setTitle:@"Add" forState:UIControlStateNormal]; + [rootLayout addSubview:vertLayoutItemAddButon]; + vertLayoutItemAddButon.weight = 1.0; + vertLayoutItemAddButon.heightSize.equalTo(@(40)); + + UIButton *vertLayoutItemRemoveButon = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [vertLayoutItemRemoveButon addTarget:self action:@selector(handleVertLayoutItemRemove:) forControlEvents:UIControlEventTouchUpInside]; + [vertLayoutItemRemoveButon setTitle:@"Remove" forState:UIControlStateNormal]; + [rootLayout addSubview:vertLayoutItemRemoveButon]; + vertLayoutItemRemoveButon.weight = 1.0; + vertLayoutItemRemoveButon.heightSize.equalTo(@(40)); + + MyFlowLayout *vertContentLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:1]; + [rootLayout addSubview:vertContentLayout]; + vertContentLayout.widthSize.equalTo(rootLayout.widthSize); + vertContentLayout.heightSize.equalTo(vertContentLayout.widthSize).multiply(3.0/5); + vertContentLayout.gravity = MyGravity_Horz_Fill | MyGravity_Vert_Center; + //单独设置行内的停靠方向。 + vertContentLayout.lineGravity = ^MyGravity(MyFlowLayout *layout, NSInteger lineIndex, NSInteger itemCount, BOOL isLastLine) { + + //只有当布局视图的子视图数量为3个,并且是最后一行时才水平居中,否则其他返回默认的停靠值 + if (layout.subviews.count == 3 && isLastLine) + return MyGravity_Horz_Center; + else + return MyGravity_None; + }; + + self.vertContentLayout = vertContentLayout; + self.vertContentLayout.backgroundColor = [UIColor lightGrayColor]; +} + +-(void)createHorzContentLayout:(MyFlowLayout*)rootLayout +{ + UIButton *horzLayoutItemAddButon = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [horzLayoutItemAddButon addTarget:self action:@selector(handleHorzLayoutItemAdd:) forControlEvents:UIControlEventTouchUpInside]; + [horzLayoutItemAddButon setTitle:@"Add" forState:UIControlStateNormal]; + [rootLayout addSubview:horzLayoutItemAddButon]; + horzLayoutItemAddButon.weight = 1.0; + horzLayoutItemAddButon.heightSize.equalTo(@(40)); + + UIButton *horzLayoutItemRemoveButon = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [horzLayoutItemRemoveButon addTarget:self action:@selector(handleHorzLayoutItemRemove:) forControlEvents:UIControlEventTouchUpInside]; + [horzLayoutItemRemoveButon setTitle:@"Remove" forState:UIControlStateNormal]; + [rootLayout addSubview:horzLayoutItemRemoveButon]; + horzLayoutItemRemoveButon.weight = 1.0; + horzLayoutItemRemoveButon.heightSize.equalTo(@(40)); + + MyFlowLayout *horzContentLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:1]; + [rootLayout addSubview:horzContentLayout]; + horzContentLayout.widthSize.equalTo(rootLayout.widthSize); + horzContentLayout.heightSize.equalTo(horzContentLayout.widthSize).multiply(3.0/5); + horzContentLayout.gravity = MyGravity_Vert_Fill | MyGravity_Horz_Center; + horzContentLayout.lineGravity = ^MyGravity(MyFlowLayout *layout, NSInteger lineIndex, NSInteger itemCount, BOOL isLastLine) { + + //只有当布局视图的子视图数量为3个,并且是最后一行时才水平居中,否则其他返回默认的停靠值 + if (layout.subviews.count == 3 && isLastLine) + return MyGravity_Vert_Center; + else + return MyGravity_None; + }; + + self.horzContentLayout = horzContentLayout; + self.horzContentLayout.backgroundColor = [UIColor lightGrayColor]; +} + + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +#pragma mark -- Handler + +-(void)handleVertLayoutItemAdd:(id)sender +{ + UILabel *itemView = [UILabel new]; + itemView.backgroundColor = [CFTool color:arc4random_uniform(14) + 1]; + itemView.text = [NSString stringWithFormat:@"%ld", self.vertContentLayout.subviews.count]; + itemView.textAlignment = NSTextAlignmentCenter; + [self.vertContentLayout addSubview:itemView]; + + + //1个就1,小于等于4个就2, 小于等于9个就3, 小于等于16个就4 + //也就是每行的数量是大于子视图数量开根的最小整数。 + self.vertContentLayout.arrangedCount = ceil(sqrt(self.vertContentLayout.subviews.count)); + //这里启用分页功能,这样子视图的高度将会被自动计算出来。 + self.vertContentLayout.pagedCount = self.vertContentLayout.arrangedCount * self.vertContentLayout.arrangedCount; +} + +-(void)handleVertLayoutItemRemove:(id)sender +{ + [self.vertContentLayout.subviews.lastObject removeFromSuperview]; + //1个就1,小于等于4个就2, 小于等于9个就3, 小于等于16个就4 + //也就是每行的数量是大于子视图数量开根的最小整数。 + self.vertContentLayout.arrangedCount = ceil(sqrt(self.vertContentLayout.subviews.count)); + self.vertContentLayout.pagedCount = self.vertContentLayout.arrangedCount * self.vertContentLayout.arrangedCount; +} + +-(void)handleHorzLayoutItemAdd:(id)sender +{ + UILabel *itemView = [UILabel new]; + itemView.backgroundColor = [CFTool color:arc4random_uniform(14) + 1]; + itemView.text = [NSString stringWithFormat:@"%ld", self.horzContentLayout.subviews.count]; + itemView.textAlignment = NSTextAlignmentCenter; + [self.horzContentLayout addSubview:itemView]; + + + //1个就1,小于等于4个就2, 小于等于9个就3, 小于等于16个就4 + //也就是每行的数量是大于子视图数量开根的最小整数。 + self.horzContentLayout.arrangedCount = ceil(sqrt(self.horzContentLayout.subviews.count)); + //这里启用分页功能,这样子视图的高度将会被自动计算出来。 + self.horzContentLayout.pagedCount = self.horzContentLayout.arrangedCount * self.horzContentLayout.arrangedCount; +} + +-(void)handleHorzLayoutItemRemove:(id)sender +{ + [self.horzContentLayout.subviews.lastObject removeFromSuperview]; + //1个就1,小于等于4个就2, 小于等于9个就3, 小于等于16个就4 + //也就是每行的数量是大于子视图数量开根的最小整数。 + self.horzContentLayout.arrangedCount = ceil(sqrt(self.horzContentLayout.subviews.count)); + self.horzContentLayout.pagedCount = self.horzContentLayout.arrangedCount * self.horzContentLayout.arrangedCount; +} + +@end diff --git a/MyLayoutDemo/RLTest6ViewController.m b/MyLayoutDemo/RLTest6ViewController.m index 300d5bc..1712510 100644 --- a/MyLayoutDemo/RLTest6ViewController.m +++ b/MyLayoutDemo/RLTest6ViewController.m @@ -96,11 +96,11 @@ -(MyRelativeLayout*)createLayout1 UIButton *clickButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [clickButton setTitle:@"Click me" forState:UIControlStateNormal]; clickButton.backgroundColor = [CFTool color:10]; - [clickButton sizeToFit]; //这里直接计算出date的size是自适应的 + [clickButton sizeToFit]; //这里直接计算出clickButton的size是自适应的 clickButton.topPos.equalTo(nameLabel.topPos); //最新版本的相对布局可以让子视图的位置设置为某些视图位置中的最大或者最小值,也就是极限值,我们可以对一个数组调用扩展分类的方法myMaxPos或者myMinPos来获取 //到数组中元素的最大或者最小位置值。使用最大最小值的前提是在计算当前位置的约束时,要求数组中的元素的约束都是已经计算好了的,否则得到的结果是未可知,就如本例中 - //在计算dateLabel的右边距时,detailLabel以及nameLabel的右边距都是已经计算好了的。 + //在计算clickButton的右边距时,detailLabel以及nameLabel的右边距都是已经计算好了的。 clickButton.rightPos.equalTo(@[detailLabel.rightPos, nameLabel.rightPos.clone(-1 *(40+clickButton.frame.size.width))].myMaxPos); [rootLayout addSubview:clickButton]; diff --git a/MyLayoutDemo/ViewController.m b/MyLayoutDemo/ViewController.m index 5f85902..39eb301 100644 --- a/MyLayoutDemo/ViewController.m +++ b/MyLayoutDemo/ViewController.m @@ -43,6 +43,7 @@ #import "FLLTest6ViewController.h" #import "FLLTest7ViewController.h" #import "FLLTest8ViewController.h" +#import "FLLTest9ViewController.h" #import "FLXTest1ViewController.h" @@ -199,6 +200,9 @@ -(NSArray*)demoTypeList }, @{@"title":NSLocalizedString(@"8.FlowLayout - Flex space", @""), @"class":[FLLTest8ViewController class] + }, + @{@"title":NSLocalizedString(@"9.FlowLayout - Line gravity", @""), + @"class":[FLLTest9ViewController class] } ] }, diff --git a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings index 47cf8b2..2cd2669 100644 --- a/MyLayoutDemo/zh-Hans.lproj/Localizable.strings +++ b/MyLayoutDemo/zh-Hans.lproj/Localizable.strings @@ -36,6 +36,7 @@ "6.FlowLayout - Scroll" = "6.流式布局-不同方向的滚动"; "7.FlowLayout - Auto Arrange" = "7.流式布局-自动布局和对瀑布流的支持"; "8.FlowLayout - Flex space" = "8.流式布局-浮动间距"; +"9.FlowLayout - Line gravity" = "9.流式布局-自定义行停靠对齐"; "1.FloatLayout - Float" = "1.浮动布局-浮动效果的演示"; "2.FloatLayout - Jagged" = "2.浮动布局-仿天猫淘宝首页实现" ; "3.FloatLayout - Card news" = "3.浮动布局-仿ZAKER今日头条实现"; From 985f72fd749b33a35ad6ea6431bb729d3acfd592 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Tue, 29 Oct 2019 08:27:30 +0800 Subject: [PATCH 066/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayoutDemo/FLLTest9ViewController.m | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/MyLayoutDemo/FLLTest9ViewController.m b/MyLayoutDemo/FLLTest9ViewController.m index 5557b92..3d5357a 100644 --- a/MyLayoutDemo/FLLTest9ViewController.m +++ b/MyLayoutDemo/FLLTest9ViewController.m @@ -22,13 +22,28 @@ @implementation FLLTest9ViewController -(void)loadView { /* - 这个例子主要演示流式布局中进行行内的自定义停靠对齐属性lineGravity的使用方法。一般情况下我们可以通过gravity来设置布局内所有行的停靠特性,而通过arrangedGravity来设置行内的对齐特性。而如果我们想自定义某行的停靠和对齐特性时则需要实现lineGravity这个block。 + 这个例子主要演示流式布局中进行行内的自定义停靠对齐属性lineGravity的使用方法。 + 在垂直流式布局中,我们可以通过gravity来设置每行的水平停靠对齐特性,并通过arrangedGravity来设置每行行内的垂直停靠对齐特性。 + 在水平流式布局中,我们可以通过gravity来设置每列的垂直停靠对齐特性,并通过arrangedGravity来设置每列列内的水平停靠对齐特性。 + + 而如果我们想自定义某行或者某列的水平和垂直停靠对齐特性时则可以通过lineGravity来实现,lineGravity是一个block方法。这个方法的入参有布局对象、行的索引、行内条目的数量、是否是最后一行标志。而方法的返回则是这一行内的水平和垂直停靠对齐特性。如果某个方向返回MyGravity_None则表明用布局指定的gravity和arrangedGravity设置的值。 + + 比如在一个垂直流式布局中所有行都是右停靠,并且每行内都是垂直居中对齐。但是我们又想将其中的第1行设置为左停靠,并且是底部对齐。那么我们就可以进行如下设置: + layout.gravity = MyGravity_Horz_Right; //整体右停靠 + layout.arrangedGravity = MyGravity_Vert_Center; //每行都是垂直居中对齐 + layout.lineGravity = ^(MyFlowLayout *layout, NSInteger lineIndex, NSInteger itemCount, BOOL isLastLine) + { + if (lineIndex == 1) + return MyGravity_Horz_Left | MyGravity_Vert_Bottom; //第一行左边停靠并且底部对齐 + else + return MyGravity_None; + }; */ self.edgesForExtendedLayout = UIRectEdgeNone; //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; - rootLayout.isFlex = YES; + rootLayout.isFlex = YES; //这个属性设置为YES表明让流式布局兼容flexbox的一些特性。 rootLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); rootLayout.subviewSpace = 5; self.view = rootLayout; @@ -45,7 +60,7 @@ -(void)createVertContentLayout:(MyFlowLayout*)rootLayout [vertLayoutItemAddButon addTarget:self action:@selector(handleVertLayoutItemAdd:) forControlEvents:UIControlEventTouchUpInside]; [vertLayoutItemAddButon setTitle:@"Add" forState:UIControlStateNormal]; [rootLayout addSubview:vertLayoutItemAddButon]; - vertLayoutItemAddButon.weight = 1.0; + vertLayoutItemAddButon.weight = 1.0; //两个按钮的比重为1表明平分宽度。 vertLayoutItemAddButon.heightSize.equalTo(@(40)); UIButton *vertLayoutItemRemoveButon = [UIButton buttonWithType:UIButtonTypeRoundedRect]; @@ -59,7 +74,7 @@ -(void)createVertContentLayout:(MyFlowLayout*)rootLayout [rootLayout addSubview:vertContentLayout]; vertContentLayout.widthSize.equalTo(rootLayout.widthSize); vertContentLayout.heightSize.equalTo(vertContentLayout.widthSize).multiply(3.0/5); - vertContentLayout.gravity = MyGravity_Horz_Fill | MyGravity_Vert_Center; + vertContentLayout.gravity = MyGravity_Horz_Fill | MyGravity_Vert_Center; //整体水平填充和垂直居中 //单独设置行内的停靠方向。 vertContentLayout.lineGravity = ^MyGravity(MyFlowLayout *layout, NSInteger lineIndex, NSInteger itemCount, BOOL isLastLine) { @@ -133,6 +148,7 @@ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { -(void)handleVertLayoutItemAdd:(id)sender { + //这里子视图不需要设置任何宽高约束。 UILabel *itemView = [UILabel new]; itemView.backgroundColor = [CFTool color:arc4random_uniform(14) + 1]; itemView.text = [NSString stringWithFormat:@"%ld", self.vertContentLayout.subviews.count]; From fbfa36f53668c1f34421d82b2328a9e75c476901 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Tue, 29 Oct 2019 09:28:37 +0800 Subject: [PATCH 067/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlowLayout.h | 71 ++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index 03d6749..7e052de 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -11,13 +11,21 @@ /** - 流式布局是一种里面的子视图按照添加的顺序依次排列,当遇到某种约束限制后会另起一排再重新排列的多行多列展示的布局视图。这里的约束限制主要有数量约束限制和内容尺寸约束限制两种,排列的方向又分为垂直和水平方向,因此流式布局一共有垂直数量约束流式布局、垂直内容约束流式布局、水平数量约束流式布局、水平内容约束流式布局。流式布局主要应用于那些有规律排列的场景,在某种程度上可以作为UICollectionView的替代品,同时流式布局实现了CSS3的flexbox的几乎全部功能。 + 流式布局是一种里面的子条目视图按照添加的顺序依次排列,当满足某种规则限制后会另起一行再重新排列,最终呈现为多行多列展示的布局视图。这里的换行规则限制主要有数量规则限制和尺寸内容规则限制两种,整体排列增长的方向又分为垂直和水平方向,因此流式布局一共有垂直数量约束流式布局、垂直内容约束流式布局、水平数量约束流式布局、水平内容约束流式布局。流式布局主要应用于那些有规律排列的场景,在某种程度上可以作为UICollectionView的替代品,同时流式布局实现了CSS3的flexbox的几乎全部功能。 + + @note + 需要注意的是这里的方向和行的概念,行的概念它是相对于流式布局的方向而具体定义的。如果是垂直流式布局那么一行内的子视图将是水平排列,而整体则是每行从上往下垂直排列。 + 而如果是水平流式布局那么一行内的子视图将是垂直排列,而整体则是每行从左往右水平排列。因此流式布局的方向所描述的是行整体的排列方向。 + @note + 所谓数量约束流式布局就是指事先约定每行的条目视图的数量,当一行的条目视图数量到达指定的数量后再添加条目视图时就会换行重新排列。而内容约束流式布局就是当添加到布局视图中的 + 条目视图的宽度(垂直流式布局)之和或者高度(水平流式布局)之和超过布局视图的宽度或者高度时再添加条目视图就会换行进行重新排列。 + 1.垂直数量约束流式布局 orientation为MyOrientation_Vert,arrangedCount不为0 @code -每排数量为3的垂直数量约束流式布局 +每行数量为3的垂直数量约束流式布局 => +------+---+-----+ | A | B | C | @@ -48,7 +56,7 @@ orientation为MyOrientation_Horz,arrangedCount不为0 @code - 每排数量为3的水平数量约束流式布局 + 每行数量为3的水平数量约束流式布局 => +-----+----+-----+ | A | D | | @@ -82,37 +90,34 @@ @endcode - @note - 流式布局中排的概念是一个通用的称呼,对于垂直方向的流式布局来说一排就是一行,垂直流式布局每排依次从上到下排列,每排内的子视图则是由左往右依次排列;对于水平方向的流式布局来说一排就是一列,水平流式布局每排依次从左到右排列,每排内的子视图则是由上往下依次排列 - */ @interface MyFlowLayout : MyBaseLayout /** - 初始化一个流式布局并指定布局的方向和布局的数量,如果数量为0则表示内容约束流式布局。 + 初始化一个流式布局并指定布局的方向和每行条目视图的数量,如果数量为0则表示内容约束流式布局。 - @param orientation 布局的方向,这个方向是指的排与排之间排列方向,而不是排内的子视图的排列方向。 - @param arrangedCount 每排内的子视图的数量,如果每排内的子视图的数量不固定则设置为0表示为内容约束流式布局。 + @param orientation 布局的方向,这个方向是指的行与行之间排列方向,而不是行内的子视图的排列方向。 + @param arrangedCount 每行内的子条目视图的数量,如果每行内的子条目视图的数量不固定则设置为0表示为内容约束流式布局。 @return 返回流式布局对象实例。 */ -(instancetype)initWithOrientation:(MyOrientation)orientation arrangedCount:(NSInteger)arrangedCount; /** - 初始化一个流式布局并指定布局视图的frame值以及方向和布局的数量,如果数量为0则表示内容约束流式布局。 + 初始化一个流式布局并指定布局视图的frame值以及方向和每行条目视图的数量,如果数量为0则表示内容约束流式布局。 @param frame 布局视图的frame值,当布局视图的父视图是非布局视图时就可以用这个方法来初始化视图的frame。 - @param orientation 布局的方向,这个方向是指的排与排之间排列方向,而不是排内的子视图的排列方向。 - @param arrangedCount 每排内的子视图的数量,如果每排内的子视图的数量不固定则设置为0表示为内容约束流式布局。 + @param orientation 布局的方向,这个方向是指的行与行之间排列方向,而不是行内的子视图的排列方向。 + @param arrangedCount 每行内的子条目视图的数量,如果每行内的子条目视图的数量不固定则设置为0表示为内容约束流式布局。 @return 返回流式布局对象实例 */ -(instancetype)initWithFrame:(CGRect)frame orientation:(MyOrientation)orientation arrangedCount:(NSInteger)arrangedCount; /** - 初始化一个流式布局并指定布局的方向和布局的数量,如果数量为0则表示内容约束流式布局。 + 初始化一个流式布局并指定布局的方向和行内条目视图的数量,如果数量为0则表示内容约束流式布局。 - @param orientation 布局的方向,这个方向是指的排与排之间排列方向,而不是排内的子视图的排列方向。 - @param arrangedCount 每排内的子视图的数量,如果每排内的子视图的数量不固定则设置为0表示为内容约束流式布局。 + @param orientation 布局的方向,这个方向是指的行与行之间排列方向,而不是行内的子视图的排列方向。 + @param arrangedCount 每行内的子条目视图的数量,如果每行内的子视图的数量不固定则设置为0表示为内容约束流式布局。 @return 返回流式布局对象实例。 */ +(instancetype)flowLayoutWithOrientation:(MyOrientation)orientation arrangedCount:(NSInteger)arrangedCount; @@ -121,25 +126,25 @@ /** 流式布局的布局方向: - 1. MyOrientation_Vert 表示排内子视图从左到右(RTL从右到左)水平排列,排与排之间依次从上到下垂直排列。这个方向是默认方向。 + 1. MyOrientation_Vert 表示行内子视图从左到右(RTL从右到左)水平排列,行与行之间依次从上到下垂直排列。这个方向是默认方向。 - 2. MyOrientation_Horz 表示排内子视图从上到下垂直排列,排与排之间依次从左到右(RTL从右到左)水平排列。 + 2. MyOrientation_Horz 表示行内子视图从上到下垂直排列,行与行之间依次从左到右(RTL从右到左)水平排列。 */ @property(nonatomic,assign) IBInspectable MyOrientation orientation; /** - 每排内的子视图数量。默认是0表示每排内的子视图的数量不固定,而是根据子视图的尺寸自动换行或者换列处理。如果非0则每排内的子视图数量等于这个值后会自动换行或者换列 + 每行内的子条目视图数量。默认是0表示每行内的子条目视图的数量不固定,而是根据子视图的尺寸自动换行或者换列处理。如果非0则每行内的子视图数量等于这个值后会自动换行。 */ @property(nonatomic, assign) IBInspectable NSInteger arrangedCount; /** - 为流式布局提供分页展示的能力,默认是0表不支持分页展示。当设置为非0时则要求必须是arrangedCount的整数倍数,表示每页的子视图的数量。而arrangedCount则表示每排内的子视图的数量。当启用pagedCount时如果流式布局的父视图是UIScrollView或者其派生类就会有分页滚动的效果。只有数量约束流式布局才支持分页展示的功能,通过pagedCount和设置尺寸的高度或者宽度自适应配合使用能实现不同的分页展示能力: + 为流式布局提供分页展示的能力,默认是0表不支持分页展示。当设置为非0时则要求必须是arrangedCount的整数倍数,表示每页的子视图的数量。而arrangedCount则表示每行内的子视图的数量。当启用pagedCount时如果流式布局的父视图是UIScrollView或者其派生类就会有分页滚动的效果。只有数量约束流式布局才支持分页展示的功能,通过pagedCount和设置尺寸的高度或者宽度自适应配合使用能实现不同的分页展示能力: @note - 1. 垂直数量约束流式布局的高度设置为自适应时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一排的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的宽度你也可以自定义),整体的分页滚动是从上到下滚动。(每页布局时从左到右再从上到下排列,新页往下滚动继续排列): + 1. 垂直数量约束流式布局的高度设置为自适应时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一行的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的宽度你也可以自定义),整体的分页滚动是从上到下滚动。(每页布局时从左到右再从上到下排列,新页往下滚动继续排列): @code 1 2 3 4 5 6 @@ -148,21 +153,21 @@ 10 11 12 @endcode - 2. 垂直数量约束流式布局的宽度设置为自适应时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一排的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的高度你也可以自定义),整体的分页滚动是从左到右滚动。(每页布局时从左到右再从上到下排列,新页往右滚动继续排列) + 2. 垂直数量约束流式布局的宽度设置为自适应时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一行的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的高度你也可以自定义),整体的分页滚动是从左到右滚动。(每页布局时从左到右再从上到下排列,新页往右滚动继续排列) @code 1 2 3 | 7 8 9 4 5 6 | 10 11 12 → @endcode - 3. 水平数量约束流式布局的宽度设置为自适应时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一排的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的高度你也可以自定义),整体的分页滚动是从左到右滚动。(每页布局时从上到下再从左到右排列,新页往右滚动继续排列) + 3. 水平数量约束流式布局的宽度设置为自适应时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一行的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的高度你也可以自定义),整体的分页滚动是从左到右滚动。(每页布局时从上到下再从左到右排列,新页往右滚动继续排列) @code 1 3 5 | 7 9 11 2 4 6 | 8 10 12 → @endcode - 4. 水平数量约束流式布局的高度设置为自适应时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一排的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的宽度你也可以自定义),整体的分页滚动是从上到下滚动。(每页布局时从上到下再从左到右排列,新页往下滚动继续排列) + 4. 水平数量约束流式布局的高度设置为自适应时则以UIScrollView的尺寸作为一页展示的大小,因为指定了一页的子视图数量,以及指定了一行的子视图数量,因此默认也会自动计算出子视图的宽度和高度,而不需要单独指出高度和宽度(子视图的宽度你也可以自定义),整体的分页滚动是从上到下滚动。(每页布局时从上到下再从左到右排列,新页往下滚动继续排列) @code 1 3 5 2 4 6 @@ -183,15 +188,15 @@ @note - 如果在内容填充约束流式布局中使用次属性时,请在将所有子视图添加完毕并且初始布局完成后再设置这个属性,否则如果预先设置这个属性则在后续添加子视图时可能会非常耗性能。 + 如果在内容填充约束流式布局中使用此属性时,请在将所有子视图添加完毕并且初始布局完成后再设置这个属性,否则如果预先设置这个属性则在后续添加子视图时可能会非常耗性能。 */ @property(nonatomic,assign) IBInspectable BOOL autoArrange; /** - 设置流式布局中每排内所有子视图的对齐停靠方式。具体的对齐停靠方式依赖于布局视图的方向: + 设置流式布局中每行内所有子视图的对齐停靠方式。具体的对齐停靠方式依赖于布局视图的方向: - 1. 如果是垂直流式布局则表示每排内子视图的上中下对齐方式,这里的对齐基础是以每排中的最高的子视图为基准。这个属性只支持: + 1. 如果是垂直流式布局则表示每行内子视图的上中下对齐方式,这里的对齐基础是以每行中的最高的子视图为基准。这个属性只支持: @code MyGravity_Vert_Top 顶部对齐 MyGravity_Vert_Center 垂直居中对齐 @@ -202,7 +207,7 @@ MyGravity_Vert_Between 数量约束垂直流式布局有效,子视图会紧凑进行排列,当设置为这个属性值时,子视图的y轴的位置总是从对应列的上一行的结尾开始,而不是上一行的最高位置开始。 MyGravity_Vert_Around 如果行内子视图没有设置高度约束,则子视图的高度填充整行,否则按子视图的高度是高度约束决定。 @endcode - 2. 如果是水平流式布局则表示每排内子视图的左中右对齐方式,这里的对齐基础是以每排中的最宽的子视图为基准。这个属性只支持: + 2. 如果是水平流式布局则表示每行内子视图的左中右对齐方式,这里的对齐基础是以每行中的最宽的子视图为基准。这个属性只支持: @code MyGravity_Horz_Left 左边对齐 MyGravity_Horz_Center 水平居中对齐 @@ -212,7 +217,7 @@ MyGravity_Horz_Between 数量约束垂直流式布局有效,子视图会紧凑进行排列,当设置为这个属性值时,子视图的x轴的位置总是从对应行的上一列的结尾开始,而不是上一列的最宽位置开始。 MyGravity_Horz_Around 如果列内子视图没有设置宽度约束,则子视图的宽度填充整行,否则按子视图的宽度是宽度约束决定。 @endcode - @note 如果您想单独设置某个子视图在排内的对齐方式则请使用子视图的扩展属性alignment。 + @note 如果您想单独设置某个子视图在行内的对齐方式则请使用子视图的扩展属性alignment。 */ @property(nonatomic,assign) MyGravity arrangedGravity; @@ -232,21 +237,21 @@ /** - 单独为某一行或者一列定制的水平和垂直停靠对齐属性,默认情况下布局视图的gravity和arrangedGravity作用于所有行或者列的停靠对齐。如果你想单独定制某一行或者某一列的停靠对齐方式时 + 单独为某一行定制的水平和垂直停靠对齐属性,默认情况下布局视图的gravity和arrangedGravity作用于所有行以及行内的停靠对齐。如果你想单独定制某一行的停靠对齐方式时 可以通过设置这个block属性。 lineGravity的入参分别是布局对象、当前行的索引(0开始)、当前行的条目视图数量、是否是最后一行四个参数。 - 函数返回的是此行的停靠对齐方式,如果返回MyGravity_None则表示使用布局默认的gravity和arrangedGravity停靠对齐属性。 + 函数返回的是此行以及行内的停靠对齐方式,如果返回MyGravity_None则表示使用布局默认的gravity和arrangedGravity停靠对齐属性。 */ @property(nonatomic, copy) MyGravity (^lineGravity)(MyFlowLayout *layout, NSInteger lineIndex, NSInteger itemCount, BOOL isLastLine); /** - 在流式布局的一些应用场景中我们希望子视图的宽度或者高度是固定的但间距是浮动的,这样就尽可能在一排中容纳更多的子视图。比如设置每个子视图的宽度固定为80,那么在小屏幕下每排只能放3个,而大屏幕则每排能放4个或者5个子视图。 因此您可以通过如下方法来设置子视图的固定尺寸和最小最大浮动间距。这个方法会根据您当前布局的方向不同而具有不同的意义: + 在流式布局的一些应用场景中我们希望子视图的宽度或者高度是固定的但间距是浮动的,这样就尽可能在一行中容纳更多的子视图。比如设置每个子视图的宽度固定为80,那么在小屏幕下每行只能放3个,而大屏幕则每行能放4个或者5个子视图。 因此您可以通过如下方法来设置子视图的固定尺寸和最小最大浮动间距。这个方法会根据您当前布局的方向不同而具有不同的意义: - 1.如果您的布局方向是垂直的则设置的是每排内子视图的水平浮动间距,其中的subviewSize指定的是子视图的固定宽度;minSpace指定的是最小的水平间距;maxSpace指定的是最大的水平间距,如果指定的subviewSize计算出的间距大于最大间距maxSpace则会缩小subviewSize的宽度值。 + 1.如果您的布局方向是垂直的则设置的是每行内子视图的水平浮动间距,其中的subviewSize指定的是子视图的固定宽度;minSpace指定的是最小的水平间距;maxSpace指定的是最大的水平间距,如果指定的subviewSize计算出的间距大于最大间距maxSpace则会缩小subviewSize的宽度值。 - 2.如果您的布局方向是水平的则设置的是每排内子视图的垂直浮动间距,其中的subviewSize指定的是子视图的固定高度;minSpace指定的是最小的垂直间距;maxSpace指定的是最大的垂直间距,如果指定的subviewSize计算出的间距大于最大间距maxSpace则会调整subviewSize的高度值。 + 2.如果您的布局方向是水平的则设置的是每行内子视图的垂直浮动间距,其中的subviewSize指定的是子视图的固定高度;minSpace指定的是最小的垂直间距;maxSpace指定的是最大的垂直间距,如果指定的subviewSize计算出的间距大于最大间距maxSpace则会调整subviewSize的高度值。 @note 如果您不想使用浮动间距则请将subviewSize设置为0就可以了。 From 99b6d041e241f751d86fa226213040867eeaa64f Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Tue, 29 Oct 2019 17:06:37 +0800 Subject: [PATCH 068/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyLayoutSizeClass.m | 16 +++++- MyLayout/Lib/MyRelativeLayout.m | 26 +++++++--- MyLayoutDemo/AllTestExampleViewController.m | 56 ++++++++++++++++++++- 3 files changed, 87 insertions(+), 11 deletions(-) diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index 0b833c3..9d528dc 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -426,18 +426,30 @@ -(BOOL)wrapContentHeight -(void)setWrapContentWidth:(BOOL)wrapContentWidth { if (wrapContentWidth) + { self.widthSize.myEqualTo(@(MyLayoutSize.wrap)); + } else - _widthSize = nil; + { + //只有是以前设置了宽度自适应,这里取消自适应后才会将尺寸清除!目的是为了兼容老版本。 + if (_widthSize.isWrap) + _widthSize = nil; + } } -(void)setWrapContentHeight:(BOOL)wrapContentHeight { if (wrapContentHeight) + { self.heightSize.myEqualTo(@(MyLayoutSize.wrap)); + } else - _heightSize = nil; + { + //只有是以前设置了高度自适应,这里取消自适应后才会将尺寸清除!目的是为了兼容老版本。 + if (_heightSize.isWrap) + _heightSize = nil; + } } -(BOOL)wrapContentSize diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index b1750b0..bf9ef6e 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -53,15 +53,25 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (pHasSubLayout != nil && (sbvsc.heightSizeInner.dimeWrapVal || sbvsc.widthSizeInner.dimeWrapVal)) *pHasSubLayout = YES; - if (isEstimate && (sbvsc.widthSizeInner.dimeWrapVal || sbvsc.heightSizeInner.dimeWrapVal)) + if (sbvsc.widthSizeInner.dimeWrapVal || sbvsc.heightSizeInner.dimeWrapVal) { - [(MyBaseLayout*)sbv sizeThatFits:sbvmyFrame.frame.size inSizeClass:sizeClass]; - - sbvmyFrame.leading = sbvmyFrame.trailing = sbvmyFrame.top = sbvmyFrame.bottom = CGFLOAT_MAX; - - //因为sizeThatFits执行后会还原,所以这里要重新设置 - if (sbvmyFrame.multiple) - sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass myFrame:sbvmyFrame]; + if (isEstimate) + { + [(MyBaseLayout*)sbv sizeThatFits:sbvmyFrame.frame.size inSizeClass:sizeClass]; + + sbvmyFrame.leading = sbvmyFrame.trailing = sbvmyFrame.top = sbvmyFrame.bottom = CGFLOAT_MAX; + + //因为sizeThatFits执行后会还原,所以这里要重新设置 + if (sbvmyFrame.multiple) + sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass myFrame:sbvmyFrame]; + } + else + { + if (sbvsc.widthSizeInner.dimeWrapVal) + sbvmyFrame.width = sbv.bounds.size.width; + if (sbvsc.heightSizeInner.dimeWrapVal) + sbvmyFrame.height = sbv.bounds.size.height; + } } } } diff --git a/MyLayoutDemo/AllTestExampleViewController.m b/MyLayoutDemo/AllTestExampleViewController.m index 53f8f62..d8ffe81 100644 --- a/MyLayoutDemo/AllTestExampleViewController.m +++ b/MyLayoutDemo/AllTestExampleViewController.m @@ -25,7 +25,8 @@ - (void)viewDidLoad { // [self example1]; // [self example2]; - [self example3]; + //[self example3]; + [self example4]; } - (void)didReceiveMemoryWarning { @@ -178,4 +179,57 @@ -(void)example3 } + +-(void)example4 +{ + MyRelativeLayout *_rootLayout = [MyRelativeLayout new]; + + _rootLayout.widthSize.equalTo(self.view.widthSize); + _rootLayout.wrapContentHeight = YES; + _rootLayout.topPadding = 15; + _rootLayout.bottomPadding = 15; + _rootLayout.backgroundColor = [UIColor whiteColor]; + [self.view addSubview:_rootLayout]; + + + + MyLinearLayout *topLayout = [MyLinearLayout linearLayoutWithOrientation:(MyOrientation_Vert)]; + + topLayout.wrapContentWidth = YES; + topLayout.myHorzMargin = 0; + topLayout.wrapContentHeight = YES; + topLayout.subviewVSpace = 5; + [_rootLayout addSubview:topLayout]; + + + return; + + UILabel *topLable = [UILabel new]; + topLable.text = @"宿州学院-皁阳火车站"; + topLable.myTop = 0; + topLable.myLeft = 11; + topLable.wrapContentSize = YES; + [topLayout addSubview:topLable]; + + + + UIButton *checkMarkBtn = [UIButton new]; + [checkMarkBtn setImage:[UIImage imageNamed:@"train_progresscomplete"] forState:(UIControlStateNormal)]; + checkMarkBtn.widthSize.equalTo(@(13)); + checkMarkBtn.heightSize.equalTo(@(13)); + checkMarkBtn.rightPos.equalTo(@(10)); + checkMarkBtn.centerYPos.equalTo(@(0)); + [_rootLayout addSubview:checkMarkBtn]; + + + UILabel *contentLabel = [UILabel new]; + contentLabel.text = @"途径:蒙城、嘎县、阜阳师范学院、嘎县、阜阳师范学院、嘎县、阜阳师范学院"; + contentLabel.myLeft = 11; + + contentLabel.wrapContentHeight= YES; + contentLabel.myRight = 27; + contentLabel.hidden = NO; + [topLayout addSubview:contentLabel]; +} + @end From be55ece6c6e9815209fa6891aa22341d56aba32d Mon Sep 17 00:00:00 2001 From: youngsoft Date: Tue, 29 Oct 2019 23:20:52 +0800 Subject: [PATCH 069/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFloatLayout.m | 8 - MyLayout/Lib/MyFlowLayout.m | 558 +++++++++++++++++----------------- MyLayout/Lib/MyLinearLayout.m | 66 ++-- 3 files changed, 314 insertions(+), 318 deletions(-) diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 87392da..d6b0175 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -586,7 +586,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i if (_myCGFloatLess(rect.origin.x + rect.size.width + trailingSpace, selfSize.width - paddingTrailing)) { - sbvl.trailingBorderline = self.intelligentBorderline; } @@ -637,10 +636,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i [leadingCandidateRects removeObjectAtIndex:i]; cRect = CGRectUnion(cRect, candidateRect); cRect.size.width += candidateMaxX - cMinx; - } - - } //记录每一行的最大子视图位置的索引值。 @@ -737,7 +733,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i if (_myCGFloatLess(rect.origin.x + rect.size.width + trailingSpace, selfSize.width - paddingTrailing)) { - sbvl.trailingBorderline = self.intelligentBorderline; } @@ -745,10 +740,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i { sbvl.bottomBorderline = self.intelligentBorderline; } - - } - } } diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index e1f1760..fc5bcda 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -222,19 +222,19 @@ -(id)createSizeClassInstance #pragma mark -- Private Methods - -- (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalWeight:(CGFloat)totalWeight sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc +//计算垂直流式布局下每行的比重值。 +- (void)myCalcVertLayoutSinglelineWeight:(CGFloat)lineTotalWeight lineSpareWidth:(CGFloat)lineSpareWidth sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize { //如果浮动宽度都是小于等于0因为没有拉升必要,所以直接返回 - if (totalFloatWidth <= 0.0) + if (lineSpareWidth <= 0.0) return; //按照flex规约,如果总的比重小于1则只会将剩余宽度的总比重部分来进行按比例拉伸。 - if (lsc.isFlex && totalWeight < 1.0) - totalFloatWidth *= totalWeight; + if (lsc.isFlex && lineTotalWeight < 1.0) + lineSpareWidth *= lineTotalWeight; - for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) + for (NSInteger itemIndex = startItemIndex; itemIndex < startItemIndex + count; itemIndex++) { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; @@ -242,7 +242,7 @@ - (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFlo if (sbvsc.weight != 0) { - CGFloat tempWidth = _myCGFloatRound((totalFloatWidth * sbvsc.weight / totalWeight)); + CGFloat tempWidth = _myCGFloatRound((lineSpareWidth * sbvsc.weight / lineTotalWeight)); if (sbvsc.widthSizeInner != nil && sbvsc.widthSizeInner.dimeVal == nil) tempWidth = [sbvsc.widthSizeInner measureWith:tempWidth]; @@ -251,15 +251,16 @@ - (void)myCalcVertLayoutSinglelineWeight:(CGSize)selfSize totalFloatWidth:(CGFlo } } -- (void)myCalcHorzLayoutSinglelineWeight:(CGSize)selfSize totalFloatHeight:(CGFloat)totalFloatHeight totalWeight:(CGFloat)totalWeight sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc +//计算水平流式布局下每行的比重值。 +- (void)myCalcHorzLayoutSinglelineWeight:(CGFloat)lineTotalWeight lineSpareHeight:(CGFloat)lineSpareHeight sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize { - if (totalFloatHeight <= 0.0) + if (lineSpareHeight <= 0.0) return; - if (lsc.isFlex && totalWeight < 1.0) - totalFloatHeight *= totalWeight; + if (lsc.isFlex && lineTotalWeight < 1.0) + lineSpareHeight *= lineTotalWeight; - for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) + for (NSInteger itemIndex = startItemIndex; itemIndex < startItemIndex + count; itemIndex++) { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; @@ -267,12 +268,12 @@ - (void)myCalcHorzLayoutSinglelineWeight:(CGSize)selfSize totalFloatHeight:(CGFl if (sbvsc.weight != 0) { - CGFloat tempHeight = _myCGFloatRound((totalFloatHeight * sbvsc.weight / totalWeight)); + CGFloat tempHeight = _myCGFloatRound((lineSpareHeight * sbvsc.weight / lineTotalWeight)); if (sbvsc.heightSizeInner != nil && sbvsc.heightSizeInner.dimeVal == nil) tempHeight = [sbvsc.heightSizeInner measureWith:tempHeight]; - totalFloatHeight -= tempHeight; - totalWeight -= sbvsc.weight; + lineSpareHeight -= tempHeight; + lineTotalWeight -= sbvsc.weight; sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:tempHeight + sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; @@ -282,42 +283,43 @@ - (void)myCalcHorzLayoutSinglelineWeight:(CGSize)selfSize totalFloatHeight:(CGFl } } -- (void)myAdjustVertLayoutSinglelineWidth:(CGSize)selfSize lineIndex:(NSInteger)lineIndex floatingWidth:(CGFloat)floatingWidth totalWeight:(CGFloat)totalWeight horzGravity:(MyGravity)horzGravity sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc +//调整内容约束垂直流式布局的每行的宽度 +- (void)myAdjustVertLayoutSingleline:(NSInteger)lineIndex lineSpareWidth:(CGFloat)lineSpareWidth lineTotalWeight:(CGFloat)lineTotalWeight horzGravity:(MyGravity)horzGravity sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize { - if (floatingWidth <= 0.0) + if (lineSpareWidth <= 0.0) return; MyGravity lineHorzGravity = horzGravity; if (self.lineGravity != nil) { - lineHorzGravity = self.lineGravity(self, lineIndex, count, startIndex == sbs.count) & MyGravity_Vert_Mask; + lineHorzGravity = self.lineGravity(self, lineIndex, count, (startItemIndex + count) == sbs.count) & MyGravity_Vert_Mask; if (lineHorzGravity == MyGravity_None) lineHorzGravity = horzGravity; } CGFloat addXFill = 0; - if (lineHorzGravity == MyGravity_Horz_Fill && totalWeight == 0.0) + if (lineHorzGravity == MyGravity_Horz_Fill && lineTotalWeight == 0.0) { //流式布局中最后一行不会进行拉伸处理。 - if (lsc.isFlex || startIndex != sbs.count) - addXFill = floatingWidth / count; + if (lsc.isFlex || (startItemIndex + count) != sbs.count) + addXFill = lineSpareWidth / count; } else { //flex规则:当总的比重小于1时,剩余的宽度要乘以这个比重值再进行分配。 - if (lsc.isFlex && totalWeight < 1.0) - floatingWidth *= totalWeight; + if (lsc.isFlex && lineTotalWeight < 1.0) + lineSpareWidth *= lineTotalWeight; } - for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) + for (NSInteger itemIndex = startItemIndex; itemIndex < startItemIndex + count; itemIndex++) { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.weight != 0.0 && totalWeight != 0.0) + if (sbvsc.weight != 0.0 && lineTotalWeight != 0.0) { - CGFloat tempWidth = _myCGFloatRound((floatingWidth * sbvsc.weight / totalWeight)); + CGFloat tempWidth = _myCGFloatRound((lineSpareWidth * sbvsc.weight / lineTotalWeight)); if (sbvsc.widthSizeInner != nil && sbvsc.widthSizeInner.dimeVal == nil) tempWidth = [sbvsc.widthSizeInner measureWith:tempWidth]; @@ -331,42 +333,43 @@ - (void)myAdjustVertLayoutSinglelineWidth:(CGSize)selfSize lineIndex:(NSInteger) } -- (void)myAdjustHorzLayoutSinglelineHeight:(CGSize)selfSize lineIndex:(NSInteger)lineIndex floatingHeight:(CGFloat)floatingHeight totalWeight:(CGFloat)totalWeight vertGravity:(MyGravity)vertGravity sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc +//调整内容约束水平流式布局的每行的高度 +- (void)myAdjustHorzLayoutSingleline:(NSInteger)lineIndex lineSpareHeight:(CGFloat)lineSpareHeight lineTotalWeight:(CGFloat)lineTotalWeight vertGravity:(MyGravity)vertGravity sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize { - if (floatingHeight <= 0.0) + if (lineSpareHeight <= 0.0) return; MyGravity lineVertGravity = vertGravity; if (self.lineGravity != nil) { - lineVertGravity = self.lineGravity(self, lineIndex, count, startIndex == sbs.count) & MyGravity_Horz_Mask; + lineVertGravity = self.lineGravity(self, lineIndex, count, (startItemIndex + count) == sbs.count) & MyGravity_Horz_Mask; if (lineVertGravity == MyGravity_None) lineVertGravity = vertGravity; } CGFloat addYFill = 0; - if (lineVertGravity == MyGravity_Vert_Fill && totalWeight == 0.0) + if (lineVertGravity == MyGravity_Vert_Fill && lineTotalWeight == 0.0) { //流式布局中最后一行不会进行拉伸处理。 - if (lsc.isFlex || startIndex != sbs.count) - addYFill = floatingHeight / count; + if (lsc.isFlex || (startItemIndex + count) != sbs.count) + addYFill = lineSpareHeight / count; } else { //flex规则:当总的比重小于1时,剩余的高度要乘以这个比重值再进行分配。 - if (lsc.isFlex && totalWeight < 1.0) - floatingHeight *= totalWeight; + if (lsc.isFlex && lineTotalWeight < 1.0) + lineSpareHeight *= lineTotalWeight; } - for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) + for (NSInteger itemIndex = startItemIndex; itemIndex < startItemIndex + count; itemIndex++) { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.weight != 0.0 && totalWeight != 0.0) + if (sbvsc.weight != 0.0 && lineTotalWeight != 0.0) { - CGFloat tempHeight = _myCGFloatRound((floatingHeight * sbvsc.weight / totalWeight)); + CGFloat tempHeight = _myCGFloatRound((lineSpareHeight * sbvsc.weight / lineTotalWeight)); if (sbvsc.heightSizeInner != nil && sbvsc.heightSizeInner.dimeVal == nil) tempHeight = [sbvsc.heightSizeInner measureWith:tempHeight]; @@ -380,20 +383,20 @@ - (void)myAdjustHorzLayoutSinglelineHeight:(CGSize)selfSize lineIndex:(NSInteger } -- (void)myCalcVertLayoutSinglelineWidthShrink:(CGSize)selfSize totalFloatWidth:(CGFloat)totalFloatWidth totalShrink:(CGFloat)totalShrink sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc +- (void)myCalcVertLayoutSinglelineShrink:(CGFloat)lineTotalShrink lineSpareWidth:(CGFloat)lineSpareWidth sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize { - if (_myCGFloatGreatOrEqual(totalFloatWidth, 0.0)) - totalShrink = 0.0; + if (_myCGFloatGreatOrEqual(lineSpareWidth, 0.0)) + lineTotalShrink = 0.0; - if (totalShrink == 0.0) + if (lineTotalShrink == 0.0) return; //根据flex规约:如果总的压缩比重小于1则超出部分会乘以这个压缩比再进行压缩。 - if (lsc.isFlex && totalShrink < 1.0) - totalFloatWidth *= totalShrink; + if (lsc.isFlex && lineTotalShrink < 1.0) + lineSpareWidth *= lineTotalShrink; //如果有压缩则调整子视图的宽度。 - for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) + for (NSInteger itemIndex = startItemIndex; itemIndex < startItemIndex + count; itemIndex++) { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; @@ -401,27 +404,27 @@ - (void)myCalcVertLayoutSinglelineWidthShrink:(CGSize)selfSize totalFloatWidth:( if (sbvsc.widthSizeInner.shrink != 0.0) { - sbvmyFrame.width += (sbvsc.widthSizeInner.shrink / totalShrink) * totalFloatWidth; + sbvmyFrame.width += (sbvsc.widthSizeInner.shrink / lineTotalShrink) * lineSpareWidth; if (sbvmyFrame.width < 0.0) sbvmyFrame.width = 0.0; } } } -- (void)myCalcHorzLayoutSinglelineHeightShrink:(CGSize)selfSize totalFloatHeight:(CGFloat)totalFloatHeight totalShrink:(CGFloat)totalShrink sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count lsc:(MyFlowLayout *)lsc +- (void)myCalcHorzLayoutSinglelineShrink:(CGFloat)lineTotalShrink lineSpareHeight:(CGFloat)lineSpareHeight sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count lsc:(MyFlowLayout *)lsc inSelfSize:(CGSize)selfSize { - if (_myCGFloatGreatOrEqual(totalFloatHeight, 0.0)) - totalShrink = 0.0; + if (_myCGFloatGreatOrEqual(lineSpareHeight, 0.0)) + lineTotalShrink = 0.0; - if (totalShrink == 0.0) + if (lineTotalShrink == 0.0) return; //根据flex规约:如果总的压缩比重小于1则超出部分会乘以这个压缩比再进行压缩。 - if (lsc.isFlex && totalShrink < 1.0) - totalFloatHeight *= totalShrink; + if (lsc.isFlex && lineTotalShrink < 1.0) + lineSpareHeight *= lineTotalShrink; //如果有压缩则调整子视图的高度。 - for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) + for (NSInteger itemIndex = startItemIndex; itemIndex < startItemIndex + count; itemIndex++) { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; @@ -429,7 +432,7 @@ - (void)myCalcHorzLayoutSinglelineHeightShrink:(CGSize)selfSize totalFloatHeight if (sbvsc.heightSizeInner.shrink != 0.0) { - sbvmyFrame.height += (sbvsc.heightSizeInner.shrink / totalShrink) * totalFloatHeight; + sbvmyFrame.height += (sbvsc.heightSizeInner.shrink / lineTotalShrink) * lineSpareHeight; if (sbvmyFrame.height < 0.0) sbvmyFrame.height = 0.0; } @@ -437,19 +440,18 @@ - (void)myCalcHorzLayoutSinglelineHeightShrink:(CGSize)selfSize totalFloatHeight } -- (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger)rowIndex rowMaxHeight:(CGFloat)rowMaxHeight rowMaxWidth:(CGFloat)rowMaxWidth rowTotalShrink:(CGFloat)rowTotalShrink horzGravity:(MyGravity)horzGravity vertAlignment:(MyGravity)vertAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +- (void)myCalcVertLayoutSingleline:(NSInteger)lineIndex vertAlignment:(MyGravity)vertAlignment horzGravity:(MyGravity)horzGravity lineMaxHeight:(CGFloat)lineMaxHeight lineMaxWidth:(CGFloat)lineMaxWidth lineTotalShrink:(CGFloat)lineTotalShrink sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize { - CGFloat lineMaxHeight = rowMaxHeight; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; CGFloat paddingHorz = paddingLeading + paddingTrailing; - CGFloat floatingWidth = selfSize.width - rowMaxWidth - paddingHorz; - if (_myCGFloatGreatOrEqual(floatingWidth, 0.0)) - rowTotalShrink = 0.0; + CGFloat lineSpareWidth = selfSize.width - lineMaxWidth - paddingHorz; + if (_myCGFloatGreatOrEqual(lineSpareWidth, 0.0)) + lineTotalShrink = 0.0; - if (rowTotalShrink != 0.0) - rowMaxWidth = selfSize.width - paddingHorz; + if (lineTotalShrink != 0.0) + lineMaxWidth = selfSize.width - paddingHorz; //计算每行的gravity情况。 CGFloat addXPos = 0; //多出来的空隙区域,用于停靠处理。 @@ -459,7 +461,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger MyGravity lineVertAlignment = vertAlignment; if (self.lineGravity != nil) { - MyGravity lineGravity = self.lineGravity(self, rowIndex, count, startIndex == sbs.count); + MyGravity lineGravity = self.lineGravity(self, lineIndex, count, (startItemIndex+count) == sbs.count); lineHorzGravity = lineGravity & MyGravity_Vert_Mask; if (lineHorzGravity == MyGravity_None) lineHorzGravity = horzGravity; @@ -475,20 +477,20 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger { case MyGravity_Horz_Center: { - addXPos = (selfSize.width - paddingHorz - rowMaxWidth) / 2; + addXPos = (selfSize.width - paddingHorz - lineMaxWidth) / 2; } break; case MyGravity_Horz_Trailing: { - addXPos = selfSize.width - paddingHorz - rowMaxWidth; //因为具有不考虑左边距,而原来的位置增加了左边距,因此 + addXPos = selfSize.width - paddingHorz - lineMaxWidth; //因为具有不考虑左边距,而原来的位置增加了左边距,因此 } break; case MyGravity_Horz_Between: { //总宽度减去最大的宽度。再除以数量表示每个应该扩展的空间。最后一行无效(如果最后一行的数量和其他行的数量一样以及总共就只有一行除外)。 - if ((lsc.isFlex || startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) + if ((lsc.isFlex || (startItemIndex + count) != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) { - addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / (count - 1); + addXFill = (selfSize.width - paddingHorz - lineMaxWidth) / (count - 1); } } break; @@ -497,12 +499,12 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger //多于一个拉伸间距,只有一个则居中处理。 if (count > 1) { - addXFill = (selfSize.width - paddingHorz - rowMaxWidth) / count; + addXFill = (selfSize.width - paddingHorz - lineMaxWidth) / count; addXPos = addXFill / 2.0; } else { - addXPos = (selfSize.width - paddingHorz - rowMaxWidth) / 2; + addXPos = (selfSize.width - paddingHorz - lineMaxWidth) / 2; } } break; @@ -515,7 +517,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger //基线位置 CGFloat baselinePos = CGFLOAT_MAX; //将整行的位置进行调整。 - for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) + for (NSInteger itemIndex = startItemIndex; itemIndex < startItemIndex + count; itemIndex++) { UIView *sbv = sbs[itemIndex]; @@ -535,11 +537,11 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger sbvl.bottomBorderline = nil; //如果不是最后一行就画下面, - if (startIndex != sbs.count) + if ((startItemIndex + count) != sbs.count) sbvl.bottomBorderline = self.intelligentBorderline; //如果不是最后一列就画右边, - if (itemIndex < startIndex - 1) + if (itemIndex < (startItemIndex + count) - 1) sbvl.trailingBorderline = self.intelligentBorderline; //如果最后一行的最后一个没有满列数时 @@ -547,11 +549,11 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger sbvl.trailingBorderline = self.intelligentBorderline; //如果有垂直间距则不是第一行就画上 - if (vertSpace != 0 && startIndex - count != 0) + if (vertSpace != 0 && startItemIndex != 0) sbvl.topBorderline = self.intelligentBorderline; //如果有水平间距则不是第一列就画左 - if (horzSpace != 0 && itemIndex != startIndex - count) + if (horzSpace != 0 && itemIndex != startItemIndex) sbvl.leadingBorderline = self.intelligentBorderline; } } @@ -572,21 +574,21 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger sbvVertAlignment = MyGravity_Vert_Top; } - if ((sbvVertAlignment != MyGravity_None && sbvVertAlignment != MyGravity_Vert_Top) || _myCGFloatNotEqual(addXPos, 0.0) || _myCGFloatNotEqual(addXFill, 0.0) || rowTotalShrink != 0.0) + if ((sbvVertAlignment != MyGravity_None && sbvVertAlignment != MyGravity_Vert_Top) || _myCGFloatNotEqual(addXPos, 0.0) || _myCGFloatNotEqual(addXFill, 0.0) || lineTotalShrink != 0.0) { sbvmyFrame.leading += addXPos; //处理对间距的压缩 - if (rowTotalShrink != 0.0) + if (lineTotalShrink != 0.0) { if (sbvsc.leadingPosInner.shrink != 0.0) - totalShrinkSize += (sbvsc.leadingPosInner.shrink / rowTotalShrink) * floatingWidth; + totalShrinkSize += (sbvsc.leadingPosInner.shrink / lineTotalShrink) * lineSpareWidth; sbvmyFrame.leading += totalShrinkSize; if (sbvsc.trailingPosInner.shrink != 0.0) - totalShrinkSize += (sbvsc.trailingPosInner.shrink / rowTotalShrink) * floatingWidth; + totalShrinkSize += (sbvsc.trailingPosInner.shrink / lineTotalShrink) * lineSpareWidth; } //内容约束布局并且是填充尺寸或者拉升尺寸。 @@ -595,7 +597,7 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger if ( lineHorzGravity != MyGravity_Horz_Fill) { //其他的只拉伸间距 - sbvmyFrame.leading += addXFill * (itemIndex - (startIndex - count)); + sbvmyFrame.leading += addXFill * (itemIndex - startItemIndex); } } @@ -639,19 +641,18 @@ - (void)myCalcVertLayoutSinglelineAlignment:(CGSize)selfSize rowIndex:(NSInteger } -- (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger)colIndex colMaxWidth:(CGFloat)colMaxWidth colMaxHeight:(CGFloat)colMaxHeight colTotalShrink:(CGFloat)colTotalShrink vertGravity:(MyGravity)vertGravity horzAlignment:(MyGravity)horzAlignment sbs:(NSArray *)sbs startIndex:(NSInteger)startIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +- (void)myCalcHorzLayoutSingleline:(NSInteger)lineIndex horzAlignment:(MyGravity)horzAlignment vertGravity:(MyGravity)vertGravity lineMaxWidth:(CGFloat)lineMaxWidth lineMaxHeight:(CGFloat)lineMaxHeight lineTotalShrink:(CGFloat)lineTotalShrink sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize { - CGFloat lineMaxWidth = colMaxWidth; CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingVert = paddingTop + paddingBottom; - CGFloat floatingHeight = selfSize.height - colMaxHeight - paddingVert; - if (_myCGFloatGreatOrEqual(floatingHeight, 0.0)) - colTotalShrink = 0.0; + CGFloat lineSpareHeight = selfSize.height - lineMaxHeight - paddingVert; + if (_myCGFloatGreatOrEqual(lineSpareHeight, 0.0)) + lineTotalShrink = 0.0; - if (colTotalShrink != 0.0) - colMaxHeight = selfSize.height - paddingVert; + if (lineTotalShrink != 0.0) + lineMaxHeight = selfSize.height - paddingVert; //计算每行的gravity情况。 CGFloat addYPos = 0; @@ -660,7 +661,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger MyGravity lineVertGravity = vertGravity; if (self.lineGravity != nil) { - MyGravity lineGravity = self.lineGravity(self, colIndex, count, startIndex == sbs.count); + MyGravity lineGravity = self.lineGravity(self, lineIndex, count, (startItemIndex + count) == sbs.count); lineHorzAlignment = lineGravity & MyGravity_Vert_Mask; if (lineHorzAlignment == MyGravity_None) lineHorzAlignment = horzAlignment; @@ -676,20 +677,20 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger { case MyGravity_Vert_Center: { - addYPos = (selfSize.height - paddingVert - colMaxHeight) / 2; + addYPos = (selfSize.height - paddingVert - lineMaxHeight) / 2; } break; case MyGravity_Vert_Bottom: { - addYPos = selfSize.height - paddingVert - colMaxHeight; + addYPos = selfSize.height - paddingVert - lineMaxHeight; } break; case MyGravity_Vert_Between: { //总高度减去最大的高度。再除以数量表示每个应该扩展的空间。最后一列无效(如果最后一列的数量和其他列的数量一样以及总共就只有一列除外)。 - if ((lsc.isFlex || startIndex != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) + if ((lsc.isFlex || (startItemIndex + count) != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) { - addYFill = (selfSize.height - paddingVert - colMaxHeight) / (count - 1); + addYFill = (selfSize.height - paddingVert - lineMaxHeight) / (count - 1); } } break; @@ -697,12 +698,12 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger { if (count > 1) { - addYFill = (selfSize.height - paddingVert - colMaxHeight) / count; + addYFill = (selfSize.height - paddingVert - lineMaxHeight) / count; addYPos = addYFill / 2.0; } else { - addYPos = (selfSize.height - paddingVert - colMaxHeight) / 2; + addYPos = (selfSize.height - paddingVert - lineMaxHeight) / 2; } } break; @@ -714,7 +715,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger //压缩减少的尺寸汇总。 CGFloat totalShrinkSize = 0; //将整行的位置进行调整。 - for (NSInteger itemIndex = startIndex - count; itemIndex < startIndex; itemIndex++) + for (NSInteger itemIndex = startItemIndex; itemIndex < startItemIndex + count; itemIndex++) { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; @@ -735,11 +736,11 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger //如果不是最后一行就画下面, - if (itemIndex < startIndex - 1) + if (itemIndex < (startItemIndex + count) - 1) sbvl.bottomBorderline = self.intelligentBorderline; //如果不是最后一列就画右边, - if (startIndex != sbs.count ) + if ((startItemIndex + count) != sbs.count ) sbvl.trailingBorderline = self.intelligentBorderline; //如果最后一行的最后一个没有满列数时 @@ -747,11 +748,11 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger sbvl.bottomBorderline = self.intelligentBorderline; //如果有垂直间距则不是第一行就画上 - if (vertSpace != 0 && itemIndex != startIndex - count) + if (vertSpace != 0 && itemIndex != startItemIndex) sbvl.topBorderline = self.intelligentBorderline; //如果有水平间距则不是第一列就画左 - if (horzSpace != 0 && startIndex - count != 0 ) + if (horzSpace != 0 && startItemIndex != 0 ) sbvl.leadingBorderline = self.intelligentBorderline; } } @@ -765,20 +766,20 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger if (horzAlignment == MyGravity_Horz_Between) sbvHorzAlignment = MyGravity_None; - if ((sbvHorzAlignment != MyGravity_None && sbvHorzAlignment != MyGravity_Horz_Leading) || _myCGFloatNotEqual(addYPos, 0.0) || _myCGFloatNotEqual(addYFill, 0.0) || colTotalShrink != 0.0) + if ((sbvHorzAlignment != MyGravity_None && sbvHorzAlignment != MyGravity_Horz_Leading) || _myCGFloatNotEqual(addYPos, 0.0) || _myCGFloatNotEqual(addYFill, 0.0) || lineTotalShrink != 0.0) { sbvmyFrame.top += addYPos; //处理对间距的压缩 - if (colTotalShrink != 0.0) + if (lineTotalShrink != 0.0) { if (sbvsc.topPosInner.shrink != 0.0) - totalShrinkSize += (sbvsc.topPosInner.shrink / colTotalShrink) * floatingHeight; + totalShrinkSize += (sbvsc.topPosInner.shrink / lineTotalShrink) * lineSpareHeight; sbvmyFrame.top += totalShrinkSize; if (sbvsc.bottomPosInner.shrink != 0.0) - totalShrinkSize += (sbvsc.bottomPosInner.shrink / colTotalShrink) * floatingHeight; + totalShrinkSize += (sbvsc.bottomPosInner.shrink / lineTotalShrink) * lineSpareHeight; } //内容约束布局并且是填充尺寸或者拉升尺寸。 @@ -787,7 +788,7 @@ - (void)myCalcHorzLayoutSinglelineAlignment:(CGSize)selfSize colIndex:(NSInteger if (lineVertGravity != MyGravity_Vert_Fill) { //只拉伸间距 - sbvmyFrame.top += addYFill * (itemIndex - (startIndex - count)); + sbvmyFrame.top += addYFill * (itemIndex - startItemIndex); } } @@ -985,7 +986,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; - MyGravity vertAlign = lsc.arrangedGravity & MyGravity_Horz_Mask; + MyGravity vertAlignment = lsc.arrangedGravity & MyGravity_Horz_Mask; //支持浮动水平间距。 CGFloat vertSpace = lsc.subviewVSpace; @@ -994,8 +995,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; - CGFloat rowMaxHeight = 0.0; //某一行的最高值。 - CGFloat rowMaxWidth = 0.0; //某一行的最宽值。 + CGFloat lineMaxHeight = 0.0; //某一行的最高值。 + CGFloat lineMaxWidth = 0.0; //某一行的最宽值。 CGFloat maxWidth = 0.0; //所有行中最宽的值。 if (lsc.autoArrange) @@ -1031,7 +1032,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab //每行行首子视图的索引位置。 NSMutableIndexSet *lineFirstSubviewIndexSet = [NSMutableIndexSet new]; NSInteger lineIndex = 0; //行的索引。 - NSInteger arrangedIndex = 0; //行内子视图的索引 + NSInteger itemIndex = 0; //行内子视图的索引 CGFloat lineTotalWeight = 0.0; NSInteger i = 0; for (; i < sbs.count; i++) @@ -1073,17 +1074,17 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab } else { - CGFloat floatingWidth = selfSize.width - paddingTrailing - xPos - leadingSpace - trailingSpace; - if (arrangedIndex != 0) - floatingWidth -= horzSpace; + CGFloat lineSpareWidth = selfSize.width - paddingTrailing - xPos - leadingSpace - trailingSpace; + if (itemIndex != 0) + lineSpareWidth -= horzSpace; - if (_myCGFloatLessOrEqual(floatingWidth, 0.0)) + if (_myCGFloatLessOrEqual(lineSpareWidth, 0.0)) { //如果当前行的剩余空间不够,则需要换行来计算相对的宽度占比,这时候剩余空间就是按整行来算,并且将行索引设置为0 - floatingWidth = selfSize.width - paddingHorz; + lineSpareWidth = selfSize.width - paddingHorz; } - rect.size.width = (floatingWidth + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace; + rect.size.width = (lineSpareWidth + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace; } } @@ -1098,7 +1099,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab //计算xPos的值加上leadingSpace + rect.size.width + trailingSpace 的值要小于整体的宽度。 CGFloat place = xPos + leadingSpace + rect.size.width + trailingSpace; - if (arrangedIndex != 0) + if (itemIndex != 0) place += horzSpace; place += paddingTrailing; @@ -1106,10 +1107,10 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab if (!lsc.widthSizeInner.dimeWrapVal && (place - selfSize.width > 0.0001)) { //保存行首子视图的索引 - [lineFirstSubviewIndexSet addIndex:i - arrangedIndex]; + [lineFirstSubviewIndexSet addIndex:i - itemIndex]; //拉伸以及调整行内子视图的宽度。 - [self myAdjustVertLayoutSinglelineWidth:selfSize lineIndex:lineIndex floatingWidth:selfSize.width - paddingTrailing - xPos totalWeight:lineTotalWeight horzGravity:horzGravity sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; + [self myAdjustVertLayoutSingleline:lineIndex lineSpareWidth:selfSize.width - paddingTrailing - xPos lineTotalWeight:lineTotalWeight horzGravity:horzGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; xPos = paddingLeading; @@ -1121,10 +1122,10 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab lineTotalWeight = 0.0; lineIndex++; - arrangedIndex = 0; + itemIndex = 0; } - if (arrangedIndex != 0) + if (itemIndex != 0) xPos += horzSpace; rect.origin.x = xPos + leadingSpace; @@ -1134,17 +1135,17 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab lineTotalWeight += sbvsc.weight; sbvmyFrame.frame = rect; - arrangedIndex++; + itemIndex++; } //最后一行的行首索引 - [lineFirstSubviewIndexSet addIndex:i - arrangedIndex]; + [lineFirstSubviewIndexSet addIndex:i - itemIndex]; - [self myAdjustVertLayoutSinglelineWidth:selfSize lineIndex:lineIndex floatingWidth:selfSize.width - paddingTrailing - xPos totalWeight:lineTotalWeight horzGravity:horzGravity sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; + [self myAdjustVertLayoutSingleline:lineIndex lineSpareWidth:selfSize.width - paddingTrailing - xPos lineTotalWeight:lineTotalWeight horzGravity:horzGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; xPos = paddingLeading; lineIndex = 0; //行的索引。 - arrangedIndex = 0; //行内的子视图索引 + itemIndex = 0; //行内的子视图索引 NSInteger oldLineFirstIndex = 0; i = 0; for (; i < sbs.count; i++) @@ -1184,7 +1185,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab //计算xPos的值加上leadingSpace + rect.size.width + trailingSpace 的值要小于整体的宽度。 maxWidth= xPos + leadingSpace + rect.size.width + trailingSpace; - if (arrangedIndex != 0) + if (itemIndex != 0) maxWidth += horzSpace; maxWidth += paddingTrailing; @@ -1195,19 +1196,19 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab xPos = paddingLeading; yPos += vertSpace; - yPos += rowMaxHeight; + yPos += lineMaxHeight; - [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:lineIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcVertLayoutSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; - rowMaxHeight = 0.0; - rowMaxWidth = 0.0; - arrangedIndex = 0; + lineMaxHeight = 0.0; + lineMaxWidth = 0.0; + itemIndex = 0; lineIndex++; } - if (arrangedIndex != 0) + if (itemIndex != 0) xPos += horzSpace; @@ -1215,17 +1216,17 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab rect.origin.y = yPos + topSpace; xPos += leadingSpace + rect.size.width + trailingSpace; - if (_myCGFloatLess(rowMaxHeight, topSpace + bottomSpace + rect.size.height)) - rowMaxHeight = topSpace + bottomSpace + rect.size.height; + if (_myCGFloatLess(lineMaxHeight, topSpace + bottomSpace + rect.size.height)) + lineMaxHeight = topSpace + bottomSpace + rect.size.height; - if (_myCGFloatLess(rowMaxWidth, (xPos - paddingLeading))) - rowMaxWidth = (xPos - paddingLeading); + if (_myCGFloatLess(lineMaxWidth, (xPos - paddingLeading))) + lineMaxWidth = (xPos - paddingLeading); sbvmyFrame.frame = rect; - arrangedIndex++; + itemIndex++; } - yPos += rowMaxHeight + paddingBottom; + yPos += lineMaxHeight + paddingBottom; //内容填充约束布局的宽度包裹计算。 @@ -1238,10 +1239,10 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab NSInteger arranges = lineFirstSubviewIndexSet.count; //根据flex规则:如果只有一行则整个高度都作为子视图的拉伸和停靠区域。 if (lsc.isFlex && arranges == 1) - rowMaxHeight = selfSize.height - paddingVert; + lineMaxHeight = selfSize.height - paddingVert; //最后一行 - [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:lineIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:0 horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcVertLayoutSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; //整体的停靠 if (vertGravity != MyGravity_None && selfSize.height != yPos) @@ -1313,7 +1314,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab //因为每行都增加了fill。所以如果有行内对齐则需要这里调整。 MyGravity sbvVertAlignment = sbvsc.alignment & MyGravity_Horz_Mask; if (sbvVertAlignment == MyGravity_None) - sbvVertAlignment = vertAlign; + sbvVertAlignment = vertAlignment; if (sbvVertAlignment == MyGravity_Vert_Center) sbvmyFrame.top += fill/2.0; @@ -1355,7 +1356,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; - MyGravity vertAlign = lsc.arrangedGravity & MyGravity_Horz_Mask; + MyGravity vertAlignment = lsc.arrangedGravity & MyGravity_Horz_Mask; CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; @@ -1363,8 +1364,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; - CGFloat rowMaxHeight = 0.0; //某一行的最高值。 - CGFloat rowMaxWidth = 0.0; //某一行的最宽值 + CGFloat lineMaxHeight = 0.0; //某一行的最高值。 + CGFloat lineMaxWidth = 0.0; //某一行的最宽值 CGFloat maxWidth = paddingLeading; //全部行的最大宽度 CGFloat maxHeight = paddingTop; //最大的高度 @@ -1422,34 +1423,34 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray averageWidth = (selfSize.width - paddingHorz - (arrangedCount - 1) * horzSpace) / arrangedCount; //行内子视图的索引号 - NSInteger arrangedIndex = 0; + NSInteger itemIndex = 0; NSInteger i = 0; - CGFloat rowTotalShrink = 0.0; //某一行的总压缩比重。 - CGFloat rowTotalWeight = 0.0; - CGFloat rowTotalFixedWidth = 0.0; + CGFloat lineTotalShrink = 0.0; //某一行的总压缩比重。 + CGFloat lineTotalWeight = 0.0; + CGFloat lineTotalFixedWidth = 0.0; for (; i < sbs.count; i++) { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (arrangedIndex >= arrangedCount) + if (itemIndex >= arrangedCount) { - arrangedIndex = 0; + itemIndex = 0; - if (rowTotalWeight != 0 && horzGravity != MyGravity_Horz_Fill) + if (lineTotalWeight != 0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedCount lsc:lsc]; + [self myCalcVertLayoutSinglelineWeight:lineTotalWeight lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount lsc:lsc inSelfSize:selfSize]; } - if (rowTotalShrink != 0 && horzGravity != MyGravity_Horz_Fill) + if (lineTotalShrink != 0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWidthShrink:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalShrink:rowTotalShrink sbs:sbs startIndex:i count:arrangedCount lsc:lsc]; + [self myCalcVertLayoutSinglelineShrink:lineTotalShrink lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount lsc:lsc inSelfSize:selfSize]; } - rowTotalWeight = 0.0; - rowTotalFixedWidth = 0.0; - rowTotalShrink = 0.0; + lineTotalWeight = 0.0; + lineTotalFixedWidth = 0.0; + lineTotalShrink = 0.0; } CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; @@ -1498,35 +1499,35 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; if (sbvsc.weight != 0.0) - rowTotalWeight += sbvsc.weight; + lineTotalWeight += sbvsc.weight; //计算总的压缩比 - rowTotalShrink += sbvsc.leadingPosInner.shrink + sbvsc.trailingPosInner.shrink; - rowTotalShrink += sbvsc.widthSizeInner.shrink; + lineTotalShrink += sbvsc.leadingPosInner.shrink + sbvsc.trailingPosInner.shrink; + lineTotalShrink += sbvsc.widthSizeInner.shrink; - rowTotalFixedWidth += rect.size.width; - rowTotalFixedWidth += leadingSpace + trailingSpace; - if (arrangedIndex != (arrangedCount - 1)) - rowTotalFixedWidth += horzSpace; + lineTotalFixedWidth += rect.size.width; + lineTotalFixedWidth += leadingSpace + trailingSpace; + if (itemIndex != (arrangedCount - 1)) + lineTotalFixedWidth += horzSpace; sbvmyFrame.frame = rect; - arrangedIndex++; + itemIndex++; } //最后一行。 - if (arrangedIndex < arrangedCount) - rowTotalFixedWidth -= horzSpace; + if (itemIndex < arrangedCount) + lineTotalFixedWidth -= horzSpace; - if (rowTotalWeight != 0.0 && horzGravity != MyGravity_Horz_Fill) + if (lineTotalWeight != 0.0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWeight:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalWeight:rowTotalWeight sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; + [self myCalcVertLayoutSinglelineWeight:lineTotalWeight lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; } //如果有压缩子视图的处理则需要压缩子视图。 - if (rowTotalShrink != 0.0 && horzGravity != MyGravity_Horz_Fill) + if (lineTotalShrink != 0.0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWidthShrink:selfSize totalFloatWidth:selfSize.width - paddingHorz - rowTotalFixedWidth totalShrink:rowTotalShrink sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; + [self myCalcVertLayoutSinglelineShrink:lineTotalShrink lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; } //初始化每行的下一个子视图的位置。 @@ -1540,10 +1541,10 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray } } - NSInteger rowIndex = 0; //行索引 + NSInteger lineIndex = 0; //行索引 CGFloat pageWidth = 0.0; //页宽。 - arrangedIndex = 0; - rowTotalShrink = 0.0; + itemIndex = 0; + lineTotalShrink = 0.0; i = 0; for (; i < sbs.count; i++) { @@ -1552,13 +1553,13 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; //新的一行 - if (arrangedIndex >= arrangedCount) + if (itemIndex >= arrangedCount) { - arrangedIndex = 0; + itemIndex = 0; yPos += vertSpace; - yPos += rowMaxHeight; + yPos += lineMaxHeight; - [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcVertLayoutSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; //分别处理水平分页和垂直分页。 if (isHorzPaging) @@ -1590,10 +1591,10 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray xPos = paddingLeading + pageWidth; - rowMaxHeight = 0.0; - rowMaxWidth = 0.0; - rowTotalShrink = 0.0; - rowIndex++; + lineMaxHeight = 0.0; + lineMaxWidth = 0.0; + lineTotalShrink = 0.0; + lineIndex++; } @@ -1639,8 +1640,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray } //得到最大的行高 - if (_myCGFloatLess(rowMaxHeight, topSpace + bottomSpace + rect.size.height)) - rowMaxHeight = topSpace + bottomSpace + rect.size.height; + if (_myCGFloatLess(lineMaxHeight, topSpace + bottomSpace + rect.size.height)) + lineMaxHeight = topSpace + bottomSpace + rect.size.height; //自动排列。 @@ -1676,7 +1677,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray maxHeight = yPos + topSpace + rect.size.height + bottomSpace; } - else if (vertAlign == MyGravity_Vert_Between) + else if (vertAlignment == MyGravity_Vert_Between) { //当列是紧凑排列时需要特殊处理当前的垂直位置。 //第0行特殊处理。 if (i - arrangedCount < 0) @@ -1699,27 +1700,27 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray else {//正常排列。 //这里的最大其实就是最后一个视图的位置加上最高的子视图的尺寸。 - maxHeight = yPos + rowMaxHeight; + maxHeight = yPos + lineMaxHeight; } rect.origin.x = xPos + leadingSpace; rect.origin.y = yPos + topSpace; xPos += leadingSpace + rect.size.width + trailingSpace; - if (arrangedIndex != (arrangedCount - 1) && !autoArrange) + if (itemIndex != (arrangedCount - 1) && !autoArrange) xPos += horzSpace; - if (_myCGFloatLess(rowMaxWidth, (xPos - paddingLeading))) - rowMaxWidth = (xPos - paddingLeading); + if (_myCGFloatLess(lineMaxWidth, (xPos - paddingLeading))) + lineMaxWidth = (xPos - paddingLeading); if (_myCGFloatLess(maxWidth, xPos)) maxWidth = xPos; sbvmyFrame.frame = rect; - arrangedIndex++; + itemIndex++; //这里只对间距进行压缩比重的计算,因为前面压缩了宽度,这里只需要压缩间距了。 - rowTotalShrink += sbvsc.leadingPosInner.shrink + sbvsc.trailingPosInner.shrink; + lineTotalShrink += sbvsc.leadingPosInner.shrink + sbvsc.trailingPosInner.shrink; } maxHeight += paddingBottom; @@ -1744,10 +1745,11 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray NSInteger arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); //行数 //根据flex规则:如果只有一行则整个高度都作为子视图的拉伸和停靠区域。 if (lsc.isFlex && arranges == 1) - rowMaxHeight = selfSize.height - paddingVert; + lineMaxHeight = selfSize.height - paddingVert; //最后一行,有可能因为行宽的压缩导致那些高度依赖宽度以及高度自适应的视图会增加高度,从而使得行高被调整。 - [self myCalcVertLayoutSinglelineAlignment:selfSize rowIndex:rowIndex rowMaxHeight:rowMaxHeight rowMaxWidth:rowMaxWidth rowTotalShrink:rowTotalShrink horzGravity:horzGravity vertAlignment:vertAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcVertLayoutSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; + //整体的停靠 if (vertGravity != MyGravity_None && selfSize.height != maxHeight && !(isVertPaging && isPagingScroll)) @@ -1808,7 +1810,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray //因为每行都增加了fill。所以如果有行内对齐则需要这里调整。 MyGravity sbvVertAlignment = sbvsc.alignment & MyGravity_Horz_Mask; if (sbvVertAlignment == MyGravity_None) - sbvVertAlignment = vertAlign; + sbvVertAlignment = vertAlignment; if (sbvVertAlignment == MyGravity_Vert_Center) sbvmyFrame.top += fill/2.0; @@ -1874,8 +1876,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; - CGFloat colMaxWidth = 0.0; //某一列的最宽值。 - CGFloat colMaxHeight = 0.0; //某一列的最高值 + CGFloat lineMaxWidth = 0.0; //某一列的最宽值。 + CGFloat lineMaxHeight = 0.0; //某一列的最高值 CGFloat maxHeight = 0.0; //所有列的最宽行 if (lsc.autoArrange) @@ -1913,7 +1915,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab NSMutableIndexSet *lineFirstSubviewIndexSet = [NSMutableIndexSet new]; NSInteger lineIndex = 0; - NSInteger arrangedIndex = 0; + NSInteger itemIndex = 0; CGFloat lineTotalWeight = 0.0; NSInteger i = 0; for (; i < sbs.count; i++) @@ -1960,15 +1962,15 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab else { //如果超过了布局尺寸,则表示当前的剩余空间为0了,所以就按新的一行来算。。 - CGFloat floatingHeight = selfSize.height - paddingBottom - yPos - topSpace - bottomSpace; - if (arrangedIndex != 0) - floatingHeight -= vertSpace; - if (_myCGFloatLessOrEqual(floatingHeight, 0.0)) + CGFloat lineSpareHeight = selfSize.height - paddingBottom - yPos - topSpace - bottomSpace; + if (itemIndex != 0) + lineSpareHeight -= vertSpace; + if (_myCGFloatLessOrEqual(lineSpareHeight, 0.0)) { - floatingHeight = selfSize.height - paddingVert; + lineSpareHeight = selfSize.height - paddingVert; } - rect.size.height = (floatingHeight + sbvsc.heightSizeInner.addVal) * sbvsc.weight - topSpace - bottomSpace; + rect.size.height = (lineSpareHeight + sbvsc.heightSizeInner.addVal) * sbvsc.weight - topSpace - bottomSpace; } } @@ -1984,17 +1986,17 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab //计算yPos的值加上topSpace + rect.size.height + bottomSpace的值要小于整体的高度。 CGFloat place = yPos + topSpace + rect.size.height + bottomSpace; - if (arrangedIndex != 0) + if (itemIndex != 0) place += vertSpace; place += paddingBottom; //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的宽度和布局视图保持一致。 if (!lsc.heightSizeInner.dimeWrapVal && (place - selfSize.height > 0.0001)) { - [lineFirstSubviewIndexSet addIndex:i - arrangedIndex]; + [lineFirstSubviewIndexSet addIndex:i - itemIndex]; //拉伸以及调整行内子视图的高度。 - [self myAdjustHorzLayoutSinglelineHeight:selfSize lineIndex:lineIndex floatingHeight:selfSize.height - paddingBottom - yPos totalWeight:lineTotalWeight vertGravity:vertGravity sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; + [self myAdjustHorzLayoutSingleline:lineIndex lineSpareHeight:selfSize.height - paddingBottom - yPos lineTotalWeight:lineTotalWeight vertGravity:vertGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; yPos = paddingTop; @@ -2006,10 +2008,10 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab lineTotalWeight = 0.0; lineIndex++; - arrangedIndex = 0; + itemIndex = 0; } - if (arrangedIndex != 0) + if (itemIndex != 0) yPos += vertSpace; @@ -2020,18 +2022,18 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab lineTotalWeight += sbvsc.weight; sbvmyFrame.frame = rect; - arrangedIndex++; + itemIndex++; } //最后一行的行首索引 - [lineFirstSubviewIndexSet addIndex:i - arrangedIndex]; + [lineFirstSubviewIndexSet addIndex:i - itemIndex]; - [self myAdjustHorzLayoutSinglelineHeight:selfSize lineIndex:lineIndex floatingHeight:selfSize.height - paddingBottom - yPos totalWeight:lineTotalWeight vertGravity:vertGravity sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; + [self myAdjustHorzLayoutSingleline:lineIndex lineSpareHeight:selfSize.height - paddingBottom - yPos lineTotalWeight:lineTotalWeight vertGravity:vertGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; yPos = paddingTop; lineIndex = 0; //行的索引。 - arrangedIndex = 0; //行内的子视图索引 + itemIndex = 0; //行内的子视图索引 NSInteger oldLineFirstIndex = 0; i = 0; for (; i < sbs.count; i++) @@ -2058,7 +2060,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab //计算yPos的值加上topSpace + rect.size.height + bottomSpace 的值要小于整体的高度。 maxHeight= yPos + topSpace + rect.size.height + bottomSpace; - if (arrangedIndex != 0) + if (itemIndex != 0) maxHeight += vertSpace; maxHeight += paddingBottom; @@ -2069,19 +2071,19 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab yPos = paddingTop; xPos += horzSpace; - xPos += colMaxWidth; + xPos += lineMaxWidth; - [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:lineIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + [self myCalcHorzLayoutSingleline:lineIndex horzAlignment:horzAlign vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; - colMaxWidth = 0.0; - colMaxHeight = 0.0; - arrangedIndex = 0; + lineMaxWidth = 0.0; + lineMaxHeight = 0.0; + itemIndex = 0; lineIndex++; } - if (arrangedIndex != 0) + if (itemIndex != 0) yPos += vertSpace; @@ -2089,17 +2091,17 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab rect.origin.y = yPos + topSpace; yPos += topSpace + rect.size.height + bottomSpace; - if (_myCGFloatLess(colMaxWidth, leadingSpace + trailingSpace + rect.size.width)) - colMaxWidth = leadingSpace + trailingSpace + rect.size.width; + if (_myCGFloatLess(lineMaxWidth, leadingSpace + trailingSpace + rect.size.width)) + lineMaxWidth = leadingSpace + trailingSpace + rect.size.width; - if (_myCGFloatLess(colMaxHeight, (yPos - paddingTop))) - colMaxHeight = (yPos - paddingTop); + if (_myCGFloatLess(lineMaxHeight, (yPos - paddingTop))) + lineMaxHeight = (yPos - paddingTop); sbvmyFrame.frame = rect; - arrangedIndex++; + itemIndex++; } - xPos += colMaxWidth + paddingTrailing; + xPos += lineMaxWidth + paddingTrailing; if (lsc.heightSizeInner.dimeWrapVal) selfSize.height = maxHeight; @@ -2111,10 +2113,10 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab NSInteger arranges = lineFirstSubviewIndexSet.count; //根据flex规则:如果只有一列则整个宽度都作为子视图的拉伸和停靠区域。 if (lsc.isFlex && arranges == 1) - colMaxWidth = selfSize.width - paddingHorz; + lineMaxWidth = selfSize.width - paddingHorz; - //最后一列 - [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:lineIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:0 vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; + //最后一行 + [self myCalcHorzLayoutSingleline:lineIndex horzAlignment:horzAlign vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; //整体的停靠 if (horzGravity != MyGravity_None && selfSize.width != xPos) @@ -2227,7 +2229,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; - MyGravity horzAlign = [self myConvertLeftRightGravityToLeadingTrailing:lsc.arrangedGravity & MyGravity_Vert_Mask]; + MyGravity horzAlignment = [self myConvertLeftRightGravityToLeadingTrailing:lsc.arrangedGravity & MyGravity_Vert_Mask]; CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; @@ -2235,8 +2237,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; - CGFloat colMaxWidth = 0.0; //每一列的最大宽度 - CGFloat colMaxHeight = 0.0; //每一列的最大高度 + CGFloat lineMaxWidth = 0.0; //每一列的最大宽度 + CGFloat lineMaxHeight = 0.0; //每一列的最大高度 CGFloat maxHeight = paddingTop; //全列的最大高度 CGFloat maxWidth = paddingLeading; //最大的宽度。 @@ -2294,34 +2296,34 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray if (vertGravity == MyGravity_Vert_Fill) averageHeight = (selfSize.height - paddingVert - (arrangedCount - 1) * vertSpace) / arrangedCount; - NSInteger arrangedIndex = 0; + NSInteger itemIndex = 0; NSInteger i = 0; - CGFloat colTotalShrink = 0.0; //某一行的总压缩比重。 - CGFloat colTotalWeight = 0.0; - CGFloat colTotalFixedHeight = 0.0; + CGFloat lineTotalShrink = 0.0; //某一行的总压缩比重。 + CGFloat lineTotalWeight = 0.0; + CGFloat lineTotalFixedHeight = 0.0; for (; i < sbs.count; i++) { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (arrangedIndex >= arrangedCount) + if (itemIndex >= arrangedCount) { - arrangedIndex = 0; + itemIndex = 0; - if (colTotalWeight != 0 && vertGravity != MyGravity_Vert_Fill) + if (lineTotalWeight != 0 && vertGravity != MyGravity_Vert_Fill) { - [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedCount lsc:lsc]; + [self myCalcHorzLayoutSinglelineWeight:lineTotalWeight lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount lsc:lsc inSelfSize:selfSize]; } - if (colTotalShrink != 0 && vertGravity != MyGravity_Vert_Fill) + if (lineTotalShrink != 0 && vertGravity != MyGravity_Vert_Fill) { - [self myCalcHorzLayoutSinglelineHeightShrink:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalShrink:colTotalShrink sbs:sbs startIndex:i count:arrangedCount lsc:lsc]; + [self myCalcHorzLayoutSinglelineShrink:lineTotalShrink lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount lsc:lsc inSelfSize:selfSize]; } - colTotalWeight = 0.0; - colTotalFixedHeight = 0.0; - colTotalShrink = 0.0; + lineTotalWeight = 0.0; + lineTotalFixedHeight = 0.0; + lineTotalShrink = 0.0; } @@ -2383,33 +2385,33 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray if (sbvsc.weight != 0) - colTotalWeight += sbvsc.weight; + lineTotalWeight += sbvsc.weight; //计算总的压缩比 - colTotalShrink += sbvsc.topPosInner.shrink + sbvsc.bottomPosInner.shrink; - colTotalShrink += sbvsc.heightSizeInner.shrink; + lineTotalShrink += sbvsc.topPosInner.shrink + sbvsc.bottomPosInner.shrink; + lineTotalShrink += sbvsc.heightSizeInner.shrink; - colTotalFixedHeight += rect.size.height; - colTotalFixedHeight += topSpace + bottomSpace; - if (arrangedIndex != (arrangedCount - 1)) - colTotalFixedHeight += vertSpace; + lineTotalFixedHeight += rect.size.height; + lineTotalFixedHeight += topSpace + bottomSpace; + if (itemIndex != (arrangedCount - 1)) + lineTotalFixedHeight += vertSpace; sbvmyFrame.frame = rect; - arrangedIndex++; + itemIndex++; } //最后一行。 - if (arrangedIndex < arrangedCount) - colTotalFixedHeight -= vertSpace; + if (itemIndex < arrangedCount) + lineTotalFixedHeight -= vertSpace; - if (colTotalWeight != 0.0 && vertGravity != MyGravity_Vert_Fill) + if (lineTotalWeight != 0.0 && vertGravity != MyGravity_Vert_Fill) { - [self myCalcHorzLayoutSinglelineWeight:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalWeight:colTotalWeight sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; + [self myCalcHorzLayoutSinglelineWeight:lineTotalWeight lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; } - if (colTotalShrink != 0.0 && vertGravity != MyGravity_Vert_Fill) + if (lineTotalShrink != 0.0 && vertGravity != MyGravity_Vert_Fill) { - [self myCalcHorzLayoutSinglelineHeightShrink:selfSize totalFloatHeight:selfSize.height - paddingVert - colTotalFixedHeight totalShrink:colTotalShrink sbs:sbs startIndex:i count:arrangedIndex lsc:lsc]; + [self myCalcHorzLayoutSinglelineShrink:lineTotalShrink lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; } //初始化每行的下一个子视图的位置。 @@ -2423,10 +2425,10 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray } } - NSInteger colIndex = 0; + NSInteger lineIndex = 0; CGFloat pageHeight = 0.0; //页高 - arrangedIndex = 0; - colTotalShrink = 0.0; + itemIndex = 0; + lineTotalShrink = 0.0; i = 0; for (; i < sbs.count; i++) { @@ -2434,13 +2436,14 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (arrangedIndex >= arrangedCount) + if (itemIndex >= arrangedCount) { - arrangedIndex = 0; + itemIndex = 0; xPos += horzSpace; - xPos += colMaxWidth; + xPos += lineMaxWidth; + + [self myCalcHorzLayoutSingleline:lineIndex horzAlignment:horzAlignment vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; - [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc];; //分别处理水平分页和垂直分页。 if (isVertPaging) @@ -2472,10 +2475,10 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray yPos = paddingTop + pageHeight; - colMaxWidth = 0.0; - colMaxHeight = 0.0; - colTotalShrink = 0.0; - colIndex++; + lineMaxWidth = 0.0; + lineMaxHeight = 0.0; + lineTotalShrink = 0.0; + lineIndex++; } CGFloat topSpace = sbvsc.topPosInner.absVal; @@ -2485,8 +2488,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray CGRect rect = sbvmyFrame.frame; //得到最大的列宽 - if (_myCGFloatLess(colMaxWidth, leadingSpace + trailingSpace + rect.size.width)) - colMaxWidth = leadingSpace + trailingSpace + rect.size.width; + if (_myCGFloatLess(lineMaxWidth, leadingSpace + trailingSpace + rect.size.width)) + lineMaxWidth = leadingSpace + trailingSpace + rect.size.width; //自动排列。 if (autoArrange) @@ -2521,7 +2524,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray maxWidth = xPos + leadingSpace + rect.size.width + trailingSpace; } - else if (horzAlign == MyGravity_Horz_Between) + else if (horzAlignment == MyGravity_Horz_Between) { //当列是紧凑排列时需要特殊处理当前的水平位置。 //第0列特殊处理。 if (i - arrangedCount < 0) @@ -2544,7 +2547,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray else {//正常排列。 //这里的最大其实就是最后一个视图的位置加上最宽的子视图的尺寸。 - maxWidth = xPos + colMaxWidth; + maxWidth = xPos + lineMaxWidth; } rect.origin.x = xPos + leadingSpace; @@ -2552,22 +2555,22 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray yPos += topSpace + rect.size.height + bottomSpace; //不是最后一行以及非自动排列时才添加布局视图设置的行间距。自动排列的情况下上面已经有添加行间距了。 - if (arrangedIndex != (arrangedCount - 1) && !autoArrange) + if (itemIndex != (arrangedCount - 1) && !autoArrange) yPos += vertSpace; - if (_myCGFloatLess(colMaxHeight, (yPos - paddingTop))) - colMaxHeight = yPos - paddingTop; + if (_myCGFloatLess(lineMaxHeight, (yPos - paddingTop))) + lineMaxHeight = yPos - paddingTop; if (_myCGFloatLess(maxHeight, yPos)) maxHeight = yPos; sbvmyFrame.frame = rect; - arrangedIndex++; + itemIndex++; //这里只对间距进行压缩比重的计算。 - colTotalShrink += sbvsc.topPosInner.shrink + sbvsc.bottomPosInner.shrink; + lineTotalShrink += sbvsc.topPosInner.shrink + sbvsc.bottomPosInner.shrink; } @@ -2593,10 +2596,11 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray NSInteger arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); //行数 //根据flex规则:如果只有一行则整个高度都作为子视图的拉伸和停靠区域。 if (lsc.isFlex && arranges == 1) - colMaxWidth = selfSize.width - paddingHorz; + lineMaxWidth = selfSize.width - paddingHorz; + + //最后一行 + [self myCalcHorzLayoutSingleline:lineIndex horzAlignment:horzAlignment vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; - //最后一列 - [self myCalcHorzLayoutSinglelineAlignment:selfSize colIndex:colIndex colMaxWidth:colMaxWidth colMaxHeight:colMaxHeight colTotalShrink:colTotalShrink vertGravity:vertGravity horzAlignment:horzAlign sbs:sbs startIndex:i count:arrangedIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc]; //整体的停靠。 if (horzGravity != MyGravity_None && selfSize.width != maxWidth && !(isHorzPaging && isPagingScroll)) @@ -2658,7 +2662,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray //因为每行都增加了fill。所以如果有行内对齐则需要这里调整。 MyGravity sbvHorzAlignment = [self myConvertLeftRightGravityToLeadingTrailing:sbvsc.alignment & MyGravity_Vert_Mask]; if (sbvHorzAlignment == MyGravity_None) - sbvHorzAlignment = horzAlign; + sbvHorzAlignment = horzAlignment; if (sbvHorzAlignment == MyGravity_Horz_Center) sbvmyFrame.leading += fill/2.0; diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 5170d43..bd0919b 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -526,7 +526,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l BOOL isWeightShrinkSpace = NO; //是否按比重缩小间距。 CGFloat weightShrinkSpaceTotalHeight = 0; - CGFloat floatingHeight = selfSize.height - fixedHeight - paddingVert; //剩余的可浮动的高度,那些weight不为0的从这个高度来进行分发 + CGFloat spareHeight = selfSize.height - fixedHeight - paddingVert; //剩余的可浮动的高度,那些weight不为0的从这个高度来进行分发 //取出shrinkType中的模式和内容类型: MySubviewsShrinkType sstMode = lsc.shrinkType & 0x0F; //压缩的模式 MySubviewsShrinkType sstContent = lsc.shrinkType & 0xF0; //压缩内容 @@ -535,17 +535,17 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l if (totalShrink != 0.0) sstMode = MySubviewsShrink_None; - if (_myCGFloatLessOrEqual(floatingHeight, 0)) + if (_myCGFloatLessOrEqual(spareHeight, 0)) { if (sstMode != MySubviewsShrink_None) { if (sstContent == MySubviewsShrink_Size) {//压缩尺寸 - if (fixedSizeSbs.count > 0 && floatingHeight < 0 && selfSize.height > 0) + if (fixedSizeSbs.count > 0 && spareHeight < 0 && selfSize.height > 0) { if (sstMode == MySubviewsShrink_Average) {//均分。 - CGFloat averageHeight = floatingHeight / fixedSizeSbs.count; + CGFloat averageHeight = spareHeight / fixedSizeSbs.count; for (UIView *fsbv in fixedSizeSbs) { @@ -556,7 +556,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l {//按比例分配。 for (UIView *fsbv in fixedSizeSbs) { - fsbv.myFrame.height += floatingHeight * (fsbv.myFrame.height / fixedSizeHeight); + fsbv.myFrame.height += spareHeight * (fsbv.myFrame.height / fixedSizeHeight); } } @@ -564,16 +564,16 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } else if (sstContent == MySubviewsShrink_Space) {//压缩间距 - if (fixedSpaceCount > 0 && floatingHeight < 0 && selfSize.height > 0 && fixedSpaceHeight > 0) + if (fixedSpaceCount > 0 && spareHeight < 0 && selfSize.height > 0 && fixedSpaceHeight > 0) { if (sstMode == MySubviewsShrink_Average) { - addSpace = floatingHeight / fixedSpaceCount; + addSpace = spareHeight / fixedSpaceCount; } else if (sstMode == MySubviewsShrink_Weight) { isWeightShrinkSpace = YES; - weightShrinkSpaceTotalHeight = floatingHeight; + weightShrinkSpaceTotalHeight = spareHeight; } } @@ -586,7 +586,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } if (totalShrink == 0.0) - floatingHeight = 0.0; + spareHeight = 0.0; } else { @@ -601,7 +601,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } //如果有浮动尺寸或者有压缩模式 - if (totalWeight != 0.0 || totalShrink != 0.0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingHeight, 0)) || vertGravity != MyGravity_None || lsc.widthSizeInner.dimeWrapVal) + if (totalWeight != 0.0 || totalShrink != 0.0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(spareHeight, 0)) || vertGravity != MyGravity_None || lsc.widthSizeInner.dimeWrapVal) { maxSelfWidth = 0.0; CGFloat between = 0.0; //间距扩充 @@ -670,7 +670,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l if ([self myIsRelativePos:topSpace]) { CGFloat topSpaceWeight = topSpace; - topSpace = _myCGFloatRound((topSpaceWeight / totalWeight) * floatingHeight); + topSpace = _myCGFloatRound((topSpaceWeight / totalWeight) * spareHeight); if (_myCGFloatLessOrEqual(topSpace, 0)) topSpace = 0; } @@ -690,7 +690,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l topSpace += sbvsc.topPosInner.offsetVal; if (totalShrink != 0.0 && sbvsc.topPosInner.shrink != 0.0) { - topSpace += (sbvsc.topPosInner.shrink / totalShrink) * floatingHeight; + topSpace += (sbvsc.topPosInner.shrink / totalShrink) * spareHeight; } pos += [self myValidMargin:sbvsc.topPosInner sbv:sbv calcPos:topSpace selfLayoutSize:selfSize]; @@ -699,7 +699,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l //分别处理相对高度和绝对高度 if (weight != 0) { - CGFloat h = _myCGFloatRound((weight / totalWeight) * floatingHeight); + CGFloat h = _myCGFloatRound((weight / totalWeight) * spareHeight); if (_myCGFloatLessOrEqual(h, 0)) h = 0; @@ -712,7 +712,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l if (totalShrink != 0.0 && sbvsc.heightSizeInner.shrink != 0.0) { - rect.size.height += (sbvsc.heightSizeInner.shrink / totalShrink) * floatingHeight; + rect.size.height += (sbvsc.heightSizeInner.shrink / totalShrink) * spareHeight; if (rect.size.height < 0.0) rect.size.height = 0.0; } @@ -745,7 +745,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l if ([self myIsRelativePos:bottomSpace]) { CGFloat bottomSpaceWeight = bottomSpace; - bottomSpace = _myCGFloatRound((bottomSpaceWeight / totalWeight) * floatingHeight); + bottomSpace = _myCGFloatRound((bottomSpaceWeight / totalWeight) * spareHeight); if ( _myCGFloatLessOrEqual(bottomSpace, 0)) bottomSpace = 0; } @@ -765,7 +765,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l bottomSpace += sbvsc.bottomPosInner.offsetVal; if (totalShrink != 0.0 && sbvsc.bottomPosInner.shrink != 0.0) { - bottomSpace += (sbvsc.bottomPosInner.shrink / totalShrink) * floatingHeight; + bottomSpace += (sbvsc.bottomPosInner.shrink / totalShrink) * spareHeight; } pos += [self myValidMargin:sbvsc.bottomPosInner sbv:sbv calcPos:bottomSpace selfLayoutSize:selfSize]; @@ -1035,7 +1035,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l //剩余的可浮动的宽度,那些weight不为0的从这个宽度来进行分发 BOOL isWeightShrinkSpace = NO; //是否按比重缩小间距。。。 CGFloat weightShrinkSpaceTotalWidth = 0.0; - CGFloat floatingWidth = selfSize.width - fixedWidth - paddingHorz; + CGFloat spareWidth = selfSize.width - fixedWidth - paddingHorz; //取出shrinkType中的模式和内容类型: MySubviewsShrinkType sstMode = lsc.shrinkType & 0x0F; //压缩的模式 MySubviewsShrinkType sstContent = lsc.shrinkType & 0xF0; //压缩内容 @@ -1044,7 +1044,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l if (totalShrink != 0.0) sstMode = MySubviewsShrink_None; - if (_myCGFloatLessOrEqual(floatingWidth, 0.0)) + if (_myCGFloatLessOrEqual(spareWidth, 0.0)) { //如果压缩方式为自动,但是浮动宽度子视图数量不为2则压缩类型无效。 if (sstMode == MySubviewsShrink_Auto && flexedSizeSbs.count != 2) @@ -1054,12 +1054,12 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l { if (sstContent == MySubviewsShrink_Size) { - if (fixedSizeSbs.count > 0 && floatingWidth < 0 && selfSize.width > 0) + if (fixedSizeSbs.count > 0 && spareWidth < 0 && selfSize.width > 0) { //均分。 if (sstMode == MySubviewsShrink_Average) { - CGFloat averageWidth = floatingWidth / fixedSizeSbs.count; + CGFloat averageWidth = spareWidth / fixedSizeSbs.count; for (UIView *fsbv in fixedSizeSbs) { @@ -1079,7 +1079,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l //如果2个都超过一半则总是一半显示。 //如果1个超过了一半则 如果两个没有超过总宽度则正常显示,如果超过了总宽度则超过一半的视图的宽度等于总宽度减去未超过一半的视图的宽度。 //如果没有一个超过一半。则正常显示 - CGFloat layoutWidth = floatingWidth + leadingWidth + trailingWidth; + CGFloat layoutWidth = spareWidth + leadingWidth + trailingWidth; CGFloat halfLayoutWidth = layoutWidth / 2; if (_myCGFloatGreat(leadingWidth, halfLayoutWidth) && _myCGFloatGreat(trailingWidth,halfLayoutWidth)) @@ -1108,23 +1108,23 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l {//按比例分配。 for (UIView *fsbv in fixedSizeSbs) { - fsbv.myFrame.width += floatingWidth * (fsbv.myFrame.width / fixedSizeWidth); + fsbv.myFrame.width += spareWidth * (fsbv.myFrame.width / fixedSizeWidth); } } } } else if (sstContent == MySubviewsShrink_Space) { - if (fixedSpaceCount > 0 && floatingWidth < 0 && selfSize.width > 0 && fixedSpaceWidth > 0) + if (fixedSpaceCount > 0 && spareWidth < 0 && selfSize.width > 0 && fixedSpaceWidth > 0) { if (sstMode == MySubviewsShrink_Average) { - addSpace = floatingWidth / fixedSpaceCount; + addSpace = spareWidth / fixedSpaceCount; } else if (sstMode == MySubviewsShrink_Weight) { isWeightShrinkSpace = YES; - weightShrinkSpaceTotalWidth = floatingWidth; + weightShrinkSpaceTotalWidth = spareWidth; } } } @@ -1135,7 +1135,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } if (totalShrink == 0.0) - floatingWidth = 0; + spareWidth = 0; } else { @@ -1148,7 +1148,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l fixedWidth = selfSize.width - paddingHorz; //如果有浮动尺寸或者有压缩模式 - if (totalWeight != 0.0 || totalShrink != 0.0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(floatingWidth, 0)) || horzGravity != MyGravity_None || lsc.heightSizeInner.dimeWrapVal) + if (totalWeight != 0.0 || totalShrink != 0.0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(spareWidth, 0)) || horzGravity != MyGravity_None || lsc.heightSizeInner.dimeWrapVal) { maxSelfHeight = 0.0; CGFloat between = 0.0; //间距扩充 @@ -1216,7 +1216,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l if ([self myIsRelativePos:leadingSpace]) { CGFloat topSpaceWeight = leadingSpace; - leadingSpace = _myCGFloatRound((topSpaceWeight / totalWeight) * floatingWidth); + leadingSpace = _myCGFloatRound((topSpaceWeight / totalWeight) * spareWidth); if (_myCGFloatLessOrEqual(leadingSpace, 0)) leadingSpace = 0; } @@ -1236,7 +1236,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l leadingSpace += sbvsc.leadingPosInner.offsetVal; if (totalShrink != 0.0 && sbvsc.leadingPosInner.shrink != 0.0) { - leadingSpace += (sbvsc.leadingPosInner.shrink / totalShrink) * floatingWidth; + leadingSpace += (sbvsc.leadingPosInner.shrink / totalShrink) * spareWidth; } pos += [self myValidMargin:sbvsc.leadingPosInner sbv:sbv calcPos:leadingSpace selfLayoutSize:selfSize]; @@ -1245,7 +1245,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l //分别处理相对高度和绝对高度 if (weight != 0.0) { - CGFloat w = _myCGFloatRound((weight / totalWeight) * floatingWidth); + CGFloat w = _myCGFloatRound((weight / totalWeight) * spareWidth); if (_myCGFloatLessOrEqual(w, 0)) w = 0; @@ -1258,7 +1258,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l if (totalShrink != 0.0 && sbvsc.widthSizeInner.shrink != 0.0) { - rect.size.width += (sbvsc.widthSizeInner.shrink / totalShrink) * floatingWidth; + rect.size.width += (sbvsc.widthSizeInner.shrink / totalShrink) * spareWidth; if (rect.size.width < 0.0) rect.size.width = 0.0; } @@ -1292,7 +1292,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l if ([self myIsRelativePos:trailingSpace]) { CGFloat trailingSpaceWeight = trailingSpace; - trailingSpace = _myCGFloatRound((trailingSpaceWeight / totalWeight) * floatingWidth); + trailingSpace = _myCGFloatRound((trailingSpaceWeight / totalWeight) * spareWidth); if (_myCGFloatLessOrEqual(trailingSpace, 0)) trailingSpace = 0; } @@ -1311,7 +1311,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l trailingSpace += sbvsc.trailingPosInner.offsetVal; if (totalShrink != 0.0 && sbvsc.trailingPosInner.shrink != 0.0) { - trailingSpace += (sbvsc.trailingPosInner.shrink / totalShrink) * floatingWidth; + trailingSpace += (sbvsc.trailingPosInner.shrink / totalShrink) * spareWidth; } pos += [self myValidMargin:sbvsc.trailingPosInner sbv:sbv calcPos:trailingSpace selfLayoutSize:selfSize]; From 297e26b928a2f7319e207687c284d2b15b914b82 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Wed, 30 Oct 2019 20:15:18 +0800 Subject: [PATCH 070/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyRelativeLayout.m | 23 +++++++++++++-------- MyLayoutDemo/AllTestExampleViewController.m | 7 ++----- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index bf9ef6e..ac8658e 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -65,13 +65,6 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbvmyFrame.multiple) sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass myFrame:sbvmyFrame]; } - else - { - if (sbvsc.widthSizeInner.dimeWrapVal) - sbvmyFrame.width = sbv.bounds.size.width; - if (sbvsc.heightSizeInner.dimeWrapVal) - sbvmyFrame.height = sbv.bounds.size.height; - } } } } @@ -738,7 +731,13 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } - else; + else if (sbvsc.widthSizeInner.dimeWrapVal) + { + if ([sbv isKindOfClass:[MyBaseLayout class]]) + { + sbvmyFrame.width = sbv.bounds.size.width; + } + } if ([self myIsNoLayoutSubview:sbv]) { @@ -853,7 +852,13 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } - else; + else if (sbvsc.heightSizeInner.dimeWrapVal) + { + if ([sbv isKindOfClass:[MyBaseLayout class]]) + { + sbvmyFrame.height = sbv.bounds.size.height; + } + } if ([self myIsNoLayoutSubview:sbv]) { diff --git a/MyLayoutDemo/AllTestExampleViewController.m b/MyLayoutDemo/AllTestExampleViewController.m index d8ffe81..fb3155c 100644 --- a/MyLayoutDemo/AllTestExampleViewController.m +++ b/MyLayoutDemo/AllTestExampleViewController.m @@ -202,8 +202,6 @@ -(void)example4 [_rootLayout addSubview:topLayout]; - return; - UILabel *topLable = [UILabel new]; topLable.text = @"宿州学院-皁阳火车站"; topLable.myTop = 0; @@ -211,7 +209,7 @@ -(void)example4 topLable.wrapContentSize = YES; [topLayout addSubview:topLable]; - + UIButton *checkMarkBtn = [UIButton new]; [checkMarkBtn setImage:[UIImage imageNamed:@"train_progresscomplete"] forState:(UIControlStateNormal)]; @@ -220,8 +218,7 @@ -(void)example4 checkMarkBtn.rightPos.equalTo(@(10)); checkMarkBtn.centerYPos.equalTo(@(0)); [_rootLayout addSubview:checkMarkBtn]; - - + UILabel *contentLabel = [UILabel new]; contentLabel.text = @"途径:蒙城、嘎县、阜阳师范学院、嘎县、阜阳师范学院、嘎县、阜阳师范学院"; contentLabel.myLeft = 11; From c1a6654aad378d1a9f30f3895f547d8ea5c7422a Mon Sep 17 00:00:00 2001 From: youngsoft Date: Fri, 1 Nov 2019 09:45:29 +0800 Subject: [PATCH 071/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 22 ++----- MyLayout/Lib/MyRelativeLayout.m | 104 +++++++++++++++++--------------- 2 files changed, 60 insertions(+), 66 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 23803ae..60d60d5 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -1196,7 +1196,7 @@ -(void)setBackgroundImage:(UIImage *)backgroundImage --(CGSize)myEstimateLayoutRect:(CGSize)size inSizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs +-(CGSize)myEstimateLayoutSize:(CGSize)size inSizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { MyFrame *selfMyFrame = self.myFrame; @@ -1258,7 +1258,7 @@ -(CGRect)subview:(UIView*)subview estimatedRectInLayoutSize:(CGSize)size NSMutableArray *sbs = [self myGetLayoutSubviews]; [sbs addObject:subview]; - [self myEstimateLayoutRect:size inSizeClass:MySizeClass_wAny | MySizeClass_hAny sbs:sbs]; + [self myEstimateLayoutSize:size inSizeClass:MySizeClass_wAny | MySizeClass_hAny sbs:sbs]; return [subview estimatedRect]; } @@ -1382,7 +1382,6 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIView*)object change:(NSDictionary *)change context:(void *)context { - //监控非布局父视图的frame的变化,而改变自身的位置和尺寸 if (context == _myObserverContextC) { @@ -1399,36 +1398,23 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIView*)object chan //监控子视图的frame的变化以便重新进行布局 if (!_isMyLayouting) { - if (context == _myObserverContextA) { [self setNeedsLayout]; //这里添加的原因是有可能子视图取消隐藏后不会绘制自身,所以这里要求子视图重新绘制自身 if ([keyPath isEqualToString:@"hidden"] && ![change[NSKeyValueChangeNewKey] boolValue]) - { [(UIView*)object setNeedsDisplay]; - } } else if (context == _myObserverContextB) {//针对UILabel特殊处理。。 UIView *sbvsc = object.myCurrentSizeClass; - - //这是什么意思? 这就是不注释的悲剧!!! - // if (sbvsc.widthSizeInner.dimeWrapVal && sbvsc.heightSizeInner.dimeWrapVal) - // { - // [self setNeedsLayout]; - // } - if (sbvsc.widthSizeInner.dimeWrapVal || sbvsc.heightSizeInner.dimeWrapVal) - { - //[object sizeToFit]; + if (sbvsc.widthSizeInner.dimeWrapVal || sbvsc.heightSizeInner.dimeWrapVal) [self setNeedsLayout]; - } } } } - #pragma mark -- Override Methods @@ -1499,7 +1485,7 @@ -(CGSize)sizeThatFits:(CGSize)size -(CGSize)sizeThatFits:(CGSize)size inSizeClass:(MySizeClass)sizeClass { - return [self myEstimateLayoutRect:size inSizeClass:sizeClass sbs:nil]; + return [self myEstimateLayoutSize:size inSizeClass:sizeClass sbs:nil]; } diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index ac8658e..16112ab 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -70,26 +70,23 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( } - BOOL reCalc = NO; - CGSize maxSize = [self myCalcLayout:&reCalc lsc:lsc selfSize:selfSize]; + BOOL reCalcWidth = NO; + BOOL reCalcHeight = NO; + CGSize maxSize = [self myCalcLayout:lsc inSelfSize:selfSize pRecalcWidth:&reCalcWidth pRecalcHeight:&reCalcHeight]; + //如果布局视图的尺寸自适应的,这里要调整一下布局视图的尺寸。但是因为有一些子视图的约束是依赖布局视图的而且可能会引发连锁反应,所以这里要再次进行重新布局处理 if (lsc.widthSizeInner.dimeWrapVal || lsc.heightSizeInner.dimeWrapVal) { if (_myCGFloatNotEqual(selfSize.height, maxSize.height) || _myCGFloatNotEqual(selfSize.width, maxSize.width)) { - if (lsc.widthSizeInner.dimeWrapVal) - { selfSize.width = maxSize.width; - } if (lsc.heightSizeInner.dimeWrapVal) - { selfSize.height = maxSize.height; - } //如果里面有需要重新计算的就重新计算布局 - if (reCalc) + if (reCalcWidth || reCalcHeight) { for (UIView *sbv in self.subviews) { @@ -97,13 +94,21 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //如果是布局视图则不清除尺寸,其他清除。 if (isEstimate && [sbv isKindOfClass:[MyBaseLayout class]]) { - sbvmyFrame.leading = sbvmyFrame.trailing = sbvmyFrame.top = sbvmyFrame.bottom = CGFLOAT_MAX; + if (reCalcWidth) + sbvmyFrame.leading = sbvmyFrame.trailing = CGFLOAT_MAX; + if (reCalcHeight) + sbvmyFrame.top = sbvmyFrame.bottom = CGFLOAT_MAX; } else - [sbvmyFrame reset]; + { + if (reCalcWidth) + sbvmyFrame.leading = sbvmyFrame.trailing = sbvmyFrame.width = CGFLOAT_MAX; + if (reCalcHeight) + sbvmyFrame.top = sbvmyFrame.bottom = sbvmyFrame.height = CGFLOAT_MAX; + } } - [self myCalcLayout:NULL lsc:lsc selfSize:selfSize]; + [self myCalcLayout:lsc inSelfSize:selfSize pRecalcWidth:NULL pRecalcHeight:NULL]; } } @@ -731,14 +736,12 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } - else if (sbvsc.widthSizeInner.dimeWrapVal) + else { - if ([sbv isKindOfClass:[MyBaseLayout class]]) - { - sbvmyFrame.width = sbv.bounds.size.width; - } + } + if ([self myIsNoLayoutSubview:sbv]) { sbvmyFrame.width = 0; @@ -852,12 +855,9 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } - else if (sbvsc.heightSizeInner.dimeWrapVal) + else { - if ([sbv isKindOfClass:[MyBaseLayout class]]) - { - sbvmyFrame.height = sbv.bounds.size.height; - } + } if ([self myIsNoLayoutSubview:sbv]) @@ -961,10 +961,12 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc } --(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize)selfSize +-(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalcWidth:(BOOL*)pRecalcWidth pRecalcHeight:(BOOL*)pRecalcHeight { - if (pRecalc != NULL) - *pRecalc = NO; + if (pRecalcWidth != NULL) + *pRecalcWidth = NO; + if (pRecalcHeight != NULL) + *pRecalcHeight = NO; //遍历所有子视图,算出所有宽度和高度根据自身内容确定的子视图的尺寸.以及计算出那些有依赖关系的尺寸限制。。。 @@ -973,7 +975,6 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; if (sbvmyFrame.width != CGFLOAT_MAX) @@ -1032,8 +1033,8 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize if (sbvsc.widthSizeInner.dimeArrVal != nil) { - if (pRecalc != NULL) - *pRecalc = YES; + if (pRecalcWidth != NULL) + *pRecalcWidth = YES; NSArray *dimeArray = sbvsc.widthSizeInner.dimeArrVal; @@ -1070,13 +1071,13 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize } - CGFloat floatingWidth = selfSize.width - lsc.myLayoutLeadingPadding - lsc.myLayoutTrailingPadding + totalAdd; - if ( _myCGFloatLessOrEqual(floatingWidth, 0)) - floatingWidth = 0; + CGFloat spareWidth = selfSize.width - lsc.myLayoutLeadingPadding - lsc.myLayoutTrailingPadding + totalAdd; + if ( _myCGFloatLessOrEqual(spareWidth, 0)) + spareWidth = 0; if (totalMulti != 0) { - CGFloat tempWidth = _myCGFloatRound(floatingWidth * (sbvsc.widthSizeInner.multiVal / totalMulti)); + CGFloat tempWidth = _myCGFloatRound(spareWidth * (sbvsc.widthSizeInner.multiVal / totalMulti)); sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:tempWidth sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; @@ -1086,7 +1087,7 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize } else { - floatingWidth -= tempWidth; + spareWidth -= tempWidth; totalMulti -= sbvsc.widthSizeInner.multiVal; } @@ -1096,8 +1097,8 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize { if (dime.dimeVal == nil) { - tempWidth = _myCGFloatRound(floatingWidth * (dime.multiVal / totalMulti)); - floatingWidth -= tempWidth; + tempWidth = _myCGFloatRound(spareWidth * (dime.multiVal / totalMulti)); + spareWidth -= tempWidth; totalMulti -= dime.multiVal; dime.view.myFrame.width = tempWidth; @@ -1115,8 +1116,8 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize if (sbvsc.heightSizeInner.dimeArrVal != nil) { - if (pRecalc != NULL) - *pRecalc = YES; + if (pRecalcHeight != NULL) + *pRecalcHeight = YES; NSArray *dimeArray = sbvsc.heightSizeInner.dimeArrVal; @@ -1149,13 +1150,13 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize } } - CGFloat floatingHeight = selfSize.height - lsc.myLayoutTopPadding - lsc.myLayoutBottomPadding + totalAdd; - if (_myCGFloatLessOrEqual(floatingHeight, 0)) - floatingHeight = 0; + CGFloat spareHeight = selfSize.height - lsc.myLayoutTopPadding - lsc.myLayoutBottomPadding + totalAdd; + if (_myCGFloatLessOrEqual(spareHeight, 0)) + spareHeight = 0; if (totalMulti != 0) { - CGFloat tempHeight = _myCGFloatRound(floatingHeight * (sbvsc.heightSizeInner.multiVal / totalMulti)); + CGFloat tempHeight = _myCGFloatRound(spareHeight * (sbvsc.heightSizeInner.multiVal / totalMulti)); sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:tempHeight sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; if ([self myIsNoLayoutSubview:sbv]) @@ -1164,7 +1165,7 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize } else { - floatingHeight -= tempHeight; + spareHeight -= tempHeight; totalMulti -= sbvsc.heightSizeInner.multiVal; } @@ -1174,8 +1175,8 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize { if (dime.dimeVal == nil) { - tempHeight = _myCGFloatRound(floatingHeight * (dime.multiVal / totalMulti)); - floatingHeight -= tempHeight; + tempHeight = _myCGFloatRound(spareHeight * (dime.multiVal / totalMulti)); + spareHeight -= tempHeight; totalMulti -= dime.multiVal; dime.view.myFrame.height = tempHeight; } @@ -1195,6 +1196,9 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize //表示视图数组水平居中 if (sbvsc.centerXPosInner.posArrVal != nil) { + if (pRecalcWidth != NULL) + *pRecalcWidth = YES; + //先算出所有关联视图的宽度。再计算出关联视图的左边和右边的绝对值。 NSArray *centerArray = sbvsc.centerXPosInner.posArrVal; @@ -1250,6 +1254,9 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize //表示视图数组垂直居中 if (sbvsc.centerYPosInner.posArrVal != nil) { + if (pRecalcHeight != NULL) + *pRecalcHeight = YES; + NSArray *centerArray = sbvsc.centerYPosInner.posArrVal; CGFloat totalHeight = 0; @@ -1329,17 +1336,18 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize continue; - if (lsc.widthSizeInner.dimeWrapVal && pRecalc != NULL) + if (lsc.widthSizeInner.dimeWrapVal && pRecalcWidth != NULL) { //当有子视图依赖于父视图的一些设置时,需要重新进行布局(设置了右边或者中间的值,或者宽度依赖父视图) if(sbvsc.trailingPosInner.posNumVal != nil || + sbvsc.trailingPosInner.posMostVal != nil || sbvsc.trailingPosInner.posRelaVal.view == self || sbvsc.centerXPosInner.posRelaVal.view == self || sbvsc.centerXPosInner.posNumVal != nil || sbvsc.widthSizeInner.dimeRelaVal.view == self ) { - *pRecalc = YES; + *pRecalcWidth = YES; } //宽度最小是任何一个子视图的左右偏移和外加内边距和。 @@ -1379,17 +1387,18 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize } } - if (lsc.heightSizeInner.dimeWrapVal && pRecalc != NULL) + if (lsc.heightSizeInner.dimeWrapVal && pRecalcHeight != NULL) { //当有子视图依赖于父视图的一些设置时,需要重新进行布局(设置了下边或者中间的值,或者高度依赖父视图) if(sbvsc.bottomPosInner.posNumVal != nil || + sbvsc.bottomPosInner.posMostVal != nil || sbvsc.bottomPosInner.posRelaVal.view == self || sbvsc.centerYPosInner.posRelaVal.view == self || sbvsc.centerYPosInner.posNumVal != nil || sbvsc.heightSizeInner.dimeRelaVal.view == self ) { - *pRecalc = YES; + *pRecalcHeight = YES; } if (_myCGFloatLess(maxHeight, sbvsc.topPosInner.absVal + sbvsc.bottomPosInner.absVal + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding)) @@ -1426,7 +1435,6 @@ -(CGSize)myCalcLayout:(BOOL*)pRecalc lsc:(MyRelativeLayout*)lsc selfSize:(CGSize if (_myCGFloatLess(maxHeight, sbvmyFrame.bottom + sbvsc.bottomPosInner.absVal + lsc.myLayoutBottomPadding)) maxHeight = sbvmyFrame.bottom + sbvsc.bottomPosInner.absVal + lsc.myLayoutBottomPadding; - } } } From 6c2cc785205084b82708887e9c15f07522d56216 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Mon, 4 Nov 2019 09:45:23 +0800 Subject: [PATCH 072/115] =?UTF-8?q?=20=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 214 +++++++++++--------- MyLayoutDemo/AllTestExampleViewController.m | 34 +++- MyLayoutDemo/LLTest7ViewController.m | 1 - 3 files changed, 151 insertions(+), 98 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 60d60d5..c1219f9 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -1195,54 +1195,6 @@ -(void)setBackgroundImage:(UIImage *)backgroundImage } - --(CGSize)myEstimateLayoutSize:(CGSize)size inSizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs -{ - MyFrame *selfMyFrame = self.myFrame; - - if (selfMyFrame.multiple) - selfMyFrame.sizeClass = [self myBestSizeClass:sizeClass myFrame:selfMyFrame]; - - for (UIView *sbv in self.subviews) - { - MyFrame *sbvmyFrame = sbv.myFrame; - if (sbvmyFrame.multiple) - sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass myFrame:sbvmyFrame]; - } - - BOOL hasSubLayout = NO; - CGSize selfSize= [self calcLayoutSize:size isEstimate:NO pHasSubLayout:&hasSubLayout sizeClass:sizeClass sbs:sbs]; - - if (hasSubLayout) - { - selfMyFrame.width = selfSize.width; - selfMyFrame.height = selfSize.height; - - selfSize = [self calcLayoutSize:CGSizeZero isEstimate:YES pHasSubLayout:&hasSubLayout sizeClass:sizeClass sbs:sbs]; - } - - selfMyFrame.width = selfSize.width; - selfMyFrame.height = selfSize.height; - - - - //计算后还原为默认sizeClass - for (UIView *sbv in self.subviews) - { - MyFrame *sbvmyFrame = sbv.myFrame; - if (sbvmyFrame.multiple) - sbvmyFrame.sizeClass = self.myDefaultSizeClass; - } - - if (selfMyFrame.multiple) - selfMyFrame.sizeClass = self.myDefaultSizeClass; - - if (self.cacheEstimatedRect) - _useCacheRects = YES; - - return CGSizeMake(_myCGFloatRound(selfSize.width), _myCGFloatRound(selfSize.height)); -} - -(void)setCacheEstimatedRect:(BOOL)cacheEstimatedRect { _cacheEstimatedRect = cacheEstimatedRect; @@ -1350,7 +1302,6 @@ -(MyLayoutDragger*)createLayoutDragger - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - [_touchEventDelegate touchesBegan:touches withEvent:event]; [super touchesBegan:touches withEvent:event]; @@ -1495,20 +1446,40 @@ -(void)setHidden:(BOOL)hidden return; [super setHidden:hidden]; - if (hidden == NO) + UIView *superview = self.superview; + if ([superview isKindOfClass:[MyBaseLayout class]]) { - + if (!((MyBaseLayout*)superview).isMyLayouting) + [superview setNeedsLayout]; + } + + if (hidden == NO) [_borderlineLayerDelegate setNeedsLayoutIn:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height) withLayer:self.layer]; - - if ([self.superview isKindOfClass:[MyBaseLayout class]]) - { - [self setNeedsLayout]; - } - +} + +-(void)setCenter:(CGPoint)center +{ + CGPoint oldCenter = self.center; + [super setCenter:center]; + UIView *superview = self.superview; + if (!CGPointEqualToPoint(oldCenter, center) && [superview isKindOfClass:[MyBaseLayout class]]) + { + if (!((MyBaseLayout*)superview).isMyLayouting) + [superview setNeedsLayout]; } - } +-(void)setFrame:(CGRect)frame +{ + CGRect oldFrame = self.frame; + [super setFrame:frame]; + UIView *superview = self.superview; + if (!CGRectEqualToRect(oldFrame, frame) && [superview isKindOfClass:[MyBaseLayout class]]) + { + if (!((MyBaseLayout*)superview).isMyLayouting) + [superview setNeedsLayout]; + } +} - (void)didAddSubview:(UIView *)subview @@ -1667,8 +1638,6 @@ - (void)willMoveToSuperview:(UIView*)newSuperview @finally { } - - } [newSuperview addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:_myObserverContextC]; @@ -1706,8 +1675,6 @@ - (void)willMoveToSuperview:(UIView*)newSuperview @finally { } - - } @@ -1737,8 +1704,6 @@ - (void)willMoveToSuperview:(UIView*)newSuperview self.beginLayoutBlock = nil; self.endLayoutBlock = nil; } - - } @@ -1783,7 +1748,6 @@ -(void)setNeedsLayout -(CGSize)intrinsicContentSize { - CGSize sz = [super intrinsicContentSize]; if (self.translatesAutoresizingMaskIntoConstraints == NO && (self.widthSizeInner.dimeWrapVal || self.heightSizeInner.dimeWrapVal)) { @@ -2016,7 +1980,6 @@ -(void)layoutSubviews if (_myCGFloatErrorEqual(sbvTempCenter.y, sbvOldCenter.y, sSizeError)) sbvTempCenter.y = sbvOldCenter.y; - if (_myCGFloatErrorNotEqual(sbvTempCenter.x, sbvOldCenter.x, sSizeError)|| _myCGFloatErrorNotEqual(sbvTempCenter.y, sbvOldCenter.y, sSizeError)) sbv.center = sbvTempCenter; @@ -2278,6 +2241,56 @@ -(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection +-(CGSize)myEstimateLayoutSize:(CGSize)size inSizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs +{ + MyFrame *selfMyFrame = self.myFrame; + + if (selfMyFrame.multiple) + selfMyFrame.sizeClass = [self myBestSizeClass:sizeClass myFrame:selfMyFrame]; + + for (UIView *sbv in self.subviews) + { + MyFrame *sbvmyFrame = sbv.myFrame; + if (sbvmyFrame.multiple) + sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass myFrame:sbvmyFrame]; + } + + //因为子布局会调用layoutSubviews来进行自身的布局,所以在非评估模式下对于尺寸自适应的子布局不应该调用sizeThatFit方法来获取尺寸。 + BOOL hasWrapSizeSubLayout = NO; + CGSize selfSize= [self calcLayoutSize:size isEstimate:NO pHasSubLayout:&hasWrapSizeSubLayout sizeClass:sizeClass sbs:sbs]; + + if (hasWrapSizeSubLayout) + { + selfMyFrame.width = selfSize.width; + selfMyFrame.height = selfSize.height; + + selfSize = [self calcLayoutSize:CGSizeZero isEstimate:YES pHasSubLayout:&hasWrapSizeSubLayout sizeClass:sizeClass sbs:sbs]; + } + + selfMyFrame.width = selfSize.width; + selfMyFrame.height = selfSize.height; + + + + //计算后还原为默认sizeClass + for (UIView *sbv in self.subviews) + { + MyFrame *sbvmyFrame = sbv.myFrame; + if (sbvmyFrame.multiple) + sbvmyFrame.sizeClass = self.myDefaultSizeClass; + } + + if (selfMyFrame.multiple) + selfMyFrame.sizeClass = self.myDefaultSizeClass; + + if (self.cacheEstimatedRect) + _useCacheRects = YES; + + return CGSizeMake(_myCGFloatRound(selfSize.width), _myCGFloatRound(selfSize.height)); +} + + + -(BOOL)myIsRelativePos:(CGFloat)margin { return margin > 0 && margin < 1; @@ -3349,30 +3362,32 @@ -(MySizeClass)myGetGlobalSizeClass -(void)myRemoveSubviewObserver:(UIView*)subview { - MyFrame *sbvmyFrame = objc_getAssociatedObject(subview, ASSOCIATEDOBJECT_KEY_MYLAYOUT_FRAME); if (sbvmyFrame != nil) { sbvmyFrame.sizeClass.viewLayoutCompleteBlock = nil; if (sbvmyFrame.hasObserver) { - [subview removeObserver:self forKeyPath:@"hidden"]; - [subview removeObserver:self forKeyPath:@"frame"]; - - //有时候我们可能会把滚动视图加入到布局视图中去,滚动视图的尺寸有可能设置为wrapContent,这样就会调整center。从而需要重新激发滚动视图的布局 - //这也就是为什么只监听center的原因了。布局子视图也是如此。 - if ([subview isKindOfClass:[MyBaseLayout class]] || [subview isKindOfClass:[UIScrollView class]]) - { - [subview removeObserver:self forKeyPath:@"center"]; - } - else if ([subview isKindOfClass:[UILabel class]]) + sbvmyFrame.hasObserver = NO; + if (![subview isKindOfClass:[MyBaseLayout class]]) { - [subview removeObserver:self forKeyPath:@"text"]; - [subview removeObserver:self forKeyPath:@"attributedText"]; + [subview removeObserver:self forKeyPath:@"hidden"]; + [subview removeObserver:self forKeyPath:@"frame"]; + + if ([subview isKindOfClass:[UIScrollView class]]) + { + [subview removeObserver:self forKeyPath:@"center"]; + } + else if ([subview isKindOfClass:[UILabel class]]) + { + [subview removeObserver:self forKeyPath:@"text"]; + [subview removeObserver:self forKeyPath:@"attributedText"]; + } + else + { + + } } - else; - - sbvmyFrame.hasObserver = NO; } } } @@ -3382,23 +3397,30 @@ -(void)myAddSubviewObserver:(UIView*)subview sbvmyFrame:(MyFrame*)sbvmyFrame if (!sbvmyFrame.hasObserver) { - //添加hidden, frame,center的属性通知。 - [subview addObserver:self forKeyPath:@"hidden" options:NSKeyValueObservingOptionNew context:_myObserverContextA]; - [subview addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:_myObserverContextA]; - if ([subview isKindOfClass:[MyBaseLayout class]] || [subview isKindOfClass:[UIScrollView class]]) + sbvmyFrame.hasObserver = YES; + + //非布局子视图添加hidden, frame的属性变化通知。 + if (![subview isKindOfClass:[MyBaseLayout class]]) { - [subview addObserver:self forKeyPath:@"center" options:NSKeyValueObservingOptionNew context:_myObserverContextA]; - } - else if ([subview isKindOfClass:[UILabel class]]) - {//如果是UILabel则一旦设置了text和attributedText则 + [subview addObserver:self forKeyPath:@"hidden" options:NSKeyValueObservingOptionNew context:_myObserverContextA]; + [subview addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:_myObserverContextA]; - [subview addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:_myObserverContextB]; - [subview addObserver:self forKeyPath:@"attributedText" options:NSKeyValueObservingOptionNew context:_myObserverContextB]; + if ([subview isKindOfClass:[UIScrollView class]]) + {//如果是UIScrollView则需要特殊监听center属性 + //有时候我们可能会把滚动视图加入到布局视图中去,滚动视图的尺寸有可能设置为高度自适应,这样就会调整center。从而需要重新激发滚动视图的布局 + //这也就是为什么只监听center的原因了。 + [subview addObserver:self forKeyPath:@"center" options:NSKeyValueObservingOptionNew context:_myObserverContextA]; + } + else if ([subview isKindOfClass:[UILabel class]]) + {//如果是UILabel则监听text和attributedText属性 + [subview addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:_myObserverContextB]; + [subview addObserver:self forKeyPath:@"attributedText" options:NSKeyValueObservingOptionNew context:_myObserverContextB]; + } + else + { + + } } - else; - - sbvmyFrame.hasObserver = YES; - } } diff --git a/MyLayoutDemo/AllTestExampleViewController.m b/MyLayoutDemo/AllTestExampleViewController.m index fb3155c..a745543 100644 --- a/MyLayoutDemo/AllTestExampleViewController.m +++ b/MyLayoutDemo/AllTestExampleViewController.m @@ -26,7 +26,8 @@ - (void)viewDidLoad { // [self example1]; // [self example2]; //[self example3]; - [self example4]; + // [self example4]; + [self example5]; } - (void)didReceiveMemoryWarning { @@ -229,4 +230,35 @@ -(void)example4 [topLayout addSubview:contentLabel]; } +-(void)example5 +{ + MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + rootLayout.myHorzMargin = 0; + rootLayout.tag = 100; + [self.view addSubview:rootLayout]; + +// UIView * v = [UIView new]; +// v.mySize = CGSizeMake(100, 100); +// [rootLayout addSubview:v]; + + MyLinearLayout *v = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + v.tag = 200; + v.hidden = YES; + v.backgroundColor = [UIColor redColor]; + v.mySize = CGSizeMake(100, 100); + // v.myHorzMargin = 0; + // v.myHeight = 100; + [rootLayout addSubview:v]; + + [NSTimer scheduledTimerWithTimeInterval:30 repeats:NO block:^(NSTimer * _Nonnull timer) { + + v.hidden = NO; + +// UIView *vv1 = [UIView new]; +// vv1.mySize = CGSizeMake(100, 100); +// [v addSubview:vv1]; + + }]; +} + @end diff --git a/MyLayoutDemo/LLTest7ViewController.m b/MyLayoutDemo/LLTest7ViewController.m index a6e8cc4..4bc1553 100644 --- a/MyLayoutDemo/LLTest7ViewController.m +++ b/MyLayoutDemo/LLTest7ViewController.m @@ -124,7 +124,6 @@ -(UIButton*)createActionButton:(NSString*)title tag:(NSInteger)tag button.titleLabel.adjustsFontSizeToFitWidth = YES; button.titleLabel.textAlignment = NSTextAlignmentCenter; button.titleLabel.font = [CFTool font:14]; - [button sizeToFit]; button.heightSize.equalTo(@(MyLayoutSize.wrap)).add(20); //高度自适应外加20的 button.layer.borderColor = [UIColor lightGrayColor].CGColor; button.layer.borderWidth = 0.5; From a4e028558365509311e54e2f3951a1024354f47f Mon Sep 17 00:00:00 2001 From: youngsoft Date: Fri, 8 Nov 2019 09:44:59 +0800 Subject: [PATCH 073/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 87 +-- MyLayout/Lib/MyFloatLayout.m | 18 +- MyLayout/Lib/MyFlowLayout.m | 4 +- MyLayout/Lib/MyFrameLayout.m | 2 +- MyLayout/Lib/MyGridLayout.m | 5 +- MyLayout/Lib/MyLayoutInner.h | 4 +- MyLayout/Lib/MyLayoutPos.m | 12 +- MyLayout/Lib/MyLayoutPosInner.h | 2 +- MyLayout/Lib/MyLayoutSize.m | 10 +- MyLayout/Lib/MyLayoutSizeInner.h | 1 + MyLayout/Lib/MyLinearLayout.m | 24 +- MyLayout/Lib/MyPathLayout.m | 124 +--- MyLayout/Lib/MyRelativeLayout.m | 873 ++++++++++------------- MyLayoutTests/MyRelativeLayoutTestCase.m | 19 +- 14 files changed, 441 insertions(+), 744 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index c1219f9..b134c0a 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -2554,38 +2554,6 @@ -(CGFloat)myCalcHorzGravity:(MyGravity)horzGravity } --(void)myCalcSizeOfWrapContentSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc sbvmyFrame:(MyFrame*)sbvmyFrame -{ - if (sbvsc.visibility == MyVisibility_Gone) - { - sbvmyFrame.width = 0; - sbvmyFrame.height = 0; - return; - } - - BOOL isLayoutView = [sbv isKindOfClass:[MyBaseLayout class]]; - BOOL isWrapWidth = (!isLayoutView && sbvsc.widthSizeInner.dimeWrapVal); //宽度包裹特殊处理 - BOOL isWrapHeight = (!isLayoutView && sbvsc.heightSizeInner.dimeWrapVal);//高度包裹也特殊处理 - - - if (isWrapWidth || isWrapHeight) - { - - CGSize thatFits = CGSizeZero; - //在一些场景中,计算包裹时有可能设置了最大的尺寸约束,所以这里要进行特殊处理。 - thatFits.width = sbvsc.widthSizeInner.uBoundValInner.dimeNumVal.doubleValue; - thatFits.height = sbvsc.heightSizeInner.uBoundValInner.dimeNumVal.doubleValue; - - CGSize fitSize = [sbv sizeThatFits:thatFits]; - if (isWrapWidth) - sbvmyFrame.width = [sbvsc.widthSizeInner measureWith:fitSize.width]; - - if (isWrapHeight) - sbvmyFrame.height = [sbvsc.heightSizeInner measureWith:fitSize.height]; - } -} - - -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize)size { if (newSuperview == nil || [newSuperview isKindOfClass:[MyBaseLayout class]]) @@ -2724,7 +2692,7 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview isAdjust = YES; //如果宽度约束的优先级很低都按左右边距来决定布局视图的宽度。 if (lsc.widthSizeInner.priority == MyPriority_Low) - [lsc.widthSizeInner __clear]; + [lsc.widthSizeInner __setActive:NO]; if (lsc.widthSizeInner.dimeVal == nil) { @@ -2822,7 +2790,7 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview isAdjust = YES; //如果高度约束优先级很低则按上下边距来决定布局视图高度。 if (lsc.heightSizeInner.priority == MyPriority_Low) - [lsc.heightSizeInner __clear]; + [lsc.heightSizeInner __setActive:NO]; if (lsc.heightSizeInner.dimeVal == nil) { @@ -2941,10 +2909,7 @@ -(CGFloat)myHeightFromFlexedHeightView:(UIView*)sbv sbvsc:(UIView*)sbvsc inWidth // do nothing... } - if (sbvsc.heightSizeInner == nil) - return h; - else - return [sbvsc.heightSizeInner measureWith:h]; + return [sbvsc.heightSizeInner measureWith:h]; } @@ -3130,7 +3095,7 @@ -(NSMutableArray*)myGetLayoutSubviewsFrom:(NSArray*)sbsFrom else [sbs addObjectsFromArray:sbsFrom]; - for (NSInteger i = sbs.count - 1; i >=0; i--) + for (NSInteger i = sbs.count - 1; i >= 0; i--) { UIView *sbv = sbs[i]; if ([self myIsNoLayoutSubview:sbv]) @@ -3425,32 +3390,30 @@ -(void)myAddSubviewObserver:(UIView*)subview sbvmyFrame:(MyFrame*)sbvmyFrame } --(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame sbvsc:(UIView*)sbvsc selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout +-(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame sbvsc:(UIView*)sbvsc selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout lsc:(MyBaseLayout*)lsc { if (!isEstimate) - { sbvmyFrame.frame = sbv.bounds; - [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; - } //只要子视图是包裹并且布局视图是fill填充,都应该清除子视图的包裹设置。 if (sbvsc.widthSizeInner.dimeWrapVal && horzGravity == MyGravity_Horz_Fill) - [sbvsc.widthSizeInner __clear]; + [sbvsc.widthSizeInner __setActive:NO]; if (sbvsc.heightSizeInner.dimeWrapVal && vertGravity == MyGravity_Vert_Fill) - [sbvsc.heightSizeInner __clear]; + [sbvsc.heightSizeInner __setActive:NO]; + if (sbvsc.leadingPosInner.posVal != nil && + sbvsc.trailingPosInner.posVal != nil && + (sbvsc.widthSizeInner.priority == MyPriority_Low || !lsc.widthSizeInner.dimeWrapVal)) + [sbvsc.widthSizeInner __setActive:NO]; + + if (sbvsc.topPosInner.posVal != nil && + sbvsc.bottomPosInner.posVal != nil && + (sbvsc.heightSizeInner.priority == MyPriority_Low || !lsc.heightSizeInner.dimeWrapVal)) + [sbvsc.heightSizeInner __setActive:NO]; + if ([sbv isKindOfClass:[MyBaseLayout class]]) { - if (sbvsc.leadingPosInner != nil && - sbvsc.trailingPosInner != nil && - sbvsc.widthSizeInner.priority == MyPriority_Low) - [sbvsc.widthSizeInner __clear]; - - if (sbvsc.topPosInner != nil && - sbvsc.bottomPosInner != nil && - sbvsc.heightSizeInner.priority == MyPriority_Low) - [sbvsc.heightSizeInner __clear]; if (pHasSubLayout != nil && (sbvsc.heightSizeInner.dimeWrapVal || sbvsc.widthSizeInner.dimeWrapVal)) *pHasSubLayout = YES; @@ -3463,7 +3426,6 @@ -(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sb sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass myFrame:sbvmyFrame]; } } - } -(CGFloat)myGetSubviewWidthSizeValue:(UIView *)sbv @@ -3503,6 +3465,11 @@ -(CGFloat)myGetSubviewWidthSizeValue:(UIView *)sbv retVal = [sbvWidthSizeInner measureWith:sbvWidthSizeInner.dimeRelaVal.view.myEstimatedHeight]; } } + else if (sbvWidthSizeInner.dimeWrapVal) + { + if (![sbv isKindOfClass:[MyBaseLayout class]]) + retVal = [sbvWidthSizeInner measureWith:[sbv sizeThatFits:CGSizeMake(0, sbvSize.height)].width]; + } return retVal; } @@ -3683,18 +3650,14 @@ -(void)myCalcSubviewsWrapContentSize:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasS MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + if (customSetting != nil) + customSetting(sbv, sbvsc); + if (!isEstimate) - { sbvmyFrame.frame = sbv.bounds; - [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; - } if ([sbv isKindOfClass:[MyBaseLayout class]]) { - - if (customSetting != nil) - customSetting(sbv, sbvsc); - BOOL isSbvWrap = sbvsc.widthSizeInner.dimeWrapVal || sbvsc.heightSizeInner.dimeWrapVal; if (pHasSubLayout != nil && isSbvWrap) diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index d6b0175..8c71803 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -132,21 +132,11 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( [self myCalcSubviewsWrapContentSize:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs withCustomSetting:^(UIView *sbv, UIView *sbvsc) { - if (sbvsc.widthSizeInner.dimeWrapVal) - { - if (orientation == MyOrientation_Vert && sbvsc.weight != 0) - { - [sbvsc.widthSizeInner __clear]; - } - } + if (sbvsc.widthSizeInner.dimeWrapVal && orientation == MyOrientation_Vert && sbvsc.weight != 0) + [sbvsc.widthSizeInner __setActive:NO]; - if (sbvsc.heightSizeInner.dimeWrapVal) - { - if (orientation == MyOrientation_Horz && sbvsc.weight != 0) - { - [sbvsc.heightSizeInner __clear]; - } - } + if (sbvsc.heightSizeInner.dimeWrapVal && orientation == MyOrientation_Horz && sbvsc.weight != 0) + [sbvsc.heightSizeInner __setActive:NO]; }]; if (orientation == MyOrientation_Vert) diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index fc5bcda..8be7db3 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -173,7 +173,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( (orientation == MyOrientation_Horz && (arrangedGravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill) || (orientation == MyOrientation_Vert && ((gravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill || sbvsc.weight != 0))) { - [sbvsc.widthSizeInner __clear]; + [sbvsc.widthSizeInner __setActive:NO]; } } @@ -183,7 +183,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( (orientation == MyOrientation_Vert && (arrangedGravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill) || (orientation == MyOrientation_Horz && ((gravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill || sbvsc.weight != 0))) { - [sbvsc.heightSizeInner __clear]; + [sbvsc.heightSizeInner __setActive:NO]; } } diff --git a/MyLayout/Lib/MyFrameLayout.m b/MyLayout/Lib/MyFrameLayout.m index e7d7bda..72271dc 100644 --- a/MyLayout/Lib/MyFrameLayout.m +++ b/MyLayout/Lib/MyFrameLayout.m @@ -52,7 +52,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - [self myAdjustSubviewWrapContentSet:sbv isEstimate:isEstimate sbvmyFrame:sbvmyFrame sbvsc:sbvsc selfSize:selfSize vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; + [self myAdjustSubviewWrapContentSet:sbv isEstimate:isEstimate sbvmyFrame:sbvmyFrame sbvsc:sbvsc selfSize:selfSize vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout lsc:lsc]; //计算自己的位置和高宽 [self myCalcSubViewRect:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame lsc:lsc vertGravity:vertGravity horzGravity:horzGravity inSelfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:pMaxWrapSize]; diff --git a/MyLayout/Lib/MyGridLayout.m b/MyLayout/Lib/MyGridLayout.m index 933a8d2..4e58db3 100644 --- a/MyLayout/Lib/MyGridLayout.m +++ b/MyLayout/Lib/MyGridLayout.m @@ -1051,7 +1051,7 @@ -(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigi //如果尺寸是0则因为前面有算出尺寸,所以这里就不进行调整了。 if (grid.measure != 0 && [sbv isKindOfClass:[MyBaseLayout class]]) { - [self myAdjustSubviewWrapContentSet:sbv isEstimate:isEstimate sbvmyFrame:sbvmyFrame sbvsc:sbvsc selfSize:grid.gridRect.size vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; + [self myAdjustSubviewWrapContentSet:sbv isEstimate:isEstimate sbvmyFrame:sbvmyFrame sbvsc:sbvsc selfSize:grid.gridRect.size vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout lsc:lsc]; } else { @@ -1317,9 +1317,6 @@ -(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc } else { - - [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; - [self myCalcSubViewRect:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame lsc:lsc vertGravity:MyGravity_None horzGravity:MyGravity_None inSelfSize:grid.gridRect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:NULL]; } diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index 51edb98..a8d2369 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -77,8 +77,6 @@ selfSize:(CGSize)selfSize pRect:(CGRect*)pRect; --(void)myCalcSizeOfWrapContentSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc sbvmyFrame:(MyFrame*)sbvmyFrame; - -(CGFloat)myHeightFromFlexedHeightView:(UIView*)sbv sbvsc:(UIView*)sbvsc inWidth:(CGFloat)width; -(CGFloat)myValidMeasure:(MyLayoutSize*)dime sbv:(UIView*)sbv calcSize:(CGFloat)calcSize sbvSize:(CGSize)sbvSize selfLayoutSize:(CGSize)selfLayoutSize; @@ -108,7 +106,7 @@ -(CGFloat)myLayoutLeadingPadding; -(CGFloat)myLayoutTrailingPadding; --(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame sbvsc:(UIView*)sbvsc selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout; +-(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame sbvsc:(UIView*)sbvsc selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout lsc:(MyBaseLayout*)lsc; //根据子视图的宽度约束得到宽度值 diff --git a/MyLayout/Lib/MyLayoutPos.m b/MyLayout/Lib/MyLayoutPos.m index 0d2ef69..a77321c 100644 --- a/MyLayout/Lib/MyLayoutPos.m +++ b/MyLayout/Lib/MyLayoutPos.m @@ -168,10 +168,8 @@ -(void)setActive:(BOOL)active { if (_active != active) { - _active = active; - _lBoundVal.active = active; - _uBoundVal.active = active; - [self setNeedsLayout]; + [self __setActive:active]; + [self setNeedsLayout]; } } @@ -551,6 +549,12 @@ -(void)__clear _shrink = 0; } +-(void)__setActive:(BOOL)active +{ + _active = active; + [_lBoundVal __setActive:active]; + [_uBoundVal __setActive:active]; +} diff --git a/MyLayout/Lib/MyLayoutPosInner.h b/MyLayout/Lib/MyLayoutPosInner.h index 9c7535f..75da7b1 100644 --- a/MyLayout/Lib/MyLayoutPosInner.h +++ b/MyLayout/Lib/MyLayoutPosInner.h @@ -44,7 +44,7 @@ -(MyLayoutPos*)__max:(CGFloat)val; -(MyLayoutPos*)__uBound:(id)posVal offsetVal:(CGFloat)offsetVal; -(void)__clear; - +-(void)__setActive:(BOOL)active; // minVal <= posNumVal + offsetVal <=maxVal . 注意这个只试用于相对布局。对于线性布局和框架布局来说,因为可以支持相对边距。 diff --git a/MyLayout/Lib/MyLayoutSize.m b/MyLayout/Lib/MyLayoutSize.m index b5c1b59..65b816f 100644 --- a/MyLayout/Lib/MyLayoutSize.m +++ b/MyLayout/Lib/MyLayoutSize.m @@ -195,9 +195,7 @@ -(void)setActive:(BOOL)active { if (_active != active) { - _active = active; - _lBoundVal.active = active; - _uBoundVal.active = active; + [self __setActive:active]; [self setNeedsLayout]; } } @@ -526,6 +524,12 @@ -(void)__clear _dimeValType = MyLayoutValueType_Nil; } +-(void)__setActive:(BOOL)active +{ + _active = active; + [_lBoundVal __setActive:active]; + [_uBoundVal __setActive:active]; +} -(CGFloat) measure diff --git a/MyLayout/Lib/MyLayoutSizeInner.h b/MyLayout/Lib/MyLayoutSizeInner.h index 9567adc..97f910f 100644 --- a/MyLayout/Lib/MyLayoutSizeInner.h +++ b/MyLayout/Lib/MyLayoutSizeInner.h @@ -53,6 +53,7 @@ -(MyLayoutSize*)__max:(CGFloat)val; -(MyLayoutSize*)__uBound:(id)sizeVal addVal:(CGFloat)addVal multiVal:(CGFloat)multiVal; -(void)__clear; +-(void)__setActive:(BOOL)active; diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index bd0919b..36fe2af 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -145,9 +145,7 @@ - (void)willRemoveSubview:(UIView *)subview { [super willRemoveSubview:subview]; if (subview == self.baselineBaseView) - { self.baselineBaseView = nil; - } } @@ -169,7 +167,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( [self myCalcSubviewsWrapContentSize:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs withCustomSetting:^(UIView *sbv, UIView *sbvsc) { - [self myAdjustSubviewWrapContent:sbv sbvsc:sbvsc orientation:orientation gravity:(orientation == MyOrientation_Vert)? horzGravity : vertGravity]; + [self myAdjustSubviewWrapContent:sbv sbvsc:sbvsc lsc:(MyLinearLayout*)lsc orientation:orientation gravity:(orientation == MyOrientation_Vert)? horzGravity : vertGravity]; }]; @@ -206,35 +204,35 @@ -(id)createSizeClassInstance #pragma mark -- Private Methods //调整子视图的wrapContent设置 -- (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc orientation:(MyOrientation)orientation gravity:(MyGravity)gravity +- (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyLinearLayout*)lsc orientation:(MyOrientation)orientation gravity:(MyGravity)gravity { if (orientation == MyOrientation_Vert) { //如果是拉伸处理则需要把包裹宽度取消。 if (sbvsc.widthSizeInner.dimeWrapVal && gravity == MyGravity_Horz_Fill) - [sbvsc.widthSizeInner __clear]; + [sbvsc.widthSizeInner __setActive:NO]; - //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 - if (sbvsc.leadingPosInner != nil && sbvsc.trailingPosInner != nil && sbvsc.widthSizeInner.priority == MyPriority_Low) - [sbvsc.widthSizeInner __clear]; + //如果同时设置了左右依赖。并且优先级低时或者布局视图不是宽度自适应则取消自视图宽度自适应,这里是为了兼容老版本。 + if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil && (sbvsc.widthSizeInner.priority == MyPriority_Low || !lsc.widthSizeInner.dimeWrapVal)) + [sbvsc.widthSizeInner __setActive:NO]; //只要同时设置了高度或者比重属性则应该把尺寸设置为空 if (sbvsc.heightSizeInner.dimeWrapVal && sbvsc.weight != 0) - [sbvsc.heightSizeInner __clear]; + [sbvsc.heightSizeInner __setActive:NO]; } else { //如果是拉伸处理则需要把包裹高度 if (sbvsc.heightSizeInner.dimeWrapVal && gravity == MyGravity_Vert_Fill) - [sbvsc.heightSizeInner __clear]; + [sbvsc.heightSizeInner __setActive:NO]; //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 - if (sbvsc.topPosInner != nil && sbvsc.bottomPosInner != nil && sbvsc.heightSizeInner.priority == MyPriority_Low) - [sbvsc.heightSizeInner __clear]; + if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil && (sbvsc.heightSizeInner.priority == MyPriority_Low || !lsc.heightSizeInner.dimeWrapVal)) + [sbvsc.heightSizeInner __setActive:NO]; //只要同时设置了宽度或者比重属性则应该把宽度置空 if (sbvsc.widthSizeInner.dimeWrapVal && sbvsc.weight != 0) - [sbvsc.widthSizeInner __clear]; + [sbvsc.widthSizeInner __setActive:NO]; } } diff --git a/MyLayout/Lib/MyPathLayout.m b/MyLayout/Lib/MyPathLayout.m index 3e66ee9..2d12bbe 100644 --- a/MyLayout/Lib/MyPathLayout.m +++ b/MyLayout/Lib/MyPathLayout.m @@ -42,8 +42,6 @@ +(MyPathSpace *)count:(NSInteger)count return [[self alloc] initWithSpaceType:MyPathSpace_Count value:count]; } - - @end @@ -72,7 +70,6 @@ -(void)setIsMath:(BOOL)isMath _isMath = isMath; [_pathLayout setNeedsLayout]; } - } -(void)setIsReverse:(BOOL)isReverse @@ -100,8 +97,6 @@ -(void)setStart:(CGFloat)start _start = start; [_pathLayout setNeedsLayout]; } - - } -(void)setEnd:(CGFloat)end @@ -110,7 +105,6 @@ -(void)setEnd:(CGFloat)end { _end = end; [_pathLayout setNeedsLayout]; - } } @@ -127,7 +121,6 @@ -(void)reset @end - @interface MyPathLayout() @property(nonatomic, strong) NSArray *pathPoints; //记录路径内所有算出来的点,内容为NSValue(CGPoint) @@ -229,13 +222,11 @@ -(void)setOriginView:(UIView *)originView [self.subviews.lastObject removeFromSuperview]; [super addSubview:originView]; } - } else { [self addSubview:originView]; } - } else { @@ -244,7 +235,6 @@ -(void)setOriginView:(UIView *)originView _hasOriginView = NO; } - } else { @@ -276,15 +266,15 @@ -(NSArray*)pathSubviews return pathsbs; } else + { return self.subviews; + } } -(NSMutableArray*)argumentArray { if (_argumentArray == nil) - { _argumentArray = [NSMutableArray new]; - } return _argumentArray; } @@ -307,7 +297,6 @@ -(CGFloat)argumentFrom:(UIView*)subview } else return NAN; - } @@ -326,7 +315,6 @@ -(void)beginSubviewPathPoint:(BOOL)full self.pathPoints = [self myCalcPoints:self.pathSubviews path:nil pointIndexArray:nil lsc:self.myCurrentSizeClass]; self.pointIndexs = nil; } - } -(void)endSubviewPathPoint @@ -361,13 +349,11 @@ -(NSArray*)getSubviewPathPoint:(NSInteger)fromIndex toIndex:(NSInteger)toIndex } else { - if (realFromIndex >= indexsCount) start = [self.pointIndexs[indexsCount - 1] integerValue]; else start = [self.pointIndexs[realFromIndex] integerValue]; - if (realToIndex >= indexsCount) end = [self.pointIndexs[indexsCount - 1] integerValue]; else @@ -393,7 +379,6 @@ -(NSArray*)getSubviewPathPoint:(NSInteger)fromIndex toIndex:(NSInteger)toIndex else end = [self.pointIndexs[realFromIndex] integerValue]; - if (realToIndex >= indexsCount) start = [self.pointIndexs[indexsCount - 1] integerValue]; else @@ -407,7 +392,6 @@ -(NSArray*)getSubviewPathPoint:(NSInteger)fromIndex toIndex:(NSInteger)toIndex } return retPoints; - } -(CGPathRef)createPath:(NSInteger)subviewCount @@ -427,7 +411,6 @@ -(CGPathRef)createPath:(NSInteger)subviewCount } return retPath; - } #pragma mark -- Override Methods @@ -446,9 +429,7 @@ - (void)insertSubview:(UIView *)view atIndex:(NSInteger)index - (void)addSubview:(UIView *)view { if (self.originView != nil) - { [super insertSubview:view atIndex:self.subviews.count - 1]; - } else [super addSubview:view]; } @@ -460,7 +441,6 @@ - (void)sendSubviewToBack:(UIView *)view return; [super sendSubviewToBack:view]; - } @@ -470,9 +450,7 @@ - (void)willRemoveSubview:(UIView *)subview if (_hasOriginView) { if (self.subviews.count > 0 && subview == self.subviews.lastObject) - { _hasOriginView = NO; - } } } @@ -576,9 +554,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( CGMutablePathRef path = nil; if ([self.layer isKindOfClass:[CAShapeLayer class]] && !isEstimate) - { path = CGPathCreateMutable(); - } NSArray *pts = [self myCalcPoints:sbs path:path pointIndexArray:nil lsc:lsc]; @@ -598,9 +574,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( CGPoint pt = CGPointZero; if (pts.count > i) - { pt = [pts[i] CGPointValue]; - } //计算得到最大的高度和最大的宽度。 @@ -631,28 +605,18 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( rect.origin.y = pt.y - rect.size.height * sbv.layer.anchorPoint.y - sbvsc.bottomPosInner.absVal + sbvsc.topPosInner.absVal; if (_myCGFloatLess(CGRectGetMinY(rect), minYPos)) - { minYPos = CGRectGetMinY(rect); - } if (_myCGFloatGreat(CGRectGetMaxY(rect), maxYPos)) - { maxYPos = CGRectGetMaxY(rect); - } if (_myCGFloatLess(CGRectGetMinX(rect), minXPos)) - { minXPos = CGRectGetMinX(rect); - } if (_myCGFloatGreat(CGRectGetMaxX(rect), maxXPos)) - { maxXPos = CGRectGetMaxX(rect); - } - sbvmyFrame.frame = rect; - } //特殊填充中心视图。 @@ -664,7 +628,6 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( CGRect rect = sbvmyFrame.frame; - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; @@ -677,83 +640,54 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) {//特殊处理宽度等于高度的情况 rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; } - //位置在原点位置。。 rect.origin.x = (selfSize.width - lsc.myLayoutLeftPadding - lsc.myLayoutRightPadding)*self.coordinateSetting.origin.x - rect.size.width *sbv.layer.anchorPoint.x + sbvsc.leftPosInner.absVal + lsc.myLayoutLeftPadding - sbvsc.rightPosInner.absVal; rect.origin.y = (selfSize.height - lsc.myLayoutTopPadding - lsc.myLayoutBottomPadding)*self.coordinateSetting.origin.y - rect.size.height * sbv.layer.anchorPoint.y + sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding - sbvsc.bottomPosInner.absVal; if (_myCGFloatLess(CGRectGetMinY(rect), minYPos)) - { minYPos = CGRectGetMinY(rect); - } if (_myCGFloatGreat(CGRectGetMaxY(rect), maxYPos)) - { maxYPos = CGRectGetMaxY(rect); - } if (_myCGFloatLess(CGRectGetMinX(rect), minXPos)) - { minXPos = CGRectGetMinX(rect); - } if (_myCGFloatGreat(CGRectGetMaxX(rect), maxXPos)) - { maxXPos = CGRectGetMaxX(rect); - } sbvmyFrame.frame = rect; - } if (minYPos == CGFLOAT_MAX) - { minYPos = 0; - } - if (maxYPos == -CGFLOAT_MAX) - { maxYPos = lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding; - } - if (minXPos == CGFLOAT_MAX) - { minXPos = 0; - } - if (maxXPos == -CGFLOAT_MAX) - { maxXPos = lsc.myLayoutLeftPadding + lsc.myLayoutRightPadding; - } - if (lsc.widthSizeInner.dimeWrapVal) - { selfSize.width = maxXPos - minXPos; - } if (lsc.heightSizeInner.dimeWrapVal) - { selfSize.height = maxYPos - minYPos; - } //调整布局视图自己的尺寸。 [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; - //对所有子视图进行布局变换 [self myAdjustSubviewsLayoutTransform:sbs lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; //路径布局不支持RTL。 - return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs2 lsc:lsc]; } @@ -834,7 +768,6 @@ -(CGPoint)myGetNearestDistancePoint:(CGFloat)startArg lastXY:(CGPoint)lastXY dis } return lastXY; - } @@ -865,14 +798,11 @@ -(void)myCalcPathPointsHelper:(NSMutableArray*)pathPointArray int segmentCount = 0; while (true) { - if (subviewCount < 0) { //如果曲线变量超过了定义域则退出。 if (arg - endArg > 0.1) //这里不能用arg > endArg 的原因是有精度问题。 - { break; - } } else if (subviewCount == 0) { @@ -890,12 +820,10 @@ -(void)myCalcPathPointsHelper:(NSMutableArray*)pathPointArray [self.argumentArray addObject:@(arg)]; if (showPath != nil) - { CGPathAddLineToPoint(showPath, NULL, lastXY.x, lastXY.y); - } + break; } - } CGPoint realXY = func(arg); @@ -903,7 +831,6 @@ -(void)myCalcPathPointsHelper:(NSMutableArray*)pathPointArray { if (isSegmentStart) { - isSegmentStart = NO; segmentCount += 1; if (subviewCount > 0 && segmentCount == 1) @@ -920,11 +847,7 @@ -(void)myCalcPathPointsHelper:(NSMutableArray*)pathPointArray [pathPointArray addObject:[NSValue valueWithCGPoint:realXY]]; if (showPath != nil) - { CGPathMoveToPoint(showPath,NULL, realXY.x, realXY.y); - } - - } else { @@ -936,13 +859,9 @@ -(void)myCalcPathPointsHelper:(NSMutableArray*)pathPointArray if (_myCGFloatGreatOrEqual(distance, viewSpace) ) {//如果距离超过间距。则需要缩小自变量步长。以便达到最小的间距误差 if (_myCGFloatGreatOrEqual(distance - viewSpace, self.distanceError) ) - { realXY = [self myGetNearestDistancePoint:arg lastXY:lastXY distance:oldDistance viewSpace:viewSpace pLastValidArg:&lastValidArg func:func]; - } else - { lastValidArg = arg; - } if (pointIndexArray == nil) [pathPointArray addObject:[NSValue valueWithCGPoint:realXY]]; @@ -982,14 +901,10 @@ -(void)myCalcPathPointsHelper:(NSMutableArray*)pathPointArray if (showPath != nil) - { CGPathAddLineToPoint(showPath,NULL, realXY.x, realXY.y); - } if (pPathLen != NULL) - { *pPathLen += [self myCalcDistance:realXY with:lastXY]; - } } lastXY = realXY; @@ -1000,8 +915,6 @@ -(void)myCalcPathPointsHelper:(NSMutableArray*)pathPointArray } arg += 1; } - - } @@ -1053,6 +966,7 @@ -(NSArray*)myCalcPathPoints:(CGMutablePathRef)showPath else endArg = selfHeight *(1 - self.coordinateSetting.origin.y); } + if (self.coordinateSetting.end != CGFLOAT_MAX) endArg = self.coordinateSetting.end; @@ -1062,21 +976,16 @@ -(NSArray*)myCalcPathPoints:(CGMutablePathRef)showPath if (!isnan(val)) { if (self.coordinateSetting.isReverse) - { return CGPointMake(val + selfWidth * self.coordinateSetting.origin.x + lsc.myLayoutLeftPadding, (self.coordinateSetting.isMath ? -arg : arg) + selfHeight * self.coordinateSetting.origin.y + lsc.myLayoutTopPadding); - - } else - { return CGPointMake(arg + selfWidth * self.coordinateSetting.origin.x + lsc.myLayoutLeftPadding, (self.coordinateSetting.isMath ? -val : val) + selfHeight * self.coordinateSetting.origin.y + lsc.myLayoutTopPadding); - - } } else + { return CGPointMake(NAN, NAN); - + } }]; } else if (self.parametricEquation != nil) @@ -1109,26 +1018,18 @@ -(NSArray*)myCalcPathPoints:(CGMutablePathRef)showPath if (!isnan(val.x) && !isnan(val.y)) { if (self.coordinateSetting.isReverse) - { return CGPointMake(val.y + selfWidth * self.coordinateSetting.origin.x + lsc.myLayoutLeftPadding, (self.coordinateSetting.isMath ? -val.x : val.x) + selfHeight * self.coordinateSetting.origin.y + lsc.myLayoutTopPadding); - - } else - { return CGPointMake(val.x + selfWidth * self.coordinateSetting.origin.x + lsc.myLayoutLeftPadding, (self.coordinateSetting.isMath ? -val.y : val.y) + selfHeight * self.coordinateSetting.origin.y + lsc.myLayoutTopPadding); - } } else return CGPointMake(NAN, NAN); - }]; - } else if (self.polarEquation != nil) { - startArg = 0; if (self.coordinateSetting.start != -CGFLOAT_MAX) startArg = self.coordinateSetting.start * 180.0 / M_PI; @@ -1162,10 +1063,10 @@ -(NSArray*)myCalcPathPoints:(CGMutablePathRef)showPath } } else + { return CGPointMake(NAN, NAN); - + } }]; - } return pathPointArray; @@ -1192,7 +1093,6 @@ -(NSArray*)myCalcPoints:(NSArray*)sbs path:(CGMutablePathRef)path pointIndexArra } - CGFloat viewSpace = 0; //每个视图之间的间距。 NSInteger sbvcount = sbs.count; if (self.spaceType.type == MyPathSpace_Count) //如果是固定数量则按固定数量来分配间距 @@ -1200,13 +1100,10 @@ -(NSArray*)myCalcPoints:(NSArray*)sbs path:(CGMutablePathRef)path pointIndexArra //总长度除视图数量得出子视图的间距。 if (sbvcount > 1) - { viewSpace = pathLen / (sbvcount - (bClose ? 0 : 1)); - } //有间距后再重新计算一遍 return [self myCalcPathPoints:nil pPathLen:NULL subviewCount:sbs.count pointIndexArray:pointIndexArray viewSpace:viewSpace lsc:lsc]; - } else { @@ -1215,11 +1112,6 @@ -(NSArray*)myCalcPoints:(NSArray*)sbs path:(CGMutablePathRef)path pointIndexArra } return nil; - } - - - @end - diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 16112ab..e0413d2 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -30,21 +30,21 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbvsc.useFrame) continue; - if (!isEstimate || (pHasSubLayout != nil && (*pHasSubLayout) == YES)) + if (!isEstimate) [sbvmyFrame reset]; //只要同时设置了左右边距且宽度优先级很低则把宽度值置空 if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil && - sbvsc.widthSizeInner.priority == MyPriority_Low) - [sbvsc.widthSizeInner __clear]; + (sbvsc.widthSizeInner.priority == MyPriority_Low || !lsc.widthSizeInner.dimeWrapVal)) + [sbvsc.widthSizeInner __setActive:NO]; //只要同时设置了上下边距且高度优先级很低则把高度值置空 if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil && - sbvsc.heightSizeInner.priority == MyPriority_Low) - [sbvsc.heightSizeInner __clear]; + (sbvsc.heightSizeInner.priority == MyPriority_Low || !lsc.heightSizeInner.dimeWrapVal)) + [sbvsc.heightSizeInner __setActive:NO]; if ([sbv isKindOfClass:[MyBaseLayout class]]) @@ -67,6 +67,10 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( } } } + else + { + [sbvmyFrame reset]; + } } @@ -167,15 +171,67 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv //左右和宽度设置完毕。 - if (sbvmyFrame.leading != CGFLOAT_MAX && sbvmyFrame.trailing != CGFLOAT_MAX && sbvmyFrame.width != CGFLOAT_MAX) return; - //先检测宽度,如果宽度是父亲的宽度则宽度和左右都确定 if ([self myCalcWidth:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]) return; + //表示视图数组水平居中 + if (sbvsc.centerXPosInner.posArrVal != nil) + { + //先算出所有关联视图的宽度。再计算出关联视图的左边和右边的绝对值。 + NSArray *centerArray = sbvsc.centerXPosInner.posArrVal; + + CGFloat totalWidth = 0; + CGFloat totalOffset = 0; + + MyLayoutPos *nextPos = nil; + for (NSInteger i = centerArray.count - 1; i >= 0; i--) + { + MyLayoutPos *pos = centerArray[i]; + if (![self myIsNoLayoutSubview:pos.view]) + { + if (totalWidth != 0) + { + if (nextPos != nil) + totalOffset += nextPos.view.centerXPos.absVal; + } + + [self myCalcWidth:pos.view sbvsc:pos.view.myCurrentSizeClass lsc:lsc sbvmyFrame:pos.view.myFrame selfSize:selfSize]; + totalWidth += pos.view.myFrame.width; + } + + nextPos = pos; + } + + if (![self myIsNoLayoutSubview:sbv]) + { + if (totalWidth != 0) + { + if (nextPos != nil) + totalOffset += nextPos.view.centerXPos.absVal; + } + + [self myCalcWidth:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + totalWidth += sbvmyFrame.width; + totalOffset += sbvsc.centerXPosInner.absVal; + } + + + //所有宽度算出后,再分别设置 + CGFloat leadingOffset = (selfSize.width - lsc.myLayoutLeadingPadding - lsc.myLayoutTrailingPadding - totalWidth - totalOffset) / 2; + leadingOffset += lsc.myLayoutLeadingPadding; + id prev = @(leadingOffset); + [sbvsc.leadingPos __equalTo:prev]; + prev = sbvsc.trailingPos; + for (MyLayoutPos *pos in centerArray) + { + [[pos.view.leadingPos __equalTo:prev] __offset:pos.view.centerXPos.absVal]; + prev = pos.view.trailingPos; + } + } if (sbvsc.centerXPosInner.posRelaVal != nil) { @@ -217,9 +273,7 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv sbvmyFrame.leading = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.leadingPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.leadingPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) - { sbvmyFrame.leading -= sbvsc.leadingPosInner.absVal; - } sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; } @@ -237,16 +291,12 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv { UIView *relaView = sbvsc.trailingPosInner.posRelaVal.view; - sbvmyFrame.trailing = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.trailingPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.trailingPosInner.absVal + sbvsc.leadingPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) - { sbvmyFrame.trailing += sbvsc.trailingPosInner.absVal; - } sbvmyFrame.leading = sbvmyFrame.trailing - sbvmyFrame.width; - } else if (sbvsc.trailingPosInner.posMostVal != nil) { @@ -255,7 +305,9 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv } else if (sbvsc.trailingPosInner.posNumVal != nil) { - sbvmyFrame.trailing = selfSize.width - lsc.myLayoutTrailingPadding - sbvsc.trailingPosInner.absVal + sbvsc.leadingPosInner.absVal; + sbvmyFrame.trailing = selfSize.width - + sbvsc.trailingPosInner.absVal - + lsc.myLayoutTrailingPadding; sbvmyFrame.leading = sbvmyFrame.trailing - sbvmyFrame.width; } else @@ -263,7 +315,6 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv sbvmyFrame.leading = sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; } - } //这里要更新左边最小和右边最大约束的情况。 @@ -332,15 +383,68 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize { - if (sbvmyFrame.top != CGFLOAT_MAX && sbvmyFrame.bottom != CGFLOAT_MAX && sbvmyFrame.height != CGFLOAT_MAX) return; - //先检测高度,如果高度是父亲的高度则高度和上下都确定 if ([self myCalcHeight:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]) return; + //表示视图数组垂直居中 + if (sbvsc.centerYPosInner.posArrVal != nil) + { + NSArray *centerArray = sbvsc.centerYPosInner.posArrVal; + + CGFloat totalHeight = 0; + CGFloat totalOffset = 0; + + MyLayoutPos *nextPos = nil; + for (NSInteger i = centerArray.count - 1; i >= 0; i--) + { + MyLayoutPos *pos = centerArray[i]; + if (![self myIsNoLayoutSubview:pos.view]) + { + if (totalHeight != 0) + { + if (nextPos != nil) + totalOffset += nextPos.view.centerYPos.absVal; + } + + [self myCalcHeight:pos.view sbvsc:pos.view.myCurrentSizeClass lsc:lsc sbvmyFrame:pos.view.myFrame selfSize:selfSize]; + totalHeight += pos.view.myFrame.height; + } + + nextPos = pos; + } + + if (![self myIsNoLayoutSubview:sbv]) + { + if (totalHeight != 0) + { + if (nextPos != nil) + totalOffset += nextPos.view.centerYPos.absVal; + } + + [self myCalcHeight:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + totalHeight += sbvmyFrame.height; + totalOffset += sbvsc.centerYPosInner.absVal; + } + + + //所有高度算出后,再分别设置 + CGFloat topOffset = (selfSize.height - lsc.myLayoutTopPadding - lsc.myLayoutBottomPadding - totalHeight - totalOffset) / 2; + topOffset += lsc.myLayoutTopPadding; + + id prev = @(topOffset); + [sbvsc.topPos __equalTo:prev]; + prev = sbvsc.bottomPos; + for (MyLayoutPos *pos in centerArray) + { + [[pos.view.topPos __equalTo:prev] __offset:pos.view.centerYPos.absVal]; + prev = pos.view.bottomPos; + } + } + if (sbvsc.baselinePosInner.posRelaVal != nil) { //得到基线的位置。基线的位置等于top + (子视图的高度 - 字体的高度) / 2 + 字体基线以上的高度。 @@ -462,9 +566,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL sbvmyFrame.bottom = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.bottomPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.bottomPosInner.absVal + sbvsc.topPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) - { sbvmyFrame.bottom += sbvsc.bottomPosInner.absVal; - } sbvmyFrame.top = sbvmyFrame.bottom - sbvmyFrame.height; @@ -476,17 +578,8 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL } else if (sbvsc.bottomPosInner.posNumVal != nil) { - if (selfSize.height == 0 && lsc.heightSizeInner.dimeWrapVal) - { - sbvmyFrame.top = lsc.myLayoutTopPadding; - sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; - } - else - { - - sbvmyFrame.bottom = selfSize.height - sbvsc.bottomPosInner.absVal - lsc.myLayoutBottomPadding + sbvsc.topPosInner.absVal; - sbvmyFrame.top = sbvmyFrame.bottom - sbvmyFrame.height; - } + sbvmyFrame.bottom = selfSize.height - sbvsc.bottomPosInner.absVal - lsc.myLayoutBottomPadding; + sbvmyFrame.top = sbvmyFrame.bottom - sbvmyFrame.height; } else { @@ -523,8 +616,6 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL } sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; - - } else if (lBoundPos.posRelaVal != nil) { @@ -552,10 +643,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL sbvmyFrame.bottom = maxBottom; sbvmyFrame.height = sbvmyFrame.bottom - sbvmyFrame.top; } - } - - } @@ -718,34 +806,106 @@ -(CGFloat)myCalcSubView:(UIView*)sbv lsc:(MyRelativeLayout*)lsc gravity:(MyGravi -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize { + BOOL hasMargin = NO; if (sbvmyFrame.width == CGFLOAT_MAX) { - - if (sbvsc.widthSizeInner.dimeRelaVal != nil) + if (sbvsc.widthSizeInner.dimeArrVal != nil) { - sbvmyFrame.width = [sbvsc.widthSizeInner measureWith:[self myCalcSubView:sbvsc.widthSizeInner.dimeRelaVal.view lsc:lsc gravity:sbvsc.widthSizeInner.dimeRelaVal.dime selfSize:selfSize] ]; + NSArray *dimeArray = sbvsc.widthSizeInner.dimeArrVal; + + BOOL isViewHidden = [self myIsNoLayoutSubview:sbv]; + CGFloat totalMulti = isViewHidden ? 0 : sbvsc.widthSizeInner.multiVal; + CGFloat totalAdd = isViewHidden ? 0 : sbvsc.widthSizeInner.addVal; + for (MyLayoutSize *dime in dimeArray) + { + + if (dime.isActive) + { + isViewHidden = [self myIsNoLayoutSubview:dime.view]; + if (!isViewHidden) + { + if (dime.dimeVal != nil) + { + [self myCalcWidth:dime.view + sbvsc:dime.view.myCurrentSizeClass + lsc:lsc + sbvmyFrame:dime.view.myFrame + selfSize:selfSize]; + + totalAdd += -1 * dime.view.myFrame.width; + } + else + { + totalMulti += dime.multiVal; + } + + totalAdd += dime.addVal; + } + } + + } + + CGFloat spareWidth = selfSize.width - lsc.myLayoutLeadingPadding - lsc.myLayoutTrailingPadding + totalAdd; + if ( _myCGFloatLessOrEqual(spareWidth, 0)) + spareWidth = 0; - sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + if (totalMulti != 0) + { + CGFloat tempWidth = _myCGFloatRound(spareWidth * (sbvsc.widthSizeInner.multiVal / totalMulti)); + sbvmyFrame.width = tempWidth; + + if ([self myIsNoLayoutSubview:sbv]) + { + sbvmyFrame.width = 0; + } + else + { + spareWidth -= tempWidth; + totalMulti -= sbvsc.widthSizeInner.multiVal; + } + + for (MyLayoutSize *dime in dimeArray) + { + if (dime.isActive && ![self myIsNoLayoutSubview:dime.view]) + { + if (dime.dimeVal == nil) + { + tempWidth = _myCGFloatRound(spareWidth * (dime.multiVal / totalMulti)); + spareWidth -= tempWidth; + totalMulti -= dime.multiVal; + dime.view.myFrame.width = tempWidth; + + } + + dime.view.myFrame.width = [self myValidMeasure:dime.view.widthSize sbv:dime.view calcSize:dime.view.myFrame.width sbvSize:dime.view.myFrame.frame.size selfLayoutSize:selfSize]; + } + else + { + dime.view.myFrame.width = 0; + } + } + } + } + else if (sbvsc.widthSizeInner.dimeRelaVal != nil) + { + sbvmyFrame.width = [sbvsc.widthSizeInner measureWith:[self myCalcSubView:sbvsc.widthSizeInner.dimeRelaVal.view lsc:lsc gravity:sbvsc.widthSizeInner.dimeRelaVal.dime selfSize:selfSize] ]; } else if (sbvsc.widthSizeInner.dimeNumVal != nil) { sbvmyFrame.width = sbvsc.widthSizeInner.measure; - sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - } - else + else if (sbvsc.widthSizeInner.dimeWrapVal) { - + //对于非布局视图进行宽度自适应计算。 + if (![sbv isKindOfClass:[MyBaseLayout class]]) + sbvmyFrame.width = [sbvsc.widthSizeInner measureWith:[sbv sizeThatFits:CGSizeZero].width]; } - - if ([self myIsNoLayoutSubview:sbv]) - { - sbvmyFrame.width = 0; - } + if (sbvmyFrame.width == CGFLOAT_MAX) + sbvmyFrame.width = CGRectGetWidth(sbv.bounds); if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { @@ -753,27 +913,24 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc { UIView *relaView = sbvsc.leadingPosInner.posRelaVal.view; sbvmyFrame.leading = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.leadingPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.leadingPosInner.absVal; - if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) - { sbvmyFrame.leading -= sbvsc.leadingPosInner.absVal; - } } else if (sbvsc.leadingPosInner.posMostVal != nil) { sbvmyFrame.leading = sbvsc.leadingPosInner.posMostVal.doubleValue + sbvsc.leadingPosInner.absVal; } else + { sbvmyFrame.leading = sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; + } if (sbvsc.trailingPosInner.posRelaVal != nil) { UIView *relaView = sbvsc.trailingPosInner.posRelaVal.view; sbvmyFrame.trailing = [self myCalcSubView:sbvsc.trailingPosInner.posRelaVal.view lsc:lsc gravity:sbvsc.trailingPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.trailingPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) - { sbvmyFrame.trailing += sbvsc.trailingPosInner.absVal; - } } else if (sbvsc.trailingPosInner.posMostVal != nil) { @@ -781,372 +938,88 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc } else { - //如果设置了宽度则认为trailing是尾部间距。 - if (sbvmyFrame.width != CGFLOAT_MAX) - { - sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width + sbvsc.trailingPosInner.absVal; - } - else - { - sbvmyFrame.trailing = selfSize.width - sbvsc.trailingPosInner.absVal - lsc.myLayoutTrailingPadding; - } + sbvmyFrame.trailing = selfSize.width - sbvsc.trailingPosInner.absVal - lsc.myLayoutTrailingPadding; } //只有在没有设置宽度时才计算宽度。 if (sbvsc.widthSizeInner.dimeVal == nil) - { sbvmyFrame.width = sbvmyFrame.trailing - sbvmyFrame.leading; - sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - } - - if ([self myIsNoLayoutSubview:sbv]) - { - sbvmyFrame.width = 0; - sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; - } + else + sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width + sbvsc.trailingPosInner.absVal; - return YES; + hasMargin = YES; } - if (sbvmyFrame.width == CGFLOAT_MAX) + //计算有最大和最小约束的情况。 + if (sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal != nil && sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal.view != self) { - sbvmyFrame.width = CGRectGetWidth(sbv.bounds); - sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + [self myCalcWidth:sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal.view + sbvsc:sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal.view.myCurrentSizeClass + lsc:lsc + sbvmyFrame:sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal.view.myFrame + selfSize:selfSize]; } - } - - if ((sbvsc.widthSizeInner.lBoundValInner != nil && sbvsc.widthSizeInner.lBoundValInner.dimeNumVal.doubleValue != -CGFLOAT_MAX) || - (sbvsc.widthSizeInner.uBoundValInner != nil && sbvsc.widthSizeInner.uBoundValInner.dimeNumVal.doubleValue != CGFLOAT_MAX) ) - { + + if (sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal != nil && sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal.view != self) + { + [self myCalcWidth:sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal.view + sbvsc:sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal.view.myCurrentSizeClass + lsc:lsc + sbvmyFrame:sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal.view.myFrame + selfSize:selfSize]; + } + sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + + if ([self myIsNoLayoutSubview:sbv]) + { + sbvmyFrame.width = 0; + sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; + } } - - return NO; + return hasMargin; } -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize { - BOOL sbvWrapContentHeight = sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]; - if (sbvWrapContentHeight && !sbvsc.widthSizeInner.dimeWrapVal) - { - [self myCalcSubViewLeadingTrailing:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; - - //特殊处理高度包裹的情况,如果高度包裹时则同时设置顶部和底部将无效。 - sbvmyFrame.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:sbvmyFrame.width]; - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - } + BOOL hasMargin = NO; if (sbvmyFrame.height == CGFLOAT_MAX) { - if (sbvsc.heightSizeInner.dimeRelaVal != nil) - { - sbvmyFrame.height = [sbvsc.heightSizeInner measureWith:[self myCalcSubView:sbvsc.heightSizeInner.dimeRelaVal.view lsc:lsc gravity:sbvsc.heightSizeInner.dimeRelaVal.dime selfSize:selfSize] ]; - - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - - } - else if (sbvsc.heightSizeInner.dimeNumVal != nil) + if (sbvsc.heightSizeInner.dimeArrVal != nil) { - sbvmyFrame.height = sbvsc.heightSizeInner.measure; - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + NSArray *dimeArray = sbvsc.heightSizeInner.dimeArrVal; - } - else - { + BOOL isViewHidden = [self myIsNoLayoutSubview:sbv]; - } - - if ([self myIsNoLayoutSubview:sbv]) - { - sbvmyFrame.height = 0; - } - - - if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) - { - if (sbvsc.topPosInner.posRelaVal != nil) + CGFloat totalMulti = isViewHidden ? 0 : sbvsc.heightSizeInner.multiVal; + CGFloat totalAdd = isViewHidden ? 0 : sbvsc.heightSizeInner.addVal; + for (MyLayoutSize *dime in dimeArray) { - UIView *relaView = sbvsc.topPosInner.posRelaVal.view; - sbvmyFrame.top = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.topPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.topPosInner.absVal; - - if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) + if (dime.isActive) { - sbvmyFrame.top -= sbvsc.topPosInner.absVal; - } - - } - else if (sbvsc.topPosInner.posMostVal != nil) - { - sbvmyFrame.top = sbvsc.topPosInner.posMostVal.doubleValue + sbvsc.topPosInner.absVal; - } - else - sbvmyFrame.top = sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding; - - if (sbvsc.bottomPosInner.posRelaVal != nil) - { - UIView *relaView = sbvsc.bottomPosInner.posRelaVal.view; - - sbvmyFrame.bottom = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.bottomPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.bottomPosInner.absVal; - - if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) - { - sbvmyFrame.bottom += sbvsc.bottomPosInner.absVal; - } - } - else if (sbvsc.bottomPosInner.posMostVal != nil) - { - sbvmyFrame.bottom = sbvsc.bottomPosInner.posMostVal.doubleValue - sbvsc.bottomPosInner.absVal; - } - else - { - //如果设置了高度则认为bottom是尾部间距。 - if (sbvmyFrame.height != CGFLOAT_MAX) - { - sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height + sbvsc.bottomPosInner.absVal; - } - else - { - sbvmyFrame.bottom = selfSize.height - sbvsc.bottomPosInner.absVal - lsc.myLayoutBottomPadding; - } - } - - //只有在没有设置高度时才计算高度。 - if (sbvsc.heightSizeInner.dimeVal == nil) - { - sbvmyFrame.height = sbvmyFrame.bottom - sbvmyFrame.top; - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - } - - if ([self myIsNoLayoutSubview:sbv]) - { - sbvmyFrame.height = 0; - sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; - } - - - return YES; - } - - - if (sbvmyFrame.height == CGFLOAT_MAX) - { - sbvmyFrame.height = CGRectGetHeight(sbv.bounds); - - if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]] && ![self myIsNoLayoutSubview:sbv]) - { - if (sbvmyFrame.width == CGFLOAT_MAX) - [self myCalcWidth:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; - - sbvmyFrame.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:sbvmyFrame.width]; - } - - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - - - } - } - - if ( (sbvsc.heightSizeInner.lBoundValInner != nil && sbvsc.heightSizeInner.lBoundValInner.dimeNumVal.doubleValue != -CGFLOAT_MAX) || - (sbvsc.heightSizeInner.uBoundValInner != nil && sbvsc.heightSizeInner.uBoundValInner.dimeNumVal.doubleValue != CGFLOAT_MAX)) - { - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - } - - return NO; - -} - - --(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalcWidth:(BOOL*)pRecalcWidth pRecalcHeight:(BOOL*)pRecalcHeight -{ - if (pRecalcWidth != NULL) - *pRecalcWidth = NO; - if (pRecalcHeight != NULL) - *pRecalcHeight = NO; - - - //遍历所有子视图,算出所有宽度和高度根据自身内容确定的子视图的尺寸.以及计算出那些有依赖关系的尺寸限制。。。 - for (UIView *sbv in self.subviews) - { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - - [self myCalcSizeOfWrapContentSubview:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame]; - - if (sbvmyFrame.width != CGFLOAT_MAX) - { - if (sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal != nil && sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal.view != self) - { - [self myCalcWidth:sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal.view - sbvsc:sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal.view.myCurrentSizeClass - lsc:lsc - sbvmyFrame:sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal.view.myFrame - selfSize:selfSize]; - } - - if (sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal != nil && sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal.view != self) - { - [self myCalcWidth:sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal.view - sbvsc:sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal.view.myCurrentSizeClass - lsc:lsc - sbvmyFrame:sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal.view.myFrame - selfSize:selfSize]; - } - - sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:sbvmyFrame.width sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - } - - if (sbvmyFrame.height != CGFLOAT_MAX) - { - if (sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal != nil && sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal.view != self) - { - [self myCalcHeight:sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal.view - sbvsc:sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal.view.myCurrentSizeClass - lsc:lsc - sbvmyFrame:sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal.view.myFrame - selfSize:selfSize]; - } - - if (sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal != nil && sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal.view != self) - { - [self myCalcHeight:sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal.view - sbvsc:sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal.view.myCurrentSizeClass - lsc:lsc - sbvmyFrame:sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal.view.myFrame - selfSize:selfSize]; - } - - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - } - - } - - //均分宽度和高度。把这部分提出来是为了实现不管数组是哪个视图指定都可以。 - for (UIView *sbv in self.subviews) - { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - - if (sbvsc.widthSizeInner.dimeArrVal != nil) - { - if (pRecalcWidth != NULL) - *pRecalcWidth = YES; - - NSArray *dimeArray = sbvsc.widthSizeInner.dimeArrVal; - - BOOL isViewHidden = [self myIsNoLayoutSubview:sbv]; - CGFloat totalMulti = isViewHidden ? 0 : sbvsc.widthSizeInner.multiVal; - CGFloat totalAdd = isViewHidden ? 0 : sbvsc.widthSizeInner.addVal; - for (MyLayoutSize *dime in dimeArray) - { - - if (dime.isActive) - { - isViewHidden = [self myIsNoLayoutSubview:dime.view]; - if (!isViewHidden) - { - if (dime.dimeVal != nil) - { - [self myCalcWidth:dime.view - sbvsc:dime.view.myCurrentSizeClass - lsc:lsc - sbvmyFrame:dime.view.myFrame - selfSize:selfSize]; - - totalAdd += -1 * dime.view.myFrame.width; - } - else - { - totalMulti += dime.multiVal; - } - - totalAdd += dime.addVal; - - } - } - - } - - CGFloat spareWidth = selfSize.width - lsc.myLayoutLeadingPadding - lsc.myLayoutTrailingPadding + totalAdd; - if ( _myCGFloatLessOrEqual(spareWidth, 0)) - spareWidth = 0; - - if (totalMulti != 0) - { - CGFloat tempWidth = _myCGFloatRound(spareWidth * (sbvsc.widthSizeInner.multiVal / totalMulti)); - - sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:tempWidth sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - - if ([self myIsNoLayoutSubview:sbv]) - { - sbvmyFrame.width = 0; - } - else - { - spareWidth -= tempWidth; - totalMulti -= sbvsc.widthSizeInner.multiVal; - } - - for (MyLayoutSize *dime in dimeArray) - { - if (dime.isActive && ![self myIsNoLayoutSubview:dime.view]) - { - if (dime.dimeVal == nil) - { - tempWidth = _myCGFloatRound(spareWidth * (dime.multiVal / totalMulti)); - spareWidth -= tempWidth; - totalMulti -= dime.multiVal; - dime.view.myFrame.width = tempWidth; - - } - - dime.view.myFrame.width = [self myValidMeasure:dime.view.widthSize sbv:dime.view calcSize:dime.view.myFrame.width sbvSize:dime.view.myFrame.frame.size selfLayoutSize:selfSize]; - } - else - { - dime.view.myFrame.width = 0; - } - } - } - } - - if (sbvsc.heightSizeInner.dimeArrVal != nil) - { - if (pRecalcHeight != NULL) - *pRecalcHeight = YES; - - NSArray *dimeArray = sbvsc.heightSizeInner.dimeArrVal; - - BOOL isViewHidden = [self myIsNoLayoutSubview:sbv]; - - CGFloat totalMulti = isViewHidden ? 0 : sbvsc.heightSizeInner.multiVal; - CGFloat totalAdd = isViewHidden ? 0 : sbvsc.heightSizeInner.addVal; - for (MyLayoutSize *dime in dimeArray) - { - if (dime.isActive) - { - isViewHidden = [self myIsNoLayoutSubview:dime.view]; - if (!isViewHidden) - { - if (dime.dimeVal != nil) - { - [self myCalcHeight:dime.view - sbvsc:dime.view.myCurrentSizeClass - lsc:lsc - sbvmyFrame:dime.view.myFrame - selfSize:selfSize]; - - totalAdd += -1 * dime.view.myFrame.height; - } - else - totalMulti += dime.multiVal; - - totalAdd += dime.addVal; - } + isViewHidden = [self myIsNoLayoutSubview:dime.view]; + if (!isViewHidden) + { + if (dime.dimeVal != nil) + { + [self myCalcHeight:dime.view + sbvsc:dime.view.myCurrentSizeClass + lsc:lsc + sbvmyFrame:dime.view.myFrame + selfSize:selfSize]; + + totalAdd += -1 * dime.view.myFrame.height; + } + else + totalMulti += dime.multiVal; + + totalAdd += dime.addVal; + } } } @@ -1157,8 +1030,7 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc if (totalMulti != 0) { CGFloat tempHeight = _myCGFloatRound(spareHeight * (sbvsc.heightSizeInner.multiVal / totalMulti)); - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:tempHeight sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - + sbvmyFrame.height = tempHeight; if ([self myIsNoLayoutSubview:sbv]) { sbvmyFrame.height = 0; @@ -1191,125 +1063,113 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc } } } + else if (sbvsc.heightSizeInner.dimeRelaVal != nil) + { + sbvmyFrame.height = [sbvsc.heightSizeInner measureWith:[self myCalcSubView:sbvsc.heightSizeInner.dimeRelaVal.view lsc:lsc gravity:sbvsc.heightSizeInner.dimeRelaVal.dime selfSize:selfSize] ]; + } + else if (sbvsc.heightSizeInner.dimeNumVal != nil) + { + sbvmyFrame.height = sbvsc.heightSizeInner.measure; + } + else if (sbvsc.heightSizeInner.dimeWrapVal) + { + if (![sbv isKindOfClass:[MyBaseLayout class]]) + { + if (sbvmyFrame.width == CGFLOAT_MAX) + [self myCalcWidth:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + + sbvmyFrame.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:sbvmyFrame.width]; + } + + } + if (sbvmyFrame.height == CGFLOAT_MAX) + sbvmyFrame.height = CGRectGetHeight(sbv.bounds); - //表示视图数组水平居中 - if (sbvsc.centerXPosInner.posArrVal != nil) + if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { - if (pRecalcWidth != NULL) - *pRecalcWidth = YES; - - //先算出所有关联视图的宽度。再计算出关联视图的左边和右边的绝对值。 - NSArray *centerArray = sbvsc.centerXPosInner.posArrVal; - - CGFloat totalWidth = 0; - CGFloat totalOffset = 0; - - MyLayoutPos *nextPos = nil; - for (NSInteger i = centerArray.count - 1; i >= 0; i--) + if (sbvsc.topPosInner.posRelaVal != nil) { - MyLayoutPos *pos = centerArray[i]; - if (![self myIsNoLayoutSubview:pos.view]) - { - if (totalWidth != 0) - { - if (nextPos != nil) - totalOffset += nextPos.view.centerXPos.absVal; - } - - [self myCalcWidth:pos.view sbvsc:pos.view.myCurrentSizeClass lsc:lsc sbvmyFrame:pos.view.myFrame selfSize:selfSize]; - totalWidth += pos.view.myFrame.width; - } + UIView *relaView = sbvsc.topPosInner.posRelaVal.view; + sbvmyFrame.top = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.topPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.topPosInner.absVal; - nextPos = pos; + if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) + sbvmyFrame.top -= sbvsc.topPosInner.absVal; } - - if (![self myIsNoLayoutSubview:sbv]) + else if (sbvsc.topPosInner.posMostVal != nil) { - if (totalWidth != 0) - { - if (nextPos != nil) - totalOffset += nextPos.view.centerXPos.absVal; - } - - [self myCalcWidth:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; - totalWidth += sbvmyFrame.width; - totalOffset += sbvsc.centerXPosInner.absVal; + sbvmyFrame.top = sbvsc.topPosInner.posMostVal.doubleValue + sbvsc.topPosInner.absVal; } - - - //所有宽度算出后,再分别设置 - CGFloat leadingOffset = (selfSize.width - lsc.myLayoutLeadingPadding - lsc.myLayoutTrailingPadding - totalWidth - totalOffset) / 2; - leadingOffset += lsc.myLayoutLeadingPadding; - id prev = @(leadingOffset); - [sbvsc.leadingPos __equalTo:prev]; - prev = sbvsc.trailingPos; - for (MyLayoutPos *pos in centerArray) + else { - [[pos.view.leadingPos __equalTo:prev] __offset:pos.view.centerXPos.absVal]; - prev = pos.view.trailingPos; + sbvmyFrame.top = sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding; } - } - - //表示视图数组垂直居中 - if (sbvsc.centerYPosInner.posArrVal != nil) - { - if (pRecalcHeight != NULL) - *pRecalcHeight = YES; - - NSArray *centerArray = sbvsc.centerYPosInner.posArrVal; - CGFloat totalHeight = 0; - CGFloat totalOffset = 0; - - MyLayoutPos *nextPos = nil; - for (NSInteger i = centerArray.count - 1; i >= 0; i--) + if (sbvsc.bottomPosInner.posRelaVal != nil) { - MyLayoutPos *pos = centerArray[i]; - if (![self myIsNoLayoutSubview:pos.view]) - { - if (totalHeight != 0) - { - if (nextPos != nil) - totalOffset += nextPos.view.centerYPos.absVal; - } - - [self myCalcHeight:pos.view sbvsc:pos.view.myCurrentSizeClass lsc:lsc sbvmyFrame:pos.view.myFrame selfSize:selfSize]; - totalHeight += pos.view.myFrame.height; - } + UIView *relaView = sbvsc.bottomPosInner.posRelaVal.view; + + sbvmyFrame.bottom = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.bottomPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.bottomPosInner.absVal; - nextPos = pos; + if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) + sbvmyFrame.bottom += sbvsc.bottomPosInner.absVal; } - - if (![self myIsNoLayoutSubview:sbv]) + else if (sbvsc.bottomPosInner.posMostVal != nil) { - if (totalHeight != 0) - { - if (nextPos != nil) - totalOffset += nextPos.view.centerYPos.absVal; - } - - [self myCalcHeight:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; - totalHeight += sbvmyFrame.height; - totalOffset += sbvsc.centerYPosInner.absVal; + sbvmyFrame.bottom = sbvsc.bottomPosInner.posMostVal.doubleValue - sbvsc.bottomPosInner.absVal; } - - - //所有高度算出后,再分别设置 - CGFloat topOffset = (selfSize.height - lsc.myLayoutTopPadding - lsc.myLayoutBottomPadding - totalHeight - totalOffset) / 2; - topOffset += lsc.myLayoutTopPadding; - - id prev = @(topOffset); - [sbvsc.topPos __equalTo:prev]; - prev = sbvsc.bottomPos; - for (MyLayoutPos *pos in centerArray) + else { - [[pos.view.topPos __equalTo:prev] __offset:pos.view.centerYPos.absVal]; - prev = pos.view.bottomPos; + sbvmyFrame.bottom = selfSize.height - sbvsc.bottomPosInner.absVal - lsc.myLayoutBottomPadding; } + + //只有在没有设置高度时才计算高度。 + if (sbvsc.heightSizeInner.dimeVal == nil) + sbvmyFrame.height = sbvmyFrame.bottom - sbvmyFrame.top; + else + sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height + sbvsc.bottomPosInner.absVal; + + hasMargin = YES; + } + + if (sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal != nil && sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal.view != self) + { + [self myCalcHeight:sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal.view + sbvsc:sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal.view.myCurrentSizeClass + lsc:lsc + sbvmyFrame:sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal.view.myFrame + selfSize:selfSize]; + } + + if (sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal != nil && sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal.view != self) + { + [self myCalcHeight:sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal.view + sbvsc:sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal.view.myCurrentSizeClass + lsc:lsc + sbvmyFrame:sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal.view.myFrame + selfSize:selfSize]; + } + + sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; + + if ([self myIsNoLayoutSubview:sbv]) + { + sbvmyFrame.height = 0; + sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; } } + return hasMargin; +} + + +-(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalcWidth:(BOOL*)pRecalcWidth pRecalcHeight:(BOOL*)pRecalcHeight +{ + if (pRecalcWidth != NULL) + *pRecalcWidth = NO; + if (pRecalcHeight != NULL) + *pRecalcHeight = NO; + //计算最大的宽度和高度 CGFloat maxWidth = lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding; CGFloat maxHeight = lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding; @@ -1319,23 +1179,13 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - BOOL sbvWrapContentHeight = sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]; [self myCalcSubViewLeadingTrailing:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; - - //特殊处理高度包裹的情况,如果高度包裹时则同时设置顶部和底部将无效。 - if (sbvWrapContentHeight) - { - sbvmyFrame.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:sbvmyFrame.width]; - sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:sbvmyFrame.height sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; - } - [self myCalcSubViewTopBottom:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; if ([self myIsNoLayoutSubview:sbv]) continue; - if (lsc.widthSizeInner.dimeWrapVal && pRecalcWidth != NULL) { //当有子视图依赖于父视图的一些设置时,需要重新进行布局(设置了右边或者中间的值,或者宽度依赖父视图) @@ -1356,7 +1206,7 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc maxWidth = sbvsc.leadingPosInner.absVal + sbvsc.trailingPosInner.absVal + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding; } - if (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) + if ( sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) { if (sbvsc.centerXPosInner.posVal != nil) { @@ -1365,9 +1215,9 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc } else if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { - if (_myCGFloatLess(maxWidth, fabs(sbvmyFrame.trailing) + sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding)) + if (sbvsc.widthSizeInner.dimeVal != nil && _myCGFloatLess(maxWidth, fabs(sbvmyFrame.trailing) + lsc.myLayoutTrailingPadding)) { - maxWidth = fabs(sbvmyFrame.trailing) + sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; + maxWidth = fabs(sbvmyFrame.trailing) + lsc.myLayoutTrailingPadding; } } else if (sbvsc.trailingPosInner.posVal != nil) @@ -1380,10 +1230,6 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc if (_myCGFloatLess(maxWidth, fabs(sbvmyFrame.trailing) + lsc.myLayoutTrailingPadding)) maxWidth = fabs(sbvmyFrame.trailing) + lsc.myLayoutTrailingPadding; } - - - if (_myCGFloatLess(maxWidth, sbvmyFrame.trailing + sbvsc.trailingPosInner.absVal + lsc.myLayoutTrailingPadding)) - maxWidth = sbvmyFrame.trailing + sbvsc.trailingPosInner.absVal + lsc.myLayoutTrailingPadding; } } @@ -1401,12 +1247,13 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc *pRecalcHeight = YES; } + //每个视图最小的高度,在计算时要进行比较。 if (_myCGFloatLess(maxHeight, sbvsc.topPosInner.absVal + sbvsc.bottomPosInner.absVal + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding)) { maxHeight = sbvsc.topPosInner.absVal + sbvsc.bottomPosInner.absVal + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding; } - + //高度不依赖父视图 if (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) { if (sbvsc.centerYPosInner.posVal != nil) @@ -1416,9 +1263,9 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc } else if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { - if (_myCGFloatLess(maxHeight, fabs(sbvmyFrame.bottom) + sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding)) + if (sbvsc.heightSizeInner.dimeVal != nil && _myCGFloatLess(maxHeight, fabs(sbvmyFrame.bottom) + lsc.myLayoutBottomPadding)) { - maxHeight = fabs(sbvmyFrame.bottom) + sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding; + maxHeight = fabs(sbvmyFrame.bottom) + lsc.myLayoutBottomPadding; } } else if (sbvsc.bottomPosInner.posVal != nil) @@ -1431,10 +1278,6 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc if (_myCGFloatLess(maxHeight, fabs(sbvmyFrame.bottom) + lsc.myLayoutBottomPadding)) maxHeight = fabs(sbvmyFrame.bottom) + lsc.myLayoutBottomPadding; } - - - if (_myCGFloatLess(maxHeight, sbvmyFrame.bottom + sbvsc.bottomPosInner.absVal + lsc.myLayoutBottomPadding)) - maxHeight = sbvmyFrame.bottom + sbvsc.bottomPosInner.absVal + lsc.myLayoutBottomPadding; } } } diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index e95eba7..b4336fb 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -411,10 +411,10 @@ -(void)testWrapContentWidth1 rightLabel.rightPos.equalTo(rootLayout.rightPos).offset(1); [rootLayout addSubview:rightLabel]; - titleLabel.rightPos.equalTo(rightLabel.leftPos).offset(10); + rightLabel.leftPos.equalTo(titleLabel.rightPos).offset(10); - XCTAssertTrue(CGSizeEqualToSize([rootLayout sizeThatFits:CGSizeMake(0, 0)], CGSizeMake(86, 50)), @"size is:%@", NSStringFromCGSize([rootLayout sizeThatFits:CGSizeMake(0, 0)])); + XCTAssertTrue(CGSizeEqualToSize([rootLayout sizeThatFits:CGSizeMake(0, 0)], CGSizeMake(176, 50)), @"size is:%@", NSStringFromCGSize([rootLayout sizeThatFits:CGSizeMake(0, 0)])); UILabel *allMoneyLabel = [UILabel new]; @@ -451,7 +451,7 @@ -(void)testWrapContentWidth1 [rootLayout addSubview:orderLabel]; - XCTAssertTrue(CGSizeEqualToSize([rootLayout sizeThatFits:CGSizeMake(0, 0)], CGSizeMake(86, 125)), @"size is:%@", NSStringFromCGSize([rootLayout sizeThatFits:CGSizeMake(0, 0)])); + XCTAssertTrue(CGSizeEqualToSize([rootLayout sizeThatFits:CGSizeMake(0, 0)], CGSizeMake(176, 125)), @"size is:%@", NSStringFromCGSize([rootLayout sizeThatFits:CGSizeMake(0, 0)])); } @@ -991,16 +991,23 @@ -(void)testMaxHeightAndWidth vv.rightPos.equalTo(label.rightPos); - label.text = @"测试12345660392034323"; + label.text = @"测试"; vv.backgroundColor = [UIColor redColor]; [rellayout sizeThatFits:CGSizeZero]; - XCTAssertTrue(CGSizeEqualToSize(label.estimatedRect.size, CGSizeMake(90, 61))); - XCTAssertTrue(CGSizeEqualToSize(vv.estimatedRect.size, CGSizeMake(90, 61))); + XCTAssertTrue(CGSizeEqualToSize(label.estimatedRect.size, CGSizeMake(35, 20.5))); + XCTAssertTrue(CGSizeEqualToSize(vv.estimatedRect.size, CGSizeMake(35, 20.5))); XCTAssertTrue(CGSizeEqualToSize(vv.estimatedRect.size, label.estimatedRect.size)); + label.text = @"测试12345660392034323"; + [rellayout sizeThatFits:CGSizeZero]; + + XCTAssertTrue(CGSizeEqualToSize(label.estimatedRect.size, CGSizeMake(100, 61))); + XCTAssertTrue(CGSizeEqualToSize(vv.estimatedRect.size, CGSizeMake(100, 61))); + XCTAssertTrue(CGSizeEqualToSize(vv.estimatedRect.size, label.estimatedRect.size)); + } -(void)test123 From ee9c114c6632befa0df40dc480d67a4273461db0 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Sat, 9 Nov 2019 01:24:29 +0800 Subject: [PATCH 074/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 7 +- MyLayout/Lib/MyRelativeLayout.m | 4 +- MyLayoutTests/MyLayoutTestCaseBase.h | 1 + MyLayoutTests/MyRelativeLayoutTestCase.m | 400 +++++++++++++++++++---- 4 files changed, 354 insertions(+), 58 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index b134c0a..469ccc0 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -2264,7 +2264,12 @@ -(CGSize)myEstimateLayoutSize:(CGSize)size inSizeClass:(MySizeClass)sizeClass sb selfMyFrame.width = selfSize.width; selfMyFrame.height = selfSize.height; - selfSize = [self calcLayoutSize:CGSizeZero isEstimate:YES pHasSubLayout:&hasWrapSizeSubLayout sizeClass:sizeClass sbs:sbs]; + if (selfMyFrame.sizeClass.widthSizeInner.dimeWrapVal) + selfSize.width = 0; + if (selfMyFrame.sizeClass.heightSizeInner.dimeWrapVal) + selfSize.height = 0; + + selfSize = [self calcLayoutSize:selfSize isEstimate:YES pHasSubLayout:&hasWrapSizeSubLayout sizeClass:sizeClass sbs:sbs]; } selfMyFrame.width = selfSize.width; diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index e0413d2..bb70f82 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -1221,7 +1221,7 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc } } else if (sbvsc.trailingPosInner.posVal != nil) - { + {//如果只有右边约束,则可以认为宽度是反过来算的,所以这里是左边的绝对值加上左边的padding来计算最宽宽度。 if (_myCGFloatLess(maxWidth, fabs(sbvmyFrame.leading) + lsc.myLayoutLeadingPadding)) maxWidth = fabs(sbvmyFrame.leading) + lsc.myLayoutLeadingPadding; } @@ -1269,7 +1269,7 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc } } else if (sbvsc.bottomPosInner.posVal != nil) - { + {//如果只有底边约束,则可以认为高度是反过来算的,所以这里是上边的绝对值加上上边的padding来计算最高高度 if (_myCGFloatLess(maxHeight, fabs(sbvmyFrame.top) + lsc.myLayoutTopPadding)) maxHeight = fabs(sbvmyFrame.top) + lsc.myLayoutTopPadding; } diff --git a/MyLayoutTests/MyLayoutTestCaseBase.h b/MyLayoutTests/MyLayoutTestCaseBase.h index f43db7c..a64d6d4 100644 --- a/MyLayoutTests/MyLayoutTestCaseBase.h +++ b/MyLayoutTests/MyLayoutTestCaseBase.h @@ -11,6 +11,7 @@ #define MyRectAssert(v, rc) XCTAssert(CGRectEqualToRect(v.frame, rc), @"the real frame = %@",NSStringFromCGRect(v.frame)); +#define MySizeAssert(v, sz1, sz2) XCTAssert(CGSizeEqualToSize(sz1, sz2), @"the real size = %@",NSStringFromCGSize(sz1)); @interface MyLayoutTestCaseBase : XCTestCase diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index b4336fb..65763e9 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -360,7 +360,7 @@ -(void)testWrapContentHeight3 leftView.heightSize.equalTo(@8); leftView.widthSize.equalTo(@8); leftView.leftPos.equalTo(@0); - leftView.centerYPos.equalTo(line.centerYPos); //118,37 + leftView.centerYPos.equalTo(line.centerYPos); //118,41 [midView addSubview:leftView]; line.leftPos.equalTo(leftView.rightPos); @@ -371,7 +371,7 @@ -(void)testWrapContentHeight3 rightView.widthSize.equalTo(@8); rightView.leftPos.equalTo(line.rightPos); rightView.centerYPos.equalTo(line.centerYPos); - [midView addSubview:rightView]; //126, 37 + [midView addSubview:rightView]; //126, 41 UILabel * numLabel = [UILabel new]; numLabel.mySize = CGSizeMake(40, 20); @@ -382,7 +382,7 @@ -(void)testWrapContentHeight3 CGSize sz = [midView sizeThatFits:CGSizeZero]; NSLog(@"%@",NSStringFromCGSize(sz)); - + MySizeAssert(midView, sz, CGSizeMake(126, 62)); } -(void)testWrapContentWidth1 @@ -671,9 +671,11 @@ -(void)testDemo1 MyRelativeLayout *_layoutRoot = nil; MyRelativeLayout* relative = [MyRelativeLayout new]; - // relative.widthSize.equalTo(self.contentView.widthSize); + // relative.widthSize.equalTo(self.contentView.widthSize); relative.myHeight = MyLayoutSize.wrap; + relative.myHorzMargin = 0; _layoutRoot = relative; + // [self.view addSubview:_layoutRoot]; // 头像区域 @@ -685,14 +687,8 @@ -(void)testDemo1 MyLinearLayout *_layoutPortrait = linear; // 头像 - CGFloat pWidth = 40.0f; UIImageView* imgv = [UIImageView new]; - [imgv setClipsToBounds:YES]; - [imgv setContentMode:UIViewContentModeScaleAspectFit]; - imgv.myWidth = pWidth; - imgv.myHeight = pWidth; - imgv.layer.masksToBounds = YES; - imgv.layer.cornerRadius = pWidth/2.0f; + imgv.mySize = CGSizeMake(40,40); [_layoutPortrait addSubview:imgv]; CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width; @@ -731,17 +727,17 @@ -(void)testDemo1 // 勿扰图标 UIImage* image = [UIImage imageNamed:@"edit"]; imgv = [[UIImageView alloc] initWithImage:image]; - [imgv sizeToFit]; - [imgv setHidden:YES]; + imgv.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + imgv.visibility = MyVisibility_Gone; [_layoutAccessoryBottom addSubview:imgv]; + UIView *hideView1 = imgv; // 勿扰状态下,有新消息时的小红点提示 UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 6.0f, 6.0f)]; [view setBackgroundColor:[UIColor greenColor]]; - [view setHidden:YES]; - view.layer.masksToBounds = YES; - view.layer.cornerRadius = 3.0f; + view.visibility = MyVisibility_Gone; [_layoutAccessoryBottom addSubview:view]; + UIView *hideView2 = view; // 非勿扰状态下未读消息数 lbl = [UILabel new]; @@ -754,14 +750,11 @@ -(void)testDemo1 [lbl setNumberOfLines:1]; lbl.heightSize.equalTo(lbl.heightSize).add(4.0f).lBound(@16,0,1); lbl.widthSize.equalTo(lbl.widthSize).add(8.0f).lBound(@16,0,1).uBound(_layoutAccessory.widthSize,0,1); - lbl.layer.masksToBounds = YES; - lbl.layer.cornerRadius = 8.0f; - // [lbl setHidden:YES]; // 中间区域 linear = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; linear.myVertMargin = 0.0f; - linear.heightSize.min(67.0f); + linear.heightSize.equalTo(@(MyLayoutSize.wrap)).min(67.0f); linear.leadingPos.equalTo(_layoutPortrait.trailingPos); linear.trailingPos.equalTo(_layoutAccessory.leadingPos); linear.gravity = MyGravity_Vert_Center; @@ -786,6 +779,7 @@ -(void)testDemo1 lbl.numberOfLines = 1; [_layoutTitle addSubview:lbl]; UILabel *_lblTitle = lbl; + UIView *hideView4 = _lblTitle; // 名称右侧的标记(例如,选题、部门等,作用是标记会话的类型) lbl = [UILabel new]; @@ -814,37 +808,361 @@ -(void)testDemo1 // 发送状态(例如:发送中,发送失败) imgv = [UIImageView new]; [imgv setContentMode:UIViewContentModeScaleAspectFit]; - imgv.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); - [imgv setHidden:YES]; + imgv.mySize = CGSizeMake(50,50); + imgv.visibility = MyVisibility_Gone; [_layoutSummary addSubview:imgv]; + UIView *hideView3 = imgv; // 勿扰状态下,在摘要显示的消息数 lbl = [UILabel new]; [lbl setTextAlignment:NSTextAlignmentCenter]; [lbl setFont:[UIFont systemFontOfSize:12]]; - lbl.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + lbl.mySize = CGSizeMake(5, 5); [lbl setNumberOfLines:1]; - [lbl setHidden:YES]; + lbl.visibility = MyVisibility_Gone; [_layoutSummary addSubview:lbl]; // 状态(包括:未读,已读,草稿,有人@) lbl = [UILabel new]; [lbl setFont:[UIFont systemFontOfSize:12]]; - lbl.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + lbl.mySize = CGSizeMake(5,5); [lbl setNumberOfLines:1]; - [lbl setHidden:YES]; + lbl.visibility = MyVisibility_Gone; [_layoutSummary addSubview:lbl]; // 摘要内容 lbl = [UILabel new]; [lbl setFont:[UIFont systemFontOfSize:12]]; lbl.weight = 1.0f; - lbl.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + lbl.mySize = CGSizeMake(70, 40); [lbl setNumberOfLines:1]; [_layoutSummary addSubview:lbl]; + + //hideView1 + //hideView2 + //hideView3 + CGSize sz = [_layoutRoot sizeThatFits:CGSizeMake(375, 0)]; + MySizeAssert(midView, sz, CGSizeMake(375, 68.5)); + + hideView3.visibility = MyVisibility_Visible; + + sz = [_layoutRoot sizeThatFits:CGSizeMake(375, 0)]; + MySizeAssert(midView, sz, CGSizeMake(375, 78.5)); + + hideView3.visibility = MyVisibility_Gone; + hideView4.visibility = MyVisibility_Gone; + + sz = [_layoutRoot sizeThatFits:CGSizeMake(375, 0)]; + MySizeAssert(midView, sz, CGSizeMake(375, 67)); + +} + +-(void)testDemo2 +{ + MyRelativeLayout *_rootLayout = [MyRelativeLayout new]; + + _rootLayout.wrapContentHeight = YES; + _rootLayout.topPadding = 15; + _rootLayout.bottomPadding = 15; + _rootLayout.backgroundColor = [UIColor whiteColor]; + + + + MyLinearLayout *topLayout = [MyLinearLayout linearLayoutWithOrientation:(MyOrientation_Vert)]; + + topLayout.wrapContentWidth = YES; + topLayout.myHorzMargin = 0; + topLayout.wrapContentHeight = YES; + topLayout.subviewVSpace = 5; + [_rootLayout addSubview:topLayout]; + + + UILabel *topLable = [UILabel new]; + topLable.text = @"宿州学院-皁阳火车站"; + topLable.myTop = 0; + topLable.myLeft = 11; + topLable.wrapContentSize = YES; + [topLayout addSubview:topLable]; + + + + UIButton *checkMarkBtn = [UIButton new]; + [checkMarkBtn setImage:[UIImage imageNamed:@"train_progresscomplete"] forState:(UIControlStateNormal)]; + checkMarkBtn.widthSize.equalTo(@(13)); + checkMarkBtn.heightSize.equalTo(@(13)); + checkMarkBtn.rightPos.equalTo(@(10)); + checkMarkBtn.centerYPos.equalTo(@(0)); + [_rootLayout addSubview:checkMarkBtn]; + + UILabel *contentLabel = [UILabel new]; + contentLabel.text = @"途径:蒙城、嘎县、阜阳师范学院、嘎县、阜阳师范学院、嘎县、阜阳师范学院"; + contentLabel.myLeft = 11; + + contentLabel.wrapContentHeight= YES; + contentLabel.myRight = 27; + contentLabel.hidden = NO; + [topLayout addSubview:contentLabel]; + + CGSize sz = [_rootLayout sizeThatFits:CGSizeMake(375, 0)]; + MySizeAssert(midView, sz, CGSizeMake(375, 96.5)); +} + +-(void)testDemo3 +{ + MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + rootLayout.myWidth = MyLayoutSize.wrap; + rootLayout.myHeight = MyLayoutSize.wrap; + rootLayout.padding = UIEdgeInsetsMake(12, 12, 12, 12); + + MyLinearLayout *headerLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + headerLayout.topPos.equalTo(rootLayout.topPos); + headerLayout.leftPos.equalTo(rootLayout.leftPos); + headerLayout.myHeight = MyLayoutSize.wrap; + [rootLayout addSubview:headerLayout]; + + UIView *headerView = [UIView new]; + headerView.mySize = CGSizeMake(32, 32); + [headerLayout addSubview:headerView]; + + UILabel *nameLabel = [UILabel new]; + nameLabel.mySize = CGSizeMake(60, 20); + nameLabel.alignment = MyGravity_Vert_Center; + nameLabel.myLeft = 5; + [headerLayout addSubview:nameLabel]; + + UILabel *titleLabel = [UILabel new]; + titleLabel.myHeight = 50; + titleLabel.leftPos.equalTo(headerLayout.leftPos); + titleLabel.topPos.equalTo(headerLayout.bottomPos).offset(5); + titleLabel.rightPos.equalTo(rootLayout.rightPos); + [rootLayout addSubview:titleLabel]; + + UIView *barView = [UIView new]; + barView.myHeight = 30; + barView.leftPos.equalTo(titleLabel.leftPos); + barView.rightPos.equalTo(titleLabel.rightPos); + barView.topPos.equalTo(titleLabel.bottomPos); + [rootLayout addSubview:barView]; + + CGSize sz = [rootLayout sizeThatFits:CGSizeMake(0, 0)]; + MySizeAssert(rootLayout, sz, CGSizeMake(121,141)); +} + +- (UILabel *)textLabel:(NSString *)text fontSize:(CGFloat)fontSize +{ + UILabel *label = [[UILabel alloc] init]; + label.font = [UIFont systemFontOfSize:fontSize]; + label.text = text; + [label sizeToFit]; + return label; +} +- (UILabel *)amountLabel:(NSString *)text fontSize:(CGFloat)fontSize +{ + UILabel *label = [[UILabel alloc] init]; + label.font = [UIFont boldSystemFontOfSize:fontSize]; + label.text = text; + [label sizeToFit]; + return label; +} + +-(void)testDemo4 +{ + MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + rootLayout.myHorzMargin = 0; + rootLayout.myHeight = MyLayoutSize.wrap; + + MyLinearLayout *baseLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + [rootLayout addSubview:baseLayout]; + baseLayout.widthSize.equalTo(rootLayout); + + ///背景布局 + CGFloat screen_width = [UIScreen mainScreen].bounds.size.width; + CGFloat ten_margin = 10; + MyLinearLayout *bgLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + // bgLayout.widthSize.equalTo(@(screen_width - 2 * ten_margin)); + bgLayout.widthSize.equalTo(baseLayout.widthSize).add(-2 * ten_margin); + bgLayout.myLeft = ten_margin; + bgLayout.myTop = ten_margin; + bgLayout.padding = UIEdgeInsetsMake(2 * ten_margin, 0, 2 * ten_margin, 0); + [baseLayout addSubview:bgLayout]; + // self.bgLayout = bgLayout; + // bgLayout.backgroundColor = UIColorFromRGB(0x6095f0); + bgLayout.backgroundColor = [UIColor lightGrayColor]; + + ///资产布局 + MyRelativeLayout *assetsLayout = [[MyRelativeLayout alloc] init]; + [bgLayout addSubview:assetsLayout]; + assetsLayout.myHorzMargin = 0; + assetsLayout.leftPadding = 1.8 * ten_margin; + assetsLayout.wrapContentHeight = YES; + + ///总资产Lab + UILabel *assetsLab = [UILabel new]; + assetsLab.text = @"TotalAssetsBracketsYuan"; + [assetsLab sizeToFit]; + assetsLab.font = [UIFont systemFontOfSize:11]; + [assetsLayout addSubview:assetsLab]; + + ///总资产金额Lab + UILabel *assetsAmountLab = [UILabel new]; + assetsAmountLab.text = @"0.00"; + assetsAmountLab.font = [UIFont systemFontOfSize:19]; + assetsAmountLab.leftPos.equalTo(assetsLab); + assetsAmountLab.topPos.equalTo(assetsLab.bottomPos).offset(0.3 * ten_margin); + [assetsLayout addSubview:assetsAmountLab]; + + /*************************************************/ + + ///本金布局 + MyFloatLayout *principalLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; + principalLayout.myHorzMargin = 0; + principalLayout.topPadding = 1.5 * ten_margin; + principalLayout.leftPadding = 1.8 * ten_margin; + principalLayout.wrapContentHeight = YES; + [bgLayout addSubview:principalLayout]; + + ///待收本金 + UILabel *principalLab = [UILabel new]; + principalLab.text = @"PendingPrincipalBracketsYuan"; + principalLab.font = [UIFont systemFontOfSize:10]; + [principalLab sizeToFit]; + principalLab.weight = 0.33 ; + [principalLayout addSubview:principalLab]; + + ///锁定资金金额 + UILabel *lockLab = [UILabel new]; + lockLab.text = @"LockFundsBracketsYuan"; + lockLab.font = [UIFont systemFontOfSize:10]; + [lockLab sizeToFit]; + lockLab.weight = 0.5; + [principalLayout addSubview:lockLab]; + + ///可用余额 + UILabel *balanceLab = [UILabel new]; + balanceLab.text = @"AvailableBalanceBracketsYuan"; + balanceLab.font = [UIFont systemFontOfSize:10]; + [balanceLab sizeToFit]; + balanceLab.weight = 1; + [principalLayout addSubview:balanceLab]; + +#define QDLabel UILabel + ///待收本金金额 + QDLabel *principalAmountLab = [self amountLabel:@"0.00" fontSize:15]; + principalAmountLab.weight = 0.33 ; + [principalLayout addSubview:principalAmountLab]; + + ///锁定资金金额 + QDLabel *lockAmountLab = [self amountLabel:@"0.00" fontSize:15]; + lockAmountLab.weight = 0.5; + [principalLayout addSubview:lockAmountLab]; + + ///可用余额金额 + QDLabel *balanceAmountLab = [self amountLabel:@"0.00" fontSize:15]; + balanceAmountLab.weight = 1; + [principalLayout addSubview:balanceAmountLab]; + + ///可伸缩布局 + MyLinearLayout *animLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + [bgLayout addSubview:animLayout]; + animLayout.myHorzMargin = 0; + + UIView *topLine = [[UIView alloc] init]; + [animLayout addSubview:topLine]; + // topLine.backgroundColor = color_bg_white; + topLine.myTop = 2 * ten_margin; + topLine.myHorzMargin = 0; + topLine.heightSize.equalTo(@(1)); + + ///收益布局 + MyFloatLayout *incomeLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; + incomeLayout.myHorzMargin = 0; + incomeLayout.topPadding = 2 * ten_margin; + incomeLayout.leftPadding = 1.8 * ten_margin; + incomeLayout.wrapContentHeight = YES; + [animLayout addSubview:incomeLayout]; + + ///待收收益 + QDLabel *pendingIncomeLab = [self textLabel:@"PendingIncomeBracketsYuan" fontSize:10]; + pendingIncomeLab.weight = 0.33 ; + [incomeLayout addSubview:pendingIncomeLab]; + + ///累计收益 + QDLabel *cumulativeIncomeLab = [self textLabel:@"CumulativeIncomeBracketsYuan" fontSize:10]; + cumulativeIncomeLab.weight = 1; + [incomeLayout addSubview:cumulativeIncomeLab]; + + ///待收收益金额 + QDLabel *pendingIncomeAmountLab = [self amountLabel:@"0.00" fontSize:15]; + pendingIncomeAmountLab.weight = 0.33 ; + [incomeLayout addSubview:pendingIncomeAmountLab]; + + ///累计收益金额 + QDLabel *cumulativeIncomeAmountLab = [self amountLabel:@"0.00" fontSize:15]; + cumulativeIncomeAmountLab.weight = 1; + [incomeLayout addSubview:cumulativeIncomeAmountLab]; + + UIView *bttomLine = [[UIView alloc] init]; + [animLayout addSubview:bttomLine]; + // bttomLine.backgroundColor = color_bg_white; + bttomLine.myTop = 2 * ten_margin; + bttomLine.myHorzMargin = 0; + bttomLine.heightSize.equalTo(@(1)); + + //出借总额布局 + MyFloatLayout *totalLoanLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; + totalLoanLayout.myHorzMargin = 0; + totalLoanLayout.topPadding = 2 * ten_margin; + totalLoanLayout.leftPadding = 1.8 * ten_margin; + totalLoanLayout.wrapContentHeight = YES; + [animLayout addSubview:totalLoanLayout]; + + ///累积出借总额 + QDLabel *totalLoanLab = [self textLabel:@"TotalAccumulatedLoanBracketsYuan" fontSize:10]; + totalLoanLab.weight = 1 ; + [totalLoanLayout addSubview:totalLoanLab]; + + ///累计收益金额 + QDLabel *totalLoanAmountLab = [self amountLabel:@"0.00" fontSize:15]; + totalLoanAmountLab.weight = 1; + [totalLoanLayout addSubview:totalLoanAmountLab]; + CGRect animRect = [baseLayout subview:animLayout estimatedRectInLayoutSize:CGSizeMake(screen_width - 2 * ten_margin, 100)]; + animLayout.frame = CGRectMake(animRect.origin.x, animRect.origin.y, animRect.size.width, animRect.size.height); + animLayout.visibility = MyVisibility_Visible; + + ///点击布局 + MyLinearLayout *stretchLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + stretchLayout.wrapContentHeight = YES; + // stretchLayout.heightSize.equalTo(@100); + stretchLayout.widthSize.equalTo(rootLayout); + stretchLayout.topPadding = stretchLayout.bottomPadding = 1.2 * ten_margin; + stretchLayout.gravity = MyGravity_Horz_Center; + [baseLayout addSubview:stretchLayout]; + + UILabel *arrowBtn = [UILabel new]; + arrowBtn.backgroundColor = [UIColor redColor]; +// [arrowBtn setImage:[UIImage imageNamed:@"assets_my_assets_header_hide"] +// forState:UIControlStateNormal]; +// [arrowBtn setImage:[UIImage imageNamed:@"assets_my_assets_header_show"] +// forState:UIControlStateSelected]; +// [arrowBtn addTarget:self +// action:@selector(arrowBtnClicked:) +// forControlEvents:UIControlEventTouchUpInside]; + arrowBtn.mySize = CGSizeMake(40, 40); + [stretchLayout addSubview:arrowBtn]; + // self.arrowBtn = arrowBtn; + + CGSize sz = [rootLayout sizeThatFits:CGSizeMake(screen_width, 0)]; + MySizeAssert(rootLayout, sz, CGSizeMake(screen_width,324.5)); + + animLayout.visibility = MyVisibility_Gone; + + sz = [rootLayout sizeThatFits:CGSizeMake(screen_width, 0)]; + MySizeAssert(rootLayout, sz, CGSizeMake(screen_width,182.5)); + } + -(void)testhideandubound { //测试视图隐藏以及 @@ -1010,34 +1328,6 @@ -(void)testMaxHeightAndWidth } --(void)test123 -{ - //创建一个视图。 - MyRelativeLayout *rootLayout = [MyRelativeLayout new]; - rootLayout.myMargin = 0; - // [self.view addSubview:rootLayout]; - - UIView *v1 = [UIView new]; - v1.myCenter = CGPointMake(0, 0); - v1.backgroundColor = [UIColor redColor]; - v1.widthSize.equalTo(@[rootLayout.widthSize, rootLayout.heightSize].myMinSize).multiply(0.5); - v1.heightSize.equalTo(v1.widthSize); - [rootLayout addSubview:v1]; - - UILabel *label = [UILabel new]; - label.myCenterX = 0; - label.myBottom = MyLayoutPos.safeAreaMargin; - label.text = @"您好!!!"; - label.backgroundColor = [UIColor redColor]; - label.widthSize.equalTo(@[@(MyLayoutSize.wrap), v1.widthSize.clone(0, 0.5)].myMaxSize); - label.heightSize.equalTo(@(MyLayoutSize.wrap)); - [rootLayout addSubview:label]; -} - --(void)testMaxAndMin -{ - -} -(void)testExample1 { From 849cac7b0a94b7f659d1a2e8210c8abe43afaee0 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Sat, 9 Nov 2019 10:30:19 +0800 Subject: [PATCH 075/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.h | 6 +- MyLayout/Lib/MyBaseLayout.m | 111 ++++++++++++++--------------- MyLayout/Lib/MyFloatLayout.m | 12 +--- MyLayout/Lib/MyFlowLayout.m | 11 +-- MyLayout/Lib/MyFrameLayout.m | 25 ++----- MyLayout/Lib/MyGridLayout.m | 18 ++--- MyLayout/Lib/MyLayoutInner.h | 15 ++-- MyLayout/Lib/MyLinearLayout.m | 119 +++++++++++++------------------- MyLayout/Lib/MyPathLayout.m | 12 +--- MyLayout/Lib/MyRelativeLayout.m | 17 +---- 10 files changed, 126 insertions(+), 220 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index 6f0febb..433184f 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -1064,13 +1064,15 @@ /** - *不建议使用这个属性了,而是直接设置视图的宽度为MyLayoutSize.wrap 比如:myWidth = MyLayoutSize.wrap 或者widthSize.equalTo(@(MyLayoutSize.wrap)) + *!!!不建议使用这个属性了,而是直接设置视图的宽度为MyLayoutSize.wrap。 比如:myWidth = MyLayoutSize.wrap 或者 widthSize.equalTo(@(MyLayoutSize.wrap))。 + *获取和判断的时候可以通过 myWidth == MyLayoutSize.wrap 或者 widthSize.isWrap 来比较判断 *视图的宽度包裹属性,表示视图的宽度由所有子视图的整体宽度来确定或者根据视图内容来宽度自适应。默认值是NO(水平线性布局默认这个属性是YES),表示必须要明确指定视图的宽度,而当设置为YES时则不需要明确的指定视图的宽度了。这个属性不能和widthSize(或者设置了左右边距)同时设置否则可能会产生约束冲突,因为前者表明宽度由子视图或者内容来决定而后者则表示宽度是一个明确的值。如果同时设置了宽度包裹属性又同时设置了明确的宽度则系统会出现约束冲突告警,虽然如此,系统在布局时做了一些优化,如果同时设置了明确的宽度和宽度包裹则会在布局前将宽度包裹属性置为NO。 */ @property(nonatomic,assign) BOOL wrapContentWidth; /** - *!!!!不建议使用这个属性了,而是直接设置视图的高度为MyLayoutSize.wrap 比如:myHeight = MyLayoutSize.wrap 或者heightSize.equalTo(@(MyLayoutSize.wrap)) + *!!!不建议使用这个属性了,而是直接设置视图的高度为MyLayoutSize.wrap。 比如:myHeight = MyLayoutSize.wrap 或者 heightSize.equalTo(@(MyLayoutSize.wrap))。 + *获取和判断的时候可以通过 myHeight == MyLayoutSize.wrap 或者 heightSize.isWrap 来比较判断 *视图的高度包裹属性,表示视图的高度由所有子视图的整体高度来确定或者根据视图内容来高度自适应。默认值是NO(垂直线性布局默认这个属性是YES),表示必须要明确指定布局的高度,而当设置为YES时则不需要明确的指定视图的高度了。这个属性不能和heightSize(或者设置了上下边距)同时设置否则可能会产生约束冲突,因为前者表明高度由子视图或者内容来决定而后者则表示高度是一个明确的值。如果同时设置了高度包裹属性又同时设置了明确的高度则系统会出现约束冲突告警,虽然如此,系统在布局时做了一些优化,如果同时设置了明确的高度和高度包裹则会在布局前将高度包裹属性置为NO。如果某个非布局视图指定了明确的宽度,而又将这个属性设置为了YES的话就能实现在固定宽度的情况下视图的高度根据内容自适应的效果,这个特性主要用于UILabel,UITextView以及实现了sizeThatFits方法的视图来实现高度根据内容自适应的场景。UILabel在使用这个属性时会自动设置numberOfLines为0,因此如果您要修改numberOfLines则需要在设置这个属性后进行;UITextView可以用这个属性以及heightSize中的max方法来实现到达指定的高度后若继续输入则产生滚动的效果;UIImageView可以用这个属性来在实现在确定宽度的情况下高度根据宽度的缩放情况进行等比例的缩放。 */ diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 469ccc0..32f59b8 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -2188,7 +2188,7 @@ -(void)layoutSubviews } //处理父视图是滚动视图时动态调整滚动视图的contentSize - [self myAlterScrollViewContentSize:newSelfSize lsc:lsc]; + [self myLayout:lsc adjustScrollViewContentWithSize:newSelfSize]; } @@ -3003,7 +3003,7 @@ -(CGFloat)myValidMeasure:(MyLayoutSize*)dime sbv:(UIView*)sbv calcSize:(CGFloat) } --(CGFloat)myGetBoundLimitMargin:(MyLayoutPos*)boundPos sbv:(UIView*)sbv selfLayoutSize:(CGSize)selfLayoutSize +-(CGFloat)myGetBound:(MyLayoutPos*)boundPos limitMarginOfSubview:(UIView*)sbv { CGFloat value = 0; if (boundPos == nil) @@ -3064,8 +3064,8 @@ -(CGFloat)myValidMargin:(MyLayoutPos*)pos sbv:(UIView*)sbv calcPos:(CGFloat)calc return calcPos; //算出最大最小值 - CGFloat min = (pos.isActive && pos.lBoundValInner != nil) ? [self myGetBoundLimitMargin:pos.lBoundValInner sbv:sbv selfLayoutSize:selfLayoutSize] : -CGFLOAT_MAX; - CGFloat max = (pos.isActive && pos.uBoundValInner != nil) ? [self myGetBoundLimitMargin:pos.uBoundValInner sbv:sbv selfLayoutSize:selfLayoutSize] : CGFLOAT_MAX; + CGFloat min = (pos.isActive && pos.lBoundValInner != nil) ? [self myGetBound:pos.lBoundValInner limitMarginOfSubview:sbv] : -CGFLOAT_MAX; + CGFloat max = (pos.isActive && pos.uBoundValInner != nil) ? [self myGetBound:pos.uBoundValInner limitMarginOfSubview:sbv] : CGFLOAT_MAX; calcPos = _myCGFloatMax(min, calcPos); calcPos = _myCGFloatMin(max, calcPos); @@ -3111,46 +3111,15 @@ -(NSMutableArray*)myGetLayoutSubviewsFrom:(NSArray*)sbsFrom } --(CGSize)myAdjustSizeWhenNoSubviews:(CGSize)size sbs:(NSArray *)sbs lsc:(MyBaseLayout*)lsc -{ - //如果没有子视图,并且padding不参与空子视图尺寸计算则尺寸应该扣除padding的值。 - if (sbs.count == 0 && !lsc.zeroPadding) - { - if (lsc.widthSizeInner.dimeWrapVal) - size.width -= (lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding); - if (lsc.heightSizeInner.dimeWrapVal) - size.height -= (lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding); - } - - return size; -} -- (void)myAdjustLayoutSelfSize:(CGSize *)pSelfSize lsc:(MyBaseLayout*)lsc +-(CGSize)myLayout:(MyBaseLayout*)lsc adjustSelfSize:(CGSize)selfSize withSubviews:(NSArray*)sbs { - //调整自己的尺寸。 - pSelfSize->height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:pSelfSize->height sbvSize:*pSelfSize selfLayoutSize:self.superview.bounds.size]; + //调整布局视图自己的尺寸。 + selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:selfSize.height sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; - pSelfSize->width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:pSelfSize->width sbvSize:*pSelfSize selfLayoutSize:self.superview.bounds.size]; -} - --(void)myAdjustSubviewsRTLPos:(NSArray*)sbs selfWidth:(CGFloat)selfWidth -{ - if ([MyBaseLayout isRTL]) - { - for (UIView *sbv in sbs) - { - MyFrame *myFrame = sbv.myFrame; - - myFrame.leading = selfWidth - myFrame.leading - myFrame.width; - myFrame.trailing = myFrame.leading + myFrame.width; - - } - } -} - - --(void)myAdjustSubviewsLayoutTransform:(NSArray*)sbs lsc:(MyBaseLayout*)lsc selfWidth:(CGFloat)selfWidth selfHeight:(CGFloat)selfHeight -{ + selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:selfSize.width sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + + //对所有子视图进行布局变换 CGAffineTransform layoutTransform = lsc.layoutTransform; if (!CGAffineTransformIsIdentity(layoutTransform)) { @@ -3159,15 +3128,15 @@ -(void)myAdjustSubviewsLayoutTransform:(NSArray*)sbs lsc:(MyBaseLayout*)lsc self MyFrame *myFrame = sbv.myFrame; //取子视图中心点坐标。因为这个坐标系的原点是布局视图的左上角,所以要转化为数学坐标系的原点坐标, 才能应用坐标变换。 - CGPoint centerPoint = CGPointMake(myFrame.leading + myFrame.width / 2 - selfWidth / 2, - myFrame.top + myFrame.height / 2 - selfHeight / 2); + CGPoint centerPoint = CGPointMake(myFrame.leading + myFrame.width / 2 - selfSize.width / 2, + myFrame.top + myFrame.height / 2 - selfSize.height / 2); //应用坐标变换 centerPoint = CGPointApplyAffineTransform(centerPoint, layoutTransform); //还原为左上角坐标系。 - centerPoint.x += selfWidth / 2; - centerPoint.y += selfHeight / 2; + centerPoint.x += selfSize.width / 2; + centerPoint.y += selfSize.height / 2; //根据中心点的变化调整开始和结束位置。 myFrame.leading = centerPoint.x - myFrame.width / 2; @@ -3176,6 +3145,28 @@ -(void)myAdjustSubviewsLayoutTransform:(NSArray*)sbs lsc:(MyBaseLayout*)lsc self myFrame.bottom = myFrame.top + myFrame.height; } } + + //对所有子视图进行RTL设置 + if ([MyBaseLayout isRTL]) + { + for (UIView *sbv in sbs) + { + MyFrame *myFrame = sbv.myFrame; + myFrame.leading = selfSize.width - myFrame.leading - myFrame.width; + myFrame.trailing = myFrame.leading + myFrame.width; + } + } + + //如果没有子视图,并且padding不参与空子视图尺寸计算则尺寸应该扣除padding的值。 + if (sbs.count == 0 && !lsc.zeroPadding) + { + if (lsc.widthSizeInner.dimeWrapVal) + selfSize.width -= (lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding); + if (lsc.heightSizeInner.dimeWrapVal) + selfSize.height -= (lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding); + } + + return selfSize; } -(MyGravity)myConvertLeftRightGravityToLeadingTrailing:(MyGravity)horzGravity @@ -3239,7 +3230,7 @@ -(CGFloat)myLayoutTrailingPadding } -- (void)myAlterScrollViewContentSize:(CGSize)newSize lsc:(MyBaseLayout*)lsc +- (void)myLayout:(MyBaseLayout*)lsc adjustScrollViewContentWithSize:(CGSize)newSize { if (self.adjustScrollViewContentSizeMode == MyAdjustScrollViewContentSizeModeYes && self.superview != nil && [self.superview isKindOfClass:[UIScrollView class]]) { @@ -3395,7 +3386,7 @@ -(void)myAddSubviewObserver:(UIView*)subview sbvmyFrame:(MyFrame*)sbvmyFrame } --(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame sbvsc:(UIView*)sbvsc selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout lsc:(MyBaseLayout*)lsc +-(void)myLayout:(MyBaseLayout*)lsc adjustSizeSettingOfSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout { if (!isEstimate) sbvmyFrame.frame = sbv.bounds; @@ -3524,18 +3515,18 @@ -(CGFloat)myGetSubviewHeightSizeValue:(UIView *)sbv --(void)myCalcSubViewRect:(UIView*)sbv - sbvsc:(UIView*)sbvsc - sbvmyFrame:(MyFrame*)sbvmyFrame - lsc:(MyBaseLayout*)lsc - vertGravity:(MyGravity)vertGravity - horzGravity:(MyGravity)horzGravity - inSelfSize:(CGSize)selfSize - paddingTop:(CGFloat)paddingTop - paddingLeading:(CGFloat)paddingLeading - paddingBottom:(CGFloat)paddingBottom - paddingTrailing:(CGFloat)paddingTrailing - pMaxWrapSize:(CGSize*)pMaxWrapSize +-(void)myLayout:(MyBaseLayout*)lsc +calcRectOfSubView:(UIView*)sbv + sbvsc:(UIView*)sbvsc + sbvmyFrame:(MyFrame*)sbvmyFrame + vertGravity:(MyGravity)vertGravity + horzGravity:(MyGravity)horzGravity + inSelfSize:(CGSize)selfSize + paddingTop:(CGFloat)paddingTop + paddingLeading:(CGFloat)paddingLeading + paddingBottom:(CGFloat)paddingBottom +paddingTrailing:(CGFloat)paddingTrailing + pMaxWrapSize:(CGSize*)pMaxWrapSize { @@ -3648,7 +3639,7 @@ -(void)myInvalidateIntrinsicContentSize } } --(void)myCalcSubviewsWrapContentSize:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSArray*)sbs withCustomSetting:(void (^)(UIView *sbv, UIView *sbvsc))customSetting +-(void)myCalcSubviewsWrapContentSize:(NSArray*)sbs isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass withCustomSetting:(void (^)(UIView *sbv, UIView *sbvsc))customSetting { for (UIView *sbv in sbs) { diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 8c71803..83d1097 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -130,7 +130,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyFloatLayout *lsc = self.myCurrentSizeClass; MyOrientation orientation = lsc.orientation; - [self myCalcSubviewsWrapContentSize:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs withCustomSetting:^(UIView *sbv, UIView *sbvsc) { + [self myCalcSubviewsWrapContentSize:sbs isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass withCustomSetting:^(UIView *sbv, UIView *sbvsc) { if (sbvsc.widthSizeInner.dimeWrapVal && orientation == MyOrientation_Vert && sbvsc.weight != 0) [sbvsc.widthSizeInner __setActive:NO]; @@ -145,14 +145,8 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( selfSize = [self myCalcLayoutSizeForHorzOrientation:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; - [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; - - //对所有子视图进行布局变换 - [self myAdjustSubviewsLayoutTransform:sbs lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; - //对所有子视图进行RTL设置 - [self myAdjustSubviewsRTLPos:sbs selfWidth:selfSize.width]; - - return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs lsc:lsc]; + return [self myLayout:lsc adjustSelfSize:selfSize withSubviews:sbs]; + } -(id)createSizeClassInstance diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 8be7db3..ccfa131 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -165,7 +165,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyGravity gravity = lsc.gravity; MyGravity arrangedGravity = lsc.arrangedGravity; - [self myCalcSubviewsWrapContentSize:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs withCustomSetting:^(UIView *sbv, UIView *sbvsc) { + [self myCalcSubviewsWrapContentSize:sbs isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass withCustomSetting:^(UIView *sbv, UIView *sbvsc) { if (sbvsc.widthSizeInner.dimeWrapVal) { @@ -205,14 +205,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( selfSize = [self myCalcLayoutSizeForHorzOrientation:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; } - //调整布局视图自己的尺寸。 - [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; - //对所有子视图进行布局变换 - [self myAdjustSubviewsLayoutTransform:sbs lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; - //对所有子视图进行RTL设置 - [self myAdjustSubviewsRTLPos:sbs selfWidth:selfSize.width]; - - return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs lsc:lsc]; + return [self myLayout:lsc adjustSelfSize:selfSize withSubviews:sbs]; } -(id)createSizeClassInstance diff --git a/MyLayout/Lib/MyFrameLayout.m b/MyLayout/Lib/MyFrameLayout.m index 72271dc..1a5adaa 100644 --- a/MyLayout/Lib/MyFrameLayout.m +++ b/MyLayout/Lib/MyFrameLayout.m @@ -52,24 +52,17 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyFrame *sbvmyFrame = sbv.myFrame; UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - [self myAdjustSubviewWrapContentSet:sbv isEstimate:isEstimate sbvmyFrame:sbvmyFrame sbvsc:sbvsc selfSize:selfSize vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout lsc:lsc]; + [self myLayout:lsc adjustSizeSettingOfSubview:sbv sbvsc:sbvsc isEstimate:isEstimate sbvmyFrame:sbvmyFrame selfSize:selfSize vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; //计算自己的位置和高宽 - [self myCalcSubViewRect:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame lsc:lsc vertGravity:vertGravity horzGravity:horzGravity inSelfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:pMaxWrapSize]; + [self myLayout:lsc calcRectOfSubView:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame vertGravity:vertGravity horzGravity:horzGravity inSelfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:pMaxWrapSize]; } if (lsc.widthSizeInner.dimeWrapVal) - { - selfSize.width = maxWrapSize.width; - } + selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:maxWrapSize.width sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; if (lsc.heightSizeInner.dimeWrapVal) - { - selfSize.height = maxWrapSize.height; - } - - //调整布局视图自己的尺寸。 - [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; + selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:maxWrapSize.height sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; //如果布局视图具有包裹属性这里要调整那些依赖父视图宽度和高度的子视图的位置和尺寸。 if ((lsc.widthSizeInner.dimeWrapVal && horzGravity != MyGravity_Horz_Fill) || (lsc.heightSizeInner.dimeWrapVal && vertGravity != MyGravity_Vert_Fill)) @@ -89,18 +82,12 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( (sbvsc.heightSizeInner.dimeRelaVal.view == self) ) { - [self myCalcSubViewRect:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame lsc:lsc vertGravity:vertGravity horzGravity:horzGravity inSelfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:NULL]; + [self myLayout:lsc calcRectOfSubView:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame vertGravity:vertGravity horzGravity:horzGravity inSelfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:NULL]; } } } - - //对所有子视图进行布局变换 - [self myAdjustSubviewsLayoutTransform:sbs lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; - //对所有子视图进行RTL设置 - [self myAdjustSubviewsRTLPos:sbs selfWidth:selfSize.width]; - - return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs lsc:lsc]; + return [self myLayout:lsc adjustSelfSize:selfSize withSubviews:sbs]; } -(id)createSizeClassInstance diff --git a/MyLayout/Lib/MyGridLayout.m b/MyLayout/Lib/MyGridLayout.m index 4e58db3..8dcb7b2 100644 --- a/MyLayout/Lib/MyGridLayout.m +++ b/MyLayout/Lib/MyGridLayout.m @@ -912,19 +912,9 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //处理那些剩余没有放入格子的子视图的frame设置为0 for (UIView *sbv = enumerator.nextObject; sbv; sbv = enumerator.nextObject) - { sbv.myFrame.frame = CGRectZero; - } - - - [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; - - //对所有子视图进行布局变换 - [self myAdjustSubviewsLayoutTransform:sbs lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; - //对所有子视图进行RTL设置 - [self myAdjustSubviewsRTLPos:sbs selfWidth:selfSize.width]; - return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs lsc:lsc]; + return [self myLayout:lsc adjustSelfSize:selfSize withSubviews:sbs]; } -(id)createSizeClassInstance @@ -1051,13 +1041,13 @@ -(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigi //如果尺寸是0则因为前面有算出尺寸,所以这里就不进行调整了。 if (grid.measure != 0 && [sbv isKindOfClass:[MyBaseLayout class]]) { - [self myAdjustSubviewWrapContentSet:sbv isEstimate:isEstimate sbvmyFrame:sbvmyFrame sbvsc:sbvsc selfSize:grid.gridRect.size vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout lsc:lsc]; + [self myLayout:lsc adjustSizeSettingOfSubview:sbv sbvsc:sbvsc isEstimate:isEstimate sbvmyFrame:sbvmyFrame selfSize:grid.gridRect.size vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; } else { } - [self myCalcSubViewRect:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame lsc:lsc vertGravity:vertGravity horzGravity:horzGravity inSelfSize:grid.gridRect.size paddingTop:tempPaddingTop paddingLeading:tempPaddingLeading paddingBottom:tempPaddingBottom paddingTrailing:tempPaddingTrailing pMaxWrapSize:NULL]; + [self myLayout:lsc calcRectOfSubView:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame vertGravity:vertGravity horzGravity:horzGravity inSelfSize:grid.gridRect.size paddingTop:tempPaddingTop paddingLeading:tempPaddingLeading paddingBottom:tempPaddingBottom paddingTrailing:tempPaddingTrailing pMaxWrapSize:NULL]; sbvmyFrame.leading += gridOrigin.x; sbvmyFrame.top += gridOrigin.y; @@ -1317,7 +1307,7 @@ -(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc } else { - [self myCalcSubViewRect:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame lsc:lsc vertGravity:MyGravity_None horzGravity:MyGravity_None inSelfSize:grid.gridRect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:NULL]; + [self myLayout:lsc calcRectOfSubView:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame vertGravity:MyGravity_None horzGravity:MyGravity_None inSelfSize:grid.gridRect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:NULL]; } if (grid.superGrid.subGridsType == MySubGridsType_Row) diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index a8d2369..afba770 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -88,13 +88,7 @@ -(NSMutableArray*)myGetLayoutSubviews; -(NSMutableArray*)myGetLayoutSubviewsFrom:(NSArray*)sbsFrom; --(CGSize)myAdjustSizeWhenNoSubviews:(CGSize)size sbs:(NSArray*)sbs lsc:(MyBaseLayout*)lsc; - -- (void)myAdjustLayoutSelfSize:(CGSize *)pSelfSize lsc:(MyBaseLayout*)lsc; - --(void)myAdjustSubviewsRTLPos:(NSArray*)sbs selfWidth:(CGFloat)selfWidth; - --(void)myAdjustSubviewsLayoutTransform:(NSArray*)sbs lsc:(MyBaseLayout*)lsc selfWidth:(CGFloat)selfWidth selfHeight:(CGFloat)selfHeight; +-(CGSize)myLayout:(MyBaseLayout*)lsc adjustSelfSize:(CGSize)selfSize withSubviews:(NSArray*)sbs; -(MyGravity)myConvertLeftRightGravityToLeadingTrailing:(MyGravity)horzGravity; @@ -106,7 +100,7 @@ -(CGFloat)myLayoutLeadingPadding; -(CGFloat)myLayoutTrailingPadding; --(void)myAdjustSubviewWrapContentSet:(UIView*)sbv isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame sbvsc:(UIView*)sbvsc selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout lsc:(MyBaseLayout*)lsc; +-(void)myLayout:(MyBaseLayout*)lsc adjustSizeSettingOfSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout; //根据子视图的宽度约束得到宽度值 @@ -132,10 +126,9 @@ sbvSize:(CGSize)sbvSize; --(void)myCalcSubViewRect:(UIView*)sbv +-(void)myLayout:(MyBaseLayout*)lsc calcRectOfSubView:(UIView*)sbv sbvsc:(UIView*)sbvsc sbvmyFrame:(MyFrame*)sbvmyFrame - lsc:(MyBaseLayout*)lsc vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity inSelfSize:(CGSize)selfSize @@ -152,7 +145,7 @@ //给父布局视图机会来更改子布局视图的边界线的显示的rect -(void)myHookSublayout:(MyBaseLayout*)sublayout borderlineRect:(CGRect*)pRect; --(void)myCalcSubviewsWrapContentSize:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSArray*)sbs withCustomSetting:(void (^)(UIView *sbv, UIView *sbvsc))customSetting; +-(void)myCalcSubviewsWrapContentSize:(NSArray*)sbs isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass withCustomSetting:(void (^)(UIView *sbv, UIView *sbvsc))customSetting; @end diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 36fe2af..17d3666 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -165,36 +165,25 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyGravity horzGravity = lsc.gravity & MyGravity_Vert_Mask; MyOrientation orientation = lsc.orientation; - [self myCalcSubviewsWrapContentSize:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs withCustomSetting:^(UIView *sbv, UIView *sbvsc) { + [self myCalcSubviewsWrapContentSize:sbs isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass withCustomSetting:^(UIView *sbv, UIView *sbvsc) { - [self myAdjustSubviewWrapContent:sbv sbvsc:sbvsc lsc:(MyLinearLayout*)lsc orientation:orientation gravity:(orientation == MyOrientation_Vert)? horzGravity : vertGravity]; + [self myLayout:lsc orientation:orientation gravity:(orientation == MyOrientation_Vert)? horzGravity : vertGravity adjustSizeSettingOfSubview:sbvsc]; }]; if (orientation == MyOrientation_Vert) - selfSize = [self myCalcLayoutSizeForVertOrientation:selfSize sbs:sbs lsc:lsc]; + selfSize = [self myVertOrientationLayout:lsc calcRectOfSubviews:sbs withSelfSize:selfSize]; else - selfSize = [self myCalcLayoutSizeForHorzOrientation:selfSize sbs:sbs lsc:lsc]; + selfSize = [self myHorzOrientationLayout:lsc calcRectOfSubviews:sbs withSelfSize:selfSize]; //绘制智能线。 if (!isEstimate) - { - [self mySetLayoutIntelligentBorderline:sbs lsc:lsc]; - } - - - //调整布局视图自己的尺寸。 - [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; - - //对所有子视图进行布局变换 - [self myAdjustSubviewsLayoutTransform:sbs lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; - //对所有子视图进行RTL设置 - [self myAdjustSubviewsRTLPos:sbs selfWidth:selfSize.width]; - - return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs lsc:lsc]; + [self myLayout:lsc setIntelligentBorderlineOnSubviews:sbs]; + return [self myLayout:lsc adjustSelfSize:selfSize withSubviews:sbs]; } + -(id)createSizeClassInstance { return [MyLinearLayoutViewSizeClass new]; @@ -204,7 +193,7 @@ -(id)createSizeClassInstance #pragma mark -- Private Methods //调整子视图的wrapContent设置 -- (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyLinearLayout*)lsc orientation:(MyOrientation)orientation gravity:(MyGravity)gravity +- (void)myLayout:(MyLinearLayout*)lsc orientation:(MyOrientation)orientation gravity:(MyGravity)gravity adjustSizeSettingOfSubview:(UIView*)sbvsc { if (orientation == MyOrientation_Vert) { @@ -237,7 +226,7 @@ - (void)myAdjustSubviewWrapContent:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyLine } //设置智能边界线 --(void)mySetLayoutIntelligentBorderline:(NSArray*)sbs lsc:(MyLinearLayout*)lsc +-(void)myLayout:(MyLinearLayout*)lsc setIntelligentBorderlineOnSubviews:(NSArray*)sbs { if (self.intelligentBorderline == nil) return; @@ -269,14 +258,10 @@ -(void)mySetLayoutIntelligentBorderline:(NSArray*)sbs lsc:(MyLinearLayout*)lsc UIView *nextSiblingView = nil; if (i != 0) - { prevSiblingView = sbs[i - 1]; - } if (i + 1 != sbs.count) - { nextSiblingView = sbs[i + 1]; - } if (prevSiblingView != nil) { @@ -307,7 +292,7 @@ -(void)mySetLayoutIntelligentBorderline:(NSArray*)sbs lsc:(MyLinearLayout*)lsc } } --(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinearLayout*)lsc +-(CGSize)myVertOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArray*)sbs withSelfSize:(CGSize)selfSize { CGFloat subviewSpace = lsc.subviewVSpace; CGFloat paddingTop = lsc.myLayoutTopPadding; @@ -387,14 +372,14 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; //计算子视图宽度以及对齐, 先计算宽度的原因是处理那些高度依赖宽度并且是wrap的情况。 - CGFloat tempSelfWidth = [self myCalcSubviewLeadingTrailingRect:horzGravity - selfSize:selfSize - pRect:&rect - sbv:sbv - paddingTrailing:paddingTrailing - paddingLeading:paddingLeading - sbvsc:sbvsc - lsc:lsc]; + CGFloat tempSelfWidth = [self myLayout:lsc + calcSubview:sbv + sbvsc:sbvsc + leadingTrailingRect:&rect + horzGravity:horzGravity + paddingTrailing:paddingTrailing + paddingLeading:paddingLeading + selfSize:selfSize]; @@ -679,17 +664,13 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l pos += addSpace; if (isWeightShrinkSpace) - { pos += weightShrinkSpaceTotalHeight * (topSpace + sbvsc.topPosInner.offsetVal) / fixedSpaceHeight; - } } } topSpace += sbvsc.topPosInner.offsetVal; if (totalShrink != 0.0 && sbvsc.topPosInner.shrink != 0.0) - { topSpace += (sbvsc.topPosInner.shrink / totalShrink) * spareHeight; - } pos += [self myValidMargin:sbvsc.topPosInner sbv:sbv calcPos:topSpace selfLayoutSize:selfSize]; rect.origin.y = pos; @@ -721,14 +702,14 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } //计算子视图宽度以及对齐 - CGFloat tempSelfWidth = [self myCalcSubviewLeadingTrailingRect:horzGravity - selfSize:selfSize - pRect:&rect - sbv:sbv - paddingTrailing:paddingTrailing - paddingLeading:paddingLeading - sbvsc:sbvsc - lsc:lsc]; + CGFloat tempSelfWidth = [self myLayout:lsc + calcSubview:sbv + sbvsc:sbvsc + leadingTrailingRect:&rect + horzGravity:horzGravity + paddingTrailing:paddingTrailing + paddingLeading:paddingLeading + selfSize:selfSize]; if ((tempSelfWidth > maxSelfWidth) && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) && @@ -754,17 +735,13 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l pos += addSpace; if (isWeightShrinkSpace) - { pos += weightShrinkSpaceTotalHeight * (bottomSpace + sbvsc.bottomPosInner.offsetVal) / fixedSpaceHeight; - } } } bottomSpace += sbvsc.bottomPosInner.offsetVal; if (totalShrink != 0.0 && sbvsc.bottomPosInner.shrink != 0.0) - { bottomSpace += (sbvsc.bottomPosInner.shrink / totalShrink) * spareHeight; - } pos += [self myValidMargin:sbvsc.bottomPosInner sbv:sbv calcPos:bottomSpace selfLayoutSize:selfSize]; @@ -778,9 +755,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l pos += addSpace; if (isWeightShrinkSpace) - { pos += weightShrinkSpaceTotalHeight * subviewSpace / fixedSpaceHeight; - } } pos += between; //只有mgvert为between才加这个间距拉伸。 @@ -801,7 +776,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l return selfSize; } --(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs lsc:(MyLinearLayout*)lsc +-(CGSize)myHorzOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArray*)sbs withSelfSize:(CGSize)selfSize { CGFloat subviewSpace = lsc.subviewHSpace; CGFloat paddingTop = lsc.myLayoutTopPadding; @@ -885,15 +860,15 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l } //计算子视图高度以及对齐 - CGFloat tempSelfHeight = [self myCalcSubviewTopBottomRect:vertGravity - selfSize:selfSize - pRect:&rect - sbv:sbv - paddingTop:paddingTop - paddingBottom:paddingBottom - baselinePos:baselinePos - sbvsc:sbvsc - lsc:lsc]; + CGFloat tempSelfHeight = [self myLayout:lsc + calcSubview:sbv + sbvsc:sbvsc + topBottomRect:&rect + vertGravity:vertGravity + paddingTop:paddingTop + paddingBottom:paddingBottom + baselinePos:baselinePos + selfSize:selfSize]; if ((tempSelfHeight > maxSelfHeight) && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) && @@ -1267,15 +1242,15 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; } - CGFloat tempSelfHeight = [self myCalcSubviewTopBottomRect:vertGravity - selfSize:selfSize - pRect:&rect - sbv:sbv - paddingTop:paddingTop - paddingBottom:paddingBottom - baselinePos:baselinePos - sbvsc:sbvsc - lsc:lsc]; + CGFloat tempSelfHeight = [self myLayout:lsc + calcSubview:sbv + sbvsc:sbvsc + topBottomRect:&rect + vertGravity:vertGravity + paddingTop:paddingTop + paddingBottom:paddingBottom + baselinePos:baselinePos + selfSize:selfSize]; if ((tempSelfHeight > maxSelfHeight) && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) && @@ -1347,7 +1322,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs l return selfSize; } -- (CGFloat)myCalcSubviewLeadingTrailingRect:(MyGravity)horzGravity selfSize:(CGSize)selfSize pRect:(CGRect *)pRect sbv:(UIView *)sbv paddingTrailing:(CGFloat)paddingTrailing paddingLeading:(CGFloat)paddingLeading sbvsc:(UIView *)sbvsc lsc:(MyLinearLayout*)lsc +- (CGFloat)myLayout:(MyLinearLayout*)lsc calcSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc leadingTrailingRect:(CGRect *)pRect horzGravity:(MyGravity)horzGravity paddingTrailing:(CGFloat)paddingTrailing paddingLeading:(CGFloat)paddingLeading selfSize:(CGSize)selfSize { pRect->size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:lsc.myLayoutTopPadding paddingLeading:paddingLeading paddingBottom:lsc.myLayoutBottomPadding paddingTrailing:paddingTrailing sbvSize:pRect->size]; @@ -1365,7 +1340,7 @@ - (CGFloat)myCalcSubviewLeadingTrailingRect:(MyGravity)horzGravity selfSize:(CGS return [self myCalcHorzGravity:[self myGetSubviewHorzGravity:sbv sbvsc:sbvsc horzGravity:horzGravity] sbv:sbv sbvsc:sbvsc paddingLeading:paddingLeading paddingTrailing:paddingTrailing selfSize:selfSize pRect:pRect]; } -- (CGFloat)myCalcSubviewTopBottomRect:(MyGravity)vertGravity selfSize:(CGSize)selfSize pRect:(CGRect *)pRect sbv:(UIView *)sbv paddingTop:(CGFloat)paddingTop paddingBottom:(CGFloat)paddingBottom baselinePos:(CGFloat)baselinePos sbvsc:(UIView *)sbvsc lsc:(MyLinearLayout*)lsc +- (CGFloat)myLayout:(MyLinearLayout*)lsc calcSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc topBottomRect:(CGRect *)pRect vertGravity:(MyGravity)vertGravity paddingTop:(CGFloat)paddingTop paddingBottom:(CGFloat)paddingBottom baselinePos:(CGFloat)baselinePos selfSize:(CGSize)selfSize { pRect->size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:lsc.myLayoutLeadingPadding paddingBottom:paddingBottom paddingTrailing:lsc.myLayoutTrailingPadding sbvSize:pRect->size]; diff --git a/MyLayout/Lib/MyPathLayout.m b/MyLayout/Lib/MyPathLayout.m index 2d12bbe..ac4c8dd 100644 --- a/MyLayout/Lib/MyPathLayout.m +++ b/MyLayout/Lib/MyPathLayout.m @@ -540,7 +540,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - [self myCalcSubviewsWrapContentSize:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs2 withCustomSetting:nil]; + [self myCalcSubviewsWrapContentSize:sbs2 isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass withCustomSetting:nil]; CGFloat minXPos = CGFLOAT_MAX; @@ -680,15 +680,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (lsc.heightSizeInner.dimeWrapVal) selfSize.height = maxYPos - minYPos; - //调整布局视图自己的尺寸。 - [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; - - //对所有子视图进行布局变换 - [self myAdjustSubviewsLayoutTransform:sbs lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; - - //路径布局不支持RTL。 - - return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs2 lsc:lsc]; + return [self myLayout:lsc adjustSelfSize:selfSize withSubviews:sbs2]; } -(id)createSizeClassInstance diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index bb70f82..5c59e64 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -117,21 +117,10 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( } } - - - //调整布局视图自己的尺寸。 - [self myAdjustLayoutSelfSize:&selfSize lsc:lsc]; - + //如果是反向则调整所有子视图的左右位置。 - NSArray *sbs2 = [self myGetLayoutSubviews]; - - //对所有子视图进行布局变换 - [self myAdjustSubviewsLayoutTransform:sbs2 lsc:lsc selfWidth:selfSize.width selfHeight:selfSize.height]; - //对所有子视图进行RTL设置 - [self myAdjustSubviewsRTLPos:sbs2 selfWidth:selfSize.width]; - - return [self myAdjustSizeWhenNoSubviews:selfSize sbs:sbs2 lsc:lsc]; - + sbs = [self myGetLayoutSubviews]; + return [self myLayout:lsc adjustSelfSize:selfSize withSubviews:sbs]; } -(id)createSizeClassInstance From 043b3af9f39e63fe829ab595f90a94d5a126f889 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Sun, 10 Nov 2019 00:34:14 +0800 Subject: [PATCH 076/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 333 +++++++------------------------ MyLayout/Lib/MyBorderline.m | 5 - MyLayout/Lib/MyDimeScale.m | 3 - MyLayout/Lib/MyFlexLayout.m | 17 +- MyLayout/Lib/MyFloatLayout.m | 141 ++++--------- MyLayout/Lib/MyFlowLayout.m | 198 ++++++++---------- MyLayout/Lib/MyFrameLayout.m | 30 +-- MyLayout/Lib/MyGridLayout.m | 142 +------------ MyLayout/Lib/MyGridNode.m | 75 ------- MyLayout/Lib/MyLayoutDelegate.m | 47 ----- MyLayout/Lib/MyLayoutInner.h | 93 +++++---- MyLayout/Lib/MyLayoutMath.m | 10 - MyLayout/Lib/MyLayoutPos.m | 83 +------- MyLayout/Lib/MyLayoutSize.m | 53 ----- MyLayout/Lib/MyLayoutSizeClass.h | 42 +--- MyLayout/Lib/MyLayoutSizeClass.m | 98 +-------- MyLayout/Lib/MyLinearLayout.m | 118 +++-------- MyLayout/Lib/MyMaker.m | 73 +------ MyLayout/Lib/MyPathLayout.m | 37 ++-- MyLayout/Lib/MyRelativeLayout.m | 183 ++++++++--------- MyLayout/Lib/MyTableLayout.m | 13 +- 21 files changed, 394 insertions(+), 1400 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 32f59b8..94a00b7 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -11,7 +11,6 @@ #import "MyLayoutDelegate.h" #import - const char * const ASSOCIATEDOBJECT_KEY_MYLAYOUT_FRAME = "ASSOCIATEDOBJECT_KEY_MYLAYOUT_FRAME"; void* _myObserverContextA = (void*)20175281; @@ -24,14 +23,11 @@ @interface MyLayoutDragger() @property(nonatomic, assign) NSUInteger currentIndex; @property(nonatomic, assign) NSUInteger oldIndex; @property(nonatomic, assign) BOOL hasDragging; - @property(nonatomic, weak) MyBaseLayout *layout; - @end - /** 窗口对RTL的支持。 */ @@ -90,7 +86,6 @@ -(MyLayoutPos*)baselinePos return self.myCurrentSizeClass.baselinePos; } - -(CGFloat)myTop { #if DEBUG @@ -117,7 +112,6 @@ -(void)setMyLeading:(CGFloat)myLeading self.myCurrentSizeClass.myLeading = myLeading; } - -(CGFloat)myBottom { #if DEBUG @@ -131,8 +125,6 @@ -(void)setMyBottom:(CGFloat)myBottom self.myCurrentSizeClass.myBottom = myBottom; } - - -(CGFloat)myTrailing { #if DEBUG @@ -146,7 +138,6 @@ -(void)setMyTrailing:(CGFloat)myTrailing self.myCurrentSizeClass.myTrailing = myTrailing; } - -(CGFloat)myCenterX { #if DEBUG @@ -173,7 +164,6 @@ -(void)setMyCenterY:(CGFloat)myCenterY self.myCurrentSizeClass.myCenterY = myCenterY; } - -(CGPoint)myCenter { #if DEBUG @@ -187,7 +177,6 @@ -(void)setMyCenter:(CGPoint)myCenter self.myCurrentSizeClass.myCenter = myCenter; } - -(CGFloat)myLeft { #if DEBUG @@ -214,7 +203,6 @@ -(void)setMyRight:(CGFloat)myRight self.myCurrentSizeClass.myRight = myRight; } - -(CGFloat)myMargin { #if DEBUG @@ -241,7 +229,6 @@ -(void)setMyHorzMargin:(CGFloat)myHorzMargin self.myCurrentSizeClass.myHorzMargin = myHorzMargin; } - -(CGFloat)myVertMargin { #if DEBUG @@ -255,25 +242,21 @@ -(void)setMyVertMargin:(CGFloat)myVertMargin self.myCurrentSizeClass.myVertMargin = myVertMargin; } - -(MyLayoutSize*)widthSize { return self.myCurrentSizeClass.widthSize; } - -(MyLayoutSize*)heightSize { return self.myCurrentSizeClass.heightSize; } - -(CGFloat)myWidth { return self.myCurrentSizeClass.myWidth; } - -(void)setMyWidth:(CGFloat)myWidth { self.myCurrentSizeClass.myWidth = myWidth; @@ -337,7 +320,6 @@ -(BOOL)wrapContentWidth return self.myCurrentSizeClassInner.wrapContentWidth; } - -(BOOL)wrapContentSize { return self.myCurrentSizeClassInner.wrapContentSize; @@ -367,7 +349,6 @@ -(void)setWeight:(CGFloat)weight } } - -(BOOL)useFrame { return self.myCurrentSizeClass.useFrame; @@ -382,7 +363,6 @@ -(void)setUseFrame:(BOOL)useFrame if (self.superview != nil) [ self.superview setNeedsLayout]; } - } -(BOOL)noLayout @@ -399,7 +379,6 @@ -(void)setNoLayout:(BOOL)noLayout if (self.superview != nil) [ self.superview setNeedsLayout]; } - } -(MyVisibility)visibility @@ -459,7 +438,6 @@ -(MyGravity)myAlignment return self.alignment; } - -(void (^)(MyBaseLayout*, UIView*))viewLayoutCompleteBlock { return self.myCurrentSizeClass.viewLayoutCompleteBlock; @@ -470,7 +448,6 @@ -(void)setViewLayoutCompleteBlock:(void (^)(MyBaseLayout *, UIView *))viewLayout self.myCurrentSizeClass.viewLayoutCompleteBlock = viewLayoutCompleteBlock; } - -(CGRect)estimatedRect { CGRect rect = self.myFrame.frame; @@ -479,7 +456,6 @@ -(CGRect)estimatedRect return rect; } - -(void)resetMyLayoutSetting { [self resetMyLayoutSettingInSizeClass:MySizeClass_wAny | MySizeClass_hAny]; @@ -490,7 +466,6 @@ -(void)resetMyLayoutSettingInSizeClass:(MySizeClass)sizeClass [self.myFrame.sizeClasses removeObjectForKey:@(sizeClass)]; } - -(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass { return [self fetchLayoutSizeClass:sizeClass copyFrom:0xFF]; @@ -515,7 +490,6 @@ -(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass copyFrom:(MySizeClass } return (UIView*)myLayoutSizeClass; - } @end @@ -523,7 +497,6 @@ -(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass copyFrom:(MySizeClass @implementation UIView(MyLayoutExtInner) - -(instancetype)myDefaultSizeClass { return [self fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hAny]; @@ -550,10 +523,8 @@ -(instancetype)myCurrentSizeClassFrom:(MyFrame*)myFrame return myFrame.sizeClass; } - -(instancetype)myBestSizeClass:(MySizeClass)sizeClass myFrame:(MyFrame*)myFrame { - MySizeClass wsc = sizeClass & 0x03; MySizeClass hsc = sizeClass & 0x0C; MySizeClass ori = sizeClass & 0xC0; @@ -561,7 +532,6 @@ -(instancetype)myBestSizeClass:(MySizeClass)sizeClass myFrame:(MyFrame*)myFrame if (myFrame.sizeClasses == nil) myFrame.sizeClasses = [NSMutableDictionary new]; - MySizeClass searchSizeClass; MyViewSizeClass *myClass = nil; if (myFrame.multiple) @@ -581,14 +551,12 @@ -(instancetype)myBestSizeClass:(MySizeClass)sizeClass myFrame:(MyFrame*)myFrame return (UIView*)myClass; } - searchSizeClass = MySizeClass_wAny | hsc | ori; if (ori != 0 && searchSizeClass != sizeClass) { myClass = (MyViewSizeClass*)[myFrame.sizeClasses objectForKey:@(searchSizeClass)]; if (myClass != nil) return (UIView*)myClass; - } searchSizeClass = MySizeClass_wAny | hsc; @@ -622,7 +590,6 @@ -(instancetype)myBestSizeClass:(MySizeClass)sizeClass myFrame:(MyFrame*)myFrame if (myClass != nil) return (UIView*)myClass; } - } searchSizeClass = MySizeClass_wAny | MySizeClass_hAny; @@ -635,20 +602,16 @@ -(instancetype)myBestSizeClass:(MySizeClass)sizeClass myFrame:(MyFrame*)myFrame } return (UIView*)myClass; - - } -(MyFrame*)myFrame { - MyFrame *obj = objc_getAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_FRAME); if (obj == nil) { obj = [MyFrame new]; objc_setAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_FRAME, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - } return obj; @@ -659,7 +622,6 @@ -(id)createSizeClassInstance return [MyViewSizeClass new]; } - -(MyLayoutPos*)topPosInner { return self.myCurrentSizeClass.topPosInner; @@ -680,7 +642,6 @@ -(MyLayoutPos*)trailingPosInner return self.myCurrentSizeClass.trailingPosInner; } - -(MyLayoutPos*)centerXPosInner { return self.myCurrentSizeClass.centerXPosInner; @@ -691,7 +652,6 @@ -(MyLayoutPos*)centerYPosInner return self.myCurrentSizeClass.centerYPosInner; } - -(MyLayoutPos*)leftPosInner { return self.myCurrentSizeClass.leftPosInner; @@ -702,25 +662,21 @@ -(MyLayoutPos*)rightPosInner return self.myCurrentSizeClass.rightPosInner; } - -(MyLayoutPos*)baselinePosInner { return self.myCurrentSizeClass.baselinePosInner; } - -(MyLayoutSize*)widthSizeInner { return self.myCurrentSizeClass.widthSizeInner; } - -(MyLayoutSize*)heightSizeInner { return self.myCurrentSizeClass.heightSizeInner; } - -(CGFloat)myEstimatedWidth { //如果视图的父视图不是布局视图则直接返回宽度值。 @@ -752,26 +708,19 @@ -(CGFloat)myEstimatedHeight } } - @end - @implementation MyBaseLayout { MyLayoutTouchEventDelegate *_touchEventDelegate; - MyBorderlineLayerDelegate *_borderlineLayerDelegate; - BOOL _isAddSuperviewKVO; - int _lastScreenOrientation; //为0为初始状态,为1为竖屏,为2为横屏。内部使用。 - BOOL _useCacheRects; } - -(void)dealloc { //如果您在使用时出现了KVO的异常崩溃,原因是您将这个视图被多次加入为子视图,请检查您的代码,是否这个视图被多次加入!! @@ -782,7 +731,6 @@ -(void)dealloc #pragma mark -- Public Methods - +(BOOL)isRTL { return [MyViewSizeClass isRTL]; @@ -802,7 +750,6 @@ + (void)myUpArabicUI:(BOOL)isArabicUI inWindow:(UIWindow *)window [self updateRTL:isArabicUI inWindow:window]; } - -(CGFloat)topPadding { return self.myCurrentSizeClass.topPadding; @@ -833,7 +780,6 @@ -(void)setLeadingPadding:(CGFloat)leadingPadding } } - -(CGFloat)bottomPadding { return self.myCurrentSizeClass.bottomPadding; @@ -849,7 +795,6 @@ -(void)setBottomPadding:(CGFloat)bottomPadding } } - -(CGFloat)trailingPadding { return self.myCurrentSizeClass.trailingPadding; @@ -865,7 +810,6 @@ -(void)setTrailingPadding:(CGFloat)trailingPadding } } - -(UIEdgeInsets)padding { return self.myCurrentSizeClass.padding; @@ -881,7 +825,6 @@ -(void)setPadding:(UIEdgeInsets)padding } } - -(CGFloat)leftPadding { return self.myCurrentSizeClass.leftPadding; @@ -897,7 +840,6 @@ -(void)setLeftPadding:(CGFloat)leftPadding } } - -(CGFloat)rightPadding { return self.myCurrentSizeClass.rightPadding; @@ -1007,7 +949,6 @@ -(CGFloat)subviewSpace -(void)setGravity:(MyGravity)gravity { - MyBaseLayout *lsc = self.myCurrentSizeClass; if (lsc.gravity != gravity) { @@ -1021,11 +962,8 @@ -(MyGravity)gravity return self.myCurrentSizeClass.gravity; } - - -(void)setReverseLayout:(BOOL)reverseLayout { - MyBaseLayout *lsc = self.myCurrentSizeClass; if (lsc.reverseLayout != reverseLayout) { @@ -1039,8 +977,6 @@ -(BOOL)reverseLayout return self.myCurrentSizeClass.reverseLayout; } - - -(CGAffineTransform)layoutTransform { return self.myCurrentSizeClass.layoutTransform; @@ -1061,7 +997,6 @@ -(void)removeAllSubviews [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; } - -(void)layoutAnimationWithDuration:(NSTimeInterval)duration { self.beginLayoutBlock = ^{ @@ -1074,7 +1009,6 @@ -(void)layoutAnimationWithDuration:(NSTimeInterval)duration [UIView commitAnimations]; }; - } -(MyBorderline*)topBorderline @@ -1085,9 +1019,7 @@ -(MyBorderline*)topBorderline -(void)setTopBorderline:(MyBorderline *)topBorderline { if (_borderlineLayerDelegate == nil) - { _borderlineLayerDelegate = [[MyBorderlineLayerDelegate alloc] initWithLayoutLayer:self.layer]; - } _borderlineLayerDelegate.topBorderline = topBorderline; } @@ -1100,9 +1032,7 @@ -(MyBorderline*)leadingBorderline -(void)setLeadingBorderline:(MyBorderline *)leadingBorderline { if (_borderlineLayerDelegate == nil) - { _borderlineLayerDelegate = [[MyBorderlineLayerDelegate alloc] initWithLayoutLayer:self.layer]; - } _borderlineLayerDelegate.leadingBorderline = leadingBorderline; } @@ -1115,14 +1045,11 @@ -(MyBorderline*)bottomBorderline -(void)setBottomBorderline:(MyBorderline *)bottomBorderline { if (_borderlineLayerDelegate == nil) - { _borderlineLayerDelegate = [[MyBorderlineLayerDelegate alloc] initWithLayoutLayer:self.layer]; - } _borderlineLayerDelegate.bottomBorderline = bottomBorderline; } - -(MyBorderline*)trailingBorderline { return _borderlineLayerDelegate.trailingBorderline; @@ -1131,15 +1058,11 @@ -(MyBorderline*)trailingBorderline -(void)setTrailingBorderline:(MyBorderline *)trailingBorderline { if (_borderlineLayerDelegate == nil) - { _borderlineLayerDelegate = [[MyBorderlineLayerDelegate alloc] initWithLayoutLayer:self.layer]; - } _borderlineLayerDelegate.trailingBorderline = trailingBorderline; } - - -(MyBorderline*)leftBorderline { return _borderlineLayerDelegate.leftBorderline; @@ -1148,14 +1071,11 @@ -(MyBorderline*)leftBorderline -(void)setLeftBorderline:(MyBorderline *)leftBorderline { if (_borderlineLayerDelegate == nil) - { _borderlineLayerDelegate = [[MyBorderlineLayerDelegate alloc] initWithLayoutLayer:self.layer]; - } _borderlineLayerDelegate.leftBorderline = leftBorderline; } - -(MyBorderline*)rightBorderline { return _borderlineLayerDelegate.rightBorderline; @@ -1164,14 +1084,11 @@ -(MyBorderline*)rightBorderline -(void)setRightBorderline:(MyBorderline *)rightBorderline { if (_borderlineLayerDelegate == nil) - { _borderlineLayerDelegate = [[MyBorderlineLayerDelegate alloc] initWithLayoutLayer:self.layer]; - } _borderlineLayerDelegate.rightBorderline = rightBorderline; } - -(void)setBoundBorderline:(MyBorderline *)boundBorderline { self.leadingBorderline = boundBorderline; @@ -1194,14 +1111,12 @@ -(void)setBackgroundImage:(UIImage *)backgroundImage } } - -(void)setCacheEstimatedRect:(BOOL)cacheEstimatedRect { _cacheEstimatedRect = cacheEstimatedRect; _useCacheRects = NO; } - -(CGRect)subview:(UIView*)subview estimatedRectInLayoutSize:(CGSize)size { if (subview.superview == self) @@ -1215,8 +1130,6 @@ -(CGRect)subview:(UIView*)subview estimatedRectInLayoutSize:(CGSize)size return [subview estimatedRect]; } - - -(void)setHighlightedOpacity:(CGFloat)highlightedOpacity { if (_touchEventDelegate == nil) @@ -1256,7 +1169,6 @@ -(UIImage*)highlightedBackgroundImage return _touchEventDelegate.highlightedBackgroundImage; } - -(void)setTarget:(id)target action:(SEL)action { if (_touchEventDelegate == nil) @@ -1265,7 +1177,6 @@ -(void)setTarget:(id)target action:(SEL)action [_touchEventDelegate setTarget:target action:action]; } - -(void)setTouchDownTarget:(id)target action:(SEL)action { if (_touchEventDelegate == nil) @@ -1280,10 +1191,8 @@ -(void)setTouchCancelTarget:(id)target action:(SEL)action _touchEventDelegate = [[MyLayoutTouchEventDelegate alloc] initWithLayout:self]; [_touchEventDelegate setTouchCancelTarget:target action:action]; - } - -(MyLayoutDragger*)createLayoutDragger { MyLayoutDragger *dragger = [MyLayoutDragger new]; @@ -1295,15 +1204,11 @@ -(MyLayoutDragger*)createLayoutDragger } - - #pragma mark -- Touches Event - - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [_touchEventDelegate touchesBegan:touches withEvent:event]; - [super touchesBegan:touches withEvent:event]; } @@ -1313,7 +1218,6 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event [super touchesMoved:touches withEvent:event]; } - - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [_touchEventDelegate touchesEnded:touches withEvent:event]; @@ -1326,11 +1230,8 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event [super touchesCancelled:touches withEvent:event]; } - - #pragma mark -- KVO - - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIView*)object change:(NSDictionary *)change context:(void *)context { //监控非布局父视图的frame的变化,而改变自身的位置和尺寸 @@ -1341,11 +1242,9 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIView*)object chan CGRect rcNew = [change[NSKeyValueChangeNewKey] CGRectValue]; if (!_myCGSizeEqual(rcOld.size, rcNew.size)) [self myUpdateLayoutRectInNoLayoutSuperview:object]; - return; } - //监控子视图的frame的变化以便重新进行布局 if (!_isMyLayouting) { @@ -1368,8 +1267,6 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIView*)object chan #pragma mark -- Override Methods - - -(void)setWrapContentHeight:(BOOL)wrapContentHeight { MyBaseLayout *lsc = self.myCurrentSizeClass; @@ -1380,7 +1277,6 @@ -(void)setWrapContentHeight:(BOOL)wrapContentHeight } } - -(void)setWrapContentWidth:(BOOL)wrapContentWidth { MyBaseLayout *lsc = self.myCurrentSizeClass; @@ -1389,7 +1285,6 @@ -(void)setWrapContentWidth:(BOOL)wrapContentWidth lsc.wrapContentWidth = wrapContentWidth; [self setNeedsLayout]; } - } -(void)setWrapContentSize:(BOOL)wrapContentSize @@ -1399,13 +1294,13 @@ -(void)setWrapContentSize:(BOOL)wrapContentSize [self setNeedsLayout]; } - - -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { CGSize selfSize; if (isEstimate) + { selfSize = self.myFrame.frame.size; + } else { selfSize = self.bounds.size; @@ -1419,7 +1314,6 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( *pHasSubLayout = NO; return selfSize; - } @@ -1481,7 +1375,6 @@ -(void)setFrame:(CGRect)frame } } - - (void)didAddSubview:(UIView *)subview { [super didAddSubview:subview]; //只要加入进来后就修改其默认的实现,而改用我们的实现,这里包括隐藏,调整大小, @@ -1492,7 +1385,6 @@ - (void)didAddSubview:(UIView *)subview } [self myInvalidateIntrinsicContentSize]; - } - (void)willRemoveSubview:(UIView *)subview @@ -1585,7 +1477,6 @@ - (void)willMoveToSuperview:(UIView*)newSuperview { //约束冲突:下边距依赖的视图不是父视图 NSCAssert(lsc.bottomPosInner.posRelaVal.view == newSuperview, @"Constraint exception!! %@bottom pos dependent on:%@is not superview",self, lsc.bottomPosInner.posRelaVal.view); - } if (lsc.centerYPosInner.posRelaVal != nil) @@ -1607,7 +1498,6 @@ - (void)willMoveToSuperview:(UIView*)newSuperview } #endif - if ([self myUpdateLayoutRectInNoLayoutSuperview:newSuperview]) { //有可能父视图不为空,所以这里先把以前父视图的KVO删除。否则会导致程序崩溃 @@ -1619,24 +1509,18 @@ - (void)willMoveToSuperview:(UIView*)newSuperview { @try { [self.superview removeObserver:self forKeyPath:@"frame"]; - } @catch (NSException *exception) { - } @finally { - } @try { [self.superview removeObserver:self forKeyPath:@"bounds"]; - } @catch (NSException *exception) { - } @finally { - } } @@ -1646,38 +1530,29 @@ - (void)willMoveToSuperview:(UIView*)newSuperview } } - if (_isAddSuperviewKVO && newSuperview == nil && self.superview != nil && ![self.superview isKindOfClass:[MyBaseLayout class]]) { - //如果您在这里出现了崩溃时,不要惊慌,是因为您开启了异常断点调试的原因。这个在release下是不会出现的,要想清除异常断点调试功能,请按下CMD+7键 //然后在左边将异常断点清除即可 - _isAddSuperviewKVO = NO; @try { [self.superview removeObserver:self forKeyPath:@"frame"]; } @catch (NSException *exception) { - } @finally { - } @try { [self.superview removeObserver:self forKeyPath:@"bounds"]; - } @catch (NSException *exception) { - } @finally { - } } - if (newSuperview != nil) { //不支持放在UITableView和UICollectionView下,因为有肯能是tableheaderView或者section下。 @@ -1706,7 +1581,6 @@ - (void)willMoveToSuperview:(UIView*)newSuperview } } - -(void)awakeFromNib { [super awakeFromNib]; @@ -1717,7 +1591,6 @@ -(void)awakeFromNib -(void)safeAreaInsetsDidChange { - #if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) [super safeAreaInsetsDidChange]; @@ -1739,7 +1612,6 @@ -(void)safeAreaInsetsDidChange } } - -(void)setNeedsLayout { [super setNeedsLayout]; @@ -1871,12 +1743,10 @@ -(CGSize)intrinsicContentSize } return sz; - } -(void)layoutSubviews { - if (!self.autoresizesSubviews) return; @@ -1886,10 +1756,8 @@ -(void)layoutSubviews int currentScreenOrientation = 0; - if (!self.isMyLayouting) { - self.isMyLayouting = YES; if (self.priorAutoresizingMask) @@ -1917,7 +1785,6 @@ -(void)layoutSubviews MyBaseLayout *lsc = (MyBaseLayout*)selfMyFrame.sizeClass; - //计算布局 CGSize oldSelfSize = self.bounds.size; CGSize newSelfSize; @@ -1940,7 +1807,7 @@ -(void)layoutSubviews CGPoint sbvOldCenter = sbv.center; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvmyFrame.leading != CGFLOAT_MAX && sbvmyFrame.top != CGFLOAT_MAX && !sbvsc.noLayout && !sbvsc.useFrame) { @@ -1959,7 +1826,6 @@ -(void)layoutSubviews { rc = _myLayoutCGRectRound(sbvmyFrame.frame); - CGRect sbvTempBounds = CGRectMake(sbvOldBounds.origin.x, sbvOldBounds.origin.y, rc.size.width, rc.size.height); if (_myCGFloatErrorEqual(sbvTempBounds.size.width, sbvOldBounds.size.width, sSizeError)) @@ -1987,7 +1853,6 @@ -(void)layoutSubviews else { rc = _myCGRectRound(sbvmyFrame.frame); - sbv.center = CGPointMake(rc.origin.x + sbv.layer.anchorPoint.x * rc.size.width, rc.origin.y + sbv.layer.anchorPoint.y * rc.size.height); sbv.bounds = CGRectMake(sbvOldBounds.origin.x, sbvOldBounds.origin.y, rc.size.width, rc.size.height); } @@ -2002,17 +1867,14 @@ -(void)layoutSubviews sbvmyFrame.sizeClass.viewLayoutCompleteBlock = nil; } - if (sbvmyFrame.multiple) sbvmyFrame.sizeClass = [sbv myDefaultSizeClass]; [sbvmyFrame reset]; } - if (newSelfSize.width != CGFLOAT_MAX && (lsc.widthSizeInner.dimeWrapVal || lsc.heightSizeInner.dimeWrapVal)) { - //因为布局子视图的新老尺寸计算在上面有两种不同的方法,因此这里需要考虑两种计算的误差值,而这两种计算的误差值是不超过1/屏幕精度的。 //因此我们认为当二者的值超过误差时我们才认为有尺寸变化。 BOOL isWidthAlter = _myCGFloatErrorNotEqual(newSelfSize.width, oldSelfSize.width, sSizeError); @@ -2069,18 +1931,14 @@ -(void)layoutSubviews self.bounds = currentBounds; self.center = currentCenter; - } } } - //这里只用width判断的原因是如果newSelfSize被计算成功则size中的所有值都不是CGFLOAT_MAX,所以这里选width只是其中一个代表。 if (newSelfSize.width != CGFLOAT_MAX) { UIView *supv = self.superview; - - //更新边界线。 if (_borderlineLayerDelegate != nil) { @@ -2095,7 +1953,6 @@ -(void)layoutSubviews [_borderlineLayerDelegate setNeedsLayoutIn:borderlineRect withLayer:self.layer]; } - //如果自己的父视图是非UIScrollView以及非布局视图。以及自己的宽度或者高度是包裹的,并且如果设置了在父视图居中或者居下或者居右时要在父视图中更新自己的位置。 if (supv != nil && ![supv isKindOfClass:[MyBaseLayout class]]) { @@ -2132,7 +1989,6 @@ -(void)layoutSubviews { centerPonintSelf.x = rectSuper.size.width - rectSelf.size.width - [lsc.trailingPosInner realPosIn:rectSuper.size.width] + self.layer.anchorPoint.x * rectSelf.size.width; } - } if (lsc.heightSizeInner.dimeWrapVal) @@ -2157,7 +2013,6 @@ -(void)layoutSubviews self.center = centerPonintSelf; } - //这里处理当布局视图的父视图是非布局父视图,且父视图具有wrap属性时需要调整父视图的尺寸。 if (supv != nil && ![supv isKindOfClass:[MyBaseLayout class]]) { @@ -2191,11 +2046,9 @@ -(void)layoutSubviews [self myLayout:lsc adjustScrollViewContentWithSize:newSelfSize]; } - if (selfMyFrame.multiple) selfMyFrame.sizeClass = [self myDefaultSizeClass]; self.isMyLayouting = NO; - } if (self.endLayoutBlock != nil) @@ -2236,11 +2089,8 @@ -(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection } } - #pragma mark -- Private Methods - - -(CGSize)myEstimateLayoutSize:(CGSize)size inSizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { MyFrame *selfMyFrame = self.myFrame; @@ -2275,8 +2125,6 @@ -(CGSize)myEstimateLayoutSize:(CGSize)size inSizeClass:(MySizeClass)sizeClass sb selfMyFrame.width = selfSize.width; selfMyFrame.height = selfSize.height; - - //计算后还原为默认sizeClass for (UIView *sbv in self.subviews) { @@ -2294,15 +2142,12 @@ -(CGSize)myEstimateLayoutSize:(CGSize)size inSizeClass:(MySizeClass)sizeClass sb return CGSizeMake(_myCGFloatRound(selfSize.width), _myCGFloatRound(selfSize.height)); } - - -(BOOL)myIsRelativePos:(CGFloat)margin { return margin > 0 && margin < 1; } - --(MyGravity)myGetSubviewVertGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc vertGravity:(MyGravity)vertGravity +-(MyGravity)myGetSubview:(MyViewSizeClass*)sbvsc vertGravity:(MyGravity)vertGravity { MyGravity sbvVertAligement = sbvsc.alignment & MyGravity_Horz_Mask; MyGravity sbvVertGravity = MyGravity_Vert_Top; @@ -2342,16 +2187,15 @@ -(MyGravity)myGetSubviewVertGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc vertGravit } --(CGFloat)myCalcVertGravity:(MyGravity)vertGravity - sbv:(UIView *)sbv - sbvsc:(UIView*)sbvsc - paddingTop:(CGFloat)paddingTop - paddingBottom:(CGFloat)paddingBottom - baselinePos:(CGFloat)baselinePos - selfSize:(CGSize)selfSize - pRect:(CGRect*)pRect +-(CGFloat)myCalcSubview:(MyViewSizeClass*)sbvsc + vertGravity:(MyGravity)vertGravity + paddingTop:(CGFloat)paddingTop + paddingBottom:(CGFloat)paddingBottom + baselinePos:(CGFloat)baselinePos + selfSize:(CGSize)selfSize + pRect:(CGRect*)pRect { - + UIView *sbv = sbvsc.view; CGFloat topMargin = [self myValidMargin:sbvsc.topPosInner sbv:sbv calcPos:[sbvsc.topPosInner realPosIn:selfSize.height - paddingTop - paddingBottom] selfLayoutSize:selfSize]; @@ -2359,7 +2203,6 @@ -(CGFloat)myCalcVertGravity:(MyGravity)vertGravity CGFloat bottomMargin = [self myValidMargin:sbvsc.bottomPosInner sbv:sbv calcPos:[sbvsc.bottomPosInner realPosIn:selfSize.height - paddingTop - paddingBottom] selfLayoutSize:selfSize]; - //垂直压缩。 CGFloat fixedHeight = topMargin + centerMargin + bottomMargin + pRect->size.height; if (fixedHeight > selfSize.height) @@ -2384,7 +2227,6 @@ -(CGFloat)myCalcVertGravity:(MyGravity)vertGravity vertGravity = MyGravity_Vert_Fill; } - //确保设置基线对齐的视图都是UILabel,UITextField,UITextView if (baselinePos == CGFLOAT_MAX && vertGravity == MyGravity_Vert_Baseline) vertGravity = MyGravity_Vert_Top; @@ -2396,7 +2238,6 @@ -(CGFloat)myCalcVertGravity:(MyGravity)vertGravity if (sbvFont == nil && vertGravity == MyGravity_Vert_Baseline) vertGravity = MyGravity_Vert_Top; - if (vertGravity == MyGravity_Vert_Top) { pRect->origin.y = paddingTop + topMargin; @@ -2434,11 +2275,10 @@ -(CGFloat)myCalcVertGravity:(MyGravity)vertGravity } return topMargin + centerMargin + bottomMargin + pRect->size.height; - } --(MyGravity)myGetSubviewHorzGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc horzGravity:(MyGravity)horzGravity +-(MyGravity)myGetSubview:(MyViewSizeClass*)sbvsc horzGravity:(MyGravity)horzGravity { MyGravity sbvHorzAligement = [self myConvertLeftRightGravityToLeadingTrailing:sbvsc.alignment & MyGravity_Vert_Mask]; MyGravity sbvHorzGravity = MyGravity_Horz_Leading; @@ -2451,7 +2291,6 @@ -(MyGravity)myGetSubviewHorzGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc horzGravit } else { - if (sbvHorzAligement != MyGravity_None) sbvHorzGravity = sbvHorzAligement; @@ -2478,15 +2317,14 @@ -(MyGravity)myGetSubviewHorzGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc horzGravit return sbvHorzGravity; } - --(CGFloat)myCalcHorzGravity:(MyGravity)horzGravity - sbv:(UIView *)sbv - sbvsc:(UIView*)sbvsc - paddingLeading:(CGFloat)paddingLeading - paddingTrailing:(CGFloat)paddingTrailing - selfSize:(CGSize)selfSize - pRect:(CGRect*)pRect +-(CGFloat)myCalcSubview:(MyViewSizeClass*)sbvsc + horzGravity:(MyGravity)horzGravity + paddingLeading:(CGFloat)paddingLeading + paddingTrailing:(CGFloat)paddingTrailing + selfSize:(CGSize)selfSize + pRect:(CGRect*)pRect { + UIView *sbv = sbvsc.view; CGFloat paddingHorz = paddingLeading + paddingTrailing; CGFloat leadingMargin = [self myValidMargin:sbvsc.leadingPosInner sbv:sbv calcPos:[sbvsc.leadingPosInner realPosIn:selfSize.width - paddingHorz] selfLayoutSize:selfSize]; @@ -2519,7 +2357,6 @@ -(CGFloat)myCalcHorzGravity:(MyGravity)horzGravity horzGravity = MyGravity_Horz_Fill; } - if (horzGravity == MyGravity_Horz_Leading) { pRect->origin.x = paddingLeading + leadingMargin; @@ -2548,7 +2385,6 @@ -(CGFloat)myCalcHorzGravity:(MyGravity)horzGravity if ([MyBaseLayout isRTL]) pRect->origin.x = selfSize.width - pRect->origin.x - pRect->size.width; } - } else { @@ -2558,7 +2394,6 @@ -(CGFloat)myCalcHorzGravity:(MyGravity)horzGravity return leadingMargin + centerMargin + trailingMargin + pRect->size.width; } - -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize)size { if (newSuperview == nil || [newSuperview isKindOfClass:[MyBaseLayout class]]) @@ -2622,11 +2457,9 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize size.height = 0; } - return size; } - -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview { BOOL isAdjust = NO; //这个变量表明是否后续父视图尺寸变化后需要调整更新布局视图的尺寸。 @@ -2690,7 +2523,6 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview if ([MyBaseLayout isRTL]) rectSelf.origin.x = rectSuper.size.width - rectSelf.origin.x - rectSelf.size.width; - if (lsc.leadingPosInner.posVal != nil && lsc.trailingPosInner.posVal != nil) { @@ -2754,7 +2586,6 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview } else; - if (lsc.heightSizeInner.dimeVal != nil) { if (lsc.heightSizeInner.dimeRelaVal != nil) @@ -2878,12 +2709,12 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview [self setNeedsLayout]; } - return isAdjust; } --(CGFloat)myHeightFromFlexedHeightView:(UIView*)sbv sbvsc:(UIView*)sbvsc inWidth:(CGFloat)width +-(CGFloat)mySubview:(MyViewSizeClass*)sbvsc wrapHeightSizeFits:(CGFloat)width { + UIView *sbv = sbvsc.view; CGFloat h = [sbv sizeThatFits:CGSizeMake(width, 0)].height; if ([sbv isKindOfClass:[UIImageView class]]) { @@ -2899,7 +2730,6 @@ -(CGFloat)myHeightFromFlexedHeightView:(UIView*)sbv sbvsc:(UIView*)sbvsc inWidth { //按钮特殊处理多行的。。 UIButton *button = (UIButton*)sbv; - if (button.titleLabel != nil) { //得到按钮本身的高度,以及单行文本的高度,这样就能算出按钮和文本的间距 @@ -2917,7 +2747,6 @@ -(CGFloat)myHeightFromFlexedHeightView:(UIView*)sbv sbvsc:(UIView*)sbvsc inWidth return [sbvsc.heightSizeInner measureWith:h]; } - -(CGFloat)myGetBoundLimitMeasure:(MyLayoutSize*)boundDime sbv:(UIView*)sbv dimeType:(MyGravity)dimeType sbvSize:(CGSize)sbvSize selfLayoutSize:(CGSize)selfLayoutSize isUBound:(BOOL)isUBound { CGFloat value = isUBound ? CGFLOAT_MAX : -CGFLOAT_MAX; @@ -2979,11 +2808,8 @@ -(CGFloat)myGetBoundLimitMeasure:(MyLayoutSize*)boundDime sbv:(UIView*)sbv dimeT return value; return [boundDime measureWith:value]; - } - - -(CGFloat)myValidMeasure:(MyLayoutSize*)dime sbv:(UIView*)sbv calcSize:(CGFloat)calcSize sbvSize:(CGSize)sbvSize selfLayoutSize:(CGSize)selfLayoutSize { if (calcSize < 0.0) @@ -3002,7 +2828,6 @@ -(CGFloat)myValidMeasure:(MyLayoutSize*)dime sbv:(UIView*)sbv calcSize:(CGFloat) return calcSize; } - -(CGFloat)myGetBound:(MyLayoutPos*)boundPos limitMarginOfSubview:(UIView*)sbv { CGFloat value = 0; @@ -3057,7 +2882,6 @@ -(CGFloat)myGetBound:(MyLayoutPos*)boundPos limitMarginOfSubview:(UIView*)sbv return value + boundPos.offsetVal; } - -(CGFloat)myValidMargin:(MyLayoutPos*)pos sbv:(UIView*)sbv calcPos:(CGFloat)calcPos selfLayoutSize:(CGSize)selfLayoutSize { if (pos == nil) @@ -3108,11 +2932,9 @@ -(NSMutableArray*)myGetLayoutSubviewsFrom:(NSArray*)sbsFrom } return sbs; - } - --(CGSize)myLayout:(MyBaseLayout*)lsc adjustSelfSize:(CGSize)selfSize withSubviews:(NSArray*)sbs +-(CGSize)myLayout:(MyLayoutViewSizeClass*)lsc adjustSelfSize:(CGSize)selfSize withSubviews:(NSArray*)sbs { //调整布局视图自己的尺寸。 selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:selfSize.height sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; @@ -3229,7 +3051,6 @@ -(CGFloat)myLayoutTrailingPadding return self.myCurrentSizeClass.myLayoutTrailingPadding; } - - (void)myLayout:(MyBaseLayout*)lsc adjustScrollViewContentWithSize:(CGSize)newSize { if (self.adjustScrollViewContentSizeMode == MyAdjustScrollViewContentSizeModeYes && self.superview != nil && [self.superview isKindOfClass:[UIScrollView class]]) @@ -3263,8 +3084,6 @@ - (void)myLayout:(MyBaseLayout*)lsc adjustScrollViewContentWithSize:(CGSize)newS } #endif - - if (contsize.height != newSize.height + topMargin + bottomMargin) contsize.height = newSize.height + topMargin + bottomMargin; if (contsize.width != newSize.width + leadingMargin + trailingMargin) @@ -3355,7 +3174,6 @@ -(void)myRemoveSubviewObserver:(UIView*)subview -(void)myAddSubviewObserver:(UIView*)subview sbvmyFrame:(MyFrame*)sbvmyFrame { - if (!sbvmyFrame.hasObserver) { sbvmyFrame.hasObserver = YES; @@ -3385,9 +3203,10 @@ -(void)myAddSubviewObserver:(UIView*)subview sbvmyFrame:(MyFrame*)sbvmyFrame } } - --(void)myLayout:(MyBaseLayout*)lsc adjustSizeSettingOfSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout +-(void)myLayout:(MyLayoutViewSizeClass*)lsc adjustSizeSettingOfSubview:(MyViewSizeClass*)sbvsc isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout { + UIView *sbv = sbvsc.view; + if (!isEstimate) sbvmyFrame.frame = sbv.bounds; @@ -3396,7 +3215,6 @@ -(void)myLayout:(MyBaseLayout*)lsc adjustSizeSettingOfSubview:(UIView*)sbv sbvsc [sbvsc.widthSizeInner __setActive:NO]; if (sbvsc.heightSizeInner.dimeWrapVal && vertGravity == MyGravity_Vert_Fill) [sbvsc.heightSizeInner __setActive:NO]; - if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil && @@ -3424,15 +3242,14 @@ -(void)myLayout:(MyBaseLayout*)lsc adjustSizeSettingOfSubview:(UIView*)sbv sbvsc } } --(CGFloat)myGetSubviewWidthSizeValue:(UIView *)sbv - sbvsc:(UIView *)sbvsc - lsc:(MyBaseLayout *)lsc - selfSize:(CGSize)selfSize - paddingTop:(CGFloat)paddingTop - paddingLeading:(CGFloat)paddingLeading - paddingBottom:(CGFloat)paddingBottom - paddingTrailing:(CGFloat)paddingTrailing - sbvSize:(CGSize)sbvSize +-(CGFloat)myLayout:(MyLayoutViewSizeClass*)lsc +widthSizeValueOfSubview:(MyViewSizeClass *)sbvsc + selfSize:(CGSize)selfSize + sbvSize:(CGSize)sbvSize + paddingTop:(CGFloat)paddingTop + paddingLeading:(CGFloat)paddingLeading + paddingBottom:(CGFloat)paddingBottom + paddingTrailing:(CGFloat)paddingTrailing { CGFloat retVal = sbvSize.width; @@ -3442,7 +3259,7 @@ -(CGFloat)myGetSubviewWidthSizeValue:(UIView *)sbv {//宽度等于固定的值。 retVal = sbvWidthSizeInner.measure; } - else if (sbvWidthSizeInner.dimeRelaVal != nil && sbvWidthSizeInner.dimeRelaVal.view != sbv) + else if (sbvWidthSizeInner.dimeRelaVal != nil && sbvWidthSizeInner.dimeRelaVal.view != sbvsc.view) {//宽度等于其他的依赖的视图。 if (sbvWidthSizeInner.dimeRelaVal == lsc.widthSizeInner) @@ -3463,22 +3280,21 @@ -(CGFloat)myGetSubviewWidthSizeValue:(UIView *)sbv } else if (sbvWidthSizeInner.dimeWrapVal) { - if (![sbv isKindOfClass:[MyBaseLayout class]]) - retVal = [sbvWidthSizeInner measureWith:[sbv sizeThatFits:CGSizeMake(0, sbvSize.height)].width]; + if (![sbvsc.view isKindOfClass:[MyBaseLayout class]]) + retVal = [sbvWidthSizeInner measureWith:[sbvsc.view sizeThatFits:CGSizeMake(0, sbvSize.height)].width]; } return retVal; } --(CGFloat)myGetSubviewHeightSizeValue:(UIView *)sbv - sbvsc:(UIView *)sbvsc - lsc:(MyBaseLayout *)lsc - selfSize:(CGSize)selfSize - paddingTop:(CGFloat)paddingTop - paddingLeading:(CGFloat)paddingLeading - paddingBottom:(CGFloat)paddingBottom - paddingTrailing:(CGFloat)paddingTrailing - sbvSize:(CGSize)sbvSize +-(CGFloat)myLayout:(MyLayoutViewSizeClass*)lsc +heightSizeValueOfSubview:(MyViewSizeClass *)sbvsc + selfSize:(CGSize)selfSize + sbvSize:(CGSize)sbvSize + paddingTop:(CGFloat)paddingTop + paddingLeading:(CGFloat)paddingLeading + paddingBottom:(CGFloat)paddingBottom + paddingTrailing:(CGFloat)paddingTrailing { CGFloat retVal = sbvSize.height; MyLayoutSize *sbvHeightSizeInner = sbvsc.heightSizeInner; @@ -3487,7 +3303,7 @@ -(CGFloat)myGetSubviewHeightSizeValue:(UIView *)sbv {//高度等于固定的值。 retVal = sbvHeightSizeInner.measure; } - else if (sbvHeightSizeInner.dimeRelaVal != nil && sbvHeightSizeInner.dimeRelaVal.view != sbv) + else if (sbvHeightSizeInner.dimeRelaVal != nil && sbvHeightSizeInner.dimeRelaVal.view != sbvsc.view) {//高度等于其他依赖的视图 if (sbvHeightSizeInner.dimeRelaVal == lsc.heightSizeInner) { @@ -3507,17 +3323,14 @@ -(CGFloat)myGetSubviewHeightSizeValue:(UIView *)sbv } //高度等于内容的高度,特殊处理。 - if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) - retVal = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:sbvSize.width]; + if (sbvsc.heightSizeInner.dimeWrapVal && ![sbvsc.view isKindOfClass:[MyBaseLayout class]]) + retVal = [self mySubview:sbvsc wrapHeightSizeFits:sbvSize.width]; return retVal; } - - --(void)myLayout:(MyBaseLayout*)lsc -calcRectOfSubView:(UIView*)sbv - sbvsc:(UIView*)sbvsc +-(void)myLayout:(MyLayoutViewSizeClass*)lsc +calcRectOfSubview:(MyViewSizeClass*)sbvsc sbvmyFrame:(MyFrame*)sbvmyFrame vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity @@ -3528,41 +3341,39 @@ -(void)myLayout:(MyBaseLayout*)lsc paddingTrailing:(CGFloat)paddingTrailing pMaxWrapSize:(CGSize*)pMaxWrapSize { - - CGRect rect = sbvmyFrame.frame; - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - [self myCalcHorzGravity:[self myGetSubviewHorzGravity:sbv sbvsc:sbvsc horzGravity:horzGravity] sbv:sbv sbvsc:sbvsc paddingLeading:paddingLeading paddingTrailing:paddingTrailing selfSize:selfSize pRect:&rect]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbvsc.view calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + [self myCalcSubview:sbvsc horzGravity:[self myGetSubview:sbvsc horzGravity:horzGravity] paddingLeading:paddingLeading paddingTrailing:paddingTrailing selfSize:selfSize pRect:&rect]; - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - [self myCalcVertGravity:[self myGetSubviewVertGravity:sbv sbvsc:sbvsc vertGravity:vertGravity] sbv:sbv sbvsc:sbvsc paddingTop:paddingTop paddingBottom:paddingBottom baselinePos:CGFLOAT_MAX selfSize:selfSize pRect:&rect]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbvsc.view calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + [self myCalcSubview:sbvsc vertGravity:[self myGetSubview:sbvsc vertGravity:vertGravity] paddingTop:paddingTop paddingBottom:paddingBottom baselinePos:CGFLOAT_MAX selfSize:selfSize pRect:&rect]; //特殊处理宽度等于高度 - if (sbvsc.widthSizeInner.dimeRelaVal.view == sbv && sbvsc.widthSizeInner.dimeRelaVal.dime == MyGravity_Vert_Fill) + if (sbvsc.widthSizeInner.dimeRelaVal.view == sbvsc.view && sbvsc.widthSizeInner.dimeRelaVal.dime == MyGravity_Vert_Fill) { rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbvsc.view calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - [self myCalcHorzGravity:[self myGetSubviewHorzGravity:sbv sbvsc:sbvsc horzGravity:horzGravity] sbv:sbv sbvsc:sbvsc paddingLeading:paddingLeading paddingTrailing:paddingTrailing selfSize:selfSize pRect:&rect]; + [self myCalcSubview:sbvsc horzGravity:[self myGetSubview:sbvsc horzGravity:horzGravity] paddingLeading:paddingLeading paddingTrailing:paddingTrailing selfSize:selfSize pRect:&rect]; } //特殊处理高度等于宽度。 - if (sbvsc.heightSizeInner.dimeRelaVal.view == sbv && sbvsc.heightSizeInner.dimeRelaVal.dime == MyGravity_Horz_Fill) + if (sbvsc.heightSizeInner.dimeRelaVal.view == sbvsc.view && sbvsc.heightSizeInner.dimeRelaVal.dime == MyGravity_Horz_Fill) { rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; - if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; + if (sbvsc.heightSizeInner.dimeWrapVal && ![sbvsc.view isKindOfClass:[MyBaseLayout class]]) + rect.size.height = [self mySubview:sbvsc wrapHeightSizeFits:rect.size.width]; - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbvsc.view calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - [self myCalcVertGravity:[self myGetSubviewVertGravity:sbv sbvsc:sbvsc vertGravity:vertGravity] sbv:sbv sbvsc:sbvsc paddingTop:paddingTop paddingBottom:paddingBottom baselinePos:CGFLOAT_MAX selfSize:selfSize pRect:&rect]; + [self myCalcSubview:sbvsc vertGravity:[self myGetSubview:sbvsc vertGravity:vertGravity] paddingTop:paddingTop paddingBottom:paddingBottom baselinePos:CGFLOAT_MAX selfSize:selfSize pRect:&rect]; } sbvmyFrame.frame = rect; @@ -3592,7 +3403,6 @@ -(void)myLayout:(MyBaseLayout*)lsc { pMaxWrapSize->width = sbvmyFrame.trailing + sbvsc.trailingPosInner.absVal + paddingTrailing; } - } } @@ -3621,8 +3431,6 @@ -(void)myLayout:(MyBaseLayout*)lsc } } } - - } -(void)myHookSublayout:(MyBaseLayout *)sublayout borderlineRect:(CGRect *)pRect @@ -3639,15 +3447,15 @@ -(void)myInvalidateIntrinsicContentSize } } --(void)myCalcSubviewsWrapContentSize:(NSArray*)sbs isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass withCustomSetting:(void (^)(UIView *sbv, UIView *sbvsc))customSetting +-(void)myCalcSubviewsWrapContentSize:(NSArray*)sbs isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass withCustomSetting:(void (^)(MyViewSizeClass *sbvsc))customSetting { for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass *)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (customSetting != nil) - customSetting(sbv, sbvsc); + customSetting(sbvsc); if (!isEstimate) sbvmyFrame.frame = sbv.bounds; @@ -3670,7 +3478,6 @@ -(void)myCalcSubviewsWrapContentSize:(NSArray*)sbs isEstimate:(BOOL)is } } - @end @@ -3702,7 +3509,6 @@ -(void)reset _height = CGFLOAT_MAX; } - -(CGRect)frame { return CGRectMake(_leading, _top,_width, _height); @@ -3730,10 +3536,8 @@ -(NSString*)description @end - @implementation UIWindow (MyLayoutExt) - -(void)myUpdateRTL:(BOOL)isRTL { BOOL oldRTL = [MyBaseLayout isRTL]; @@ -3744,7 +3548,6 @@ -(void)myUpdateRTL:(BOOL)isRTL } } - -(void)mySetNeedLayoutAllSubviews:(UIView *)v { NSArray *sbs = v.subviews; @@ -3763,7 +3566,6 @@ -(void)mySetNeedLayoutAllSubviews:(UIView *)v @implementation MyLayoutDragger - //开始拖动 -(void)dragView:(UIView *)view withEvent:(UIEvent *)event { @@ -3836,7 +3638,6 @@ -(void)dragginView:(UIView *)view withEvent:(UIEvent *)event [self.layout layoutIfNeeded]; } - //在进行sender的位置调整时,要把sender移动到最顶端,也就子视图数组的的最后。同时布局视图不能激发子视图布局,因此要把autoresizesSubviews设置为NO,同时因为要自定义sender的位置,因此要把useFrame设置为YES,并且恢复noLayout为NO。 [self.layout bringSubviewToFront:view]; //把拖动的子视图放在最后,这样这个子视图在移动时就会在所有兄弟视图的上面。 self.layout.autoresizesSubviews = NO; //在拖动时不要让布局视图激发布局 diff --git a/MyLayout/Lib/MyBorderline.m b/MyLayout/Lib/MyBorderline.m index 3bdb5d1..f3bbc93 100644 --- a/MyLayout/Lib/MyBorderline.m +++ b/MyLayout/Lib/MyBorderline.m @@ -59,16 +59,13 @@ -(instancetype)initWithColor:(UIColor *)color thick:(CGFloat)thick headIndent:(C } return self; - } -(instancetype)initWithColor:(UIColor *)color thick:(CGFloat)thick headIndent:(CGFloat)headIndent tailIndent:(CGFloat)tailIndent offset:(CGFloat)offset { self = [self initWithColor:color thick:thick headIndent:headIndent tailIndent:tailIndent]; if (self != nil) - { _offset = offset; - } return self; } @@ -78,9 +75,7 @@ -(void)setThick:(CGFloat)thick if (thick < 1) thick = 1; if (_thick != thick) - { _thick = thick; - } } @end diff --git a/MyLayout/Lib/MyDimeScale.m b/MyLayout/Lib/MyDimeScale.m index 4c708f1..4d52a6a 100644 --- a/MyLayout/Lib/MyDimeScale.m +++ b/MyLayout/Lib/MyDimeScale.m @@ -67,9 +67,6 @@ +(CGRect)roundRect:(CGRect)rect return _myCGRectRound(rect); } - - - @end #endif diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index 5e6c4b4..68585ed 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -11,10 +11,7 @@ #import const char * const ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM = "ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM"; - - - const int MyFlex_Auto = -1; - +const int MyFlex_Auto = -1; @implementation MyFlexItem { @@ -22,7 +19,6 @@ @implementation MyFlexItem __weak UIView *_view; } - -(instancetype)initWithView:(UIView*)view; { self = [super init]; @@ -90,7 +86,6 @@ -(void)setVisibility_val:(MyVisibility)visibility_val self.view.visibility = visibility_val; } - -(MyFlexItem* (^)(NSInteger))order { return ^id(NSInteger val) { @@ -319,7 +314,6 @@ -(void)setHorz_space_val:(CGFloat)horz_space_val ((MyFlexLayout*)self.view).subviewHSpace = horz_space_val; } - -(MyFlex* (^)(MyFlexDirection))flex_direction { return ^id(MyFlexDirection val){ @@ -349,7 +343,6 @@ -(void)setHorz_space_val:(CGFloat)horz_space_val -(MyFlex* (^)(MyFlexGravity))justify_content { - return ^id(MyFlexGravity val) { self.justify_content_val = val; return self; @@ -400,7 +393,6 @@ -(void)setHorz_space_val:(CGFloat)horz_space_val @implementation UIView(MyFlexLayout) - -(MyFlexItem*)flexItem { MyFlexItem *obj = nil; @@ -423,7 +415,6 @@ -(MyFlexItem*)flexItem @end - @implementation MyFlexLayout -(instancetype)init @@ -439,12 +430,9 @@ -(instancetype)init return self; } - -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { - //将flexbox中的属性映射为MyFlowLayout中的属性。 - MyFlexLayout *lsc = self.myCurrentSizeClass; //最先设置方向。 @@ -554,7 +542,6 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( } } - //设置主轴的水平对齐和拉伸 MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = lsc.gravity & MyGravity_Vert_Mask; @@ -675,6 +662,4 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( return [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; } - - @end diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 83d1097..5ebfaf5 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -11,7 +11,6 @@ @implementation UIView(MyFloatLayoutExt) - -(void)setReverseFloat:(BOOL)reverseFloat { UIView *sc = self.myCurrentSizeClass; @@ -47,8 +46,6 @@ -(BOOL)clearFloat @end - - @implementation MyFloatLayout #pragma mark -- Public Methods @@ -60,7 +57,6 @@ -(instancetype)initWithFrame:(CGRect)frame orientation:(MyOrientation)orientatio { self.myCurrentSizeClass.orientation = orientation; } - return self; } @@ -69,7 +65,6 @@ -(instancetype)initWithOrientation:(MyOrientation)orientation return [self initWithFrame:CGRectZero orientation:orientation]; } - +(instancetype)floatLayoutWithOrientation:(MyOrientation)orientation { MyFloatLayout *layout = [[[self class] alloc] initWithOrientation:orientation]; @@ -91,7 +86,6 @@ -(MyOrientation)orientation return self.myCurrentSizeClass.orientation; } - -(void)setNoBoundaryLimit:(BOOL)noBoundaryLimit { NSLog(@"属性已经过期!请直接设置宽度或者高度值为MyLayoutSize.wrap"); @@ -102,7 +96,6 @@ -(BOOL)noBoundaryLimit return NO; } - -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace { [self setSubviewsSize:subviewSize minSpace:minSpace maxSpace:maxSpace inSizeClass:MySizeClass_hAny | MySizeClass_wAny]; @@ -117,7 +110,6 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace: [self setNeedsLayout]; } - #pragma mark -- Override Methods -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs @@ -127,26 +119,30 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbs == nil) sbs = [self myGetLayoutSubviews]; - MyFloatLayout *lsc = self.myCurrentSizeClass; + MyFloatLayoutViewSizeClass *lsc = (MyFloatLayoutViewSizeClass*)self.myCurrentSizeClass; MyOrientation orientation = lsc.orientation; - [self myCalcSubviewsWrapContentSize:sbs isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass withCustomSetting:^(UIView *sbv, UIView *sbvsc) { + [self myCalcSubviewsWrapContentSize:sbs isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass withCustomSetting:^(MyViewSizeClass *sbvsc) { - if (sbvsc.widthSizeInner.dimeWrapVal && orientation == MyOrientation_Vert && sbvsc.weight != 0) + if (sbvsc.widthSizeInner.dimeWrapVal && + orientation == MyOrientation_Vert && + sbvsc.weight != 0 && + [sbvsc.view isKindOfClass:[MyBaseLayout class]]) [sbvsc.widthSizeInner __setActive:NO]; - if (sbvsc.heightSizeInner.dimeWrapVal && orientation == MyOrientation_Horz && sbvsc.weight != 0) + if (sbvsc.heightSizeInner.dimeWrapVal && + orientation == MyOrientation_Horz && + sbvsc.weight != 0 && + [sbvsc.view isKindOfClass:[MyBaseLayout class]]) [sbvsc.heightSizeInner __setActive:NO]; }]; if (orientation == MyOrientation_Vert) - selfSize = [self myCalcLayoutSizeForVertOrientation:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; + selfSize = [self myVertOrientationLayout:lsc calcRectOfSubviews:sbs withSelfSize:selfSize isEstimate:isEstimate]; else - selfSize = [self myCalcLayoutSizeForHorzOrientation:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; - + selfSize = [self myHorzOrientationLayout:lsc calcRectOfSubviews:sbs withSelfSize:selfSize isEstimate:isEstimate]; return [self myLayout:lsc adjustSelfSize:selfSize withSubviews:sbs]; - } -(id)createSizeClassInstance @@ -158,13 +154,11 @@ -(id)createSizeClassInstance -(CGPoint)myFindTrailingCandidatePoint:(CGRect)leadingCandidateRect width:(CGFloat)width trailingBoundary:(CGFloat)trailingBoundary trailingCandidateRects:(NSArray*)trailingCandidateRects hasWeight:(BOOL)hasWeight paddingTop:(CGFloat)paddingTop { - CGPoint retPoint = {trailingBoundary,CGFLOAT_MAX}; CGFloat lastHeight = paddingTop; for (NSInteger i = trailingCandidateRects.count - 1; i >= 0; i--) { - CGRect trailingCandidateRect = ((NSValue*)trailingCandidateRects[i]).CGRectValue; //如果有比重则不能相等只能小于。 @@ -187,7 +181,6 @@ -(CGPoint)myFindTrailingCandidatePoint:(CGRect)leadingCandidateRect width:(CGFl } lastHeight = CGRectGetMaxY(trailingCandidateRect); - } if (retPoint.y == CGFLOAT_MAX) @@ -204,13 +197,10 @@ -(CGPoint)myFindTrailingCandidatePoint:(CGRect)leadingCandidateRect width:(CGFl -(CGPoint)myFindBottomCandidatePoint:(CGRect)topCandidateRect height:(CGFloat)height bottomBoundary:(CGFloat)bottomBoundary bottomCandidateRects:(NSArray*)bottomCandidateRects hasWeight:(BOOL)hasWeight paddingLeading:(CGFloat)paddingLeading { - CGPoint retPoint = {CGFLOAT_MAX,bottomBoundary}; - CGFloat lastWidth = paddingLeading; for (NSInteger i = bottomCandidateRects.count - 1; i >= 0; i--) { - CGRect bottomCandidateRect = ((NSValue*)bottomCandidateRects[i]).CGRectValue; if ((hasWeight ? _myCGFloatLess(CGRectGetMaxY(topCandidateRect) + height, CGRectGetMinY(bottomCandidateRect)) : @@ -232,7 +222,6 @@ -(CGPoint)myFindBottomCandidatePoint:(CGRect)topCandidateRect height:(CGFloat)h } lastWidth = CGRectGetMaxX(bottomCandidateRect); - } if (retPoint.x == CGFLOAT_MAX) @@ -247,16 +236,12 @@ -(CGPoint)myFindBottomCandidatePoint:(CGRect)topCandidateRect height:(CGFloat)h return retPoint; } - -(CGPoint)myFindLeadingCandidatePoint:(CGRect)trailingCandidateRect width:(CGFloat)width leadingBoundary:(CGFloat)leadingBoundary leadingCandidateRects:(NSArray*)leadingCandidateRects hasWeight:(BOOL)hasWeight paddingTop:(CGFloat)paddingTop { - CGPoint retPoint = {leadingBoundary,CGFLOAT_MAX}; - CGFloat lastHeight = paddingTop; for (NSInteger i = leadingCandidateRects.count - 1; i >= 0; i--) { - CGRect leadingCandidateRect = ((NSValue*)leadingCandidateRects[i]).CGRectValue; if ((hasWeight ? _myCGFloatGreat(CGRectGetMinX(trailingCandidateRect) - width, CGRectGetMaxX(leadingCandidateRect)) : @@ -273,12 +258,10 @@ -(CGPoint)myFindLeadingCandidatePoint:(CGRect)trailingCandidateRect width:(CGFl { retPoint.x = leadingBoundary; } - break; } lastHeight = CGRectGetMaxY(leadingCandidateRect); - } if (retPoint.y == CGFLOAT_MAX) @@ -296,13 +279,11 @@ -(CGPoint)myFindLeadingCandidatePoint:(CGRect)trailingCandidateRect width:(CGFl -(CGPoint)myFindTopCandidatePoint:(CGRect)bottomCandidateRect height:(CGFloat)height topBoundary:(CGFloat)topBoundary topCandidateRects:(NSArray*)topCandidateRects hasWeight:(BOOL)hasWeight paddingLeading:(CGFloat)paddingLeading { - CGPoint retPoint = {CGFLOAT_MAX, topBoundary}; CGFloat lastWidth = paddingLeading; for (NSInteger i = topCandidateRects.count - 1; i >= 0; i--) { - CGRect topCandidateRect = ((NSValue*)topCandidateRects[i]).CGRectValue; if ((hasWeight ? _myCGFloatGreat(CGRectGetMinY(bottomCandidateRect) - height, CGRectGetMaxY(topCandidateRect)) : @@ -319,13 +300,10 @@ -(CGPoint)myFindTopCandidatePoint:(CGRect)bottomCandidateRect height:(CGFloat)h { retPoint.y = topBoundary; } - - break; } lastWidth = CGRectGetMaxX(topCandidateRect); - } if (retPoint.x == CGFLOAT_MAX) @@ -341,13 +319,11 @@ -(CGPoint)myFindTopCandidatePoint:(CGRect)bottomCandidateRect height:(CGFloat)h return retPoint; } - --(CGFloat)myCalcMaxMinSubviewSize:(CGFloat)selfSize lsc:(MyFloatLayoutViewSizeClass*)lsc space:(CGFloat*)pSpace +-(CGFloat)myLayout:(MyFloatLayoutViewSizeClass*)lsc calcMaxMinSubviewSizeWithSelfSize:(CGFloat)selfSize space:(CGFloat*)pSpace { CGFloat subviewSize = lsc.subviewSize; if (subviewSize != 0) { - CGFloat minSpace = lsc.minSpace; CGFloat maxSpace = lsc.maxSpace; @@ -372,22 +348,21 @@ -(CGFloat)myCalcMaxMinSubviewSize:(CGFloat)selfSize lsc:(MyFloatLayoutViewSizeCl return subviewSize; } - --(void)myCalcFloatLayoutSubviewsSize:(NSArray*)sbs - lsc:(MyFloatLayout*)lsc - selfSize:(CGSize)selfSize - paddingTop:(CGFloat)paddingTop - paddingLeading:(CGFloat)paddingLeading - paddingBottom:(CGFloat)paddingBottom - paddingTrailing:(CGFloat)paddingTrailing - subviewSize:(CGFloat)subviewSize - isWidth:(BOOL)isWidth +-(void)myLayout:(MyFloatLayoutViewSizeClass*)lsc +calcSizeOfSubviews:(NSArray*)sbs + selfSize:(CGSize)selfSize + paddingTop:(CGFloat)paddingTop + paddingLeading:(CGFloat)paddingLeading + paddingBottom:(CGFloat)paddingBottom +paddingTrailing:(CGFloat)paddingTrailing + subviewSize:(CGFloat)subviewSize + isWidth:(BOOL)isWidth { //设置子视图的宽度和高度。 for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGRect rect = sbvmyFrame.frame; if (subviewSize != 0) @@ -398,10 +373,10 @@ -(void)myCalcFloatLayoutSubviewsSize:(NSArray*)sbs rect.size.height = subviewSize; } - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) @@ -410,7 +385,6 @@ -(void)myCalcFloatLayoutSubviewsSize:(NSArray*)sbs rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) {//特殊处理宽度等于高度的情况 rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; @@ -420,14 +394,11 @@ -(void)myCalcFloatLayoutSubviewsSize:(NSArray*)sbs sbvmyFrame.width = rect.size.width; sbvmyFrame.height = rect.size.height; } - } - --(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFloatLayout*)lsc +-(CGSize)myVertOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubviews:(NSArray*)sbs withSelfSize:(CGSize)selfSize isEstimate:(BOOL)isEstimate { //对于垂直浮动布局来说,默认是左浮动,当设置为RTL时则默认是右浮动,因此我们只需要改变一下sbv.reverseFloat的定义就好了。 - CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; @@ -439,14 +410,13 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i if (lsc.widthSizeInner.dimeWrapVal) selfSize.width = CGFLOAT_MAX; - //支持浮动水平间距。 CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = [self myCalcMaxMinSubviewSize:selfSize.width - paddingHorz lsc:(MyFloatLayoutViewSizeClass *)lsc space:&horzSpace]; + CGFloat subviewSize = [self myLayout:lsc calcMaxMinSubviewSizeWithSelfSize:selfSize.width - paddingHorz space:&horzSpace]; //设置子视图的宽度和高度。 - [self myCalcFloatLayoutSubviewsSize:sbs lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing subviewSize:subviewSize isWidth:YES]; + [self myLayout:lsc calcSizeOfSubviews:sbs selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing subviewSize:subviewSize isWidth:YES]; //左边候选区域数组,保存的是CGRect值。 NSMutableArray *leadingCandidateRects = [NSMutableArray new]; @@ -476,7 +446,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i { UIView *sbv = sbs[idx]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; @@ -529,7 +499,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i //重新设置宽度 if (sbvsc.weight != 0) { - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:(nextPoint.x - leadingCandidateXBoundary + sbvsc.widthSizeInner.addVal) * sbvsc.weight - leadingSpace - trailingSpace sbvSize:rect.size selfLayoutSize:selfSize]; //特殊处理高度等于宽度,并且高度依赖宽度的情况。 @@ -542,14 +511,11 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i //特殊处理高度包裹的场景 if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) { - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; + rect.size.height = [self mySubview:sbvsc wrapHeightSizeFits:rect.size.width]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } - - } - rect.origin.x = nextPoint.x - trailingSpace - rect.size.width; rect.origin.y = _myCGFloatMin(nextPoint.y, maxHeight) + topSpace; @@ -567,7 +533,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i sbvl.trailingBorderline = nil; sbvl.leadingBorderline = nil; - if (_myCGFloatLess(rect.origin.x + rect.size.width + trailingSpace, selfSize.width - paddingTrailing)) { sbvl.trailingBorderline = self.intelligentBorderline; @@ -582,13 +547,10 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i { sbvl.leadingBorderline = self.intelligentBorderline; } - } - } } - //这里有可能子视图本身的宽度会超过布局视图本身,但是我们的候选区域则不存储超过的宽度部分。 CGRect cRect = CGRectMake(_myCGFloatMax((rect.origin.x - leadingSpace - horzSpace),paddingLeading), rect.origin.y - topSpace, _myCGFloatMin((rect.size.width + leadingSpace + trailingSpace),(selfSize.width - paddingHorz)), rect.size.height + topSpace + bottomSpace + vertSpace); @@ -625,9 +587,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i //记录每一行的最大子视图位置的索引值。 if (trailingLastYOffset != rect.origin.y - topSpace) - { [lineIndexes addObject:@(idx - 1)]; - } [trailingCandidateRects addObject:[NSValue valueWithCGRect:cRect]]; trailingLastYOffset = rect.origin.y - topSpace; @@ -655,7 +615,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i } else { - //依次从后往前,每个都比较右边的。 for (NSInteger i = leadingCandidateRects.count - 1; i >= 0; i--) { @@ -692,10 +651,9 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i //特殊处理高度包裹的场景 if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) { - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; + rect.size.height = [self mySubview:sbvsc wrapHeightSizeFits:rect.size.width]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } - } rect.origin.x = nextPoint.x + leadingSpace; @@ -728,10 +686,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i } } - CGRect cRect = CGRectMake(rect.origin.x - leadingSpace, rect.origin.y - topSpace, _myCGFloatMin((rect.size.width + leadingSpace + trailingSpace + horzSpace),(selfSize.width - paddingHorz)), rect.size.height + topSpace + bottomSpace + vertSpace); - //把新添加到候选中去。并删除高度小于的候选键。和高度 for (NSInteger i = leadingCandidateRects.count - 1; i >= 0; i--) { @@ -772,7 +728,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i if (_myCGFloatGreat(rect.origin.y + rect.size.height + bottomSpace + vertSpace, leadingMaxHeight)) leadingMaxHeight = rect.origin.y + rect.size.height + bottomSpace + vertSpace; - } if (_myCGFloatGreat(rect.origin.y + rect.size.height + bottomSpace + vertSpace, maxHeight)) @@ -782,7 +737,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i maxWidth = rect.origin.x + rect.size.width + trailingSpace + horzSpace; sbvmyFrame.frame = rect; - } if (sbs.count > 0) @@ -827,16 +781,13 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i } } - //如果有子视图设置了对齐属性,那么就要对处在同一行内的子视图进行对齐设置。 //对齐的规则是以行内最高的子视图作为参考的对象,其他的子视图按照行内最高子视图进行垂直对齐的调整。 if (sbvHasAlignment) { //最后一行。 if (sbs.count > 0) - { [lineIndexes addObject:@(sbs.count - 1)]; - } NSInteger lineFirstIndex = 0; for (NSNumber *idxnum in lineIndexes) @@ -849,7 +800,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvmyFrame.height > lineMaxHeight) lineMaxHeight = sbvmyFrame.height; @@ -864,7 +815,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; MyGravity sbvVertAlignment = sbvsc.alignment & MyGravity_Horz_Mask; UIFont *sbvFont = nil; if (sbvVertAlignment == MyGravity_Vert_Baseline) @@ -908,14 +859,12 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i } } - return selfSize; } --(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFloatLayout*)lsc +-(CGSize)myHorzOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubviews:(NSArray*)sbs withSelfSize:(CGSize)selfSize isEstimate:(BOOL)isEstimate { //对于水平浮动布局来说,最终是从左到右排列,而对于RTL则是从右到左排列,因此这里先抽象定义头尾的概念,然后最后再计算时统一将抽象位置转化为CGRect的左边值。 - CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; @@ -930,10 +879,10 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i //支持浮动垂直间距。 CGFloat horzSpace = lsc.subviewHSpace; CGFloat vertSpace = lsc.subviewVSpace; - CGFloat subviewSize = [self myCalcMaxMinSubviewSize:selfSize.height - paddingVert lsc:(MyFloatLayoutViewSizeClass*)lsc space:&vertSpace]; + CGFloat subviewSize = [self myLayout:lsc calcMaxMinSubviewSizeWithSelfSize:selfSize.height - paddingVert space:&vertSpace]; //设置子视图的宽度和高度。 - [self myCalcFloatLayoutSubviewsSize:sbs lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing subviewSize:subviewSize isWidth:NO]; + [self myLayout:lsc calcSizeOfSubviews:sbs selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing subviewSize:subviewSize isWidth:NO]; //上边候选区域数组,保存的是CGRect值。 NSMutableArray *topCandidateRects = [NSMutableArray new]; @@ -963,7 +912,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i { UIView *sbv = sbs[idx]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; @@ -1023,7 +972,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i } - rect.origin.y = nextPoint.y - bottomSpace - rect.size.height; rect.origin.x = _myCGFloatMin(nextPoint.x, maxWidth) + leadingSpace; @@ -1061,7 +1009,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i } } - //这里有可能子视图本身的高度会超过布局视图本身,但是我们的候选区域则不存储超过的高度部分。 CGRect cRect = CGRectMake(rect.origin.x - leadingSpace, _myCGFloatMax((rect.origin.y - topSpace - vertSpace),paddingTop), rect.size.width + leadingSpace + trailingSpace + horzSpace, _myCGFloatMin((rect.size.height + topSpace + bottomSpace),(selfSize.height - paddingVert))); @@ -1094,7 +1041,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i cRect = CGRectUnion(cRect, candidateRect); cRect.size.height += candidateMaxY - cMinY; } - } //记录每一列的最大子视图位置的索引值。 @@ -1191,10 +1137,8 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i } } - CGRect cRect = CGRectMake(rect.origin.x - leadingSpace, rect.origin.y - topSpace,rect.size.width + leadingSpace + trailingSpace + horzSpace,_myCGFloatMin((rect.size.height + topSpace + bottomSpace + vertSpace),(selfSize.height - paddingVert))); - //把新添加到候选中去。并删除宽度小于的最新候选区域的候选区域 for (NSInteger i = topCandidateRects.count - 1; i >= 0; i--) { @@ -1228,16 +1172,13 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i //记录每一列的最大子视图位置的索引值。 if (topLastXOffset != rect.origin.x - leadingSpace) - { [lineIndexes addObject:@(idx - 1)]; - } [topCandidateRects addObject:[NSValue valueWithCGRect:cRect]]; topLastXOffset = rect.origin.x - leadingSpace; if (_myCGFloatGreat(rect.origin.x + rect.size.width + trailingSpace + horzSpace,topMaxWidth)) topMaxWidth = rect.origin.x + rect.size.width + trailingSpace + horzSpace; - } if (_myCGFloatGreat(rect.origin.x + rect.size.width + trailingSpace + horzSpace, maxWidth)) @@ -1247,7 +1188,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i maxHeight = rect.origin.y + rect.size.height + bottomSpace + vertSpace; sbvmyFrame.frame = rect; - } if (sbs.count > 0) @@ -1298,9 +1238,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i { //最后一列。 if (sbs.count > 0) - { [lineIndexes addObject:@(sbs.count - 1)]; - } NSInteger lineFirstIndex = 0; for (NSNumber *idxnum in lineIndexes) @@ -1313,7 +1251,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvmyFrame.width > lineMaxWidth) lineMaxWidth = sbvmyFrame.width; @@ -1327,7 +1265,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; switch ([self myConvertLeftRightGravityToLeadingTrailing:sbvsc.alignment & MyGravity_Vert_Mask]) { case MyGravity_Horz_Center: sbvmyFrame.leading += (lineMaxWidth - sbvmyFrame.width) / 2.0; @@ -1357,5 +1295,4 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSArray*)sbs i return selfSize; } - @end diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index ccfa131..1642634 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -9,7 +9,6 @@ #import "MyFlowLayout.h" #import "MyLayoutInner.h" - @implementation MyFlowLayout #pragma mark -- Public Methods @@ -31,7 +30,6 @@ -(instancetype)initWithOrientation:(MyOrientation)orientation arrangedCount:(NSI return [self initWithFrame:CGRectZero orientation:orientation arrangedCount:arrangedCount]; } - +(instancetype)flowLayoutWithOrientation:(MyOrientation)orientation arrangedCount:(NSInteger)arrangedCount { MyFlowLayout *layout = [[[self class] alloc] initWithOrientation:orientation arrangedCount:arrangedCount]; @@ -40,7 +38,7 @@ +(instancetype)flowLayoutWithOrientation:(MyOrientation)orientation arrangedCoun -(void)setOrientation:(MyOrientation)orientation { - MyFlowLayout *lsc = self.myCurrentSizeClass; + MyFlowLayout *lsc = self.myCurrentSizeClass; if (lsc.orientation != orientation) { lsc.orientation = orientation; @@ -53,7 +51,6 @@ -(MyOrientation)orientation return self.myCurrentSizeClass.orientation; } - -(void)setArrangedCount:(NSInteger)arrangedCount { MyFlowLayout *lsc = self.myCurrentSizeClass; @@ -70,7 +67,6 @@ -(NSInteger)arrangedCount return lsc.arrangedCount; } - -(NSInteger)pagedCount { MyFlowLayout *lsc = self.myCurrentSizeClass; @@ -87,11 +83,9 @@ -(void)setPagedCount:(NSInteger)pagedCount } } - -(void)setAutoArrange:(BOOL)autoArrange { MyFlowLayout *lsc = self.myCurrentSizeClass; - if (lsc.autoArrange != autoArrange) { lsc.autoArrange = autoArrange; @@ -104,7 +98,6 @@ -(BOOL)autoArrange return self.myCurrentSizeClass.autoArrange; } - -(void)setArrangedGravity:(MyGravity)arrangedGravity { MyFlowLayout *lsc = self.myCurrentSizeClass; @@ -159,13 +152,12 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbs == nil) sbs = [self myGetLayoutSubviews]; - MyFlowLayout *lsc = self.myCurrentSizeClass; - + MyFlowLayoutViewSizeClass *lsc = (MyFlowLayoutViewSizeClass*)self.myCurrentSizeClass; MyOrientation orientation = lsc.orientation; MyGravity gravity = lsc.gravity; MyGravity arrangedGravity = lsc.arrangedGravity; - [self myCalcSubviewsWrapContentSize:sbs isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass withCustomSetting:^(UIView *sbv, UIView *sbvsc) { + [self myCalcSubviewsWrapContentSize:sbs isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass withCustomSetting:^(MyViewSizeClass *sbvsc) { if (sbvsc.widthSizeInner.dimeWrapVal) { @@ -173,7 +165,8 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( (orientation == MyOrientation_Horz && (arrangedGravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill) || (orientation == MyOrientation_Vert && ((gravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill || sbvsc.weight != 0))) { - [sbvsc.widthSizeInner __setActive:NO]; + if ([sbvsc.view isKindOfClass:[MyBaseLayout class]]) + [sbvsc.widthSizeInner __setActive:NO]; } } @@ -183,26 +176,25 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( (orientation == MyOrientation_Vert && (arrangedGravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill) || (orientation == MyOrientation_Horz && ((gravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill || sbvsc.weight != 0))) { - [sbvsc.heightSizeInner __setActive:NO]; + if ([sbvsc.view isKindOfClass:[MyBaseLayout class]]) + [sbvsc.heightSizeInner __setActive:NO]; } } - }]; - if (orientation == MyOrientation_Vert) { if (lsc.arrangedCount == 0) - selfSize = [self myCalcLayoutSizeForVertOrientationContent:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; + selfSize = [self myLayout:lsc calcSizeForVertOrientationContent:selfSize sbs:sbs isEstimate:isEstimate]; else - selfSize = [self myCalcLayoutSizeForVertOrientation:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; + selfSize = [self myLayout:lsc calcSizeForVertOrientation:selfSize sbs:sbs isEstimate:isEstimate]; } else { if (lsc.arrangedCount == 0) - selfSize = [self myCalcLayoutSizeForHorzOrientationContent:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; + selfSize = [self myLayout:lsc calcSizeForHorzOrientationContent:selfSize sbs:sbs isEstimate:isEstimate]; else - selfSize = [self myCalcLayoutSizeForHorzOrientation:selfSize sbs:sbs isEstimate:isEstimate lsc:lsc]; + selfSize = [self myLayout:lsc calcSizeForHorzOrientation:selfSize sbs:sbs isEstimate:isEstimate]; } return [self myLayout:lsc adjustSelfSize:selfSize withSubviews:sbs]; @@ -216,7 +208,7 @@ -(id)createSizeClassInstance #pragma mark -- Private Methods //计算垂直流式布局下每行的比重值。 -- (void)myCalcVertLayoutSinglelineWeight:(CGFloat)lineTotalWeight lineSpareWidth:(CGFloat)lineSpareWidth sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize +- (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSinglelineWeight:(CGFloat)lineTotalWeight lineSpareWidth:(CGFloat)lineSpareWidth sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count inSelfSize:(CGSize)selfSize { //如果浮动宽度都是小于等于0因为没有拉升必要,所以直接返回 if (lineSpareWidth <= 0.0) @@ -226,12 +218,11 @@ - (void)myCalcVertLayoutSinglelineWeight:(CGFloat)lineTotalWeight lineSpareWidth if (lsc.isFlex && lineTotalWeight < 1.0) lineSpareWidth *= lineTotalWeight; - for (NSInteger itemIndex = startItemIndex; itemIndex < startItemIndex + count; itemIndex++) { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.weight != 0) { @@ -245,7 +236,7 @@ - (void)myCalcVertLayoutSinglelineWeight:(CGFloat)lineTotalWeight lineSpareWidth } //计算水平流式布局下每行的比重值。 -- (void)myCalcHorzLayoutSinglelineWeight:(CGFloat)lineTotalWeight lineSpareHeight:(CGFloat)lineSpareHeight sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize +- (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSinglelineWeight:(CGFloat)lineTotalWeight lineSpareHeight:(CGFloat)lineSpareHeight sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count inSelfSize:(CGSize)selfSize { if (lineSpareHeight <= 0.0) return; @@ -257,7 +248,7 @@ - (void)myCalcHorzLayoutSinglelineWeight:(CGFloat)lineTotalWeight lineSpareHeigh { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.weight != 0) { @@ -277,7 +268,7 @@ - (void)myCalcHorzLayoutSinglelineWeight:(CGFloat)lineTotalWeight lineSpareHeigh } //调整内容约束垂直流式布局的每行的宽度 -- (void)myAdjustVertLayoutSingleline:(NSInteger)lineIndex lineSpareWidth:(CGFloat)lineSpareWidth lineTotalWeight:(CGFloat)lineTotalWeight horzGravity:(MyGravity)horzGravity sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize +- (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc adjustSingleline:(NSInteger)lineIndex lineSpareWidth:(CGFloat)lineSpareWidth lineTotalWeight:(CGFloat)lineTotalWeight horzGravity:(MyGravity)horzGravity sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count inSelfSize:(CGSize)selfSize { if (lineSpareWidth <= 0.0) return; @@ -308,7 +299,7 @@ - (void)myAdjustVertLayoutSingleline:(NSInteger)lineIndex lineSpareWidth:(CGFloa { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.weight != 0.0 && lineTotalWeight != 0.0) { @@ -327,7 +318,7 @@ - (void)myAdjustVertLayoutSingleline:(NSInteger)lineIndex lineSpareWidth:(CGFloa } //调整内容约束水平流式布局的每行的高度 -- (void)myAdjustHorzLayoutSingleline:(NSInteger)lineIndex lineSpareHeight:(CGFloat)lineSpareHeight lineTotalWeight:(CGFloat)lineTotalWeight vertGravity:(MyGravity)vertGravity sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize +- (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc adjustSingleline:(NSInteger)lineIndex lineSpareHeight:(CGFloat)lineSpareHeight lineTotalWeight:(CGFloat)lineTotalWeight vertGravity:(MyGravity)vertGravity sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count inSelfSize:(CGSize)selfSize { if (lineSpareHeight <= 0.0) return; @@ -358,7 +349,7 @@ - (void)myAdjustHorzLayoutSingleline:(NSInteger)lineIndex lineSpareHeight:(CGFlo { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.weight != 0.0 && lineTotalWeight != 0.0) { @@ -373,10 +364,9 @@ - (void)myAdjustHorzLayoutSingleline:(NSInteger)lineIndex lineSpareHeight:(CGFlo if (addYFill != 0.0) sbvmyFrame.height += addYFill; } - } -- (void)myCalcVertLayoutSinglelineShrink:(CGFloat)lineTotalShrink lineSpareWidth:(CGFloat)lineSpareWidth sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize +- (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSinglelineShrink:(CGFloat)lineTotalShrink lineSpareWidth:(CGFloat)lineSpareWidth sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count inSelfSize:(CGSize)selfSize { if (_myCGFloatGreatOrEqual(lineSpareWidth, 0.0)) lineTotalShrink = 0.0; @@ -393,7 +383,7 @@ - (void)myCalcVertLayoutSinglelineShrink:(CGFloat)lineTotalShrink lineSpareWidth { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.widthSizeInner.shrink != 0.0) { @@ -404,7 +394,7 @@ - (void)myCalcVertLayoutSinglelineShrink:(CGFloat)lineTotalShrink lineSpareWidth } } -- (void)myCalcHorzLayoutSinglelineShrink:(CGFloat)lineTotalShrink lineSpareHeight:(CGFloat)lineSpareHeight sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count lsc:(MyFlowLayout *)lsc inSelfSize:(CGSize)selfSize +- (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSinglelineShrink:(CGFloat)lineTotalShrink lineSpareHeight:(CGFloat)lineSpareHeight sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count inSelfSize:(CGSize)selfSize { if (_myCGFloatGreatOrEqual(lineSpareHeight, 0.0)) lineTotalShrink = 0.0; @@ -421,7 +411,7 @@ - (void)myCalcHorzLayoutSinglelineShrink:(CGFloat)lineTotalShrink lineSpareHeigh { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.heightSizeInner.shrink != 0.0) { @@ -433,7 +423,7 @@ - (void)myCalcHorzLayoutSinglelineShrink:(CGFloat)lineTotalShrink lineSpareHeigh } -- (void)myCalcVertLayoutSingleline:(NSInteger)lineIndex vertAlignment:(MyGravity)vertAlignment horzGravity:(MyGravity)horzGravity lineMaxHeight:(CGFloat)lineMaxHeight lineMaxWidth:(CGFloat)lineMaxWidth lineTotalShrink:(CGFloat)lineTotalShrink sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize +- (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)lineIndex vertAlignment:(MyGravity)vertAlignment horzGravity:(MyGravity)horzGravity lineMaxHeight:(CGFloat)lineMaxHeight lineMaxWidth:(CGFloat)lineMaxWidth lineTotalShrink:(CGFloat)lineTotalShrink sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate inSelfSize:(CGSize)selfSize { CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; @@ -513,9 +503,8 @@ - (void)myCalcVertLayoutSingleline:(NSInteger)lineIndex vertAlignment:(MyGravity for (NSInteger itemIndex = startItemIndex; itemIndex < startItemIndex + count; itemIndex++) { UIView *sbv = sbs[itemIndex]; - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (!isEstimate && self.intelligentBorderline != nil) { @@ -631,10 +620,9 @@ - (void)myCalcVertLayoutSingleline:(NSInteger)lineIndex vertAlignment:(MyGravity } } } - } -- (void)myCalcHorzLayoutSingleline:(NSInteger)lineIndex horzAlignment:(MyGravity)horzAlignment vertGravity:(MyGravity)vertGravity lineMaxWidth:(CGFloat)lineMaxWidth lineMaxHeight:(CGFloat)lineMaxHeight lineTotalShrink:(CGFloat)lineTotalShrink sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc inSelfSize:(CGSize)selfSize +- (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)lineIndex horzAlignment:(MyGravity)horzAlignment vertGravity:(MyGravity)vertGravity lineMaxWidth:(CGFloat)lineMaxWidth lineMaxHeight:(CGFloat)lineMaxHeight lineTotalShrink:(CGFloat)lineTotalShrink sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate inSelfSize:(CGSize)selfSize { CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; @@ -712,7 +700,7 @@ - (void)myCalcHorzLayoutSingleline:(NSInteger)lineIndex horzAlignment:(MyGravity { UIView *sbv = sbs[itemIndex]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (!isEstimate && self.intelligentBorderline != nil) @@ -727,7 +715,6 @@ - (void)myCalcHorzLayoutSingleline:(NSInteger)lineIndex horzAlignment:(MyGravity sbvl.trailingBorderline = nil; sbvl.bottomBorderline = nil; - //如果不是最后一行就画下面, if (itemIndex < (startItemIndex + count) - 1) sbvl.bottomBorderline = self.intelligentBorderline; @@ -751,7 +738,6 @@ - (void)myCalcHorzLayoutSingleline:(NSInteger)lineIndex horzAlignment:(MyGravity } } - MyGravity sbvHorzAlignment = [self myConvertLeftRightGravityToLeadingTrailing:sbvsc.alignment & MyGravity_Vert_Mask]; if (sbvHorzAlignment == MyGravity_None) sbvHorzAlignment = lineHorzAlignment; @@ -814,10 +800,8 @@ - (void)myCalcHorzLayoutSingleline:(NSInteger)lineIndex horzAlignment:(MyGravity } } } - } - -(CGFloat)myCalcSinglelineSize:(NSArray*)sbs space:(CGFloat)space { CGFloat size = 0; @@ -835,7 +819,6 @@ -(NSArray*)myGetAutoArrangeSubviews:(NSMutableArray*)sbs selfSize:(CGFloat)selfS { NSMutableArray *retArray = [NSMutableArray arrayWithCapacity:sbs.count]; - NSMutableArray *bestSinglelineArray = [NSMutableArray arrayWithCapacity:sbs.count /2]; while (sbs.count) { @@ -876,10 +859,8 @@ -(void)myCalcAutoArrangeSinglelineSubviews:(NSMutableArray*)sbs return; } - for (NSInteger i = index; i < sbs.count; i++) { - NSMutableArray *calcArray2 = [NSMutableArray arrayWithArray:calcArray]; [calcArray2 addObject:sbs[i]]; @@ -905,17 +886,14 @@ -(void)myCalcAutoArrangeSinglelineSubviews:(NSMutableArray*)sbs { break; } - } - } --(CGFloat)myCalcMaxMinSubviewSizeForContent:(CGFloat)selfSize lsc:(MyFlowLayoutViewSizeClass*)lsc space:(CGFloat*)pSpace +-(CGFloat)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcMaxMinSubviewSizeForContent:(CGFloat)selfSize space:(CGFloat*)pSpace { CGFloat subviewSize = lsc.subviewSize; if (subviewSize != 0) { - CGFloat minSpace = lsc.minSpace; CGFloat maxSpace = lsc.maxSpace; @@ -939,7 +917,7 @@ -(CGFloat)myCalcMaxMinSubviewSizeForContent:(CGFloat)selfSize lsc:(MyFlowLayoutV } --(CGFloat)myCalcMaxMinSubviewSize:(CGFloat)selfSize lsc:(MyFlowLayoutViewSizeClass*)lsc arrangedCount:(NSInteger)arrangedCount space:(CGFloat*)pSpace +-(CGFloat)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcMaxMinSubviewSize:(CGFloat)selfSize arrangedCount:(NSInteger)arrangedCount space:(CGFloat*)pSpace { CGFloat subviewSize = lsc.subviewSize; if (subviewSize != 0) @@ -957,7 +935,6 @@ -(CGFloat)myCalcMaxMinSubviewSize:(CGFloat)selfSize lsc:(MyFlowLayoutViewSizeCla *pSpace = minSpace; subviewSize = (selfSize - (*pSpace) * (arrangedCount - 1)) / arrangedCount; - } } } @@ -966,9 +943,8 @@ -(CGFloat)myCalcMaxMinSubviewSize:(CGFloat)selfSize lsc:(MyFlowLayoutViewSizeCla } --(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +-(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate { - CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; @@ -976,7 +952,6 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab CGFloat paddingHorz = paddingLeading + paddingTrailing; CGFloat paddingVert = paddingTop + paddingBottom; - MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; MyGravity vertAlignment = lsc.arrangedGravity & MyGravity_Horz_Mask; @@ -984,7 +959,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab //支持浮动水平间距。 CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = [self myCalcMaxMinSubviewSizeForContent:selfSize.width - paddingHorz lsc:(MyFlowLayoutViewSizeClass*)lsc space:&horzSpace]; + CGFloat subviewSize = [self myLayout:lsc calcMaxMinSubviewSizeForContent:selfSize.width - paddingHorz space:&horzSpace]; CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; @@ -998,7 +973,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab for (UIView* sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; #ifdef DEBUG //约束异常:垂直流式布局设置autoArrange为YES时,子视图不能将weight设置为非0. @@ -1008,7 +983,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; //暂时把宽度存放sbv.myFrame.trailing上。因为流式布局来说这个属性无用。 @@ -1018,10 +993,8 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab } [sbs setArray:[self myGetAutoArrangeSubviews:sbs selfSize:selfSize.width - paddingHorz space:horzSpace]]; - } - //每行行首子视图的索引位置。 NSMutableIndexSet *lineFirstSubviewIndexSet = [NSMutableIndexSet new]; NSInteger lineIndex = 0; //行的索引。 @@ -1032,7 +1005,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; @@ -1041,7 +1014,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab //这里先算一下那些有约束的高度,因为有可能有一些子视图的宽度等于这个子视图的高度。 if (sbvsc.heightSizeInner.dimeVal != nil) { - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } @@ -1052,7 +1025,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab } else if (sbvsc.widthSizeInner.dimeVal != nil) { - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) {//特殊处理宽度等于高度的情况 @@ -1103,7 +1076,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab [lineFirstSubviewIndexSet addIndex:i - itemIndex]; //拉伸以及调整行内子视图的宽度。 - [self myAdjustVertLayoutSingleline:lineIndex lineSpareWidth:selfSize.width - paddingTrailing - xPos lineTotalWeight:lineTotalWeight horzGravity:horzGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; + [self myVertLayout:lsc adjustSingleline:lineIndex lineSpareWidth:selfSize.width - paddingTrailing - xPos lineTotalWeight:lineTotalWeight horzGravity:horzGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; xPos = paddingLeading; @@ -1134,7 +1107,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab //最后一行的行首索引 [lineFirstSubviewIndexSet addIndex:i - itemIndex]; - [self myAdjustVertLayoutSingleline:lineIndex lineSpareWidth:selfSize.width - paddingTrailing - xPos lineTotalWeight:lineTotalWeight horzGravity:horzGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; + [self myVertLayout:lsc adjustSingleline:lineIndex lineSpareWidth:selfSize.width - paddingTrailing - xPos lineTotalWeight:lineTotalWeight horzGravity:horzGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; xPos = paddingLeading; lineIndex = 0; //行的索引。 @@ -1145,7 +1118,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; @@ -1159,7 +1132,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab //计算子视图的高度。 if (sbvsc.heightSizeInner.dimeVal != nil) { - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; } else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) { @@ -1191,7 +1164,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab yPos += vertSpace; yPos += lineMaxHeight; - [self myCalcVertLayoutSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; + [self myVertLayout:lsc calcSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; lineMaxHeight = 0.0; @@ -1235,7 +1208,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab lineMaxHeight = selfSize.height - paddingVert; //最后一行 - [self myCalcVertLayoutSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; + [self myVertLayout:lsc calcSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; //整体的停靠 if (vertGravity != MyGravity_None && selfSize.height != yPos) @@ -1297,7 +1270,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab if (vertGravity == MyGravity_Vert_Stretch) { - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.heightSizeInner.dimeVal == nil) { sbvmyFrame.height += fill; @@ -1335,7 +1308,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutab } --(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +-(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate { CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; @@ -1353,7 +1326,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = [self myCalcMaxMinSubviewSize:selfSize.width - paddingHorz lsc:(MyFlowLayoutViewSizeClass*)lsc arrangedCount:arrangedCount space:&horzSpace]; + CGFloat subviewSize = [self myLayout:lsc calcMaxMinSubviewSize:selfSize.width - paddingHorz arrangedCount:arrangedCount space:&horzSpace]; CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; @@ -1425,7 +1398,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (itemIndex >= arrangedCount) { @@ -1433,12 +1406,12 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (lineTotalWeight != 0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWeight:lineTotalWeight lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount lsc:lsc inSelfSize:selfSize]; + [self myVertLayout:lsc calcSinglelineWeight:lineTotalWeight lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount inSelfSize:selfSize]; } if (lineTotalShrink != 0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineShrink:lineTotalShrink lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount lsc:lsc inSelfSize:selfSize]; + [self myVertLayout:lsc calcSinglelineShrink:lineTotalShrink lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount inSelfSize:selfSize]; } lineTotalWeight = 0.0; @@ -1473,14 +1446,14 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (pagingItemHeight != 0.0) rect.size.height = pagingItemHeight - topSpace - bottomSpace; else - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; } else { - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; } } else if (sbvsc.weight != 0.0) @@ -1514,13 +1487,13 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray if (lineTotalWeight != 0.0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineWeight:lineTotalWeight lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; + [self myVertLayout:lsc calcSinglelineWeight:lineTotalWeight lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; } //如果有压缩子视图的处理则需要压缩子视图。 if (lineTotalShrink != 0.0 && horzGravity != MyGravity_Horz_Fill) { - [self myCalcVertLayoutSinglelineShrink:lineTotalShrink lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; + [self myVertLayout:lsc calcSinglelineShrink:lineTotalShrink lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; } //初始化每行的下一个子视图的位置。 @@ -1543,7 +1516,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; //新的一行 if (itemIndex >= arrangedCount) @@ -1552,7 +1525,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray yPos += vertSpace; yPos += lineMaxHeight; - [self myCalcVertLayoutSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; + [self myVertLayout:lsc calcSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; //分别处理水平分页和垂直分页。 if (isHorzPaging) @@ -1603,7 +1576,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray } else if (sbvsc.heightSizeInner.dimeVal != nil) { - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; } else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) {//如果没有设置高度约束但是又是垂直拉伸则将高度设置为0. @@ -1616,7 +1589,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray //再算一次宽度,只有比重为0并且不压缩的情况下计算。否则有可能前面被压缩或者被拉升而又会在这里重置了 if (sbvsc.weight == 0.0 && sbvsc.widthSizeInner.shrink == 0 && horzGravity != MyGravity_Horz_Fill) { - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; } //特殊处理宽度和高度相互依赖的情况。。 @@ -1741,7 +1714,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray lineMaxHeight = selfSize.height - paddingVert; //最后一行,有可能因为行宽的压缩导致那些高度依赖宽度以及高度自适应的视图会增加高度,从而使得行高被调整。 - [self myCalcVertLayoutSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; + [self myVertLayout:lsc calcSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; //整体的停靠 @@ -1793,7 +1766,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray int lineidx = i / arrangedCount; if (vertGravity == MyGravity_Vert_Stretch) { - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.heightSizeInner.dimeVal == nil) { sbvmyFrame.height += fill; @@ -1847,7 +1820,7 @@ -(CGSize)myCalcLayoutSizeForVertOrientation:(CGSize)selfSize sbs:(NSMutableArray return selfSize; } --(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +-(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate { CGFloat paddingTop = lsc.myLayoutTopPadding; @@ -1865,7 +1838,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab //支持浮动垂直间距。 CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = [self myCalcMaxMinSubviewSizeForContent:selfSize.height - paddingVert lsc:(MyFlowLayoutViewSizeClass*)lsc space:&vertSpace]; + CGFloat subviewSize = [self myLayout:lsc calcMaxMinSubviewSizeForContent:selfSize.height - paddingVert space:&vertSpace]; CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; @@ -1879,7 +1852,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab for (UIView* sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; #ifdef DEBUG //约束异常:水平流式布局设置autoArrange为YES时,子视图不能将weight设置为非0. @@ -1891,10 +1864,10 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab CGRect rect = sbvmyFrame.frame; - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; //暂时把宽度存放sbv.myFrame.trailing上。因为流式布局来说这个属性无用。 @@ -1915,7 +1888,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; @@ -1924,7 +1897,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab //这里先计算一下宽度,因为有可能有宽度固定,高度自适应的情况。 if (sbvsc.widthSizeInner.dimeVal != nil) { - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; } else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) @@ -1938,7 +1911,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab } else if (sbvsc.heightSizeInner.dimeVal != nil) { - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) {//特殊处理高度等于宽度的情况 @@ -1989,7 +1962,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab [lineFirstSubviewIndexSet addIndex:i - itemIndex]; //拉伸以及调整行内子视图的高度。 - [self myAdjustHorzLayoutSingleline:lineIndex lineSpareHeight:selfSize.height - paddingBottom - yPos lineTotalWeight:lineTotalWeight vertGravity:vertGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; + [self myHorzLayout:lsc adjustSingleline:lineIndex lineSpareHeight:selfSize.height - paddingBottom - yPos lineTotalWeight:lineTotalWeight vertGravity:vertGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; yPos = paddingTop; @@ -2021,7 +1994,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab //最后一行的行首索引 [lineFirstSubviewIndexSet addIndex:i - itemIndex]; - [self myAdjustHorzLayoutSingleline:lineIndex lineSpareHeight:selfSize.height - paddingBottom - yPos lineTotalWeight:lineTotalWeight vertGravity:vertGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; + [self myHorzLayout:lsc adjustSingleline:lineIndex lineSpareHeight:selfSize.height - paddingBottom - yPos lineTotalWeight:lineTotalWeight vertGravity:vertGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; yPos = paddingTop; @@ -2033,7 +2006,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; @@ -2066,7 +2039,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab xPos += horzSpace; xPos += lineMaxWidth; - [self myCalcHorzLayoutSingleline:lineIndex horzAlignment:horzAlign vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; + [self myHorzLayout:lsc calcSingleline:lineIndex horzAlignment:horzAlign vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; lineMaxWidth = 0.0; @@ -2109,7 +2082,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab lineMaxWidth = selfSize.width - paddingHorz; //最后一行 - [self myCalcHorzLayoutSingleline:lineIndex horzAlignment:horzAlign vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; + [self myHorzLayout:lsc calcSingleline:lineIndex horzAlignment:horzAlign vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; //整体的停靠 if (horzGravity != MyGravity_None && selfSize.width != xPos) @@ -2169,7 +2142,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab if (horzGravity == MyGravity_Horz_Stretch) { - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.widthSizeInner.dimeVal == nil) { sbvmyFrame.width += fill; @@ -2208,7 +2181,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientationContent:(CGSize)selfSize sbs:(NSMutab --(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate lsc:(MyFlowLayout*)lsc +-(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate { CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; @@ -2226,7 +2199,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = [self myCalcMaxMinSubviewSize:selfSize.height - paddingVert lsc:(MyFlowLayoutViewSizeClass*)lsc arrangedCount:arrangedCount space:&vertSpace]; + CGFloat subviewSize = [self myLayout:lsc calcMaxMinSubviewSize:selfSize.height - paddingVert arrangedCount:arrangedCount space:&vertSpace]; CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; @@ -2298,7 +2271,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (itemIndex >= arrangedCount) { @@ -2306,12 +2279,12 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray if (lineTotalWeight != 0 && vertGravity != MyGravity_Vert_Fill) { - [self myCalcHorzLayoutSinglelineWeight:lineTotalWeight lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount lsc:lsc inSelfSize:selfSize]; + [self myHorzLayout:lsc calcSinglelineWeight:lineTotalWeight lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount inSelfSize:selfSize]; } if (lineTotalShrink != 0 && vertGravity != MyGravity_Vert_Fill) { - [self myCalcHorzLayoutSinglelineShrink:lineTotalShrink lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount lsc:lsc inSelfSize:selfSize]; + [self myHorzLayout:lsc calcSinglelineShrink:lineTotalShrink lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount inSelfSize:selfSize]; } lineTotalWeight = 0.0; @@ -2331,7 +2304,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray rect.size.width = pagingItemWidth - leadingSpace - trailingSpace; else if (sbvsc.widthSizeInner.dimeVal != nil) { - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; } else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) { @@ -2360,7 +2333,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray } else { - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; } } else if (sbvsc.weight != 0.0) @@ -2376,7 +2349,6 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; } - if (sbvsc.weight != 0) lineTotalWeight += sbvsc.weight; @@ -2399,12 +2371,12 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray if (lineTotalWeight != 0.0 && vertGravity != MyGravity_Vert_Fill) { - [self myCalcHorzLayoutSinglelineWeight:lineTotalWeight lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; + [self myHorzLayout:lsc calcSinglelineWeight:lineTotalWeight lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; } if (lineTotalShrink != 0.0 && vertGravity != MyGravity_Vert_Fill) { - [self myCalcHorzLayoutSinglelineShrink:lineTotalShrink lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - itemIndex count:itemIndex lsc:lsc inSelfSize:selfSize]; + [self myHorzLayout:lsc calcSinglelineShrink:lineTotalShrink lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; } //初始化每行的下一个子视图的位置。 @@ -2427,7 +2399,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (itemIndex >= arrangedCount) { @@ -2435,7 +2407,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray xPos += horzSpace; xPos += lineMaxWidth; - [self myCalcHorzLayoutSingleline:lineIndex horzAlignment:horzAlignment vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; + [self myHorzLayout:lsc calcSingleline:lineIndex horzAlignment:horzAlignment vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; //分别处理水平分页和垂直分页。 @@ -2592,7 +2564,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray lineMaxWidth = selfSize.width - paddingHorz; //最后一行 - [self myCalcHorzLayoutSingleline:lineIndex horzAlignment:horzAlignment vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate lsc:lsc inSelfSize:selfSize]; + [self myHorzLayout:lsc calcSingleline:lineIndex horzAlignment:horzAlignment vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; //整体的停靠。 @@ -2645,7 +2617,7 @@ -(CGSize)myCalcLayoutSizeForHorzOrientation:(CGSize)selfSize sbs:(NSMutableArray int lineidx = i / arrangedCount; if (horzGravity == MyGravity_Horz_Stretch) { - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.widthSizeInner.dimeVal == nil) { sbvmyFrame.width += fill; diff --git a/MyLayout/Lib/MyFrameLayout.m b/MyLayout/Lib/MyFrameLayout.m index 1a5adaa..e655e04 100644 --- a/MyLayout/Lib/MyFrameLayout.m +++ b/MyLayout/Lib/MyFrameLayout.m @@ -9,22 +9,10 @@ #import "MyFrameLayout.h" #import "MyLayoutInner.h" - - @implementation MyFrameLayout -/* - // Only override drawRect: if you perform custom drawing. - // An empty implementation adversely affects performance during animation. - - (void)drawRect:(CGRect)rect { - // Drawing code - } - */ - - #pragma mark -- Override Methods - -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray *)sbs { CGSize selfSize = [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; @@ -32,7 +20,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbs == nil) sbs = [self myGetLayoutSubviews]; - MyFrameLayout *lsc = self.myCurrentSizeClass; + MyFrameLayoutViewSizeClass *lsc = (MyFrameLayoutViewSizeClass*)self.myCurrentSizeClass; CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; @@ -41,7 +29,6 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; - CGSize maxWrapSize = CGSizeMake(paddingLeading + paddingTrailing, paddingTop + paddingBottom); CGSize *pMaxWrapSize = &maxWrapSize; if (!lsc.heightSizeInner.dimeWrapVal && !lsc.widthSizeInner.dimeWrapVal) @@ -50,12 +37,12 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; - [self myLayout:lsc adjustSizeSettingOfSubview:sbv sbvsc:sbvsc isEstimate:isEstimate sbvmyFrame:sbvmyFrame selfSize:selfSize vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; + [self myLayout:lsc adjustSizeSettingOfSubview:sbvsc isEstimate:isEstimate sbvmyFrame:sbvmyFrame selfSize:selfSize vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; //计算自己的位置和高宽 - [self myLayout:lsc calcRectOfSubView:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame vertGravity:vertGravity horzGravity:horzGravity inSelfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:pMaxWrapSize]; + [self myLayout:lsc calcRectOfSubview:sbvsc sbvmyFrame:sbvmyFrame vertGravity:vertGravity horzGravity:horzGravity inSelfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:pMaxWrapSize]; } if (lsc.widthSizeInner.dimeWrapVal) @@ -70,7 +57,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; //只有子视图的尺寸或者位置依赖父视图的情况下才需要重新计算位置和尺寸。 @@ -82,7 +69,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( (sbvsc.heightSizeInner.dimeRelaVal.view == self) ) { - [self myLayout:lsc calcRectOfSubView:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame vertGravity:vertGravity horzGravity:horzGravity inSelfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:NULL]; + [self myLayout:lsc calcRectOfSubview:sbvsc sbvmyFrame:sbvmyFrame vertGravity:vertGravity horzGravity:horzGravity inSelfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:NULL]; } } } @@ -95,9 +82,4 @@ -(id)createSizeClassInstance return [MyFrameLayoutViewSizeClass new]; } - -#pragma mark -- Private Methods - - - @end diff --git a/MyLayout/Lib/MyGridLayout.m b/MyLayout/Lib/MyGridLayout.m index 8dcb7b2..51a1eb9 100644 --- a/MyLayout/Lib/MyGridLayout.m +++ b/MyLayout/Lib/MyGridLayout.m @@ -34,11 +34,9 @@ NSString * const kMyGridBorderlineOffset = @"offset"; NSString * const kMyGridBorderlineDash = @"dash"; - NSString * const vMyGridSizeWrap = @"wrap"; NSString * const vMyGridSizeFill = @"fill"; - NSString * const vMyGridGravityTop = @"top"; NSString * const vMyGridGravityBottom = @"bottom"; NSString * const vMyGridGravityLeft = @"left"; @@ -80,13 +78,9 @@ +(instancetype)viewGroup:(NSArray*)viewGroup actionData:(id)actionData return [[[self class] alloc] initWithViewGroup:viewGroup actionData:actionData]; } - @end - - - @interface MyGridLayout() @property(nonatomic, weak) MyGridLayoutViewSizeClass *lastSizeClass; @@ -96,7 +90,6 @@ @interface MyGridLayout() @end - @implementation MyGridLayout -(NSMutableDictionary*)tagsDict @@ -142,7 +135,6 @@ -(void)removeGridsIn:(MySizeClass)sizeClass -(NSArray*) subviewsContainedInGrid:(id)grid { - id gridNode = (id)grid; #ifdef DEBUG @@ -192,13 +184,9 @@ -(void)insertViewGroup:(NSArray *)viewGroup withActionData:(id)actionDa MyViewGroupAndActionData *va = [MyViewGroupAndActionData viewGroup:viewGroup actionData:actionData]; if (index == (NSUInteger)-1) - { [viewGroupArray addObject:va]; - } else - { [viewGroupArray insertObject:va atIndex:index]; - } for (UIView *sbv in viewGroup) { @@ -212,9 +200,7 @@ -(void)insertViewGroup:(NSArray *)viewGroup withActionData:(id)actionDa -(void)replaceViewGroup:(NSArray *)viewGroup withActionData:(id)actionData atIndex:(NSUInteger)index to:(NSInteger)gridTag { if (gridTag == 0) - { return; - } //... NSNumber *key = @(gridTag); @@ -225,7 +211,6 @@ -(void)replaceViewGroup:(NSArray *)viewGroup withActionData:(id)actionD return; } - //这里面有可能有存在的视图, 有可能存在于子视图数组里面,有可能存在于其他视图组里面。 //如果存在于其他标签则要从其他标签删除。。。 //而且多余的还要删除。。。这个好复杂啊。。 @@ -265,9 +250,7 @@ -(void)replaceViewGroup:(NSArray *)viewGroup withActionData:(id)actionD self.tagsDictLock = NO; - [self setNeedsLayout]; - } @@ -312,11 +295,9 @@ -(void)moveViewGroupAtIndex:(NSUInteger)index1 from:(NSInteger)origGridTag toIn [destViewGroupArray insertObject:va atIndex:index2]; - } [self setNeedsLayout]; - } @@ -356,8 +337,6 @@ -(void)removeViewGroupAtIndex:(NSUInteger)index from:(NSInteger)gridTag [self setNeedsLayout]; } - - -(void)removeViewGroupFrom:(NSInteger)gridTag { if (gridTag == 0) @@ -386,11 +365,8 @@ -(void)removeViewGroupFrom:(NSInteger)gridTag } [self setNeedsLayout]; - } - - -(void)exchangeViewGroupAtIndex:(NSUInteger)index1 from:(NSInteger)gridTag1 withViewGroupAtIndex:(NSUInteger)index2 from:(NSInteger)gridTag2 { if (gridTag1 == 0 || gridTag2 == 0) @@ -432,18 +408,12 @@ -(void)exchangeViewGroupAtIndex:(NSUInteger)index1 from:(NSInteger)gridTag1 wit [viewGroupArray1 insertObject:va2 atIndex:index1]; [viewGroupArray2 insertObject:va1 atIndex:index2]; } - - self.tagsDictLock = NO; - - } [self setNeedsLayout]; - } - -(NSUInteger)viewGroupCountOf:(NSInteger)gridTag { if (gridTag == 0) @@ -458,8 +428,6 @@ -(NSUInteger)viewGroupCountOf:(NSInteger)gridTag return viewGroupArray.count; } - - -(NSArray *)viewGroupAtIndex:(NSUInteger)index from:(NSInteger)gridTag { if (gridTag == 0) @@ -467,7 +435,6 @@ -(NSUInteger)viewGroupCountOf:(NSInteger)gridTag if (_tagsDict == nil) return nil; - NSNumber *key = @(gridTag); NSMutableArray *viewGroupArray = [self.tagsDict objectForKey:key]; @@ -481,11 +448,6 @@ -(NSUInteger)viewGroupCountOf:(NSInteger)gridTag - - - - - #pragma mark -- MyGrid -(id)actionData @@ -540,7 +502,6 @@ -(void)setActionData:(id)actionData id node = (id)[lsc addRowGrid:grid measure:measure]; node.superGrid = self; return node; - } -(id)addColGrid:(id)grid measure:(CGFloat)measure @@ -549,11 +510,8 @@ -(void)setActionData:(id)actionData id node = (id)[lsc addColGrid:grid measure:measure]; node.superGrid = self; return node; - } - - -(id)cloneGrid { MyGridLayout *lsc = self.myCurrentSizeClass; @@ -564,13 +522,11 @@ -(void)removeFromSuperGrid { MyGridLayout *lsc = self.myCurrentSizeClass; return [lsc removeFromSuperGrid]; - } -(id)superGrid { MyGridLayout *lsc = self.myCurrentSizeClass; - return lsc.superGrid; } @@ -593,12 +549,9 @@ -(void)setPlaceholder:(BOOL)placeholder lsc.placeholder = placeholder; } - -(BOOL)anchor { - MyGridLayout *lsc = self.myCurrentSizeClass; - return lsc.anchor; } @@ -611,7 +564,6 @@ -(void)setAnchor:(BOOL)anchor -(MyGravity)overlap { MyGridLayout *lsc = self.myCurrentSizeClass; - return lsc.overlap; } @@ -627,7 +579,6 @@ -(NSDictionary*)gridDictionary return lsc.gridDictionary; } - -(void)setGridDictionary:(NSDictionary *)gridDictionary { MyGridLayout *lsc = self.myCurrentSizeClass; @@ -637,7 +588,6 @@ -(void)setGridDictionary:(NSDictionary *)gridDictionary #pragma mark -- MyGridNode - -(NSMutableArray> *)subGrids { MyGridLayout *lsc = self.myCurrentSizeClass; @@ -653,7 +603,6 @@ -(void)setSubGrids:(NSMutableArray> *)subGrids -(MySubGridsType)subGridsType { MyGridLayout *lsc = self.myCurrentSizeClass; - return lsc.subGridsType; } @@ -663,7 +612,6 @@ -(void)setSubGridsType:(MySubGridsType)subGridsType lsc.subGridsType = subGridsType; } - -(CGFloat)measure { MyGridLayout *lsc = self.myCurrentSizeClass; @@ -698,12 +646,10 @@ -(CGFloat)updateGridSize:(CGSize)superSize superGrid:(id)superGrid w -(CGFloat)updateGridOrigin:(CGPoint)superOrigin superGrid:(id)superGrid withOffset:(CGFloat)offset { MyGridLayout *lsc = self.myCurrentSizeClass; - return [lsc updateGridOrigin:superOrigin superGrid:superGrid withOffset:offset]; } - -(UIView*)gridLayoutView { return self; @@ -718,14 +664,12 @@ -(void)setBorderlineNeedLayoutIn:(CGRect)rect withLayer:(CALayer *)layer { MyGridLayout *lsc = self.myCurrentSizeClass; [lsc setBorderlineNeedLayoutIn:rect withLayer:layer]; - } -(void)showBorderline:(BOOL)show { MyGridLayout *lsc = self.myCurrentSizeClass; [lsc showBorderline:show]; - } -(id)gridHitTest:(CGPoint)point @@ -734,7 +678,6 @@ -(void)showBorderline:(BOOL)show return [lsc gridHitTest:point]; } - #pragma mark -- Touches Event -(id)myBestHitGrid:(NSSet *)touches @@ -749,10 +692,8 @@ -(void)showBorderline:(BOOL)show - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - [[self myBestHitGrid:touches] touchesBegan:touches withEvent:event]; [super touchesBegan:touches withEvent:event]; - } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event @@ -825,12 +766,10 @@ -(void)willRemoveSubview:(UIView *)subview break; } - }]; } } - -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs { CGSize selfSize = [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; @@ -838,10 +777,9 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbs == nil) sbs = [self myGetLayoutSubviews]; - MyFrame *myFrame = self.myFrame; - MyGridLayout *lsc = [self myCurrentSizeClassFrom:myFrame]; + MyGridLayoutViewSizeClass *lsc = (MyGridLayoutViewSizeClass*)[self myCurrentSizeClassFrom:myFrame]; //只有在非评估,并且当sizeclass的数量大于1个,并且当前的sizeclass和lastSizeClass不一致的时候 if (!isEstimate && myFrame.multiple) @@ -853,11 +791,9 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( self.lastSizeClass = (MyGridLayoutViewSizeClass*)lsc; } - //设置根格子的rect为布局视图的大小。 lsc.gridRect = CGRectMake(0, 0, selfSize.width, selfSize.height); - NSMutableDictionary *tagKeyIndexDict = [NSMutableDictionary dictionaryWithCapacity:self.tagsDict.count]; for (NSNumber *key in self.tagsDict) { @@ -868,14 +804,10 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( NSInteger index = 0; CGFloat selfMeasure = [self myTraversalGridSize:lsc gridSize:selfSize lsc:lsc sbs:sbs pIndex:&index tagViewGroupIndexDict:tagKeyIndexDict tagViewGroup:nil pTagIndex:nil]; if (lsc.heightSizeInner.dimeWrapVal) - { selfSize.height = selfMeasure; - } if (lsc.widthSizeInner.dimeWrapVal) - { selfSize.width = selfMeasure; - } //遍历位置。 for (NSNumber *key in self.tagsDict) @@ -886,7 +818,6 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( NSEnumerator *enumerator = sbs.objectEnumerator; [self myTraversalGridOrigin:lsc gridOrigin:CGPointMake(0, 0) lsc:lsc sbvEnumerator:enumerator tagViewGroupIndexDict:tagKeyIndexDict tagSbvEnumerator:nil isEstimate:isEstimate sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; - //遍历那些还剩余的然后设置为0. [tagKeyIndexDict enumerateKeysAndObjectsUsingBlock:^(id key, NSNumber *viewGroupIndexNumber, BOOL * stop) { @@ -909,7 +840,6 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( } }]; - //处理那些剩余没有放入格子的子视图的frame设置为0 for (UIView *sbv = enumerator.nextObject; sbv; sbv = enumerator.nextObject) sbv.myFrame.frame = CGRectZero; @@ -925,7 +855,7 @@ -(id)createSizeClassInstance #pragma mark -- Private Methods //遍历位置 --(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigin lsc:(MyGridLayout*)lsc sbvEnumerator:(NSEnumerator*)sbvEnumerator tagViewGroupIndexDict:(NSMutableDictionary*)tagViewGroupIndexDict tagSbvEnumerator:(NSEnumerator*)tagSbvEnumerator isEstimate:(BOOL)isEstimate sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout +-(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigin lsc:(MyGridLayoutViewSizeClass*)lsc sbvEnumerator:(NSEnumerator*)sbvEnumerator tagViewGroupIndexDict:(NSMutableDictionary*)tagViewGroupIndexDict tagSbvEnumerator:(NSEnumerator*)tagSbvEnumerator isEstimate:(BOOL)isEstimate sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout { //这要优化减少不必要的空数组的建立。。 NSArray> * subGrids = nil; @@ -934,9 +864,7 @@ -(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigi //绘制边界线。。 if (!isEstimate) - { [grid setBorderlineNeedLayoutIn:grid.gridRect withLayer:self.layer]; - } if (grid.tag != 0) @@ -972,7 +900,7 @@ -(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigi CGFloat paddingLeading; CGFloat paddingBottom; CGFloat paddingTrailing; - if (grid == lsc) + if (grid == (id)lsc) { paddingTop = lsc.myLayoutTopPadding; paddingLeading = lsc.myLayoutLeadingPadding; @@ -1006,7 +934,7 @@ -(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigi //调整位置和尺寸。。。 MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; //取垂直和水平对齐 MyGravity vertGravity = grid.gravity & MyGravity_Horz_Mask; @@ -1041,24 +969,18 @@ -(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigi //如果尺寸是0则因为前面有算出尺寸,所以这里就不进行调整了。 if (grid.measure != 0 && [sbv isKindOfClass:[MyBaseLayout class]]) { - [self myLayout:lsc adjustSizeSettingOfSubview:sbv sbvsc:sbvsc isEstimate:isEstimate sbvmyFrame:sbvmyFrame selfSize:grid.gridRect.size vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; - } - else - { + [self myLayout:lsc adjustSizeSettingOfSubview:sbvsc isEstimate:isEstimate sbvmyFrame:sbvmyFrame selfSize:grid.gridRect.size vertGravity:vertGravity horzGravity:horzGravity sizeClass:sizeClass pHasSubLayout:pHasSubLayout]; } - [self myLayout:lsc calcRectOfSubView:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame vertGravity:vertGravity horzGravity:horzGravity inSelfSize:grid.gridRect.size paddingTop:tempPaddingTop paddingLeading:tempPaddingLeading paddingBottom:tempPaddingBottom paddingTrailing:tempPaddingTrailing pMaxWrapSize:NULL]; + [self myLayout:lsc calcRectOfSubview:sbvsc sbvmyFrame:sbvmyFrame vertGravity:vertGravity horzGravity:horzGravity inSelfSize:grid.gridRect.size paddingTop:tempPaddingTop paddingLeading:tempPaddingLeading paddingBottom:tempPaddingBottom paddingTrailing:tempPaddingTrailing pMaxWrapSize:NULL]; sbvmyFrame.leading += gridOrigin.x; sbvmyFrame.top += gridOrigin.y; - } } - //处理子格子的位置。 - CGFloat offset = 0; if (grid.subGridsType == MySubGridsType_Col) { @@ -1079,16 +1001,11 @@ -(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigi if (horzGravity == MyGravity_Horz_Center) - { offset += (grid.gridRect.size.width - paddingLeading - paddingTrailing - subGridsWidth)/2; - } else - { offset += grid.gridRect.size.width - paddingLeading - paddingTrailing - subGridsWidth; - } } - } else if (grid.subGridsType == MySubGridsType_Row) { @@ -1108,23 +1025,12 @@ -(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigi subGridsHeight += grid.subviewSpace * (subGrids.count - 1); if (vertGravity == MyGravity_Vert_Center) - { offset += (grid.gridRect.size.height - paddingTop - paddingBottom - subGridsHeight)/2; - } else - { offset += grid.gridRect.size.height - paddingTop - paddingBottom - subGridsHeight; - } } - - } - else - { - } - - CGPoint paddingGridOrigin = CGPointMake(gridOrigin.x + paddingLeading, gridOrigin.y + paddingTop); for (id sbvGrid in subGrids) { @@ -1149,7 +1055,6 @@ -(void)myTraversalGridOrigin:(id)grid gridOrigin:(CGPoint)gridOrigi } } } - } -(void)myBlankTraverse:(id)grid sbs:(NSArray*)sbs pIndex:(NSInteger*)pIndex tagSbs:(NSArray *)tagSbs pTagIndex:(NSInteger*)pTagIndex @@ -1171,7 +1076,6 @@ -(void)myBlankTraverse:(id)grid sbs:(NSArray*)sbs pIndex:(N if (isNoNullSbv) *pIndex = *pIndex + 1; - } for (id sbvGrid in subGrids) @@ -1181,7 +1085,7 @@ -(void)myBlankTraverse:(id)grid sbs:(NSArray*)sbs pIndex:(N } //遍历尺寸。 --(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc:(MyGridLayout*)lsc sbs:(NSArray*)sbs pIndex:(NSInteger*)pIndex tagViewGroupIndexDict:(NSMutableDictionary*)tagViewGroupIndexDict tagViewGroup:(NSArray*)tagViewGroup pTagIndex:(NSInteger*)pTagIndex +-(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc:(MyGridLayoutViewSizeClass*)lsc sbs:(NSArray*)sbs pIndex:(NSInteger*)pIndex tagViewGroupIndexDict:(NSMutableDictionary*)tagViewGroupIndexDict tagViewGroup:(NSArray*)tagViewGroup pTagIndex:(NSInteger*)pTagIndex { NSArray> *subGrids = nil; if (grid.subGridsType != MySubGridsType_Unknown) @@ -1192,7 +1096,7 @@ -(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc CGFloat paddingLeading; CGFloat paddingBottom; CGFloat paddingTrailing; - if (grid == lsc) + if (grid == (id)lsc) { paddingTop = lsc.myLayoutTopPadding; paddingLeading = lsc.myLayoutLeadingPadding; @@ -1280,12 +1184,11 @@ -(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc UIView *sbv = tempSbs[*pTempIndex]; if (sbv != (UIView*)[NSNull null]) { - //叶子节点 if (!grid.anchor || (grid.measure == 0 && grid.anchor)) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; sbvmyFrame.frame = sbv.bounds; //如果子视图不设置任何约束要进行特殊处理。 @@ -1293,13 +1196,9 @@ -(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc { CGSize size = CGSizeZero; if (grid.superGrid.subGridsType == MySubGridsType_Row) - { size.width = gridSize.width - paddingLeading - paddingTrailing; - } else - { size.height = gridSize.height - paddingTop - paddingBottom; - } size = [sbv sizeThatFits:size]; sbvmyFrame.width = size.width; @@ -1307,17 +1206,13 @@ -(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc } else { - [self myLayout:lsc calcRectOfSubView:sbv sbvsc:sbvsc sbvmyFrame:sbvmyFrame vertGravity:MyGravity_None horzGravity:MyGravity_None inSelfSize:grid.gridRect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:NULL]; + [self myLayout:lsc calcRectOfSubview:sbvsc sbvmyFrame:sbvmyFrame vertGravity:MyGravity_None horzGravity:MyGravity_None inSelfSize:grid.gridRect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:NULL]; } if (grid.superGrid.subGridsType == MySubGridsType_Row) - { fixedMeasure = paddingTop + paddingBottom + sbvmyFrame.height; - } else - { fixedMeasure = paddingLeading + paddingTrailing + sbvmyFrame.width; - } } } else @@ -1328,38 +1223,28 @@ -(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc //索引加1跳转到下一个节点。 if (tagViewGroup != nil && pTagIndex != NULL) - { *pTempIndex = *pTempIndex + 1; - } if (isNotNullSbv) *pIndex = *pIndex + 1; } - if (subGrids.count > 0) { - NSMutableArray> *weightSubGrids = [NSMutableArray new]; //比重尺寸子格子数组 NSMutableArray *weightSubGridsIndexs = [NSMutableArray new]; //比重尺寸格子的开头子视图位置索引 NSMutableArray *weightSubGridsTagIndexs = [NSMutableArray new]; //比重尺寸格子的开头子视图位置索引 - NSMutableArray> *fillSubGrids = [NSMutableArray new]; //填充尺寸格子数组 NSMutableArray *fillSubGridsIndexs = [NSMutableArray new]; //填充尺寸格子的开头子视图位置索引 NSMutableArray *fillSubGridsTagIndexs = [NSMutableArray new]; //填充尺寸格子的开头子视图位置索引 - //包裹尺寸先遍历所有子格子 CGSize gridSize2 = gridSize; if (grid.subGridsType == MySubGridsType_Row) - { gridSize2.width -= (paddingLeading + paddingTrailing); - } else - { gridSize2.height -= (paddingTop + paddingBottom); - } for (id sbvGrid in subGrids) { @@ -1392,14 +1277,11 @@ -(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc [weightSubGridsIndexs addObject:@(*pIndex)]; if (pTagIndex != NULL) - { [weightSubGridsTagIndexs addObject:@(*pTagIndex)]; - } //这里面空转一下。 [self myBlankTraverse:sbvGrid sbs:sbs pIndex:pIndex tagSbs:tagViewGroup pTagIndex:pTagIndex]; - } else if (sbvGrid.measure == MyLayoutSize.fill) { @@ -1408,9 +1290,7 @@ -(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc [fillSubGridsIndexs addObject:@(*pIndex)]; if (pTagIndex != NULL) - { [fillSubGridsTagIndexs addObject:@(*pTagIndex)]; - } //这里面空转一下。 [self myBlankTraverse:sbvGrid sbs:sbs pIndex:pIndex tagSbs:tagViewGroup pTagIndex:pTagIndex]; @@ -1421,7 +1301,6 @@ -(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc } } - //算出剩余的尺寸。 BOOL hasTagIndex = (pTagIndex != NULL); CGFloat remainedMeasure = 0; @@ -1487,5 +1366,4 @@ -(CGFloat)myTraversalGridSize:(id)grid gridSize:(CGSize)gridSize lsc return fixedMeasure; } - @end diff --git a/MyLayout/Lib/MyGridNode.m b/MyLayout/Lib/MyGridNode.m index 359b54d..1a0a1da 100644 --- a/MyLayout/Lib/MyGridNode.m +++ b/MyLayout/Lib/MyGridNode.m @@ -38,14 +38,11 @@ -(instancetype)initWithLayout:(MyBaseLayout*)layout grid:(id)grid { self = [super initWithLayout:layout]; if (self != nil) - { _grid = grid; - } return self; } - -(void)mySetTouchHighlighted { //如果有高亮则建立一个高亮子层。 @@ -83,7 +80,6 @@ -(void)dealloc [self myResetTouchHighlighted]; } - @end @@ -171,9 +167,7 @@ -(void)setTag:(NSInteger)tag { if (_touchEventDelegate == nil && tag != 0) - { _touchEventDelegate = [[MyGridNodeTouchEventDelegate alloc] initWithLayout:(MyBaseLayout*)[self gridLayoutView] grid:self]; - } _touchEventDelegate.tag = tag; } @@ -191,9 +185,7 @@ - (NSString *)action -(void)setActionData:(id)actionData { if (_touchEventDelegate == nil && actionData != nil) - { _touchEventDelegate = [[MyGridNodeTouchEventDelegate alloc] initWithLayout:(MyBaseLayout*)[self gridLayoutView] grid:self]; - } _touchEventDelegate.actionData = actionData; } @@ -202,9 +194,7 @@ -(void)setActionData:(id)actionData -(void)setTarget:(id)target action:(SEL)action { if (_touchEventDelegate == nil && target != nil) - { _touchEventDelegate = [[MyGridNodeTouchEventDelegate alloc] initWithLayout:(MyBaseLayout*)[self gridLayoutView] grid:self]; - } [_touchEventDelegate setTarget:target action:action]; @@ -231,7 +221,6 @@ - (void)setGridDictionary:(NSDictionary *)gridDictionary - #pragma mark -- MyGrid -(MySubGridsType)subGridsType @@ -288,15 +277,11 @@ -(void)setOverlap:(MyGravity)overlap self.gravity = overlap; } - - -(id)addRow:(CGFloat)measure { //如果有子格子,但是第一个子格子不是行则报错误。 if (self.subGridsType == MySubGridsType_Col) - { NSAssert(0, @"oops! 当前的子格子是列格子,不能再添加行格子。"); - } MyGridNode *rowGrid = [[MyGridNode alloc] initWithMeasure:measure superGrid:self]; self.subGridsType = MySubGridsType_Row; @@ -308,9 +293,7 @@ -(void)setOverlap:(MyGravity)overlap { //如果有子格子,但是第一个子格子不是行则报错误。 if (self.subGridsType == MySubGridsType_Row) - { NSAssert(0, @"oops! 当前的子格子是行格子,不能再添加列格子。"); - } MyGridNode *colGrid = [[MyGridNode alloc] initWithMeasure:measure superGrid:self]; self.subGridsType = MySubGridsType_Col; @@ -324,9 +307,7 @@ -(void)setOverlap:(MyGravity)overlap //如果有子格子,但是第一个子格子不是行则报错误。 if (self.subGridsType == MySubGridsType_Col) - { NSAssert(0, @"oops! 当前的子格子是列格子,不能再添加行格子。"); - } self.subGridsType = MySubGridsType_Row; [self.subGrids addObject:(id)grid]; @@ -340,15 +321,12 @@ -(void)setOverlap:(MyGravity)overlap //如果有子格子,但是第一个子格子不是行则报错误。 if (self.subGridsType == MySubGridsType_Row) - { NSAssert(0, @"oops! 当前的子格子是列格子,不能再添加行格子。"); - } self.subGridsType = MySubGridsType_Col; [self.subGrids addObject:(id)grid]; ((MyGridNode*)grid).superGrid = self; return grid; - } -(id)addRowGrid:(id)grid measure:(CGFloat)measure @@ -365,8 +343,6 @@ -(void)setOverlap:(MyGravity)overlap return gridNode; } - - -(id)cloneGrid { MyGridNode *grid = [[MyGridNode alloc] initWithMeasure:self.measure superGrid:nil]; @@ -394,9 +370,7 @@ -(void)setOverlap:(MyGravity)overlap //拷贝事件处理。 if (self->_touchEventDelegate != nil) - { [grid setTarget:self->_touchEventDelegate.target action:self->_touchEventDelegate.action]; - } //克隆子节点。 if (self.subGridsType != MySubGridsType_Unknown) @@ -414,14 +388,11 @@ -(void)setOverlap:(MyGravity)overlap return grid; } - -(void)removeFromSuperGrid { [self.superGrid.subGrids removeObject:self]; if (self.superGrid.subGrids.count == 0) - { self.superGrid.subGridsType = MySubGridsType_Unknown; - } //如果可能销毁高亮层。 [_touchEventDelegate myResetTouchHighlighted]; @@ -434,9 +405,7 @@ -(void)removeFromSuperGrid -(NSMutableArray>*)subGrids { if (_subGrids == nil) - { _subGrids = [NSMutableArray new]; - } return _subGrids; } @@ -461,7 +430,6 @@ -(UIEdgeInsets)padding return UIEdgeInsetsZero; else return _optionalProperties2->padding; - } -(void)setPadding:(UIEdgeInsets)padding @@ -469,9 +437,6 @@ -(void)setPadding:(UIEdgeInsets)padding self.optionalProperties2->padding = padding; } - - - -(CGFloat)updateGridSize:(CGSize)superSize superGrid:(id)superGrid withMeasure:(CGFloat)measure { if (superGrid.subGridsType == MySubGridsType_Col) @@ -483,7 +448,6 @@ -(CGFloat)updateGridSize:(CGSize)superSize superGrid:(id)superGrid w { _gridRect.size.width = superSize.width; _gridRect.size.height = measure; - } return measure; @@ -501,17 +465,14 @@ -(CGFloat)updateGridOrigin:(CGPoint)superOrigin superGrid:(id)superG { _gridRect.origin.x = superOrigin.x; _gridRect.origin.y = offset; - return _gridRect.size.height; } else { return 0; } - } - -(UIView*)gridLayoutView { return [[self superGrid] gridLayoutView]; @@ -522,7 +483,6 @@ -(SEL)gridAction return _touchEventDelegate.action; } - -(void)setBorderlineNeedLayoutIn:(CGRect)rect withLayer:(CALayer*)layer { [_borderlineLayerDelegate setNeedsLayoutIn:rect withLayer:layer]; @@ -545,7 +505,6 @@ -(void)showBorderline:(BOOL)show } } - -(MyBorderline*)topBorderline { return _borderlineLayerDelegate.topBorderline; @@ -561,7 +520,6 @@ -(void)setTopBorderline:(MyBorderline *)topBorderline _borderlineLayerDelegate.topBorderline = topBorderline; } - -(MyBorderline*)bottomBorderline { return _borderlineLayerDelegate.bottomBorderline; @@ -570,10 +528,7 @@ -(MyBorderline*)bottomBorderline -(void)setBottomBorderline:(MyBorderline *)bottomBorderline { if (_borderlineLayerDelegate == nil) - { _borderlineLayerDelegate = [[MyBorderlineLayerDelegate alloc] initWithLayoutLayer:[self gridLayoutView].layer]; - } - _borderlineLayerDelegate.bottomBorderline = bottomBorderline; } @@ -586,14 +541,10 @@ -(MyBorderline*)leftBorderline -(void)setLeftBorderline:(MyBorderline *)leftBorderline { if (_borderlineLayerDelegate == nil) - { _borderlineLayerDelegate = [[MyBorderlineLayerDelegate alloc] initWithLayoutLayer:[self gridLayoutView].layer]; - } - _borderlineLayerDelegate.leftBorderline = leftBorderline; } - -(MyBorderline*)rightBorderline { return _borderlineLayerDelegate.rightBorderline; @@ -602,14 +553,10 @@ -(MyBorderline*)rightBorderline -(void)setRightBorderline:(MyBorderline *)rightBorderline { if (_borderlineLayerDelegate == nil) - { _borderlineLayerDelegate = [[MyBorderlineLayerDelegate alloc] initWithLayoutLayer:[self gridLayoutView].layer]; - } - _borderlineLayerDelegate.rightBorderline = rightBorderline; } - -(MyBorderline*)leadingBorderline { return _borderlineLayerDelegate.leadingBorderline; @@ -618,15 +565,10 @@ -(MyBorderline*)leadingBorderline -(void)setLeadingBorderline:(MyBorderline *)leadingBorderline { if (_borderlineLayerDelegate == nil) - { _borderlineLayerDelegate = [[MyBorderlineLayerDelegate alloc] initWithLayoutLayer:[self gridLayoutView].layer]; - } - _borderlineLayerDelegate.leadingBorderline = leadingBorderline; } - - -(MyBorderline*)trailingBorderline { return _borderlineLayerDelegate.trailingBorderline; @@ -635,28 +577,21 @@ -(MyBorderline*)trailingBorderline -(void)setTrailingBorderline:(MyBorderline *)trailingBorderline { if (_borderlineLayerDelegate == nil) - { _borderlineLayerDelegate = [[MyBorderlineLayerDelegate alloc] initWithLayoutLayer:[self gridLayoutView].layer]; - } - _borderlineLayerDelegate.trailingBorderline = trailingBorderline; } - -(id)gridHitTest:(CGPoint)point { - //如果不在范围内点击则直接返回 if (!CGRectContainsPoint(self.gridRect, point)) return nil; - //优先测试子视图。。然后再自己。。 NSArray> * subGrids = nil; if (self.subGridsType != MySubGridsType_Unknown) subGrids = self.subGrids; - for (id sbvGrid in subGrids) { id testGrid = [sbvGrid gridHitTest:point]; @@ -673,44 +608,34 @@ -(void)setTrailingBorderline:(MyBorderline *)trailingBorderline - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { if (_touchEventDelegate != nil && _touchEventDelegate.layout == nil) - { _touchEventDelegate.layout = (MyBaseLayout*)[self gridLayoutView]; - } [_touchEventDelegate touchesBegan:touches withEvent:event]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { if (_touchEventDelegate != nil && _touchEventDelegate.layout == nil) - { _touchEventDelegate.layout = (MyBaseLayout*)[self gridLayoutView]; - } [_touchEventDelegate touchesMoved:touches withEvent:event]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if (_touchEventDelegate != nil && _touchEventDelegate.layout == nil) - { _touchEventDelegate.layout = (MyBaseLayout*)[self gridLayoutView]; - } [_touchEventDelegate touchesEnded:touches withEvent:event]; } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { if (_touchEventDelegate != nil && _touchEventDelegate.layout == nil) - { _touchEventDelegate.layout = (MyBaseLayout*)[self gridLayoutView]; - } [_touchEventDelegate touchesCancelled:touches withEvent:event]; } - //////////////////////////////////////////// - +(void)translateGridDicionary:(NSDictionary *)gridDictionary toGridNode:(id)gridNode { id actionData = [gridDictionary objectForKey:kMyGridActionData]; diff --git a/MyLayout/Lib/MyLayoutDelegate.m b/MyLayout/Lib/MyLayoutDelegate.m index 48b9b52..22f57df 100644 --- a/MyLayout/Lib/MyLayoutDelegate.m +++ b/MyLayout/Lib/MyLayoutDelegate.m @@ -25,7 +25,6 @@ -(id)initWithLayoutLayer:(CALayer*)layoutLayer _layoutLayer = layoutLayer; _layoutRect = CGRectZero; } - return self; } @@ -58,9 +57,6 @@ -(void)dealloc [_trailingBorderlineLayer removeFromSuperlayer]; _trailingBorderlineLayer = nil; } - - - } -(void)setTopBorderline:(MyBorderline *)topBorderline @@ -72,7 +68,6 @@ -(void)setTopBorderline:(MyBorderline *)topBorderline CAShapeLayer *borderLayer = _topBorderlineLayer; [self updateBorderLayer:&borderLayer withBorderline:_topBorderline]; _topBorderlineLayer = borderLayer; - } } @@ -100,7 +95,6 @@ -(void)setBottomBorderline:(MyBorderline *)bottomBorderline } } - -(void)setTrailingBorderline:(MyBorderline *)trailingBorderline { if (_trailingBorderline != trailingBorderline) @@ -111,7 +105,6 @@ -(void)setTrailingBorderline:(MyBorderline *)trailingBorderline [self updateBorderLayer:&borderLayer withBorderline:_trailingBorderline]; _trailingBorderlineLayer = borderLayer; } - } -(MyBorderline*)leftBorderline @@ -130,7 +123,6 @@ -(void)setLeftBorderline:(MyBorderline *)leftBorderline self.leadingBorderline = leftBorderline; } - -(MyBorderline*)rightBorderline { if ([MyBaseLayout isRTL]) @@ -147,14 +139,10 @@ -(void)setRightBorderline:(MyBorderline *)rightBorderline self.trailingBorderline = rightBorderline; } - - -(void)updateBorderLayer:(CAShapeLayer**)ppLayer withBorderline:(MyBorderline*)borderline { - if (borderline == nil) { - if (*ppLayer != nil) { [(*ppLayer) removeFromSuperlayer]; @@ -164,7 +152,6 @@ -(void)updateBorderLayer:(CAShapeLayer**)ppLayer withBorderline:(MyBorderline*)b } else { - if ( *ppLayer == nil) { *ppLayer = [[CAShapeLayer alloc] init]; @@ -184,7 +171,6 @@ -(void)updateBorderLayer:(CAShapeLayer**)ppLayer withBorderline:(MyBorderline*)b (*ppLayer).strokeColor = borderline.color.CGColor; (*ppLayer).lineWidth = borderline.thick; (*ppLayer).backgroundColor = nil; - } else { @@ -194,15 +180,12 @@ -(void)updateBorderLayer:(CAShapeLayer**)ppLayer withBorderline:(MyBorderline*)b (*ppLayer).strokeColor = nil; (*ppLayer).lineWidth = 0; (*ppLayer).backgroundColor = borderline.color.CGColor; - } [(*ppLayer) setNeedsLayout]; - } } - -(void)layoutSublayersOfLayer:(CAShapeLayer *)layer { if (_layoutLayer == nil) @@ -267,13 +250,9 @@ -(void)layoutSublayersOfLayer:(CAShapeLayer *)layer } if ([MyBaseLayout isRTL]) - { layerRect.origin.x = layoutSize.width - layerRect.origin.x - layerRect.size.width; - } //把动画效果取消。 - - if (!_myCGRectEqual(layer.frame, layerRect)) { if (layer.lineDashPhase == 0) @@ -289,18 +268,14 @@ -(void)layoutSublayersOfLayer:(CAShapeLayer *)layer CGPathRelease(path); } layer.frame = layerRect; - } - } - - (nullable id)actionForLayer:(CALayer *)layer forKey:(NSString *)event { return [NSNull null]; } - -(void)setNeedsLayoutIn:(CGRect)rect withLayer:(CALayer*)layer { _layoutLayer = layer; @@ -344,7 +319,6 @@ -(void)setNeedsLayoutIn:(CGRect)rect withLayer:(CALayer*)layer _trailingBorderlineLayer.hidden = NO; [_trailingBorderlineLayer setNeedsLayout]; } - } -(void)updateAllBorderlineColor @@ -383,11 +357,9 @@ @implementation MyTouchEventDelegate SEL _touchCancelAction; BOOL _hasDoCancel; - BOOL _forbidTouch; BOOL _canCallAction; CGPoint _beginPoint; - } BOOL _hasBegin; @@ -439,9 +411,7 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event [self myPerformTouch:_touchCancelTarget withAction:_touchCancelAction]; _hasDoCancel = YES; - } - } } } @@ -449,7 +419,6 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event -(void)doTargetAction:(UITouch*)touch { - [self myResetTouchHighlighted]; //距离太远则不会处理 @@ -466,17 +435,13 @@ -(void)doTargetAction:(UITouch*)touch [self myPerformTouch:_touchCancelTarget withAction:_touchCancelAction]; _hasDoCancel = YES; } - } - _forbidTouch = NO; - } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - if (_layout != nil && _target != nil && _hasBegin && (_layout == _currentLayout || _currentLayout == nil)) { //设置一个延时. @@ -493,7 +458,6 @@ - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - if (_layout != nil && _target != nil && _hasBegin && (_layout == _currentLayout || _currentLayout == nil)) { [self myResetTouchHighlighted]; @@ -504,14 +468,11 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event if (!_hasDoCancel) { [self myPerformTouch:_touchCancelTarget withAction:_touchCancelAction]; - _hasDoCancel = YES; } - } } - ///设置触摸时的高亮 -(void)mySetTouchHighlighted { @@ -527,13 +488,11 @@ -(void)myResetTouchHighlighted2 } - -(id)myActionSender { return _layout; } - -(void)myPerformTouch:(id)target withAction:(SEL)action { if (_layout != nil && target != nil && action != nil && self.myActionSender != nil) @@ -562,14 +521,11 @@ -(void)setTouchCancelTarget:(id)target action:(SEL)action { _touchCancelTarget = target; _touchCancelAction = action; - } - @end - @implementation MyLayoutTouchEventDelegate { UIColor *_oldBackgroundColor; @@ -608,7 +564,6 @@ -(void)mySetTouchHighlighted _oldBackgroundImage = self.layout.backgroundImage; self.layout.backgroundImage = self.highlightedBackgroundImage; } - } //恢复触摸时的高亮。 @@ -626,13 +581,11 @@ -(void)myResetTouchHighlighted _oldBackgroundColor = nil; } - if (self.highlightedBackgroundImage != nil) { self.layout.backgroundImage = _oldBackgroundImage; _oldBackgroundImage = nil; } - } -(void)myResetTouchHighlighted2 diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index afba770..a0f8bf7 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -54,30 +54,28 @@ //判断margin是否是相对margin -(BOOL)myIsRelativePos:(CGFloat)margin; --(MyGravity)myGetSubviewVertGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc vertGravity:(MyGravity)vertGravity; +-(MyGravity)myGetSubview:(MyViewSizeClass*)sbvsc vertGravity:(MyGravity)vertGravity; --(CGFloat)myCalcVertGravity:(MyGravity)vert - sbv:(UIView *)sbv - sbvsc:(UIView*)sbvsc - paddingTop:(CGFloat)paddingTop - paddingBottom:(CGFloat)paddingBottom - baselinePos:(CGFloat)baselinePos - selfSize:(CGSize)selfSize - pRect:(CGRect*)pRect; +-(CGFloat)myCalcSubview:(MyViewSizeClass*)sbvsc + vertGravity:(MyGravity)vert + paddingTop:(CGFloat)paddingTop + paddingBottom:(CGFloat)paddingBottom + baselinePos:(CGFloat)baselinePos + selfSize:(CGSize)selfSize + pRect:(CGRect*)pRect; --(MyGravity)myGetSubviewHorzGravity:(UIView*)sbv sbvsc:(UIView*)sbvsc horzGravity:(MyGravity)horzGravity; +-(MyGravity)myGetSubview:(MyViewSizeClass*)sbvsc horzGravity:(MyGravity)horzGravity; --(CGFloat)myCalcHorzGravity:(MyGravity)horz - sbv:(UIView *)sbv - sbvsc:(UIView*)sbvsc +-(CGFloat)myCalcSubview:(MyViewSizeClass*)sbvsc + horzGravity:(MyGravity)horz paddingLeading:(CGFloat)paddingLeading paddingTrailing:(CGFloat)paddingTrailing selfSize:(CGSize)selfSize pRect:(CGRect*)pRect; --(CGFloat)myHeightFromFlexedHeightView:(UIView*)sbv sbvsc:(UIView*)sbvsc inWidth:(CGFloat)width; +-(CGFloat)mySubview:(MyViewSizeClass*)sbvsc wrapHeightSizeFits:(CGFloat)width; -(CGFloat)myValidMeasure:(MyLayoutSize*)dime sbv:(UIView*)sbv calcSize:(CGFloat)calcSize sbvSize:(CGSize)sbvSize selfLayoutSize:(CGSize)selfLayoutSize; @@ -88,7 +86,7 @@ -(NSMutableArray*)myGetLayoutSubviews; -(NSMutableArray*)myGetLayoutSubviewsFrom:(NSArray*)sbsFrom; --(CGSize)myLayout:(MyBaseLayout*)lsc adjustSelfSize:(CGSize)selfSize withSubviews:(NSArray*)sbs; +-(CGSize)myLayout:(MyLayoutViewSizeClass*)lsc adjustSelfSize:(CGSize)selfSize withSubviews:(NSArray*)sbs; -(MyGravity)myConvertLeftRightGravityToLeadingTrailing:(MyGravity)horzGravity; @@ -100,43 +98,42 @@ -(CGFloat)myLayoutLeadingPadding; -(CGFloat)myLayoutTrailingPadding; --(void)myLayout:(MyBaseLayout*)lsc adjustSizeSettingOfSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout; +-(void)myLayout:(MyLayoutViewSizeClass*)lsc adjustSizeSettingOfSubview:(MyViewSizeClass*)sbvsc isEstimate:(BOOL)isEstimate sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize vertGravity:(MyGravity)vertGravity horzGravity:(MyGravity)horzGravity sizeClass:(MySizeClass)sizeClass pHasSubLayout:(BOOL*)pHasSubLayout; //根据子视图的宽度约束得到宽度值 --(CGFloat)myGetSubviewWidthSizeValue:(UIView *)sbv - sbvsc:(UIView *)sbvsc - lsc:(MyBaseLayout *)lsc - selfSize:(CGSize)selfSize - paddingTop:(CGFloat)paddingTop - paddingLeading:(CGFloat)paddingLeading - paddingBottom:(CGFloat)paddingBottom - paddingTrailing:(CGFloat)paddingTrailing - sbvSize:(CGSize)sbvSize; +-(CGFloat)myLayout:(MyLayoutViewSizeClass*)lsc +widthSizeValueOfSubview:(MyViewSizeClass *)sbvsc + selfSize:(CGSize)selfSize + sbvSize:(CGSize)sbvSize + paddingTop:(CGFloat)paddingTop + paddingLeading:(CGFloat)paddingLeading + paddingBottom:(CGFloat)paddingBottom + paddingTrailing:(CGFloat)paddingTrailing; + //根据子视图的高度约束得到高度值 --(CGFloat)myGetSubviewHeightSizeValue:(UIView *)sbv - sbvsc:(UIView *)sbvsc - lsc:(MyBaseLayout *)lsc - selfSize:(CGSize)selfSize - paddingTop:(CGFloat)paddingTop - paddingLeading:(CGFloat)paddingLeading - paddingBottom:(CGFloat)paddingBottom - paddingTrailing:(CGFloat)paddingTrailing - sbvSize:(CGSize)sbvSize; - - --(void)myLayout:(MyBaseLayout*)lsc calcRectOfSubView:(UIView*)sbv - sbvsc:(UIView*)sbvsc - sbvmyFrame:(MyFrame*)sbvmyFrame - vertGravity:(MyGravity)vertGravity - horzGravity:(MyGravity)horzGravity - inSelfSize:(CGSize)selfSize - paddingTop:(CGFloat)paddingTop - paddingLeading:(CGFloat)paddingLeading - paddingBottom:(CGFloat)paddingBottom - paddingTrailing:(CGFloat)paddingTrailing - pMaxWrapSize:(CGSize*)pMaxWrapSize; +-(CGFloat)myLayout:(MyLayoutViewSizeClass*)lsc +heightSizeValueOfSubview:(MyViewSizeClass *)sbvsc + selfSize:(CGSize)selfSize + sbvSize:(CGSize)sbvSize + paddingTop:(CGFloat)paddingTop + paddingLeading:(CGFloat)paddingLeading + paddingBottom:(CGFloat)paddingBottom + paddingTrailing:(CGFloat)paddingTrailing; + + +-(void)myLayout:(MyLayoutViewSizeClass*)lsc +calcRectOfSubview:(MyViewSizeClass*)sbvsc + sbvmyFrame:(MyFrame*)sbvmyFrame + vertGravity:(MyGravity)vertGravity + horzGravity:(MyGravity)horzGravity + inSelfSize:(CGSize)selfSize + paddingTop:(CGFloat)paddingTop + paddingLeading:(CGFloat)paddingLeading + paddingBottom:(CGFloat)paddingBottom +paddingTrailing:(CGFloat)paddingTrailing + pMaxWrapSize:(CGSize*)pMaxWrapSize; -(UIFont*)myGetSubviewFont:(UIView*)sbv; @@ -145,7 +142,7 @@ //给父布局视图机会来更改子布局视图的边界线的显示的rect -(void)myHookSublayout:(MyBaseLayout*)sublayout borderlineRect:(CGRect*)pRect; --(void)myCalcSubviewsWrapContentSize:(NSArray*)sbs isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass withCustomSetting:(void (^)(UIView *sbv, UIView *sbvsc))customSetting; +-(void)myCalcSubviewsWrapContentSize:(NSArray*)sbs isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass withCustomSetting:(void (^)(MyViewSizeClass *sbvsc))customSetting; @end diff --git a/MyLayout/Lib/MyLayoutMath.m b/MyLayout/Lib/MyLayoutMath.m index c724861..8faa6db 100644 --- a/MyLayout/Lib/MyLayoutMath.m +++ b/MyLayout/Lib/MyLayoutMath.m @@ -28,9 +28,6 @@ BOOL _myCGFloatErrorNotEqual(CGFloat f1, CGFloat f2, CGFloat error) #endif } - - - BOOL _myCGFloatEqual(CGFloat f1, CGFloat f2) { #if CGFLOAT_IS_DOUBLE == 1 @@ -102,7 +99,6 @@ BOOL _myCGRectEqual(CGRect rect1, CGRect rect2) return _myCGSizeEqual(rect1.size, rect2.size) && _myCGPointEqual(rect1.origin, rect2.origin); } - CGFloat _myCGFloatRound(CGFloat f) { if (f == 0 || f == CGFLOAT_MAX || f == -CGFLOAT_MAX) @@ -111,7 +107,6 @@ CGFloat _myCGFloatRound(CGFloat f) static CGFloat scale = 0; if (scale == 0) scale = [UIScreen mainScreen].scale; - //因为设备点转化为像素时,如果偏移了半个像素点就有可能会产生虚化的效果,因此这里要将设备点先转化为像素点,然后再添加0.5个偏移取整后再除以倍数则是转化为有效的设备逻辑点。 #if CGFLOAT_IS_DOUBLE == 1 if (f < 0) @@ -143,11 +138,8 @@ CGRect _myLayoutCGRectRound(CGRect rect) rect.size.height = my - rect.origin.y; return rect; - } - - CGRect _myCGRectRound(CGRect rect) { rect.origin.x = _myCGFloatRound(rect.origin.x); @@ -156,7 +148,6 @@ CGRect _myCGRectRound(CGRect rect) rect.size.height = _myCGFloatRound(rect.size.height); return rect; - } CGSize _myCGSizeRound(CGSize size) @@ -189,7 +180,6 @@ CGFloat _myCGFloatMin(CGFloat a, CGFloat b) #else return fminf(a, b); #endif - } extern CGFloat _myCGFloatFma(CGFloat a, CGFloat b, CGFloat c) diff --git a/MyLayout/Lib/MyLayoutPos.m b/MyLayout/Lib/MyLayoutPos.m index a77321c..c7b402a 100644 --- a/MyLayout/Lib/MyLayoutPos.m +++ b/MyLayout/Lib/MyLayoutPos.m @@ -12,7 +12,6 @@ #import "MyLayoutInner.h" - @implementation MyLayoutPos { id _posVal; @@ -46,8 +45,6 @@ -(id)init return self; } - - -(MyLayoutPos* (^)(id val))myEqualTo { return ^id(id val){ @@ -58,7 +55,6 @@ -(id)init }; } - -(MyLayoutPos* (^)(CGFloat val))myOffset { return ^id(CGFloat val){ @@ -69,7 +65,6 @@ -(id)init }; } - -(MyLayoutPos* (^)(CGFloat val))myMin { return ^id(CGFloat val){ @@ -80,7 +75,6 @@ -(id)init }; } - -(MyLayoutPos* (^)(CGFloat val))myMax { return ^id(CGFloat val){ @@ -111,29 +105,22 @@ -(id)init }; } - - - - -(void)myClear { [self __clear]; [self setNeedsLayout]; } - -(MyLayoutPos* (^)(id val))equalTo { return self.myEqualTo; } - -(MyLayoutPos* (^)(CGFloat val))offset { return self.myOffset; } - -(MyLayoutPos* (^)(CGFloat val))min { return self.myMin; @@ -144,7 +131,6 @@ -(void)myClear return self.myLBound; } - -(MyLayoutPos* (^)(CGFloat val))max { return self.myMax; @@ -155,15 +141,11 @@ -(void)myClear return self.myUBound; } - - - -(void)clear { [self myClear]; } - -(void)setActive:(BOOL)active { if (_active != active) @@ -199,7 +181,6 @@ -(CGFloat)maxVal } - #pragma mark -- NSCopying -(id)copyWithZone:(NSZone *)zone @@ -226,13 +207,11 @@ -(id)copyWithZone:(NSZone *)zone } return layoutPos; - } #pragma mark -- Private Methods - -(NSNumber*)posNumVal { if (_posVal == nil || !self.isActive) @@ -308,7 +287,6 @@ -(NSNumber*)posNumVal } return nil; - } -(UIViewController*)findContainerVC @@ -327,14 +305,11 @@ -(UIViewController*)findContainerVC } } @catch (NSException *exception) { - } return vc; } - - -(MyLayoutPos*)posRelaVal { if (_posVal == nil || !self.isActive) @@ -344,7 +319,6 @@ -(MyLayoutPos*)posRelaVal return _posVal; return nil; - } @@ -357,7 +331,6 @@ -(NSArray*)posArrVal return _posVal; return nil; - } -(NSNumber*)posMostVal @@ -407,24 +380,17 @@ -(MyLayoutPos*)uBoundValInner return _uBoundVal; } - - -(MyLayoutPos*)__equalTo:(id)val { - if (![_posVal isEqual:val]) { if ([val isKindOfClass:[NSNumber class]]) { //特殊处理设置为safeAreaMargin边距的值。 if ([val doubleValue] == [MyLayoutPos safeAreaMargin]) - { _posValType = MyLayoutValueType_SafeArea; - } else - { _posValType = MyLayoutValueType_NSNumber; - } } else if ([val isKindOfClass:[MyLayoutPos class]]) _posValType = MyLayoutValueType_LayoutPos; @@ -475,7 +441,6 @@ -(MyLayoutPos*)__equalTo:(id)val NSAssert(0, @"oops!"); break; } - } else _posValType = MyLayoutValueType_Nil; @@ -488,7 +453,6 @@ -(MyLayoutPos*)__equalTo:(id)val -(MyLayoutPos*)__offset:(CGFloat)val { - if (_offsetVal != val) { _offsetVal = val; @@ -510,34 +474,25 @@ -(MyLayoutPos*)__min:(CGFloat)val -(MyLayoutPos*)__lBound:(id)posVal offsetVal:(CGFloat)offsetVal { - [[self.lBoundVal __equalTo:posVal] __offset:offsetVal]; return self; } - -(MyLayoutPos*)__max:(CGFloat)val { - if (self.uBoundVal.posNumVal.doubleValue != val) - { [self.uBoundVal __equalTo:@(val)]; - } return self; } -(MyLayoutPos*)__uBound:(id)posVal offsetVal:(CGFloat)offsetVal { - [[self.uBoundVal __equalTo:posVal] __offset:offsetVal]; - return self; } - - -(void)__clear { _active = YES; @@ -556,8 +511,6 @@ -(void)__setActive:(BOOL)active [_uBoundVal __setActive:active]; } - - -(CGFloat)absVal { if (self.isActive) @@ -588,7 +541,9 @@ -(BOOL)isRelativePos } else + { return NO; + } } -(BOOL)isSafeAreaPos @@ -596,7 +551,6 @@ -(BOOL)isSafeAreaPos return self.isActive && (_posValType == MyLayoutValueType_SafeArea || _posValType == MyLayoutValueType_UILayoutSupport); } - -(CGFloat)realPosIn:(CGFloat)size { if (self.isActive) @@ -616,11 +570,11 @@ -(CGFloat)realPosIn:(CGFloat)size return realPos; } else + { return 0; - + } } - -(void)setNeedsLayout { if (_view != nil && _view.superview != nil && [_view.superview isKindOfClass:[MyBaseLayout class]]) @@ -629,19 +583,13 @@ -(void)setNeedsLayout if (!lb.isMyLayouting) [_view.superview setNeedsLayout]; } - } - - +(NSString*)posstrFromPos:(MyLayoutPos*)posobj showView:(BOOL)showView { - NSString *viewstr = @""; if (showView) - { viewstr = [NSString stringWithFormat:@"View:%p.", posobj.view]; - } NSString *posStr = @""; @@ -672,11 +620,8 @@ +(NSString*)posstrFromPos:(MyLayoutPos*)posobj showView:(BOOL)showView } return [NSString stringWithFormat:@"%@%@",viewstr,posStr]; - - } - #pragma mark -- Override Method -(NSString*)description @@ -698,18 +643,12 @@ -(NSString*)description for (NSObject *obj in _posVal) { if ([obj isKindOfClass:[MyLayoutPos class]]) - { posValStr = [posValStr stringByAppendingString:[MyLayoutPos posstrFromPos:(MyLayoutPos*)obj showView:YES]]; - } else - { posValStr = [posValStr stringByAppendingString:[obj description]]; - - } if (obj != [_posVal lastObject]) posValStr = [posValStr stringByAppendingString:@", "]; - } posValStr = [posValStr stringByAppendingString:@"]"]; @@ -720,7 +659,6 @@ -(NSString*)description } return [NSString stringWithFormat:@"%@=%@, Offset=%g, Max=%g, Min=%g",[MyLayoutPos posstrFromPos:self showView:NO], posValStr, _offsetVal, _uBoundVal.posNumVal.doubleValue == CGFLOAT_MAX ? NAN : _uBoundVal.posNumVal.doubleValue , _uBoundVal.posNumVal.doubleValue == -CGFLOAT_MAX ? NAN : _lBoundVal.posNumVal.doubleValue]; - } @end @@ -760,7 +698,6 @@ -(instancetype)initWith:(NSArray *)poss isMax:(BOOL)isMax return self; } - -(CGFloat)getMostPosFrom:(MyLayoutPos *)layoutPos { CGFloat retVal = _isMax ? -CGFLOAT_MAX : CGFLOAT_MAX; @@ -787,32 +724,20 @@ -(CGFloat)getMostPosFrom:(MyLayoutPos *)layoutPos if (layoutPos.pos & MyGravity_Vert_Mask) {//水平 if (lpos.pos == MyGravity_Horz_Leading) - { val = myFrame.leading + offsetVal; - } else if (lpos.pos == MyGravity_Horz_Center) - { val = myFrame.leading + myFrame.width / 2.0 + offsetVal; - } else - { val = myFrame.trailing - offsetVal; - } } else {//垂直 if (lpos.pos == MyGravity_Vert_Top) - { val = myFrame.top + offsetVal; - } else if (lpos.pos == MyGravity_Vert_Center) - { val = myFrame.top + myFrame.height / 2.0 + offsetVal; - } else - { val = myFrame.bottom - offsetVal; - } } } else diff --git a/MyLayout/Lib/MyLayoutSize.m b/MyLayout/Lib/MyLayoutSize.m index 65b816f..c193b35 100644 --- a/MyLayout/Lib/MyLayoutSize.m +++ b/MyLayout/Lib/MyLayoutSize.m @@ -37,7 +37,6 @@ +(NSInteger)average return -99997; //这么定义纯粹是一个数字没有其他意义 } - -(id)init { self= [super init]; @@ -59,7 +58,6 @@ -(id)init return self; } - -(MyLayoutSize* (^)(id val))myEqualTo { return ^id(id val){ @@ -99,7 +97,6 @@ -(id)init [self setNeedsLayout]; return self; }; - } -(MyLayoutSize* (^)(CGFloat val))myMin @@ -110,12 +107,10 @@ -(id)init [self setNeedsLayout]; return self; }; - } -(MyLayoutSize* (^)(id sizeVal, CGFloat addVal, CGFloat multiVal))myLBound { - return ^id(id sizeVal, CGFloat addVal, CGFloat multiVal){ [self __lBound:sizeVal addVal:addVal multiVal:multiVal]; @@ -150,7 +145,6 @@ -(void)myClear [self setNeedsLayout]; } - -(MyLayoutSize* (^)(id val))equalTo { return self.myEqualTo; @@ -205,7 +199,6 @@ -(CGFloat)shrink return _active ? _shrink : 0.0; } - -(id)dimeVal { return self.isActive ? _dimeVal : nil; @@ -226,7 +219,6 @@ -(BOOL)isWrap return [self dimeWrapVal]; } - #pragma mark -- NSCopying -(id)copyWithZone:(NSZone *)zone @@ -260,7 +252,6 @@ -(id)copyWithZone:(NSZone *)zone #pragma mark -- Private Methods - -(NSNumber*)dimeNumVal { if (_dimeVal == nil || !self.isActive) @@ -285,7 +276,6 @@ -(MyLayoutSize*)dimeRelaVal return nil; } - -(NSArray*)dimeArrVal { if (_dimeVal == nil || !self.isActive) @@ -296,13 +286,11 @@ -(NSArray*)dimeArrVal return nil; } - -(BOOL)dimeWrapVal { return self.isActive && _dimeValType == MyLayoutValueType_Wrap; } - -(MyLayoutSize*)lBoundVal { if (_lBoundVal == nil) @@ -344,7 +332,6 @@ -(MyLayoutSize*)__equalTo:(id)val -(MyLayoutSize*)__equalTo:(id)val priority:(NSInteger)priority { - _priority = priority; if (![_dimeVal isEqual:val]) @@ -353,17 +340,11 @@ -(MyLayoutSize*)__equalTo:(id)val priority:(NSInteger)priority { //特殊处理。 if ([val integerValue] == MyLayoutSize.wrap) - { _dimeValType = MyLayoutValueType_Wrap; - } else if ([val integerValue] == MyLayoutSize.fill) - { NSAssert(0, @"oops! 暂时不支持"); - } else - { _dimeValType = MyLayoutValueType_NSNumber; - } } else if ([val isMemberOfClass:[MyLayoutSize class]]) { @@ -430,45 +411,32 @@ -(MyLayoutSize*)__equalTo:(id)val priority:(NSInteger)priority return self; } - //加 -(MyLayoutSize*)__add:(CGFloat)val { - if (_addVal != val) - { _addVal = val; - } return self; } - //乘 -(MyLayoutSize*)__multiply:(CGFloat)val { - if (_multiVal != val) - { _multiVal = val; - } return self; - } - -(MyLayoutSize*)__min:(CGFloat)val { if (self.lBoundVal.dimeNumVal.doubleValue != val) - { [self.lBoundVal __equalTo:@(val)]; - } return self; } - -(MyLayoutSize*)__lBound:(id)sizeVal addVal:(CGFloat)addVal multiVal:(CGFloat)multiVal { if (sizeVal == self) @@ -487,9 +455,7 @@ -(MyLayoutSize*)__lBound:(id)sizeVal addVal:(CGFloat)addVal multiVal:(CGFloat)mu -(MyLayoutSize*)__max:(CGFloat)val { if (self.uBoundVal.dimeNumVal.doubleValue != val) - { [self.uBoundVal __equalTo:@(val)]; - } return self; } @@ -509,8 +475,6 @@ -(MyLayoutSize*)__uBound:(id)sizeVal addVal:(CGFloat)addVal multiVal:(CGFloat)mu return self; } - - -(void)__clear { _active = YES; @@ -531,7 +495,6 @@ -(void)__setActive:(BOOL)active [_uBoundVal __setActive:active]; } - -(CGFloat) measure { return self.isActive ? _myCGFloatFma(self.dimeNumVal.doubleValue, _multiVal, _addVal) : 0; @@ -542,8 +505,6 @@ -(CGFloat)measureWith:(CGFloat)size return self.isActive ? _myCGFloatFma(size, _multiVal , _addVal) : size; } - - -(void)setNeedsLayout { if (_view != nil && _view.superview != nil && [_view.superview isKindOfClass:[MyBaseLayout class]]) @@ -554,15 +515,11 @@ -(void)setNeedsLayout } } - +(NSString*)dimestrFromDime:(MyLayoutSize*)dimeobj showView:(BOOL)showView { - NSString *viewstr = @""; if (showView) - { viewstr = [NSString stringWithFormat:@"View:%p.", dimeobj.view]; - } NSString *dimeStr = @""; @@ -578,7 +535,6 @@ +(NSString*)dimestrFromDime:(MyLayoutSize*)dimeobj showView:(BOOL)showView } return [NSString stringWithFormat:@"%@%@",viewstr,dimeStr]; - } #pragma mark -- Override Methods @@ -605,29 +561,21 @@ -(NSString*)description for (NSObject *obj in _dimeVal) { if ([obj isMemberOfClass:[MyLayoutSize class]]) - { dimeValStr = [dimeValStr stringByAppendingString:[MyLayoutSize dimestrFromDime:(MyLayoutSize*)obj showView:YES]]; - } else - { dimeValStr = [dimeValStr stringByAppendingString:[obj description]]; - - } if (obj != [_dimeVal lastObject]) dimeValStr = [dimeValStr stringByAppendingString:@", "]; - } dimeValStr = [dimeValStr stringByAppendingString:@"]"]; - } default: break; } return [NSString stringWithFormat:@"%@=%@, Multiply=%g, Add=%g, Max=%g, Min=%g",[MyLayoutSize dimestrFromDime:self showView:NO], dimeValStr, _multiVal, _addVal, _uBoundVal.dimeNumVal.doubleValue == CGFLOAT_MAX ? NAN : _uBoundVal.dimeNumVal.doubleValue , _lBoundVal.dimeNumVal.doubleValue == -CGFLOAT_MAX ? NAN : _lBoundVal.dimeNumVal.doubleValue]; - } @end @@ -670,7 +618,6 @@ -(instancetype)initWith:(NSArray *)sizes isMax:(BOOL)isMax return self; } - -(CGFloat)getMostSizeFrom:(MyLayoutSize *)layoutSize { CGFloat retVal = _isMax ? -CGFLOAT_MAX : CGFLOAT_MAX; diff --git a/MyLayout/Lib/MyLayoutSizeClass.h b/MyLayout/Lib/MyLayoutSizeClass.h index e4dc5ef..8e0528a 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.h +++ b/MyLayout/Lib/MyLayoutSizeClass.h @@ -37,13 +37,11 @@ @property(nonatomic, strong) MyLayoutPos *centerXPos; @property(nonatomic, strong) MyLayoutPos *centerYPos; - @property(nonatomic, strong,readonly) MyLayoutPos *leftPos; @property(nonatomic, strong,readonly) MyLayoutPos *rightPos; @property(nonatomic, strong) MyLayoutPos *baselinePos; - @property(nonatomic, assign) CGFloat myTop; @property(nonatomic, assign) CGFloat myLeading; @property(nonatomic, assign) CGFloat myBottom; @@ -52,17 +50,13 @@ @property(nonatomic, assign) CGFloat myCenterY; @property(nonatomic, assign) CGPoint myCenter; - @property(nonatomic, assign) CGFloat myLeft; @property(nonatomic, assign) CGFloat myRight; - - @property(nonatomic, assign) CGFloat myMargin; @property(nonatomic, assign) CGFloat myHorzMargin; @property(nonatomic, assign) CGFloat myVertMargin; - @property(nonatomic, strong) MyLayoutSize *widthSize; @property(nonatomic, strong) MyLayoutSize *heightSize; @@ -70,7 +64,6 @@ @property(nonatomic, assign) CGFloat myHeight; @property(nonatomic, assign) CGSize mySize; - @property(nonatomic, assign) BOOL wrapContentWidth; @property(nonatomic, assign) BOOL wrapContentHeight; @@ -93,7 +86,6 @@ @end - @interface MyLayoutViewSizeClass : MyViewSizeClass @property(nonatomic, assign) BOOL zeroPadding; @@ -111,52 +103,41 @@ @property(nonatomic, assign) CGFloat trailingPadding; @property(nonatomic, assign) UIEdgeInsets padding; - @property(nonatomic, assign) CGFloat leftPadding; @property(nonatomic, assign) CGFloat rightPadding; - +//为支持iOS11的safeArea而进行的padding的转化 +-(CGFloat)myLayoutTopPadding; +-(CGFloat)myLayoutBottomPadding; +-(CGFloat)myLayoutLeftPadding; +-(CGFloat)myLayoutRightPadding; +-(CGFloat)myLayoutLeadingPadding; +-(CGFloat)myLayoutTrailingPadding; @property(nonatomic, assign) UIRectEdge insetsPaddingFromSafeArea; - - @property(nonatomic ,assign) CGFloat subviewVSpace; @property(nonatomic, assign) CGFloat subviewHSpace; @property(nonatomic, assign) CGFloat subviewSpace; - - - - - @end - @interface MySequentLayoutViewSizeClass : MyLayoutViewSizeClass @property(nonatomic,assign) MyOrientation orientation; - - @end - - - @interface MyLinearLayoutViewSizeClass : MySequentLayoutViewSizeClass @property(nonatomic, assign) MySubviewsShrinkType shrinkType; @end - - @interface MyTableLayoutViewSizeClass : MyLinearLayoutViewSizeClass @end - @interface MyFlowLayoutViewSizeClass : MySequentLayoutViewSizeClass @property(nonatomic,assign) MyGravity arrangedGravity; @@ -170,11 +151,8 @@ @property(nonatomic, assign) CGFloat minSpace; @property(nonatomic, assign) CGFloat maxSpace; - - @end - @interface MyFloatLayoutViewSizeClass : MySequentLayoutViewSizeClass @property(nonatomic, assign) CGFloat subviewSize; @@ -183,24 +161,18 @@ @end - @interface MyRelativeLayoutViewSizeClass : MyLayoutViewSizeClass - @end - @interface MyFrameLayoutViewSizeClass : MyLayoutViewSizeClass - @end @interface MyPathLayoutViewSizeClass : MyLayoutViewSizeClass - @end - @interface MyGridLayoutViewSizeClass : MyLayoutViewSizeClass @end diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index 9d528dc..ce91418 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -45,7 +45,6 @@ -(MyLayoutPos*)leadingPosInner return _leadingPos; } - -(MyLayoutPos*)bottomPosInner { return _bottomPos; @@ -86,14 +85,11 @@ -(MyLayoutSize*)widthSizeInner return _widthSize; } - -(MyLayoutSize*)heightSizeInner { return _heightSize; } - - //.. -(MyLayoutPos*)topPos @@ -105,7 +101,6 @@ -(MyLayoutPos*)topPos _topPos.pos = MyGravity_Vert_Top; } - return _topPos; } @@ -121,7 +116,6 @@ -(MyLayoutPos*)leadingPos return _leadingPos; } - -(MyLayoutPos*)bottomPos { if (_bottomPos == nil) @@ -129,13 +123,11 @@ -(MyLayoutPos*)bottomPos _bottomPos = [MyLayoutPos new]; _bottomPos.view = self.view; _bottomPos.pos = MyGravity_Vert_Bottom; - } return _bottomPos; } - -(MyLayoutPos*)trailingPos { if (_trailingPos == nil) @@ -146,10 +138,8 @@ -(MyLayoutPos*)trailingPos } return _trailingPos; - } - -(MyLayoutPos*)centerXPos { if (_centerXPos == nil) @@ -157,7 +147,6 @@ -(MyLayoutPos*)centerXPos _centerXPos = [MyLayoutPos new]; _centerXPos.view = self.view; _centerXPos.pos = MyGravity_Horz_Center; - } return _centerXPos; @@ -170,14 +159,11 @@ -(MyLayoutPos*)centerYPos _centerYPos = [MyLayoutPos new]; _centerYPos.view = self.view; _centerYPos.pos = MyGravity_Vert_Center; - } return _centerYPos; } - - -(MyLayoutPos*)leftPos { return [MyViewSizeClass isRTL] ? self.trailingPos : self.leadingPos; @@ -200,8 +186,6 @@ -(MyLayoutPos*)baselinePos return _baselinePos; } - - -(CGFloat)myTop { return self.topPosInner.absVal; @@ -212,7 +196,6 @@ -(void)setMyTop:(CGFloat)myTop self.topPos.myEqualTo(@(myTop)); } - -(CGFloat)myLeading { return self.leadingPosInner.absVal; @@ -223,7 +206,6 @@ -(void)setMyLeading:(CGFloat)myLeading self.leadingPos.myEqualTo(@(myLeading)); } - -(CGFloat)myBottom { return self.bottomPosInner.absVal; @@ -234,7 +216,6 @@ -(void)setMyBottom:(CGFloat)myBottom self.bottomPos.myEqualTo(@(myBottom)); } - -(CGFloat)myTrailing { return self.trailingPosInner.absVal; @@ -245,7 +226,6 @@ -(void)setMyTrailing:(CGFloat)myTrailing self.trailingPos.myEqualTo(@(myTrailing)); } - -(CGFloat)myCenterX { return self.centerXPosInner.absVal; @@ -266,7 +246,6 @@ -(void)setMyCenterY:(CGFloat)myCenterY self.centerYPos.myEqualTo(@(myCenterY)); } - -(CGPoint)myCenter { return CGPointMake(self.myCenterX, self.myCenterY); @@ -278,8 +257,6 @@ -(void)setMyCenter:(CGPoint)myCenter self.myCenterY = myCenter.y; } - - -(CGFloat)myLeft { return self.leftPosInner.absVal; @@ -300,9 +277,6 @@ -(void)setMyRight:(CGFloat)myRight self.rightPos.myEqualTo(@(myRight)); } - - - -(CGFloat)myMargin { return self.leftPosInner.absVal; @@ -316,7 +290,6 @@ -(void)setMyMargin:(CGFloat)myMargin self.bottomPos.myEqualTo(@(myMargin)); } - -(CGFloat)myHorzMargin { return self.leftPosInner.absVal; @@ -351,7 +324,6 @@ -(MyLayoutSize*)widthSize return _widthSize; } - -(MyLayoutSize*)heightSize { if (_heightSize == nil) @@ -364,7 +336,6 @@ -(MyLayoutSize*)heightSize return _heightSize; } - -(CGFloat)myWidth { //特殊处理设置为MyLayoutSize.wrap的返回 @@ -403,7 +374,6 @@ -(void)setMySize:(CGSize)mySize self.myHeight = mySize.height; } - -(void)setWeight:(CGFloat)weight { if (weight < 0) @@ -437,7 +407,6 @@ -(void)setWrapContentWidth:(BOOL)wrapContentWidth } } - -(void)setWrapContentHeight:(BOOL)wrapContentHeight { if (wrapContentHeight) @@ -457,7 +426,6 @@ -(BOOL)wrapContentSize return self.wrapContentWidth && self.wrapContentHeight; } - -(void)setWrapContentSize:(BOOL)wrapContentSize { self.wrapContentWidth = self.wrapContentHeight = wrapContentSize; @@ -465,7 +433,6 @@ -(void)setWrapContentSize:(BOOL)wrapContentSize -(NSString*)debugDescription { - NSString*dbgDesc = [NSString stringWithFormat:@"\nView:\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\nweight=%f\nuseFrame=%@\nnoLayout=%@\nvisibility=%c\nalignment=%hu\nreverseFloat=%@\nclearFloat=%@", self.topPosInner, self.leadingPosInner, @@ -483,11 +450,9 @@ -(NSString*)debugDescription self.reverseFloat ? @"YES":@"NO", self.clearFloat ? @"YES":@"NO"]; - return dbgDesc; } - #pragma mark -- NSCopying - (id)copyWithZone:(NSZone *)zone @@ -516,7 +481,6 @@ - (id)copyWithZone:(NSZone *)zone return lsc; } - @end @implementation MyLayoutViewSizeClass @@ -535,7 +499,6 @@ -(id)init return self; } - -(UIEdgeInsets)padding { return UIEdgeInsetsMake(self.topPadding, self.leftPadding, self.bottomPadding, self.rightPadding); @@ -556,14 +519,10 @@ -(CGFloat)leftPadding -(void)setLeftPadding:(CGFloat)leftPadding { - if ([MyViewSizeClass isRTL]) - { - self.trailingPadding = leftPadding; - } - else - { - self.leadingPadding = leftPadding; - } + if ([MyViewSizeClass isRTL]) + self.trailingPadding = leftPadding; + else + self.leadingPadding = leftPadding; } -(CGFloat)rightPadding @@ -574,16 +533,11 @@ -(CGFloat)rightPadding -(void)setRightPadding:(CGFloat)rightPadding { if ([MyViewSizeClass isRTL]) - { self.leadingPadding = rightPadding; - } else - { self.trailingPadding = rightPadding; - } } - -(CGFloat)myLayoutTopPadding { //如果padding值是特殊的值。 @@ -741,7 +695,6 @@ -(CGFloat)myLayoutRightPadding return [MyViewSizeClass isRTL] ? [self myLayoutLeadingPadding] : [self myLayoutTrailingPadding]; } - -(CGFloat)subviewSpace { return self.subviewVSpace; @@ -753,7 +706,6 @@ -(void)setSubviewSpace:(CGFloat)subviewSpace self.subviewHSpace = subviewSpace; } - - (id)copyWithZone:(NSZone *)zone { MyLayoutViewSizeClass *lsc = [super copyWithZone:zone]; @@ -776,7 +728,6 @@ - (id)copyWithZone:(NSZone *)zone -(NSString*)debugDescription { NSString *dbgDesc = [super debugDescription]; - dbgDesc = [NSString stringWithFormat:@"%@\nLayout:\npadding=%@\nzeroPadding=%@\ngravity=%hu\nreverseLayout=%@\nsubviewVertSpace=%f\nsubviewHorzSpace=%f", dbgDesc, NSStringFromUIEdgeInsets(self.padding), @@ -787,24 +738,17 @@ -(NSString*)debugDescription self.subviewHSpace ]; - return dbgDesc; } - @end - @implementation MySequentLayoutViewSizeClass - - - (id)copyWithZone:(NSZone *)zone { MySequentLayoutViewSizeClass *lsc = [super copyWithZone:zone]; lsc.orientation = self.orientation; - - return lsc; } @@ -817,12 +761,9 @@ -(NSString*)debugDescription (unsigned long)self.orientation ]; - return dbgDesc; } - - @end @@ -831,7 +772,6 @@ @implementation MyLinearLayoutViewSizeClass - (id)copyWithZone:(NSZone *)zone { MyLinearLayoutViewSizeClass *lsc = [super copyWithZone:zone]; - lsc.shrinkType = self.shrinkType; return lsc; @@ -846,12 +786,9 @@ -(NSString*)debugDescription (unsigned long)self.shrinkType ]; - return dbgDesc; } - - @end @@ -896,7 +833,6 @@ - (id)copyWithZone:(NSZone *)zone -(NSString*)debugDescription { NSString *dbgDesc = [super debugDescription]; - dbgDesc = [NSString stringWithFormat:@"%@\nFlowLayout: \narrangedCount=%ld\nautoArrange=%@\nisFlex=%@\narrangedGravity=%hu\npagedCount=%ld", dbgDesc, (long)self.arrangedCount, @@ -918,13 +854,9 @@ @implementation MyRelativeLayoutViewSizeClass @end @implementation MyFrameLayoutViewSizeClass - - - @end @implementation MyPathLayoutViewSizeClass - @end @@ -937,13 +869,10 @@ @interface MyGridLayoutViewSizeClass() @implementation MyGridLayoutViewSizeClass - -(MyGridNode*)rootGrid { if (_rootGrid == nil) - { _rootGrid = [[MyGridNode alloc] initWithMeasure:0 superGrid:nil]; - } return _rootGrid; } @@ -983,7 +912,6 @@ -(MyGridNode*)rootGrid id node = (id)[self.rootGrid addRowGrid:grid measure:measure]; node.superGrid = self; return node; - } -(id)addColGrid:(id)grid measure:(CGFloat)measure @@ -991,7 +919,6 @@ -(MyGridNode*)rootGrid id node = (id)[self.rootGrid addColGrid:grid measure:measure]; node.superGrid = self; return node; - } @@ -1046,7 +973,6 @@ -(void)setOverlap:(MyGravity)overlap self.gravity = overlap; } - -(NSInteger)tag { return self.view.tag; @@ -1078,7 +1004,6 @@ -(void)setTarget:(id)target action:(SEL)action return self.rootGrid.subGrids; } - -(void)setSubGrids:(NSMutableArray *)subGrids { self.rootGrid.subGrids = subGrids; @@ -1094,7 +1019,6 @@ -(void)setSubGridsType:(MySubGridsType)subGridsType self.rootGrid.subGridsType = subGridsType; } - -(MyBorderline*)topBorderline { return nil; @@ -1104,7 +1028,6 @@ -(void)setTopBorderline:(MyBorderline *)topBorderline { } - -(MyBorderline*)bottomBorderline { return nil; @@ -1114,7 +1037,6 @@ -(void)setBottomBorderline:(MyBorderline *)bottomBorderline { } - -(MyBorderline*)leftBorderline { return nil; @@ -1124,7 +1046,6 @@ -(void)setLeftBorderline:(MyBorderline *)leftBorderline { } - -(MyBorderline*)rightBorderline { return nil; @@ -1141,7 +1062,6 @@ -(MyBorderline*)leadingBorderline -(void)setLeadingBorderline:(MyBorderline *)leadingBorderline { - } -(MyBorderline*)trailingBorderline @@ -1151,10 +1071,8 @@ -(MyBorderline*)trailingBorderline -(void)setTrailingBorderline:(MyBorderline *)trailingBorderline { - } - -(NSDictionary*)gridDictionary { return [MyGridNode translateGridNode:self toGridDictionary:[NSMutableDictionary new]]; @@ -1206,7 +1124,6 @@ -(CGFloat)updateGridOrigin:(CGPoint)superOrigin superGrid:(id)superG return [self.rootGrid updateGridOrigin:superOrigin superGrid:superGrid withOffset:offset]; } - -(UIView*)gridLayoutView { return self.view; @@ -1232,7 +1149,6 @@ -(void)showBorderline:(BOOL)show return [self.rootGrid gridHitTest:point]; } - - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { //do nothing; @@ -1253,17 +1169,11 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event //do nothing; } - - - - (id)copyWithZone:(NSZone *)zone { MyGridLayoutViewSizeClass *lsc = [super copyWithZone:zone]; lsc->_rootGrid = (MyGridNode*)[self.rootGrid cloneGrid]; - - return lsc; } - @end diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 17d3666..9c4f4c3 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -25,11 +25,9 @@ -(instancetype)initWithFrame:(CGRect)frame orientation:(MyOrientation)orientatio [lsc.widthSize __equalTo:@(MyLayoutSize.wrap) priority:MyPriority_Low]; lsc.orientation = orientation; } - return self; } - -(instancetype)initWithOrientation:(MyOrientation)orientation { return [self initWithFrame:CGRectZero orientation:orientation]; @@ -55,8 +53,6 @@ -(MyOrientation)orientation return self.myCurrentSizeClass.orientation; } - - -(void)setShrinkType:(MySubviewsShrinkType)shrinkType { MyLinearLayout *lsc = self.myCurrentSizeClass; @@ -72,7 +68,6 @@ -(MySubviewsShrinkType)shrinkType return self.myCurrentSizeClass.shrinkType; } - -(void)equalizeSubviews:(BOOL)centered { [self equalizeSubviews:centered inSizeClass:MySizeClass_hAny | MySizeClass_wAny]; @@ -118,7 +113,6 @@ -(void)equalizeSubviewsSpace:(BOOL)centered -(void)equalizeSubviewsSpace:(BOOL)centered inSizeClass:(MySizeClass)sizeClass { - self.myFrame.sizeClass = [self fetchLayoutSizeClass:sizeClass]; for (UIView *sbv in self.subviews) sbv.myFrame.sizeClass = [sbv fetchLayoutSizeClass:sizeClass]; @@ -135,7 +129,6 @@ -(void)equalizeSubviewsSpace:(BOOL)centered inSizeClass:(MySizeClass)sizeClass self.myFrame.sizeClass = self.myDefaultSizeClass; for (UIView *sbv in self.subviews) sbv.myFrame.sizeClass = sbv.myDefaultSizeClass; - } @@ -148,29 +141,22 @@ - (void)willRemoveSubview:(UIView *)subview self.baselineBaseView = nil; } - - - -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray *)sbs { CGSize selfSize = [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; - if (sbs == nil) sbs = [self myGetLayoutSubviews]; - - MyLinearLayout *lsc = self.myCurrentSizeClass; - + MyLinearLayoutViewSizeClass *lsc = (MyLinearLayoutViewSizeClass*)self.myCurrentSizeClass; MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = lsc.gravity & MyGravity_Vert_Mask; MyOrientation orientation = lsc.orientation; - [self myCalcSubviewsWrapContentSize:sbs isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass withCustomSetting:^(UIView *sbv, UIView *sbvsc) { + [self myCalcSubviewsWrapContentSize:sbs isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass withCustomSetting:^(MyViewSizeClass *sbvsc) { [self myLayout:lsc orientation:orientation gravity:(orientation == MyOrientation_Vert)? horzGravity : vertGravity adjustSizeSettingOfSubview:sbvsc]; }]; - if (orientation == MyOrientation_Vert) selfSize = [self myVertOrientationLayout:lsc calcRectOfSubviews:sbs withSelfSize:selfSize]; else @@ -183,17 +169,15 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( return [self myLayout:lsc adjustSelfSize:selfSize withSubviews:sbs]; } - -(id)createSizeClassInstance { return [MyLinearLayoutViewSizeClass new]; } - #pragma mark -- Private Methods //调整子视图的wrapContent设置 -- (void)myLayout:(MyLinearLayout*)lsc orientation:(MyOrientation)orientation gravity:(MyGravity)gravity adjustSizeSettingOfSubview:(UIView*)sbvsc +- (void)myLayout:(MyLinearLayoutViewSizeClass*)lsc orientation:(MyOrientation)orientation gravity:(MyGravity)gravity adjustSizeSettingOfSubview:(MyViewSizeClass*)sbvsc { if (orientation == MyOrientation_Vert) { @@ -226,7 +210,7 @@ - (void)myLayout:(MyLinearLayout*)lsc orientation:(MyOrientation)orientation gra } //设置智能边界线 --(void)myLayout:(MyLinearLayout*)lsc setIntelligentBorderlineOnSubviews:(NSArray*)sbs +-(void)myLayout:(MyLinearLayoutViewSizeClass*)lsc setIntelligentBorderlineOnSubviews:(NSArray*)sbs { if (self.intelligentBorderline == nil) return; @@ -292,7 +276,7 @@ -(void)myLayout:(MyLinearLayout*)lsc setIntelligentBorderlineOnSubviews:(NSArray } } --(CGSize)myVertOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArray*)sbs withSelfSize:(CGSize)selfSize +-(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSubviews:(NSArray*)sbs withSelfSize:(CGSize)selfSize { CGFloat subviewSpace = lsc.subviewVSpace; CGFloat paddingTop = lsc.myLayoutTopPadding; @@ -319,9 +303,8 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra CGFloat pos = paddingTop; for (UIView *sbv in sbs) { - MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGRect rect = sbvmyFrame.frame; if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) @@ -356,15 +339,7 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra } //计算子视图的高度 - rect.size.height = [self myGetSubviewHeightSizeValue:sbv - sbvsc:sbvsc - lsc:lsc - selfSize:selfSize - paddingTop:paddingTop - paddingLeading:paddingLeading - paddingBottom:paddingBottom - paddingTrailing:paddingTrailing - sbvSize:rect.size]; + rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; //特殊处理宽度等于高度的情况 @@ -373,16 +348,13 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra //计算子视图宽度以及对齐, 先计算宽度的原因是处理那些高度依赖宽度并且是wrap的情况。 CGFloat tempSelfWidth = [self myLayout:lsc - calcSubview:sbv - sbvsc:sbvsc + calcSubview:sbvsc leadingTrailingRect:&rect horzGravity:horzGravity paddingTrailing:paddingTrailing paddingLeading:paddingLeading selfSize:selfSize]; - - //左右依赖的,或者依赖父视图宽度的不参数最宽计算!! if ((tempSelfWidth > maxSelfWidth) && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) && @@ -401,7 +373,7 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra //再次特殊处理高度包裹的场景 if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) { - rect.size.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:rect.size.width]; + rect.size.height = [self mySubview:sbvsc wrapHeightSizeFits:rect.size.width]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; } @@ -506,7 +478,6 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra } //这里需要特殊处理当子视图的尺寸高度大于布局视图的高度的情况。 - BOOL isWeightShrinkSpace = NO; //是否按比重缩小间距。 CGFloat weightShrinkSpaceTotalHeight = 0; CGFloat spareHeight = selfSize.height - fixedHeight - paddingVert; //剩余的可浮动的高度,那些weight不为0的从这个高度来进行分发 @@ -559,13 +530,11 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra weightShrinkSpaceTotalHeight = spareHeight; } } - } else { ; } - } if (totalShrink == 0.0) @@ -579,9 +548,7 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra //如果是总的压缩比重不为0则认为固定高度和布局视图高度保持一致。 if (totalShrink != 0.0) - { fixedHeight = selfSize.height - paddingVert; - } //如果有浮动尺寸或者有压缩模式 if (totalWeight != 0.0 || totalShrink != 0.0 || (sstMode != MySubviewsShrink_None && _myCGFloatLessOrEqual(spareHeight, 0)) || vertGravity != MyGravity_None || lsc.widthSizeInner.dimeWrapVal) @@ -598,7 +565,6 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra if (self.window != nil) { pos = (CGRectGetHeight(self.window.bounds) - fixedHeight)/2.0; - CGPoint pt = CGPointMake(0, pos); pos = [self.window convertPoint:pt toView:self].y; } @@ -641,8 +607,7 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; - + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.posNumVal.doubleValue; CGFloat bottomSpace = sbvsc.bottomPosInner.posNumVal.doubleValue; @@ -703,8 +668,7 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra //计算子视图宽度以及对齐 CGFloat tempSelfWidth = [self myLayout:lsc - calcSubview:sbv - sbvsc:sbvsc + calcSubview:sbvsc leadingTrailingRect:&rect horzGravity:horzGravity paddingTrailing:paddingTrailing @@ -776,7 +740,7 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra return selfSize; } --(CGSize)myHorzOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArray*)sbs withSelfSize:(CGSize)selfSize +-(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSubviews:(NSArray*)sbs withSelfSize:(CGSize)selfSize { CGFloat subviewSpace = lsc.subviewHSpace; CGFloat paddingTop = lsc.myLayoutTopPadding; @@ -809,7 +773,7 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra //计算出固定宽度部分以及weight部分。这里的宽度可能依赖高度。如果不是高度包裹则计算出所有高度。 MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGRect rect = sbvmyFrame.frame; if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) @@ -843,15 +807,7 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra } //计算子视图的宽度,这里不管是否设置约束以及是否宽度是weight的都是进行计算。 - rect.size.width = [self myGetSubviewWidthSizeValue:sbv - sbvsc:sbvsc - lsc:lsc - selfSize:selfSize - paddingTop:paddingTop - paddingLeading:paddingLeading - paddingBottom:paddingBottom - paddingTrailing:paddingTrailing - sbvSize:rect.size]; + rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) @@ -861,8 +817,7 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra //计算子视图高度以及对齐 CGFloat tempSelfHeight = [self myLayout:lsc - calcSubview:sbv - sbvsc:sbvsc + calcSubview:sbvsc topBottomRect:&rect vertGravity:vertGravity paddingTop:paddingTop @@ -877,7 +832,6 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra maxSelfHeight = tempSelfHeight; } - //如果垂直方向的对齐方式是基线对齐,那么就以第一个具有基线的视图作为标准位置。 if (vertGravity == MyGravity_Vert_Baseline && baselinePos == CGFLOAT_MAX && self.baselineBaseView == sbv) { @@ -885,7 +839,6 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra //这里要求baselineBaseView必须要具有font属性。 //得到基线位置。 baselinePos = rect.origin.y + (rect.size.height - sbvFont.lineHeight) / 2.0 + sbvFont.ascender; - } if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) @@ -895,7 +848,6 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; } - //计算固定宽度尺寸和浮动宽度尺寸部分 if (sbvsc.leadingPosInner.isRelativePos) { @@ -996,7 +948,6 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra //如果是宽度自适应则不需要压缩。 totalShrink = 0.0; - } if (lsc.heightSizeInner.dimeWrapVal) @@ -1037,15 +988,12 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra for (UIView *fsbv in fixedSizeSbs) { fsbv.myFrame.width += averageWidth; - } } else if (sstMode == MySubviewsShrink_Auto) { - UIView *leadingView = flexedSizeSbs[0]; UIView *trailingView = flexedSizeSbs[1]; - CGFloat leadingWidth = leadingView.myFrame.width; CGFloat trailingWidth = trailingView.myFrame.width; @@ -1178,7 +1126,7 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra for (UIView *sbv in sbs) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat leadingSpace = sbvsc.leadingPosInner.posNumVal.doubleValue; CGFloat trailingSpace = sbvsc.trailingPosInner.posNumVal.doubleValue; @@ -1243,8 +1191,7 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra } CGFloat tempSelfHeight = [self myLayout:lsc - calcSubview:sbv - sbvsc:sbvsc + calcSubview:sbvsc topBottomRect:&rect vertGravity:vertGravity paddingTop:paddingTop @@ -1322,10 +1269,11 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayout*)lsc calcRectOfSubviews:(NSArra return selfSize; } -- (CGFloat)myLayout:(MyLinearLayout*)lsc calcSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc leadingTrailingRect:(CGRect *)pRect horzGravity:(MyGravity)horzGravity paddingTrailing:(CGFloat)paddingTrailing paddingLeading:(CGFloat)paddingLeading selfSize:(CGSize)selfSize +- (CGFloat)myLayout:(MyLinearLayoutViewSizeClass*)lsc calcSubview:(MyViewSizeClass*)sbvsc leadingTrailingRect:(CGRect *)pRect horzGravity:(MyGravity)horzGravity paddingTrailing:(CGFloat)paddingTrailing paddingLeading:(CGFloat)paddingLeading selfSize:(CGSize)selfSize { + UIView *sbv = sbvsc.view; - pRect->size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:lsc.myLayoutTopPadding paddingLeading:paddingLeading paddingBottom:lsc.myLayoutBottomPadding paddingTrailing:paddingTrailing sbvSize:pRect->size]; + pRect->size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:pRect->size paddingTop:lsc.myLayoutTopPadding paddingLeading:paddingLeading paddingBottom:lsc.myLayoutBottomPadding paddingTrailing:paddingTrailing]; if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) { @@ -1337,32 +1285,29 @@ - (CGFloat)myLayout:(MyLinearLayout*)lsc calcSubview:(UIView*)sbv sbvsc:(UIView* pRect->size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:pRect->size.width sbvSize:pRect->size selfLayoutSize:selfSize]; - return [self myCalcHorzGravity:[self myGetSubviewHorzGravity:sbv sbvsc:sbvsc horzGravity:horzGravity] sbv:sbv sbvsc:sbvsc paddingLeading:paddingLeading paddingTrailing:paddingTrailing selfSize:selfSize pRect:pRect]; + return [self myCalcSubview:sbvsc horzGravity:[self myGetSubview:sbvsc horzGravity:horzGravity] paddingLeading:paddingLeading paddingTrailing:paddingTrailing selfSize:selfSize pRect:pRect]; } -- (CGFloat)myLayout:(MyLinearLayout*)lsc calcSubview:(UIView*)sbv sbvsc:(UIView*)sbvsc topBottomRect:(CGRect *)pRect vertGravity:(MyGravity)vertGravity paddingTop:(CGFloat)paddingTop paddingBottom:(CGFloat)paddingBottom baselinePos:(CGFloat)baselinePos selfSize:(CGSize)selfSize +- (CGFloat)myLayout:(MyLinearLayoutViewSizeClass*)lsc calcSubview:(MyViewSizeClass*)sbvsc topBottomRect:(CGRect *)pRect vertGravity:(MyGravity)vertGravity paddingTop:(CGFloat)paddingTop paddingBottom:(CGFloat)paddingBottom baselinePos:(CGFloat)baselinePos selfSize:(CGSize)selfSize { - pRect->size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:lsc.myLayoutLeadingPadding paddingBottom:paddingBottom paddingTrailing:lsc.myLayoutTrailingPadding sbvSize:pRect->size]; + UIView *sbv = sbvsc.view; + + pRect->size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:pRect->size paddingTop:paddingTop paddingLeading:lsc.myLayoutLeadingPadding paddingBottom:paddingBottom paddingTrailing:lsc.myLayoutTrailingPadding]; if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) { if (sbvsc.heightSizeInner.dimeVal == nil) - { pRect->size.height = selfSize.height - paddingTop - paddingBottom - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal; - } } pRect->size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:pRect->size.height sbvSize:pRect->size selfLayoutSize:selfSize]; - return [self myCalcVertGravity:[self myGetSubviewVertGravity:sbv sbvsc:sbvsc vertGravity:vertGravity] sbv:sbv sbvsc:sbvsc paddingTop:paddingTop paddingBottom:paddingBottom baselinePos:baselinePos selfSize:selfSize pRect:pRect]; + return [self myCalcSubview:sbvsc vertGravity:[self myGetSubview:sbvsc vertGravity:vertGravity] paddingTop:paddingTop paddingBottom:paddingBottom baselinePos:baselinePos selfSize:selfSize pRect:pRect]; } -(void)myEqualizeSubviewsForVert:(BOOL)centered withSpace:(CGFloat)margin { - - //如果居中和不居中则拆分出来的片段是不一样的。 - CGFloat scale; CGFloat scale2; NSArray *sbs = [self myGetLayoutSubviews]; @@ -1371,7 +1316,6 @@ -(void)myEqualizeSubviewsForVert:(BOOL)centered withSpace:(CGFloat)margin CGFloat fragments = centered ? sbs.count * 2 + 1 : sbs.count * 2 - 1; scale = 1 / fragments; scale2 = scale; - } else { @@ -1379,7 +1323,6 @@ -(void)myEqualizeSubviewsForVert:(BOOL)centered withSpace:(CGFloat)margin scale2 = margin; } - for (UIView *sbv in sbs) { UIView *sbvsc = sbv.myCurrentSizeClass; @@ -1398,8 +1341,6 @@ -(void)myEqualizeSubviewsForVert:(BOOL)centered withSpace:(CGFloat)margin -(void)myEqualizeSubviewsForHorz:(BOOL)centered withSpace:(CGFloat)space { - - NSArray *sbs = [self myGetLayoutSubviews]; //如果居中和不居中则拆分出来的片段是不一样的。 CGFloat scale; @@ -1410,7 +1351,6 @@ -(void)myEqualizeSubviewsForHorz:(BOOL)centered withSpace:(CGFloat)space CGFloat fragments = centered ? sbs.count * 2 + 1 : sbs.count * 2 - 1; scale = 1 / fragments; scale2 = scale; - } else { @@ -1432,13 +1372,10 @@ -(void)myEqualizeSubviewsForHorz:(BOOL)centered withSpace:(CGFloat)space if (sbv == sbs.lastObject && centered) [sbvsc.trailingPos __equalTo:@(scale2)]; } - } - -(void)myEqualizeSubviewsSpaceForVert:(BOOL)centered { - //如果居中和不居中则拆分出来的片段是不一样的。 NSArray *sbs = [self myGetLayoutSubviews]; CGFloat fragments = centered ? sbs.count + 1 : sbs.count - 1; @@ -1456,13 +1393,10 @@ -(void)myEqualizeSubviewsSpaceForVert:(BOOL)centered if (sbv == sbs.lastObject) [sbvsc.bottomPos __equalTo: centered? @(scale) : @0]; } - - } -(void)myEqualizeSubviewsSpaceForHorz:(BOOL)centered { - //如果居中和不居中则拆分出来的片段是不一样的。 NSArray *sbs = [self myGetLayoutSubviews]; CGFloat fragments = centered ? sbs.count + 1 : sbs.count - 1; diff --git a/MyLayout/Lib/MyMaker.m b/MyLayout/Lib/MyMaker.m index 8eb7d69..4e3395a 100644 --- a/MyLayout/Lib/MyMaker.m +++ b/MyLayout/Lib/MyMaker.m @@ -45,8 +45,6 @@ -(MyMaker*)addMethod:(NSString*)method return self; } - - -(MyMaker*)top { return [self addMethod:@"topPos"]; @@ -78,16 +76,13 @@ -(MyMaker*)margin -(MyMaker*)leading { return [self addMethod:@"leadingPos"]; - } -(MyMaker*)trailing { return [self addMethod:@"trailingPos"]; - } - -(MyMaker*)height { return [self addMethod:@"heightSize"]; @@ -106,10 +101,8 @@ -(MyMaker*)useFrame -(MyMaker*)noLayout { return [self addMethod:@"noLayout"]; - } - -(MyMaker*)wrapContentHeight { return [self addMethod:@"wrapContentHeight"]; @@ -125,12 +118,9 @@ -(MyMaker*)reverseLayout return [self addMethod:@"reverseLayout"]; } - - -(MyMaker*)weight { return [self addMethod:@"weight"]; - } -(MyMaker*)reverseFloat @@ -145,49 +135,39 @@ -(MyMaker*)clearFloat -(MyMaker*)topPadding { - return [self addMethod:@"topPadding"]; - } -(MyMaker*)leftPadding { return [self addMethod:@"leftPadding"]; - } -(MyMaker*)bottomPadding { - return [self addMethod:@"bottomPadding"]; - } -(MyMaker*)rightPadding { return [self addMethod:@"rightPadding"]; - } -(MyMaker*)leadingPadding { - return [self addMethod:@"leadingPadding"]; - } -(MyMaker*)trailingPadding { return [self addMethod:@"trailingPadding"]; - } - -(MyMaker*)padding { - [self addMethod:@"topPadding"]; - [self addMethod:@"leftPadding"]; - [self addMethod:@"bottomPadding"]; + [self addMethod:@"topPadding"]; + [self addMethod:@"leftPadding"]; + [self addMethod:@"bottomPadding"]; return [self addMethod:@"rightPadding"]; } @@ -199,16 +179,13 @@ -(MyMaker*)zeroPadding -(MyMaker*)orientation { return [self addMethod:@"orientation"]; - } -(MyMaker*)gravity { return [self addMethod:@"gravity"]; - } - -(MyMaker*)centerX { return [self addMethod:@"centerXPos"]; @@ -229,7 +206,6 @@ -(MyMaker*)baseline return [self addMethod:@"baselinePos"]; } - -(MyMaker*)visibility { return [self addMethod:@"visibility"]; @@ -240,8 +216,6 @@ -(MyMaker*)alignment return [self addMethod:@"alignment"]; } - - -(MyMaker*)sizeToFit { for (UIView *myView in _myViews) @@ -252,21 +226,16 @@ -(MyMaker*)sizeToFit return self; } - - -(MyMaker*)space { return [self addMethod:@"subviewSpace"]; - } -(MyMaker*)shrinkType { return [self addMethod:@"shrinkType"]; - } - -(MyMaker*)arrangedCount { return [self addMethod:@"arrangedCount"]; @@ -280,30 +249,23 @@ -(MyMaker*)autoArrange -(MyMaker*)arrangedGravity { return [self addMethod:@"arrangedGravity"]; - } -(MyMaker*)vertSpace { return [self addMethod:@"subviewVSpace"]; - } -(MyMaker*)horzSpace { return [self addMethod:@"subviewHSpace"]; - } -(MyMaker*)pagedCount { return [self addMethod:@"pagedCount"]; - } - - - -(MyMaker* (^)(id val))equalTo { _clear = YES; @@ -311,20 +273,15 @@ -(MyMaker*)pagedCount for (NSString *key in self->_keys) { - for (UIView * myView in self->_myViews) { if ([val isKindOfClass:[NSNumber class]]) { id oldVal = [myView valueForKey:key]; if ([oldVal isKindOfClass:[MyLayoutPos class]]) - { ((MyLayoutPos*)oldVal).myEqualTo(val); - } else if ([oldVal isKindOfClass:[MyLayoutSize class]]) - { ((MyLayoutSize*)oldVal).myEqualTo(val); - } else [myView setValue:val forKey:key]; } @@ -344,21 +301,13 @@ -(MyMaker*)pagedCount { id oldVal = [val valueForKey:key]; if ([oldVal isKindOfClass:[MyLayoutPos class]]) - { ((MyLayoutPos*)[myView valueForKey:key]).myEqualTo(oldVal); - } else if ([oldVal isKindOfClass:[MyLayoutSize class]]) - { ((MyLayoutSize*)[myView valueForKey:key]).myEqualTo(oldVal); - - } else - { [myView setValue:oldVal forKey:key]; - } } } - } return self; @@ -375,7 +324,6 @@ -(MyMaker*)pagedCount { for (UIView *myView in self->_myViews) { - [((MyLayoutPos*)[myView valueForKey:key]) __offset:val]; } } @@ -393,13 +341,11 @@ -(MyMaker*)pagedCount { for (UIView *myView in self->_myViews) { - [((MyLayoutSize*)[myView valueForKey:key]) __multiply:val]; } } return self; }; - } -(MyMaker* (^)(CGFloat val))add @@ -409,16 +355,13 @@ -(MyMaker*)pagedCount for (NSString *key in self->_keys) { - for (UIView *myView in self->_myViews) { - [((MyLayoutSize*)[myView valueForKey:key]) __add:val]; } } return self; }; - } -(MyMaker* (^)(id val))min @@ -428,11 +371,8 @@ -(MyMaker*)pagedCount for (NSString *key in self->_keys) { - for (UIView *myView in self->_myViews) { - - id val2 = val; if ([val isKindOfClass:[UIView class]]) val2 = [val valueForKey:key]; @@ -452,7 +392,6 @@ -(MyMaker*)pagedCount } return self; }; - } -(MyMaker* (^)(id val))max @@ -483,20 +422,15 @@ -(MyMaker*)pagedCount } return self; }; - } - - @end @implementation UIView(MyMakerExt) - -(void)makeLayout:(void(^)(MyMaker *make))layoutMaker { - MyMaker *myMaker = [[MyMaker alloc] initWithView:@[self]]; layoutMaker(myMaker); } @@ -507,7 +441,6 @@ -(void)allSubviewMakeLayout:(void(^)(MyMaker *make))layoutMaker layoutMaker(myMaker); } - @end #endif diff --git a/MyLayout/Lib/MyPathLayout.m b/MyLayout/Lib/MyPathLayout.m index ac4c8dd..c28609e 100644 --- a/MyLayout/Lib/MyPathLayout.m +++ b/MyLayout/Lib/MyPathLayout.m @@ -307,12 +307,12 @@ -(void)beginSubviewPathPoint:(BOOL)full if (full) { NSMutableArray *pointIndexs = [NSMutableArray new]; - self.pathPoints = [self myCalcPoints:self.pathSubviews path:nil pointIndexArray:pointIndexs lsc:self.myCurrentSizeClass]; + self.pathPoints = [self myLayout:(MyPathLayoutViewSizeClass*)self.myCurrentSizeClass calcPointsOfSubviews:self.pathSubviews path:nil pointIndexArray:pointIndexs]; self.pointIndexs = pointIndexs; } else { - self.pathPoints = [self myCalcPoints:self.pathSubviews path:nil pointIndexArray:nil lsc:self.myCurrentSizeClass]; + self.pathPoints = [self myLayout:(MyPathLayoutViewSizeClass*)self.myCurrentSizeClass calcPointsOfSubviews:self.pathSubviews path:nil pointIndexArray:nil ]; self.pointIndexs = nil; } } @@ -400,14 +400,14 @@ -(CGPathRef)createPath:(NSInteger)subviewCount if (self.spaceType.type != MyPathSpace_Fixed) { - [self myCalcPathPoints:retPath pPathLen:NULL subviewCount:-1 pointIndexArray:nil viewSpace:0 lsc:self.myCurrentSizeClass]; + [self myLayout:(MyPathLayoutViewSizeClass*)self.myCurrentSizeClass calcPathPoints:retPath pPathLen:NULL subviewCount:-1 pointIndexArray:nil viewSpace:0]; } else { if (subviewCount == -1) subviewCount = self.pathSubviews.count; - [self myCalcPathPoints:retPath pPathLen:NULL subviewCount:subviewCount pointIndexArray:nil viewSpace:self.spaceType.value lsc:self.myCurrentSizeClass]; + [self myLayout:(MyPathLayoutViewSizeClass*)self.myCurrentSizeClass calcPathPoints:retPath pPathLen:NULL subviewCount:subviewCount pointIndexArray:nil viewSpace:self.spaceType.value]; } return retPath; @@ -534,7 +534,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( sbs = [self myGetLayoutSubviews]; NSArray *sbs2 = sbs; - MyPathLayout *lsc = self.myCurrentSizeClass; + MyPathLayoutViewSizeClass *lsc = (MyPathLayoutViewSizeClass*)self.myCurrentSizeClass; CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; @@ -556,7 +556,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if ([self.layer isKindOfClass:[CAShapeLayer class]] && !isEstimate) path = CGPathCreateMutable(); - NSArray *pts = [self myCalcPoints:sbs path:path pointIndexArray:nil lsc:lsc]; + NSArray *pts = [self myLayout:lsc calcPointsOfSubviews:sbs path:path pointIndexArray:nil]; if (path != nil) { @@ -570,7 +570,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGPoint pt = CGPointZero; if (pts.count > i) @@ -580,10 +580,10 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( CGRect rect = sbvmyFrame.frame; - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) @@ -624,14 +624,14 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbv != nil) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGRect rect = sbvmyFrame.frame; - rect.size.width = [self myGetSubviewWidthSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - rect.size.height = [self myGetSubviewHeightSizeValue:sbv sbvsc:sbvsc lsc:lsc selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing sbvSize:rect.size]; + rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) @@ -913,20 +913,19 @@ -(void)myCalcPathPointsHelper:(NSMutableArray*)pathPointArray /** 计算曲线路径 + @param lsc lsc @param showPath 将计算的路径保存到showPath中,可选参数 @param pPathLen 返回路径的总长度 @param subviewCount 子视图的数量,如果为-1则表示只计算路径的长度不会把每个子视图所在的路径点索引保存 @param pointIndexArray 返回所有子视图在路径点的索引 @param viewSpace 子视图之间的间距 - @param lsc lsc @return 返回所有路径点 */ --(NSArray*)myCalcPathPoints:(CGMutablePathRef)showPath +-(NSArray*)myLayout:(MyPathLayoutViewSizeClass*)lsc calcPathPoints:(CGMutablePathRef)showPath pPathLen:(CGFloat*)pPathLen subviewCount:(NSInteger)subviewCount pointIndexArray:(NSMutableArray*)pointIndexArray viewSpace:(CGFloat)viewSpace - lsc:(MyPathLayout*)lsc { NSMutableArray *pathPointArray = [NSMutableArray new]; @@ -1064,7 +1063,7 @@ -(NSArray*)myCalcPathPoints:(CGMutablePathRef)showPath return pathPointArray; } --(NSArray*)myCalcPoints:(NSArray*)sbs path:(CGMutablePathRef)path pointIndexArray:(NSMutableArray*)pointIndexArray lsc:(MyPathLayout*)lsc +-(NSArray*)myLayout:(MyPathLayoutViewSizeClass*)lsc calcPointsOfSubviews:(NSArray*)sbs path:(CGMutablePathRef)path pointIndexArray:(NSMutableArray*)pointIndexArray { if (sbs.count > 0) { @@ -1073,7 +1072,7 @@ -(NSArray*)myCalcPoints:(NSArray*)sbs path:(CGMutablePathRef)path pointIndexArra //如果间距不是固定的,那么要先算出路径的长度pathLen,以及是否是封闭曲线标志来算出每个子视图在曲线上的间距viewSpacing CGFloat pathLen = 0; //曲线的总长度 - NSArray *tempArray = [self myCalcPathPoints:path pPathLen:&pathLen subviewCount:-1 pointIndexArray:nil viewSpace:0 lsc:lsc]; + NSArray *tempArray = [self myLayout:lsc calcPathPoints:path pPathLen:&pathLen subviewCount:-1 pointIndexArray:nil viewSpace:0]; //判断是否是封闭路径,方法为第一个路径点和最后一个之间的距离差小于1 BOOL bClose = NO; @@ -1095,11 +1094,11 @@ -(NSArray*)myCalcPoints:(NSArray*)sbs path:(CGMutablePathRef)path pointIndexArra viewSpace = pathLen / (sbvcount - (bClose ? 0 : 1)); //有间距后再重新计算一遍 - return [self myCalcPathPoints:nil pPathLen:NULL subviewCount:sbs.count pointIndexArray:pointIndexArray viewSpace:viewSpace lsc:lsc]; + return [self myLayout:lsc calcPathPoints:nil pPathLen:NULL subviewCount:sbs.count pointIndexArray:pointIndexArray viewSpace:viewSpace]; } else { - return [self myCalcPathPoints:path pPathLen:NULL subviewCount:sbs.count pointIndexArray:pointIndexArray viewSpace:self.spaceType.value lsc:lsc]; + return [self myLayout:lsc calcPathPoints:path pPathLen:NULL subviewCount:sbs.count pointIndexArray:pointIndexArray viewSpace:self.spaceType.value]; } } diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 5c59e64..f927ad4 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -19,13 +19,12 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( { CGSize selfSize = [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; - MyRelativeLayout *lsc = self.myCurrentSizeClass; - + MyRelativeLayoutViewSizeClass *lsc = (MyRelativeLayoutViewSizeClass*)self.myCurrentSizeClass; for (UIView *sbv in self.subviews) { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; if (sbvsc.useFrame) continue; @@ -76,7 +75,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( BOOL reCalcWidth = NO; BOOL reCalcHeight = NO; - CGSize maxSize = [self myCalcLayout:lsc inSelfSize:selfSize pRecalcWidth:&reCalcWidth pRecalcHeight:&reCalcHeight]; + CGSize maxSize = [self myLayout:lsc calcSelfSize:selfSize pRecalcWidth:&reCalcWidth pRecalcHeight:&reCalcHeight]; //如果布局视图的尺寸自适应的,这里要调整一下布局视图的尺寸。但是因为有一些子视图的约束是依赖布局视图的而且可能会引发连锁反应,所以这里要再次进行重新布局处理 if (lsc.widthSizeInner.dimeWrapVal || lsc.heightSizeInner.dimeWrapVal) @@ -112,7 +111,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( } } - [self myCalcLayout:lsc inSelfSize:selfSize pRecalcWidth:NULL pRecalcHeight:NULL]; + [self myLayout:lsc calcSelfSize:selfSize pRecalcWidth:NULL pRecalcHeight:NULL]; } } @@ -129,13 +128,11 @@ -(id)createSizeClassInstance } - #pragma mark -- Private Method --(void)myCalcSubViewLeadingTrailing:(UIView*)sbv - sbvsc:(UIView*)sbvsc - lsc:(MyRelativeLayout*)lsc - sbvmyFrame:(MyFrame*)sbvmyFrame - selfSize:(CGSize)selfSize +-(void)myLayout:(MyRelativeLayoutViewSizeClass*)lsc +calcLeadingTrailingOfSubview:(MyViewSizeClass*)sbvsc + sbvmyFrame:(MyFrame*)sbvmyFrame + selfSize:(CGSize)selfSize { @@ -164,9 +161,11 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv return; //先检测宽度,如果宽度是父亲的宽度则宽度和左右都确定 - if ([self myCalcWidth:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]) + if ([self myLayout:lsc calcWidthOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]) return; + UIView *sbv = sbvsc.view; + //表示视图数组水平居中 if (sbvsc.centerXPosInner.posArrVal != nil) { @@ -188,7 +187,7 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv totalOffset += nextPos.view.centerXPos.absVal; } - [self myCalcWidth:pos.view sbvsc:pos.view.myCurrentSizeClass lsc:lsc sbvmyFrame:pos.view.myFrame selfSize:selfSize]; + [self myLayout:lsc calcWidthOfSubview:(MyViewSizeClass*)pos.view.myCurrentSizeClass sbvmyFrame:pos.view.myFrame selfSize:selfSize]; totalWidth += pos.view.myFrame.width; } @@ -203,7 +202,7 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv totalOffset += nextPos.view.centerXPos.absVal; } - [self myCalcWidth:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + [self myLayout:lsc calcWidthOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; totalWidth += sbvmyFrame.width; totalOffset += sbvsc.centerXPosInner.absVal; } @@ -226,7 +225,7 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv { UIView *relaView = sbvsc.centerXPosInner.posRelaVal.view; - sbvmyFrame.leading = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.centerXPosInner.posRelaVal.pos selfSize:selfSize] - sbvmyFrame.width / 2 + sbvsc.centerXPosInner.absVal; + sbvmyFrame.leading = [self myLayout:lsc calcSizeOrPosOfSubview:relaView gravity:sbvsc.centerXPosInner.posRelaVal.pos selfSize:selfSize] - sbvmyFrame.width / 2 + sbvsc.centerXPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) { @@ -259,7 +258,7 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv { UIView *relaView = sbvsc.leadingPosInner.posRelaVal.view; - sbvmyFrame.leading = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.leadingPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.leadingPosInner.absVal; + sbvmyFrame.leading = [self myLayout:lsc calcSizeOrPosOfSubview:relaView gravity:sbvsc.leadingPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.leadingPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) sbvmyFrame.leading -= sbvsc.leadingPosInner.absVal; @@ -280,7 +279,7 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv { UIView *relaView = sbvsc.trailingPosInner.posRelaVal.view; - sbvmyFrame.trailing = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.trailingPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.trailingPosInner.absVal + sbvsc.leadingPosInner.absVal; + sbvmyFrame.trailing = [self myLayout:lsc calcSizeOrPosOfSubview:relaView gravity:sbvsc.trailingPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.trailingPosInner.absVal + sbvsc.leadingPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) sbvmyFrame.trailing += sbvsc.trailingPosInner.absVal; @@ -315,11 +314,11 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv if (lBoundPos.posRelaVal != nil && uBoundPos.posRelaVal != nil) { //让宽度缩小并在最小和最大的中间排列。 - CGFloat minLeading = [self myCalcSubView:lBoundRelaView lsc:lsc gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; + CGFloat minLeading = [self myLayout:lsc calcSizeOrPosOfSubview:lBoundRelaView gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; if (lBoundRelaView != nil && lBoundRelaView != self && [self myIsNoLayoutSubview:lBoundRelaView]) minLeading -= lBoundPos.offsetVal; - CGFloat maxTrailing = [self myCalcSubView:uBoundRelaView lsc:lsc gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; + CGFloat maxTrailing = [self myLayout:lsc calcSizeOrPosOfSubview:uBoundRelaView gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; if (uBoundRelaView != nil && uBoundRelaView != self && [self myIsNoLayoutSubview:uBoundRelaView]) maxTrailing += uBoundPos.offsetVal; @@ -342,7 +341,7 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv else if (lBoundPos.posRelaVal != nil) { //得到左边的最小位置。如果当前的左边距小于这个位置则缩小视图的宽度。 - CGFloat minLeading = [self myCalcSubView:lBoundRelaView lsc:lsc gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; + CGFloat minLeading = [self myLayout:lsc calcSizeOrPosOfSubview:lBoundRelaView gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; if (lBoundRelaView != nil && lBoundRelaView != self && [self myIsNoLayoutSubview:lBoundRelaView]) minLeading -= lBoundPos.offsetVal; @@ -356,7 +355,7 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv else if (uBoundPos.posRelaVal != nil) { //得到右边的最大位置。如果当前的右边距大于了这个位置则缩小视图的宽度。 - CGFloat maxTrailing = [self myCalcSubView:uBoundRelaView lsc:lsc gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; + CGFloat maxTrailing = [self myLayout:lsc calcSizeOrPosOfSubview:uBoundRelaView gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; if (uBoundRelaView != nil && uBoundRelaView != self && [self myIsNoLayoutSubview:uBoundRelaView]) maxTrailing += uBoundPos.offsetVal; @@ -369,16 +368,18 @@ -(void)myCalcSubViewLeadingTrailing:(UIView*)sbv } --(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize +-(void)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcTopBottomOfSubview:(MyViewSizeClass*)sbvsc sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize { if (sbvmyFrame.top != CGFLOAT_MAX && sbvmyFrame.bottom != CGFLOAT_MAX && sbvmyFrame.height != CGFLOAT_MAX) return; //先检测高度,如果高度是父亲的高度则高度和上下都确定 - if ([self myCalcHeight:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]) + if ([self myLayout:lsc calcHeightOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]) return; + UIView *sbv = sbvsc.view; + //表示视图数组垂直居中 if (sbvsc.centerYPosInner.posArrVal != nil) { @@ -399,7 +400,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL totalOffset += nextPos.view.centerYPos.absVal; } - [self myCalcHeight:pos.view sbvsc:pos.view.myCurrentSizeClass lsc:lsc sbvmyFrame:pos.view.myFrame selfSize:selfSize]; + [self myLayout:lsc calcHeightOfSubview:(MyViewSizeClass*)pos.view.myCurrentSizeClass sbvmyFrame:pos.view.myFrame selfSize:selfSize]; totalHeight += pos.view.myFrame.height; } @@ -414,7 +415,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL totalOffset += nextPos.view.centerYPos.absVal; } - [self myCalcHeight:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + [self myLayout:lsc calcHeightOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; totalHeight += sbvmyFrame.height; totalOffset += sbvsc.centerYPosInner.absVal; } @@ -443,7 +444,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL { //得到基线的位置。 UIView *relaView = sbvsc.baselinePosInner.posRelaVal.view; - sbvmyFrame.top = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.baselinePosInner.posRelaVal.pos selfSize:selfSize] - sbvFont.ascender - (sbvmyFrame.height - sbvFont.lineHeight) / 2 + sbvsc.baselinePosInner.absVal; + sbvmyFrame.top = [self myLayout:lsc calcSizeOrPosOfSubview:relaView gravity:sbvsc.baselinePosInner.posRelaVal.pos selfSize:selfSize] - sbvFont.ascender - (sbvmyFrame.height - sbvFont.lineHeight) / 2 + sbvsc.baselinePosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) { @@ -492,7 +493,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL { UIView *relaView = sbvsc.centerYPosInner.posRelaVal.view; - sbvmyFrame.top = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.centerYPosInner.posRelaVal.pos selfSize:selfSize] - sbvmyFrame.height / 2 + sbvsc.centerYPosInner.absVal; + sbvmyFrame.top = [self myLayout:lsc calcSizeOrPosOfSubview:relaView gravity:sbvsc.centerYPosInner.posRelaVal.pos selfSize:selfSize] - sbvmyFrame.height / 2 + sbvsc.centerYPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) @@ -529,7 +530,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL { UIView *relaView = sbvsc.topPosInner.posRelaVal.view; - sbvmyFrame.top = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.topPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.topPosInner.absVal; + sbvmyFrame.top = [self myLayout:lsc calcSizeOrPosOfSubview:relaView gravity:sbvsc.topPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.topPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) { @@ -552,7 +553,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL { UIView *relaView = sbvsc.bottomPosInner.posRelaVal.view; - sbvmyFrame.bottom = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.bottomPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.bottomPosInner.absVal + sbvsc.topPosInner.absVal; + sbvmyFrame.bottom = [self myLayout:lsc calcSizeOrPosOfSubview:relaView gravity:sbvsc.bottomPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.bottomPosInner.absVal + sbvsc.topPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) sbvmyFrame.bottom += sbvsc.bottomPosInner.absVal; @@ -586,10 +587,10 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL if (lBoundPos.posRelaVal != nil && uBoundPos.posRelaVal != nil) { //让宽度缩小并在最小和最大的中间排列。 - CGFloat minTop = [self myCalcSubView:lBoundRelaView lsc:lsc gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; + CGFloat minTop = [self myLayout:lsc calcSizeOrPosOfSubview:lBoundRelaView gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; if (lBoundRelaView != nil && lBoundRelaView != self && [self myIsNoLayoutSubview:lBoundRelaView]) minTop -= lBoundPos.offsetVal; - CGFloat maxBottom = [self myCalcSubView:uBoundRelaView lsc:lsc gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; + CGFloat maxBottom = [self myLayout:lsc calcSizeOrPosOfSubview:uBoundRelaView gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; if (uBoundRelaView != nil && uBoundRelaView != self && [self myIsNoLayoutSubview:uBoundRelaView]) maxBottom += uBoundPos.offsetVal; @@ -609,7 +610,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL else if (lBoundPos.posRelaVal != nil) { //得到左边的最小位置。如果当前的左边距小于这个位置则缩小视图的宽度。 - CGFloat minTop = [self myCalcSubView:lBoundRelaView lsc:lsc gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; + CGFloat minTop = [self myLayout:lsc calcSizeOrPosOfSubview:lBoundRelaView gravity:lBoundPos.posRelaVal.pos selfSize:selfSize] + lBoundPos.offsetVal; if (lBoundRelaView != nil && lBoundRelaView != self && [self myIsNoLayoutSubview:lBoundRelaView]) minTop -= lBoundPos.offsetVal; @@ -623,7 +624,7 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL else if (uBoundPos.posRelaVal != nil) { //得到右边的最大位置。如果当前的右边距大于了这个位置则缩小视图的宽度。 - CGFloat maxBottom = [self myCalcSubView:uBoundRelaView lsc:lsc gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; + CGFloat maxBottom = [self myLayout:lsc calcSizeOrPosOfSubview:uBoundRelaView gravity:uBoundPos.posRelaVal.pos selfSize:selfSize] - uBoundPos.offsetVal; if (uBoundRelaView != nil && uBoundRelaView != self && [self myIsNoLayoutSubview:uBoundRelaView]) maxBottom += uBoundPos.offsetVal; @@ -637,10 +638,10 @@ -(void)myCalcSubViewTopBottom:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeL --(CGFloat)myCalcSubView:(UIView*)sbv lsc:(MyRelativeLayout*)lsc gravity:(MyGravity)gravity selfSize:(CGSize)selfSize +-(CGFloat)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcSizeOrPosOfSubview:(UIView*)sbv gravity:(MyGravity)gravity selfSize:(CGSize)selfSize { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; switch (gravity) { case MyGravity_Horz_Leading: @@ -652,10 +653,9 @@ -(CGFloat)myCalcSubView:(UIView*)sbv lsc:(MyRelativeLayout*)lsc gravity:(MyGravi if (sbvmyFrame.leading != CGFLOAT_MAX) return sbvmyFrame.leading; - [self myCalcSubViewLeadingTrailing:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + [self myLayout:lsc calcLeadingTrailingOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; return sbvmyFrame.leading; - } break; case MyGravity_Horz_Trailing: @@ -666,10 +666,9 @@ -(CGFloat)myCalcSubView:(UIView*)sbv lsc:(MyRelativeLayout*)lsc gravity:(MyGravi if (sbvmyFrame.trailing != CGFLOAT_MAX) return sbvmyFrame.trailing; - [self myCalcSubViewLeadingTrailing:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; - + [self myLayout:lsc calcLeadingTrailingOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + return sbvmyFrame.trailing; - } break; case MyGravity_Vert_Top: @@ -681,7 +680,7 @@ -(CGFloat)myCalcSubView:(UIView*)sbv lsc:(MyRelativeLayout*)lsc gravity:(MyGravi if (sbvmyFrame.top != CGFLOAT_MAX) return sbvmyFrame.top; - [self myCalcSubViewTopBottom:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + [self myLayout:lsc calcTopBottomOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; return sbvmyFrame.top; @@ -696,8 +695,8 @@ -(CGFloat)myCalcSubView:(UIView*)sbv lsc:(MyRelativeLayout*)lsc gravity:(MyGravi if (sbvmyFrame.bottom != CGFLOAT_MAX) return sbvmyFrame.bottom; - [self myCalcSubViewTopBottom:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; - + [self myLayout:lsc calcTopBottomOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + return sbvmyFrame.bottom; } break; @@ -710,22 +709,20 @@ -(CGFloat)myCalcSubView:(UIView*)sbv lsc:(MyRelativeLayout*)lsc gravity:(MyGravi if (sbvFont != nil) { if (sbvmyFrame.top == CGFLOAT_MAX || sbvmyFrame.height == CGFLOAT_MAX) - [self myCalcSubViewTopBottom:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + [self myLayout:lsc calcTopBottomOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; //得到基线的位置。 return sbvmyFrame.top + (sbvmyFrame.height - sbvFont.lineHeight)/2.0 + sbvFont.ascender; - } else { if (sbvmyFrame.top != CGFLOAT_MAX) return sbvmyFrame.top; - [self myCalcSubViewTopBottom:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + [self myLayout:lsc calcTopBottomOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; return sbvmyFrame.top; } - } break; case MyGravity_Horz_Fill: @@ -737,10 +734,9 @@ -(CGFloat)myCalcSubView:(UIView*)sbv lsc:(MyRelativeLayout*)lsc gravity:(MyGravi if (sbvmyFrame.width != CGFLOAT_MAX) return sbvmyFrame.width; - [self myCalcSubViewLeadingTrailing:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + [self myLayout:lsc calcLeadingTrailingOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; return sbvmyFrame.width; - } break; case MyGravity_Vert_Fill: @@ -752,7 +748,7 @@ -(CGFloat)myCalcSubView:(UIView*)sbv lsc:(MyRelativeLayout*)lsc gravity:(MyGravi if (sbvmyFrame.height != CGFLOAT_MAX) return sbvmyFrame.height; - [self myCalcSubViewTopBottom:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + [self myLayout:lsc calcTopBottomOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; return sbvmyFrame.height; } @@ -765,7 +761,7 @@ -(CGFloat)myCalcSubView:(UIView*)sbv lsc:(MyRelativeLayout*)lsc gravity:(MyGravi if (sbvmyFrame.leading != CGFLOAT_MAX && sbvmyFrame.trailing != CGFLOAT_MAX && sbvmyFrame.width != CGFLOAT_MAX) return sbvmyFrame.leading + sbvmyFrame.width / 2; - [self myCalcSubViewLeadingTrailing:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + [self myLayout:lsc calcLeadingTrailingOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; return sbvmyFrame.leading + sbvmyFrame.width / 2; @@ -780,7 +776,7 @@ -(CGFloat)myCalcSubView:(UIView*)sbv lsc:(MyRelativeLayout*)lsc gravity:(MyGravi if (sbvmyFrame.top != CGFLOAT_MAX && sbvmyFrame.bottom != CGFLOAT_MAX && sbvmyFrame.height != CGFLOAT_MAX) return sbvmyFrame.top + sbvmyFrame.height / 2; - [self myCalcSubViewTopBottom:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + [self myLayout:lsc calcTopBottomOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; return sbvmyFrame.top + sbvmyFrame.height / 2; } @@ -793,8 +789,9 @@ -(CGFloat)myCalcSubView:(UIView*)sbv lsc:(MyRelativeLayout*)lsc gravity:(MyGravi } --(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize +-(BOOL)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcWidthOfSubview:(MyViewSizeClass*)sbvsc sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize { + UIView *sbv = sbvsc.view; BOOL hasMargin = NO; if (sbvmyFrame.width == CGFLOAT_MAX) @@ -817,9 +814,7 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc { if (dime.dimeVal != nil) { - [self myCalcWidth:dime.view - sbvsc:dime.view.myCurrentSizeClass - lsc:lsc + [self myLayout:lsc calcWidthOfSubview:(MyViewSizeClass*)dime.view.myCurrentSizeClass sbvmyFrame:dime.view.myFrame selfSize:selfSize]; @@ -880,7 +875,7 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc else if (sbvsc.widthSizeInner.dimeRelaVal != nil) { - sbvmyFrame.width = [sbvsc.widthSizeInner measureWith:[self myCalcSubView:sbvsc.widthSizeInner.dimeRelaVal.view lsc:lsc gravity:sbvsc.widthSizeInner.dimeRelaVal.dime selfSize:selfSize] ]; + sbvmyFrame.width = [sbvsc.widthSizeInner measureWith:[self myLayout:lsc calcSizeOrPosOfSubview:sbvsc.widthSizeInner.dimeRelaVal.view gravity:sbvsc.widthSizeInner.dimeRelaVal.dime selfSize:selfSize] ]; } else if (sbvsc.widthSizeInner.dimeNumVal != nil) { @@ -901,7 +896,7 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc if (sbvsc.leadingPosInner.posRelaVal != nil) { UIView *relaView = sbvsc.leadingPosInner.posRelaVal.view; - sbvmyFrame.leading = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.leadingPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.leadingPosInner.absVal; + sbvmyFrame.leading = [self myLayout:lsc calcSizeOrPosOfSubview:relaView gravity:sbvsc.leadingPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.leadingPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) sbvmyFrame.leading -= sbvsc.leadingPosInner.absVal; } @@ -917,7 +912,7 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc if (sbvsc.trailingPosInner.posRelaVal != nil) { UIView *relaView = sbvsc.trailingPosInner.posRelaVal.view; - sbvmyFrame.trailing = [self myCalcSubView:sbvsc.trailingPosInner.posRelaVal.view lsc:lsc gravity:sbvsc.trailingPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.trailingPosInner.absVal; + sbvmyFrame.trailing = [self myLayout:lsc calcSizeOrPosOfSubview:sbvsc.trailingPosInner.posRelaVal.view gravity:sbvsc.trailingPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.trailingPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) sbvmyFrame.trailing += sbvsc.trailingPosInner.absVal; } @@ -943,18 +938,14 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc //计算有最大和最小约束的情况。 if (sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal != nil && sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal.view != self) { - [self myCalcWidth:sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal.view - sbvsc:sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal.view.myCurrentSizeClass - lsc:lsc + [self myLayout:lsc calcWidthOfSubview:(MyViewSizeClass*)sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal.view.myCurrentSizeClass sbvmyFrame:sbvsc.widthSizeInner.uBoundValInner.dimeRelaVal.view.myFrame selfSize:selfSize]; } if (sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal != nil && sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal.view != self) { - [self myCalcWidth:sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal.view - sbvsc:sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal.view.myCurrentSizeClass - lsc:lsc + [self myLayout:lsc calcWidthOfSubview:(MyViewSizeClass*)sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal.view.myCurrentSizeClass sbvmyFrame:sbvsc.widthSizeInner.lBoundValInner.dimeRelaVal.view.myFrame selfSize:selfSize]; } @@ -972,9 +963,9 @@ -(BOOL)myCalcWidth:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc } --(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize +-(BOOL)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcHeightOfSubview:(MyViewSizeClass*)sbvsc sbvmyFrame:(MyFrame*)sbvmyFrame selfSize:(CGSize)selfSize { - + UIView *sbv = sbvsc.view; BOOL hasMargin = NO; if (sbvmyFrame.height == CGFLOAT_MAX) @@ -996,9 +987,7 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc { if (dime.dimeVal != nil) { - [self myCalcHeight:dime.view - sbvsc:dime.view.myCurrentSizeClass - lsc:lsc + [self myLayout:lsc calcHeightOfSubview:(MyViewSizeClass*)dime.view.myCurrentSizeClass sbvmyFrame:dime.view.myFrame selfSize:selfSize]; @@ -1054,7 +1043,7 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc } else if (sbvsc.heightSizeInner.dimeRelaVal != nil) { - sbvmyFrame.height = [sbvsc.heightSizeInner measureWith:[self myCalcSubView:sbvsc.heightSizeInner.dimeRelaVal.view lsc:lsc gravity:sbvsc.heightSizeInner.dimeRelaVal.dime selfSize:selfSize] ]; + sbvmyFrame.height = [sbvsc.heightSizeInner measureWith:[self myLayout:lsc calcSizeOrPosOfSubview:sbvsc.heightSizeInner.dimeRelaVal.view gravity:sbvsc.heightSizeInner.dimeRelaVal.dime selfSize:selfSize] ]; } else if (sbvsc.heightSizeInner.dimeNumVal != nil) { @@ -1065,9 +1054,9 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc if (![sbv isKindOfClass:[MyBaseLayout class]]) { if (sbvmyFrame.width == CGFLOAT_MAX) - [self myCalcWidth:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + [self myLayout:lsc calcWidthOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; - sbvmyFrame.height = [self myHeightFromFlexedHeightView:sbv sbvsc:sbvsc inWidth:sbvmyFrame.width]; + sbvmyFrame.height = [self mySubview:sbvsc wrapHeightSizeFits:sbvmyFrame.width]; } } @@ -1080,7 +1069,7 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc if (sbvsc.topPosInner.posRelaVal != nil) { UIView *relaView = sbvsc.topPosInner.posRelaVal.view; - sbvmyFrame.top = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.topPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.topPosInner.absVal; + sbvmyFrame.top = [self myLayout:lsc calcSizeOrPosOfSubview:relaView gravity:sbvsc.topPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.topPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) sbvmyFrame.top -= sbvsc.topPosInner.absVal; @@ -1098,7 +1087,7 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc { UIView *relaView = sbvsc.bottomPosInner.posRelaVal.view; - sbvmyFrame.bottom = [self myCalcSubView:relaView lsc:lsc gravity:sbvsc.bottomPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.bottomPosInner.absVal; + sbvmyFrame.bottom = [self myLayout:lsc calcSizeOrPosOfSubview:relaView gravity:sbvsc.bottomPosInner.posRelaVal.pos selfSize:selfSize] - sbvsc.bottomPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) sbvmyFrame.bottom += sbvsc.bottomPosInner.absVal; @@ -1123,18 +1112,14 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc if (sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal != nil && sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal.view != self) { - [self myCalcHeight:sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal.view - sbvsc:sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal.view.myCurrentSizeClass - lsc:lsc + [self myLayout:lsc calcHeightOfSubview:(MyViewSizeClass*)sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal.view.myCurrentSizeClass sbvmyFrame:sbvsc.heightSizeInner.uBoundValInner.dimeRelaVal.view.myFrame selfSize:selfSize]; } if (sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal != nil && sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal.view != self) { - [self myCalcHeight:sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal.view - sbvsc:sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal.view.myCurrentSizeClass - lsc:lsc + [self myLayout:lsc calcHeightOfSubview:(MyViewSizeClass*)sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal.view.myCurrentSizeClass sbvmyFrame:sbvsc.heightSizeInner.lBoundValInner.dimeRelaVal.view.myFrame selfSize:selfSize]; } @@ -1152,7 +1137,7 @@ -(BOOL)myCalcHeight:(UIView*)sbv sbvsc:(UIView*)sbvsc lsc:(MyRelativeLayout*)lsc } --(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalcWidth:(BOOL*)pRecalcWidth pRecalcHeight:(BOOL*)pRecalcHeight +-(CGSize)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcSelfSize:(CGSize)selfSize pRecalcWidth:(BOOL*)pRecalcWidth pRecalcHeight:(BOOL*)pRecalcHeight { if (pRecalcWidth != NULL) *pRecalcWidth = NO; @@ -1167,10 +1152,10 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc { MyFrame *sbvmyFrame = sbv.myFrame; - UIView *sbvsc = [sbv myCurrentSizeClassFrom:sbvmyFrame]; + MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; - [self myCalcSubViewLeadingTrailing:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; - [self myCalcSubViewTopBottom:sbv sbvsc:sbvsc lsc:lsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + [self myLayout:lsc calcLeadingTrailingOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; + [self myLayout:lsc calcTopBottomOfSubview:sbvsc sbvmyFrame:sbvmyFrame selfSize:selfSize]; if ([self myIsNoLayoutSubview:sbv]) continue; @@ -1202,13 +1187,6 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc if (_myCGFloatLess(maxWidth, sbvmyFrame.width + sbvsc.leadingPosInner.absVal + sbvsc.trailingPosInner.absVal + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding)) maxWidth = sbvmyFrame.width + sbvsc.leadingPosInner.absVal + sbvsc.trailingPosInner.absVal + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding; } - else if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil) - { - if (sbvsc.widthSizeInner.dimeVal != nil && _myCGFloatLess(maxWidth, fabs(sbvmyFrame.trailing) + lsc.myLayoutTrailingPadding)) - { - maxWidth = fabs(sbvmyFrame.trailing) + lsc.myLayoutTrailingPadding; - } - } else if (sbvsc.trailingPosInner.posVal != nil) {//如果只有右边约束,则可以认为宽度是反过来算的,所以这里是左边的绝对值加上左边的padding来计算最宽宽度。 if (_myCGFloatLess(maxWidth, fabs(sbvmyFrame.leading) + lsc.myLayoutLeadingPadding)) @@ -1216,9 +1194,11 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc } else { - if (_myCGFloatLess(maxWidth, fabs(sbvmyFrame.trailing) + lsc.myLayoutTrailingPadding)) - maxWidth = fabs(sbvmyFrame.trailing) + lsc.myLayoutTrailingPadding; + } + + if (_myCGFloatLess(maxWidth, fabs(sbvmyFrame.trailing) + lsc.myLayoutTrailingPadding)) + maxWidth = fabs(sbvmyFrame.trailing) + lsc.myLayoutTrailingPadding; } } @@ -1250,13 +1230,6 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc if (_myCGFloatLess(maxHeight, sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.bottomPosInner.absVal + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding)) maxHeight = sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.bottomPosInner.absVal + lsc.myLayoutTopPadding + lsc.myLayoutBottomPadding; } - else if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil) - { - if (sbvsc.heightSizeInner.dimeVal != nil && _myCGFloatLess(maxHeight, fabs(sbvmyFrame.bottom) + lsc.myLayoutBottomPadding)) - { - maxHeight = fabs(sbvmyFrame.bottom) + lsc.myLayoutBottomPadding; - } - } else if (sbvsc.bottomPosInner.posVal != nil) {//如果只有底边约束,则可以认为高度是反过来算的,所以这里是上边的绝对值加上上边的padding来计算最高高度 if (_myCGFloatLess(maxHeight, fabs(sbvmyFrame.top) + lsc.myLayoutTopPadding)) @@ -1264,9 +1237,11 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc } else { - if (_myCGFloatLess(maxHeight, fabs(sbvmyFrame.bottom) + lsc.myLayoutBottomPadding)) - maxHeight = fabs(sbvmyFrame.bottom) + lsc.myLayoutBottomPadding; + } + + if (_myCGFloatLess(maxHeight, fabs(sbvmyFrame.bottom) + lsc.myLayoutBottomPadding)) + maxHeight = fabs(sbvmyFrame.bottom) + lsc.myLayoutBottomPadding; } } } @@ -1276,6 +1251,4 @@ -(CGSize)myCalcLayout:(MyRelativeLayout*)lsc inSelfSize:(CGSize)selfSize pRecalc } - - @end diff --git a/MyLayout/Lib/MyTableLayout.m b/MyLayout/Lib/MyTableLayout.m index b11482f..911f0f1 100644 --- a/MyLayout/Lib/MyTableLayout.m +++ b/MyLayout/Lib/MyTableLayout.m @@ -13,7 +13,6 @@ @interface MyTableRowLayout : MyLinearLayout - +(MyTableRowLayout *)rowSize:(CGFloat)rowSize colSize:(CGFloat)colSize orientation:(MyOrientation)orientation; @property(nonatomic,assign, readonly) CGFloat rowSize; @@ -27,7 +26,6 @@ @implementation MyTableRowLayout CGFloat _colSize; } - -(instancetype)initWith:(CGFloat)rowSize colSize:(CGFloat)colSize orientation:(MyOrientation)orientation { self = [super initWithOrientation:orientation]; @@ -104,13 +102,11 @@ -(void)myHookSublayout:(MyBaseLayout *)sublayout borderlineRect:(CGRect *)pRect } } - +(MyTableRowLayout *)rowSize:(CGFloat)rowSize colSize:(CGFloat)colSize orientation:(MyOrientation)orientation { return [[self alloc] initWith:rowSize colSize:colSize orientation:orientation]; } - @end @@ -128,7 +124,6 @@ -(NSInteger)col @end - @implementation MyTableLayout #pragma mark -- Public Methods @@ -138,7 +133,6 @@ +(instancetype)tableLayoutWithOrientation:(MyOrientation)orientation return [self linearLayoutWithOrientation:orientation]; } - -(MyLinearLayout*)addRow:(CGFloat)rowSize colSize:(CGFloat)colSize { return [self insertRow:rowSize colSize:colSize atIndex:self.countOfRow]; @@ -155,7 +149,6 @@ -(MyLinearLayout*)insertRow:(CGFloat)rowSize colCount:(NSUInteger)colCount atInd return [self insertRow:rowSize colSize:sColCountTag - colCount atIndex:rowIndex]; } - -(MyLinearLayout*)insertRow:(CGFloat)rowSize colSize:(CGFloat)colSize atIndex:(NSInteger)rowIndex { MyTableLayout *lsc = self.myCurrentSizeClass; @@ -171,6 +164,7 @@ -(MyLinearLayout*)insertRow:(CGFloat)rowSize colSize:(CGFloat)colSize atIndex:(N rowView.subviewHSpace = lsc.subviewHSpace; else rowView.subviewVSpace = lsc.subviewVSpace; + rowView.intelligentBorderline = self.intelligentBorderline; [super insertSubview:rowView atIndex:rowIndex]; return rowView; @@ -261,7 +255,6 @@ -(void)exchangeColAt:(NSIndexPath*)indexPath1 withCol:(NSIndexPath*)indexPath2 if (colView1 == colView2) return; - [self removeColAt:indexPath1]; [self removeColAt:indexPath2]; @@ -304,10 +297,8 @@ -(void)setSubviewHSpace:(CGFloat)subviewHSpace [self viewAtRowIndex:i].subviewHSpace = subviewHSpace; } } - } - //不能直接调用如下的函数。 - (void)insertSubview:(UIView *)view atIndex:(NSInteger)index { @@ -333,11 +324,9 @@ - (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview NSCAssert(0, @"Constraint exception!! Can't call insertSubview"); } - -(id)createSizeClassInstance { return [MyTableLayoutViewSizeClass new]; } - @end From 5601a567bcf7ba02c24247bc5717831144a1e069 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Mon, 11 Nov 2019 21:37:34 +0800 Subject: [PATCH 077/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlowLayout.m | 19 +- MyLayout/Lib/MyRelativeLayout.m | 15 -- MyLayoutTests/MyFlowLayoutTestCase.m | 271 +++++++++++++++++++++++++++ 3 files changed, 279 insertions(+), 26 deletions(-) diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 1642634..5caf8dd 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -1673,15 +1673,15 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG rect.origin.y = yPos + topSpace; xPos += leadingSpace + rect.size.width + trailingSpace; - if (itemIndex != (arrangedCount - 1) && !autoArrange) - xPos += horzSpace; - if (_myCGFloatLess(lineMaxWidth, (xPos - paddingLeading))) lineMaxWidth = (xPos - paddingLeading); if (_myCGFloatLess(maxWidth, xPos)) maxWidth = xPos; - + + if (itemIndex != (arrangedCount - 1) && !autoArrange) + xPos += horzSpace; + sbvmyFrame.frame = rect; itemIndex++; @@ -2519,18 +2519,15 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG rect.origin.y = yPos + topSpace; yPos += topSpace + rect.size.height + bottomSpace; - //不是最后一行以及非自动排列时才添加布局视图设置的行间距。自动排列的情况下上面已经有添加行间距了。 - if (itemIndex != (arrangedCount - 1) && !autoArrange) - yPos += vertSpace; - - if (_myCGFloatLess(lineMaxHeight, (yPos - paddingTop))) lineMaxHeight = yPos - paddingTop; if (_myCGFloatLess(maxHeight, yPos)) - maxHeight = yPos; + maxHeight = yPos; + //不是最后一行以及非自动排列时才添加布局视图设置的行间距。自动排列的情况下上面已经有添加行间距了。 + if (itemIndex != (arrangedCount - 1) && !autoArrange) + yPos += vertSpace; - sbvmyFrame.frame = rect; itemIndex++; diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index f927ad4..45bb4c6 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -228,9 +228,7 @@ -(void)myLayout:(MyRelativeLayoutViewSizeClass*)lsc sbvmyFrame.leading = [self myLayout:lsc calcSizeOrPosOfSubview:relaView gravity:sbvsc.centerXPosInner.posRelaVal.pos selfSize:selfSize] - sbvmyFrame.width / 2 + sbvsc.centerXPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) - { sbvmyFrame.leading -= sbvsc.centerXPosInner.absVal; - } if (sbvmyFrame.leading < 0 && relaView == self && lsc.widthSizeInner.dimeWrapVal) sbvmyFrame.leading = 0; @@ -447,9 +445,7 @@ -(void)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcTopBottomOfSubview:(MyVi sbvmyFrame.top = [self myLayout:lsc calcSizeOrPosOfSubview:relaView gravity:sbvsc.baselinePosInner.posRelaVal.pos selfSize:selfSize] - sbvFont.ascender - (sbvmyFrame.height - sbvFont.lineHeight) / 2 + sbvsc.baselinePosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) - { sbvmyFrame.top -= sbvsc.baselinePosInner.absVal; - } } else { @@ -497,9 +493,7 @@ -(void)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcTopBottomOfSubview:(MyVi if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) - { sbvmyFrame.top -= sbvsc.centerYPosInner.absVal; - } if (sbvmyFrame.top < 0 && relaView == self && lsc.heightSizeInner.dimeWrapVal) sbvmyFrame.top = 0; @@ -533,9 +527,7 @@ -(void)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcTopBottomOfSubview:(MyVi sbvmyFrame.top = [self myLayout:lsc calcSizeOrPosOfSubview:relaView gravity:sbvsc.topPosInner.posRelaVal.pos selfSize:selfSize] + sbvsc.topPosInner.absVal; if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) - { sbvmyFrame.top -= sbvsc.topPosInner.absVal; - } sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; } @@ -649,7 +641,6 @@ -(CGFloat)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcSizeOrPosOfSubview:(U if (sbv == self || sbv == nil) return lsc.myLayoutLeadingPadding; - if (sbvmyFrame.leading != CGFLOAT_MAX) return sbvmyFrame.leading; @@ -676,7 +667,6 @@ -(CGFloat)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcSizeOrPosOfSubview:(U if (sbv == self || sbv == nil) return lsc.myLayoutTopPadding; - if (sbvmyFrame.top != CGFLOAT_MAX) return sbvmyFrame.top; @@ -691,7 +681,6 @@ -(CGFloat)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcSizeOrPosOfSubview:(U if (sbv == self || sbv == nil) return selfSize.height - lsc.myLayoutBottomPadding; - if (sbvmyFrame.bottom != CGFLOAT_MAX) return sbvmyFrame.bottom; @@ -730,7 +719,6 @@ -(CGFloat)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcSizeOrPosOfSubview:(U if (sbv == self || sbv == nil) return selfSize.width - lsc.myLayoutLeadingPadding - lsc.myLayoutTrailingPadding; - if (sbvmyFrame.width != CGFLOAT_MAX) return sbvmyFrame.width; @@ -744,7 +732,6 @@ -(CGFloat)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcSizeOrPosOfSubview:(U if (sbv == self || sbv == nil) return selfSize.height - lsc.myLayoutTopPadding - lsc.myLayoutBottomPadding; - if (sbvmyFrame.height != CGFLOAT_MAX) return sbvmyFrame.height; @@ -1246,9 +1233,7 @@ -(CGSize)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcSelfSize:(CGSize)selfS } } - return CGSizeMake(maxWidth, maxHeight); - } @end diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index 7bc75ed..ba508bf 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -455,6 +455,88 @@ -(void)testWrapContentSize2 } } +-(void)testWrapContentSize3 +{ + { + MyFlowLayout *layout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:4]; + layout.frame = CGRectMake(0, 0, 0, 0); + layout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + layout.subviewHSpace = 5; + layout.subviewVSpace = 5; + + for (int i = 0; i < 1; i++) + { + UIView *sbv = [UIView new]; + sbv.mySize = CGSizeMake(50, 50); + [layout addSubview:sbv]; + } + + [layout layoutIfNeeded]; + MyRectAssert(layout, CGRectMake(0, 0, 50, 50)); + + for (int i = 0; i < 1; i++) + { + UIView *sbv = [UIView new]; + sbv.mySize = CGSizeMake(50, 50); + [layout addSubview:sbv]; + + } + [layout layoutIfNeeded]; + MyRectAssert(layout, CGRectMake(0, 0, 105, 50)); + + for (int i =0; i < 4; i++) + { + UIView *sbv = [UIView new]; + sbv.mySize = CGSizeMake(50, 50); + [layout addSubview:sbv]; + } + + [layout layoutIfNeeded]; + MyRectAssert(layout, CGRectMake(0, 0, 215, 105)); + } + + { + MyFlowLayout *layout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:4]; + layout.frame = CGRectMake(0, 0, 0, 0); + layout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + layout.subviewHSpace = 5; + layout.subviewVSpace = 5; + + for (int i = 0; i < 1; i++) + { + UIView *sbv = [UIView new]; + sbv.mySize = CGSizeMake(50, 50); + [layout addSubview:sbv]; + + } + + [layout layoutIfNeeded]; + MyRectAssert(layout, CGRectMake(0, 0, 50, 50)); + + for (int i = 0; i < 1; i++) + { + UIView *sbv = [UIView new]; + sbv.mySize = CGSizeMake(50, 50); + [layout addSubview:sbv]; + + } + [layout layoutIfNeeded]; + MyRectAssert(layout, CGRectMake(0, 0, 50, 105)); + + for (int i =0; i < 4; i++) + { + UIView *sbv = [UIView new]; + sbv.mySize = CGSizeMake(50, 50); + [layout addSubview:sbv]; + + } + + [layout layoutIfNeeded]; + MyRectAssert(layout, CGRectMake(0, 0, 105, 215)); + } +} + + -(void)testWeight { //测试内容约束布局中weight刚好在边界的情况。 @@ -642,4 +724,193 @@ -(void)testWrapAndGravity } +-(void)testRightAndBottomGravity +{ + //测试 + { + MyFlowLayout *layout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:4]; + layout.frame = CGRectMake(0, 0, 200, 200); + layout.gravity = MyGravity_Horz_Right; + layout.subviewHSpace = 5; + layout.subviewVSpace = 5; + + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(50, 50); + [layout addSubview:v1]; + + [layout layoutIfNeeded]; + + MyRectAssert(v1, CGRectMake(150, 0, 50, 50)); + + UIView *v2 = [UIView new]; + v2.mySize = CGSizeMake(50, 50); + [layout addSubview:v2]; + [layout layoutIfNeeded]; + + MyRectAssert(v2, CGRectMake(150, 0, 50, 50)); + + + UIView *v3 = [UIView new]; + v3.mySize = CGSizeMake(50, 50); + [layout addSubview:v3]; + [layout layoutIfNeeded]; + + UIView *v4 = [UIView new]; + v4.mySize = CGSizeMake(50, 50); + [layout addSubview:v4]; + [layout layoutIfNeeded]; + + UIView *v5 = [UIView new]; + v5.mySize = CGSizeMake(50, 50); + [layout addSubview:v5]; + [layout layoutIfNeeded]; + + UIView *v6 = [UIView new]; + v6.mySize = CGSizeMake(50, 50); + [layout addSubview:v6]; + [layout layoutIfNeeded]; + + MyRectAssert(v6, CGRectMake(150, 55, 50, 50)); + + } + { + MyFlowLayout *layout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:4]; + layout.frame = CGRectMake(0, 0, 200, 200); + layout.gravity = MyGravity_Vert_Bottom; + layout.subviewHSpace = 5; + layout.subviewVSpace = 5; + + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(50, 50); + [layout addSubview:v1]; + + [layout layoutIfNeeded]; + + MyRectAssert(v1, CGRectMake(0, 150, 50, 50)); + + UIView *v2 = [UIView new]; + v2.mySize = CGSizeMake(50, 50); + [layout addSubview:v2]; + [layout layoutIfNeeded]; + + MyRectAssert(v2, CGRectMake(0, 150, 50, 50)); + + + UIView *v3 = [UIView new]; + v3.mySize = CGSizeMake(50, 50); + [layout addSubview:v3]; + [layout layoutIfNeeded]; + + UIView *v4 = [UIView new]; + v4.mySize = CGSizeMake(50, 50); + [layout addSubview:v4]; + [layout layoutIfNeeded]; + + UIView *v5 = [UIView new]; + v5.mySize = CGSizeMake(50, 50); + [layout addSubview:v5]; + [layout layoutIfNeeded]; + + UIView *v6 = [UIView new]; + v6.mySize = CGSizeMake(50, 50); + [layout addSubview:v6]; + [layout layoutIfNeeded]; + + MyRectAssert(v6, CGRectMake(55, 150, 50, 50)); + } + + //测试 + { + MyFlowLayout *layout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; + layout.frame = CGRectMake(0, 0, 200, 200); + layout.gravity = MyGravity_Horz_Right; + layout.subviewHSpace = 5; + layout.subviewVSpace = 5; + + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(50, 50); + [layout addSubview:v1]; + + [layout layoutIfNeeded]; + + MyRectAssert(v1, CGRectMake(150, 0, 50, 50)); + + UIView *v2 = [UIView new]; + v2.mySize = CGSizeMake(50, 50); + [layout addSubview:v2]; + [layout layoutIfNeeded]; + + MyRectAssert(v2, CGRectMake(150, 0, 50, 50)); + + + UIView *v3 = [UIView new]; + v3.mySize = CGSizeMake(50, 50); + [layout addSubview:v3]; + [layout layoutIfNeeded]; + + UIView *v4 = [UIView new]; + v4.mySize = CGSizeMake(50, 50); + [layout addSubview:v4]; + [layout layoutIfNeeded]; + + UIView *v5 = [UIView new]; + v5.mySize = CGSizeMake(50, 50); + [layout addSubview:v5]; + [layout layoutIfNeeded]; + + UIView *v6 = [UIView new]; + v6.mySize = CGSizeMake(50, 50); + [layout addSubview:v6]; + [layout layoutIfNeeded]; + + MyRectAssert(v6, CGRectMake(150, 55, 50, 50)); + + } + { + MyFlowLayout *layout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:0]; + layout.frame = CGRectMake(0, 0, 200, 200); + layout.gravity = MyGravity_Vert_Bottom; + layout.subviewHSpace = 5; + layout.subviewVSpace = 5; + + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(50, 50); + [layout addSubview:v1]; + + [layout layoutIfNeeded]; + + MyRectAssert(v1, CGRectMake(0, 150, 50, 50)); + + UIView *v2 = [UIView new]; + v2.mySize = CGSizeMake(50, 50); + [layout addSubview:v2]; + [layout layoutIfNeeded]; + + MyRectAssert(v2, CGRectMake(0, 150, 50, 50)); + + + UIView *v3 = [UIView new]; + v3.mySize = CGSizeMake(50, 50); + [layout addSubview:v3]; + [layout layoutIfNeeded]; + + UIView *v4 = [UIView new]; + v4.mySize = CGSizeMake(50, 50); + [layout addSubview:v4]; + [layout layoutIfNeeded]; + + UIView *v5 = [UIView new]; + v5.mySize = CGSizeMake(50, 50); + [layout addSubview:v5]; + [layout layoutIfNeeded]; + + UIView *v6 = [UIView new]; + v6.mySize = CGSizeMake(50, 50); + [layout addSubview:v6]; + [layout layoutIfNeeded]; + + MyRectAssert(v6, CGRectMake(55, 150, 50, 50)); + } +} + @end From 6c39dd0729fbca0514787cfc202db0cf8e4b0b54 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Tue, 12 Nov 2019 01:29:16 +0800 Subject: [PATCH 078/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.m | 2 +- MyLayout/Lib/MyFlexLayout.h | 68 +++++--- MyLayout/Lib/MyFlexLayout.m | 222 +++++++++++++++----------- MyLayout/Lib/MyFlowLayout.m | 73 +++++++-- MyLayout/Lib/MyLayoutInner.h | 2 + MyLayoutDemo/FLXTest1ViewController.m | 93 +++++------ 6 files changed, 289 insertions(+), 171 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 94a00b7..cc9240c 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -2750,7 +2750,7 @@ -(CGFloat)mySubview:(MyViewSizeClass*)sbvsc wrapHeightSizeFits:(CGFloat)width -(CGFloat)myGetBoundLimitMeasure:(MyLayoutSize*)boundDime sbv:(UIView*)sbv dimeType:(MyGravity)dimeType sbvSize:(CGSize)sbvSize selfLayoutSize:(CGSize)selfLayoutSize isUBound:(BOOL)isUBound { CGFloat value = isUBound ? CGFLOAT_MAX : -CGFLOAT_MAX; - if (boundDime == nil) + if (boundDime == nil || !boundDime.isActive) return value; MyLayoutValueType lValueType = boundDime.dimeValType; diff --git a/MyLayout/Lib/MyFlexLayout.h b/MyLayout/Lib/MyFlexLayout.h index 7ec041f..3f71de6 100644 --- a/MyLayout/Lib/MyFlexLayout.h +++ b/MyLayout/Lib/MyFlexLayout.h @@ -37,26 +37,40 @@ typedef enum : int { extern const int MyFlex_Auto; +//条目的属性,用于设置和获取。 +@interface MyFlexItemAttrs:NSObject + +@property(nonatomic, assign) NSInteger order; +@property(nonatomic, assign) CGFloat flex_grow; +@property(nonatomic, assign) CGFloat flex_shrink; +@property(nonatomic, assign) CGFloat flex_basis; +@property(nonatomic, assign) MyFlexGravity align_self; +@property(nonatomic, assign) CGFloat width; +@property(nonatomic, assign) CGFloat height; +@property(nonatomic, assign) CGFloat margin_top; +@property(nonatomic, assign) CGFloat margin_bottom; +@property(nonatomic, assign) CGFloat margin_left; +@property(nonatomic, assign) CGFloat margin_right; +@property(nonatomic, assign) MyVisibility visibility; + +@end + +@protocol MyFlexItemAttrsContainer + +@property(nonatomic, strong, readonly) MyFlexItemAttrs *attrs; + +@end + + + + /* flexbox中项目的设置类。 */ -@interface MyFlexItem:NSObject +@interface MyFlexItem:NSObject //您可以用链式语法进行属性设置,也可以直接通过属性赋值进行设置和获取。 @property(nonatomic, weak, readonly) __kindof UIView *view; -@property(nonatomic, assign) NSInteger order_val; -@property(nonatomic, assign) CGFloat flex_grow_val; -@property(nonatomic, assign) CGFloat flex_shrink_val; -@property(nonatomic, assign) CGFloat flex_basis_val; -@property(nonatomic, assign) MyFlexGravity align_self_val; -@property(nonatomic, assign) CGFloat width_val; -@property(nonatomic, assign) CGFloat height_val; -@property(nonatomic, assign) CGFloat margin_top_val; -@property(nonatomic, assign) CGFloat margin_bottom_val; -@property(nonatomic, assign) CGFloat margin_left_val; -@property(nonatomic, assign) CGFloat margin_right_val; -@property(nonatomic, assign) MyVisibility visibility_val; - //条目的顺序设置 -(MyFlexItem* (^)(NSInteger))order; @@ -89,16 +103,30 @@ extern const int MyFlex_Auto; @end + +//条目的属性,用于设置和获取。 +@interface MyFlexAttrs:MyFlexItemAttrs + +@property(nonatomic, assign) MyFlexDirection flex_direction; +@property(nonatomic, assign) MyFlexWrap flex_wrap; +@property(nonatomic, assign) MyFlexGravity justify_content; +@property(nonatomic, assign) MyFlexGravity align_items; +@property(nonatomic, assign) MyFlexGravity align_content; + +@end + +@protocol MyFlexAttrsContainer + +@property(nonatomic, strong, readonly) MyFlexAttrs *attrs; + +@end + + /* flexbox的设置类。 */ -@interface MyFlex:MyFlexItem +@interface MyFlex:MyFlexItem -@property(nonatomic, assign) MyFlexDirection flex_direction_val; -@property(nonatomic, assign) MyFlexWrap flex_wrap_val; -@property(nonatomic, assign) MyFlexGravity justify_content_val; -@property(nonatomic, assign) MyFlexGravity align_items_val; -@property(nonatomic, assign) MyFlexGravity align_content_val; @property(nonatomic, assign) UIEdgeInsets padding_val; @property(nonatomic, assign) CGFloat vert_space_val; @property(nonatomic, assign) CGFloat horz_space_val; diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index 68585ed..1569858 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -13,83 +13,116 @@ const char * const ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM = "ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM"; const int MyFlex_Auto = -1; -@implementation MyFlexItem -{ - @package - __weak UIView *_view; -} +@interface MyFlexItemAttrs() + +@property(nonatomic, weak) UIView *view; --(instancetype)initWithView:(UIView*)view; +@end + +@implementation MyFlexItemAttrs + +-(instancetype)init { self = [super init]; if (self != nil) { - _order_val = 0; - _flex_grow_val = 0; - _flex_basis_val = MyFlex_Auto; - _flex_shrink_val = 1; - _align_self_val = MyFlex_Auto; - _view = view; - _width_val = 0; - _height_val = 0; + _order = 0; + _flex_grow = 0; + _flex_shrink = 1; + _flex_basis = MyFlex_Auto; + _align_self = MyFlex_Auto; + _width = 0; + _height = 0; } + return self; } --(CGFloat)margin_top_val +-(CGFloat)margin_top { return self.view.myTop; } --(void)setMargin_top_val:(CGFloat)margin_top_val +-(void)setMargin_top:(CGFloat)margin_top { - self.view.myTop = margin_top_val; + self.view.myTop = margin_top; } --(CGFloat)margin_bottom_val +-(CGFloat)margin_bottom { return self.view.myBottom; } --(void)setMargin_bottom_val:(CGFloat)margin_bottom_val +-(void)setMargin_bottom:(CGFloat)margin_bottom { - self.view.myBottom = margin_bottom_val; + self.view.myBottom = margin_bottom; } --(CGFloat)margin_left_val +-(CGFloat)margin_left { return self.view.myLeft; } --(void)setMargin_left_val:(CGFloat)margin_left_val +-(void)setMargin_left:(CGFloat)margin_left { - self.view.myLeft = margin_left_val; + self.view.myLeft = margin_left; } --(CGFloat)margin_right_val +-(CGFloat)margin_right { return self.view.myRight; } --(void)setMargin_right_val:(CGFloat)margin_right_val +-(void)setMargin_right:(CGFloat)margin_right { - self.view.myRight = margin_right_val; + self.view.myRight = margin_right; } --(MyVisibility)visibility_val +-(MyVisibility)visibility { return self.view.visibility; } --(void)setVisibility_val:(MyVisibility)visibility_val +-(void)setVisibility:(MyVisibility)visibility +{ + self.view.visibility = visibility; +} + +@end + +@implementation MyFlexItem +{ + @package + __weak UIView *_view; + MyFlexItemAttrs *_attrs; +} + +@dynamic attrs; + + +-(instancetype)initWithView:(UIView*)view attrs:(MyFlexItemAttrs*)attrs +{ + self = [super init]; + if (self != nil) + { + _view = view; + _attrs = attrs; + _attrs.view = view; + // _attrs = [MyFlexItemAttrs new]; + // _attrs.view = view; + } + return self; +} + +-(MyFlexItemAttrs*)attrs { - self.view.visibility = visibility_val; + return _attrs; } -(MyFlexItem* (^)(NSInteger))order { return ^id(NSInteger val) { - self.order_val = val; + self.attrs.order = val; return self; }; } @@ -97,7 +130,7 @@ -(void)setVisibility_val:(MyVisibility)visibility_val -(MyFlexItem* (^)(CGFloat))flex_grow { return ^id(CGFloat val) { - self.flex_grow_val = val; + self.attrs.flex_grow = val; return self; }; } @@ -105,7 +138,7 @@ -(void)setVisibility_val:(MyVisibility)visibility_val -(MyFlexItem* (^)(CGFloat))flex_shrink { return ^id(CGFloat val) { - self.flex_shrink_val = val; + self.attrs.flex_shrink = val; return self; }; } @@ -113,7 +146,7 @@ -(void)setVisibility_val:(MyVisibility)visibility_val -(MyFlexItem* (^)(CGFloat))flex_basis { return ^id(CGFloat val) { - self.flex_basis_val = val; + self.attrs.flex_basis = val; return self; }; } @@ -121,7 +154,7 @@ -(void)setVisibility_val:(MyVisibility)visibility_val -(MyFlexItem* (^)(MyFlexGravity))align_self { return ^id(MyFlexGravity val) { - self.align_self_val = val; + self.attrs.align_self = val; return self; }; } @@ -142,7 +175,7 @@ -(void)setVisibility_val:(MyVisibility)visibility_val -(MyFlexItem* (^)(CGFloat))width { return ^id(CGFloat val) { - self.width_val = val; + self.attrs.width = val; return self; }; } @@ -166,7 +199,7 @@ -(void)setVisibility_val:(MyVisibility)visibility_val -(MyFlexItem* (^)(CGFloat))height { return ^id(CGFloat val) { - self.height_val = val; + self.attrs.height = val; return self; }; } @@ -241,83 +274,94 @@ -(void)setVisibility_val:(MyVisibility)visibility_val -(void)setSizeConstraintWithSuperview:(UIView*)superview { //宽度设置 - if (self.width_val == MyLayoutSize.wrap) + if (self.attrs.width == MyLayoutSize.wrap) [self.view.widthSize __equalTo:@(MyLayoutSize.wrap)]; - else if (self.width_val == MyLayoutSize.fill) + else if (self.attrs.width == MyLayoutSize.fill) [self.view.widthSize __equalTo:superview.widthSize]; - else if (self.width_val > 0 && self.width_val < 1) - [[self.view.widthSize __equalTo:superview.widthSize] __multiply:self.width_val]; - else if (self.width_val == 0.0) + else if (self.attrs.width > 0 && self.attrs.width < 1) + [[self.view.widthSize __equalTo:superview.widthSize] __multiply:self.attrs.width]; + else if (self.attrs.width == 0.0) [self.view.widthSize __equalTo:nil]; else - [self.view.widthSize __equalTo:@(self.width_val)]; + [self.view.widthSize __equalTo:@(self.attrs.width)]; //高度设置 - if (self.height_val == MyLayoutSize.wrap) + if (self.attrs.height == MyLayoutSize.wrap) [self.view.heightSize __equalTo:@(MyLayoutSize.wrap)]; - else if (self.height_val == MyLayoutSize.fill) + else if (self.attrs.height == MyLayoutSize.fill) [self.view.heightSize __equalTo:superview.heightSize]; - else if (self.height_val > 0 && self.height_val < 1) - [[self.view.heightSize __equalTo:superview.heightSize] __multiply:self.height_val]; - else if (self.height_val == 0.0) + else if (self.attrs.height > 0 && self.attrs.height < 1) + [[self.view.heightSize __equalTo:superview.heightSize] __multiply:self.attrs.height]; + else if (self.attrs.height == 0.0) [self.view.heightSize __equalTo:nil]; else - [self.view.heightSize __equalTo:@(self.height_val)]; + [self.view.heightSize __equalTo:@(self.attrs.height)]; } @end -@implementation MyFlex +@implementation MyFlexAttrs --(instancetype)initWithView:(UIView*)view +-(instancetype)init { - self = [super initWithView:view]; + self = [super init]; if (self != nil) { - _flex_direction_val = MyFlexDirection_Row; - _flex_wrap_val = MyFlexWrap_NoWrap; - _justify_content_val = MyFlexGravity_Flex_Start; - _align_items_val = MyFlexGravity_Stretch; - _align_content_val = MyFlexGravity_Stretch; + _flex_direction = MyFlexDirection_Row; + _flex_wrap = MyFlexWrap_NoWrap; + _justify_content = MyFlexGravity_Flex_Start; + _align_items = MyFlexGravity_Stretch; + _align_content = MyFlexGravity_Stretch; } + return self; } --(UIEdgeInsets)padding_val +-(UIEdgeInsets)padding { return ((MyFlexLayout*)self.view).padding; } --(void)setPadding_val:(UIEdgeInsets)padding_val +-(void)setPadding:(UIEdgeInsets)padding { - ((MyFlexLayout*)self.view).padding = padding_val; + ((MyFlexLayout*)self.view).padding = padding; } --(CGFloat)vert_space_val +-(CGFloat)vert_space { return ((MyFlexLayout*)self.view).subviewVSpace; } --(void)setVert_space_val:(CGFloat)vert_space_val +-(void)setVert_space:(CGFloat)vert_space { - ((MyFlexLayout*)self.view).subviewVSpace = vert_space_val; + ((MyFlexLayout*)self.view).subviewVSpace = vert_space; } --(CGFloat)horz_space_val +-(CGFloat)horz_space { return ((MyFlexLayout*)self.view).subviewHSpace; } --(void)setHorz_space_val:(CGFloat)horz_space_val +-(void)setHorz_space:(CGFloat)horz_space +{ + ((MyFlexLayout*)self.view).subviewHSpace = horz_space; +} + +@end + + +@implementation MyFlex + +-(MyFlexAttrs*)attrs { - ((MyFlexLayout*)self.view).subviewHSpace = horz_space_val; + return (MyFlexAttrs*)_attrs; } -(MyFlex* (^)(MyFlexDirection))flex_direction { return ^id(MyFlexDirection val){ - self.flex_direction_val = val; + self.attrs.flex_direction = val; return self; }; } @@ -325,7 +369,7 @@ -(void)setHorz_space_val:(CGFloat)horz_space_val -(MyFlex* (^)(MyFlexWrap))flex_wrap { return ^id(MyFlexWrap val){ - self.flex_wrap_val = val; + self.attrs.flex_wrap = val; return self; }; } @@ -344,7 +388,7 @@ -(void)setHorz_space_val:(CGFloat)horz_space_val -(MyFlex* (^)(MyFlexGravity))justify_content { return ^id(MyFlexGravity val) { - self.justify_content_val = val; + self.attrs.justify_content = val; return self; }; } @@ -352,7 +396,7 @@ -(void)setHorz_space_val:(CGFloat)horz_space_val -(MyFlex* (^)(MyFlexGravity))align_items { return ^id(MyFlexGravity val) { - self.align_items_val = val; + self.attrs.align_items = val; return self; }; } @@ -360,7 +404,7 @@ -(void)setHorz_space_val:(CGFloat)horz_space_val -(MyFlex* (^)(MyFlexGravity))align_content { return ^id(MyFlexGravity val) { - self.align_content_val = val; + self.attrs.align_content = val; return self; }; } @@ -405,7 +449,7 @@ -(MyFlexItem*)flexItem obj = (MyFlexItem*)objc_getAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM); if (obj == nil) { - obj = [[MyFlexItem alloc] initWithView:self]; + obj = [[MyFlexItem alloc] initWithView:self attrs:[MyFlexItemAttrs new]]; objc_setAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } } @@ -422,7 +466,7 @@ -(instancetype)init self = [super init]; if (self != nil) { - _flex = [[MyFlex alloc] initWithView:self]; + _flex = [[MyFlex alloc] initWithView:self attrs:[MyFlexAttrs new]]; self.orientation = MyOrientation_Vert; //默认row self.arrangedCount = NSIntegerMax; //默认单行 self.isFlex = YES; //满足flexbox的需求。 @@ -436,7 +480,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyFlexLayout *lsc = self.myCurrentSizeClass; //最先设置方向。 - switch (self.flex.flex_direction_val) { + switch (self.flex.attrs.flex_direction) { case MyFlexDirection_Column_Reverse: //column_reverse lsc.orientation = MyOrientation_Horz; lsc.layoutTransform = CGAffineTransformMake(1,0,0,-1,0,0); //垂直翻转 @@ -457,7 +501,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( } //设置换行. - switch (self.flex.flex_wrap_val) { + switch (self.flex.attrs.flex_wrap) { case MyFlexWrap_Wrap: lsc.arrangedCount = 0; break; @@ -478,7 +522,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //按order排序。 [sbs sortWithOptions:NSSortStable usingComparator:^NSComparisonResult(UIView* _Nonnull obj1, UIView* _Nonnull obj2) { - return obj1.flexItem.order_val - obj2.flexItem.order_val; + return obj1.flexItem.attrs.order - obj2.flexItem.attrs.order; }]; for (UIView *sbv in sbs) @@ -487,37 +531,37 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( UIView *sbvsc = sbv.myCurrentSizeClass; //flex_grow,如果子视图有设置grow则父视图的换行不起作用。 - sbvsc.weight = flexItem.flex_grow_val; + sbvsc.weight = flexItem.attrs.flex_grow; //flex_shrink if (lsc.orientation == MyOrientation_Vert) - sbvsc.widthSize.shrink = flexItem.flex_shrink_val != MyFlex_Auto? flexItem.flex_shrink_val:0; + sbvsc.widthSize.shrink = flexItem.attrs.flex_shrink != MyFlex_Auto? flexItem.attrs.flex_shrink:0; else - sbvsc.heightSize.shrink = flexItem.flex_shrink_val != MyFlex_Auto? flexItem.flex_shrink_val:0; + sbvsc.heightSize.shrink = flexItem.attrs.flex_shrink != MyFlex_Auto? flexItem.attrs.flex_shrink:0; [flexItem setSizeConstraintWithSuperview:self]; //基准值设置。 - if (flexItem.flex_basis_val != MyFlex_Auto) + if (flexItem.attrs.flex_basis != MyFlex_Auto) { if (lsc.orientation == MyOrientation_Vert) { - if (flexItem.flex_basis_val < 1 && flexItem.flex_basis_val > 0) - [[sbvsc.widthSize __equalTo:lsc.widthSize] __multiply:flexItem.flex_basis_val]; + if (flexItem.attrs.flex_basis < 1 && flexItem.attrs.flex_basis > 0) + [[sbvsc.widthSize __equalTo:lsc.widthSize] __multiply:flexItem.attrs.flex_basis]; else - [sbvsc.widthSize __equalTo:@(flexItem.flex_basis_val)]; + [sbvsc.widthSize __equalTo:@(flexItem.attrs.flex_basis)]; } else { - if (flexItem.flex_basis_val < 1 && flexItem.flex_basis_val > 0) - [[sbvsc.heightSize __equalTo:lsc.heightSize] __multiply:flexItem.flex_basis_val]; + if (flexItem.attrs.flex_basis < 1 && flexItem.attrs.flex_basis > 0) + [[sbvsc.heightSize __equalTo:lsc.heightSize] __multiply:flexItem.attrs.flex_basis]; else - [sbvsc.heightSize __equalTo:@(flexItem.flex_basis_val)]; + [sbvsc.heightSize __equalTo:@(flexItem.attrs.flex_basis)]; } } //对齐方式设置。 - int align_self = flexItem.align_self_val; + int align_self = flexItem.attrs.align_self; switch (align_self) { case MyFlex_Auto: sbvsc.alignment = MyGravity_None; @@ -545,7 +589,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //设置主轴的水平对齐和拉伸 MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = lsc.gravity & MyGravity_Vert_Mask; - switch (self.flex.justify_content_val) { + switch (self.flex.attrs.justify_content) { case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Vert) lsc.gravity = MyGravity_Horz_Trailing | vertGravity; @@ -582,7 +626,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //次轴的对齐处理。 MyGravity vertArrangedGravity = lsc.arrangedGravity & MyGravity_Horz_Mask; MyGravity horzArrangedGravity = lsc.arrangedGravity & MyGravity_Vert_Mask; - switch (self.flex.align_items_val) { + switch (self.flex.attrs.align_items) { case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Vert) lsc.arrangedGravity = MyGravity_Vert_Bottom | horzArrangedGravity; @@ -619,7 +663,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //多行下的整体停靠处理。 vertGravity = lsc.gravity & MyGravity_Horz_Mask; horzGravity = lsc.gravity & MyGravity_Vert_Mask; - switch (self.flex.align_content_val) { + switch (self.flex.attrs.align_content) { case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Horz) lsc.gravity = MyGravity_Horz_Trailing | vertGravity; diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 5caf8dd..5fda8a1 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -967,6 +967,18 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont CGFloat lineMaxWidth = 0.0; //某一行的最宽值。 CGFloat maxWidth = 0.0; //所有行中最宽的值。 + + //limitedSelfWidth是用来限制子视图换行的宽度,默认是selfSize.width + //但是一种特殊情况就是布局视图宽度自适应,但是设置了最宽宽度的情况。 + //这种情况下当子视图超过最宽宽度时还是需要进行换行处理。 + //而如果没有设置最宽宽度的话那么默认限制的宽度就是最大值CGFLOAT_MAX + CGFloat limitedSelfWidth = selfSize.width; + if (lsc.widthSizeInner.dimeWrapVal) + { + limitedSelfWidth = [self myGetBoundLimitMeasure:lsc.widthSizeInner.uBoundValInner sbv:self dimeType:lsc.widthSizeInner.dime sbvSize:selfSize selfLayoutSize:self.superview.bounds.size isUBound:YES]; + limitedSelfWidth = _myCGFloatMin(limitedSelfWidth, CGFLOAT_MAX); + } + if (lsc.autoArrange) { //计算出每个子视图的宽度。 @@ -1069,9 +1081,11 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont place += horzSpace; place += paddingTrailing; - //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。 - if (!lsc.widthSizeInner.dimeWrapVal && (place - selfSize.width > 0.0001)) + //sbv所占据的宽度超过了布局视图的限制宽度时需要换行。 + if (place - limitedSelfWidth > 0.0001) { + selfSize.width = limitedSelfWidth; + //保存行首子视图的索引 [lineFirstSubviewIndexSet addIndex:i - itemIndex]; @@ -1107,6 +1121,16 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont //最后一行的行首索引 [lineFirstSubviewIndexSet addIndex:i - itemIndex]; + //在宽度为自适应时,如果没有设置最大宽度限制,那么就一定是单行,因此宽度就是子视图的总和。 + //如果设置了最大宽度限制时,那就要区分最后一行是单行还是多行,所以我们取限宽和当前计算出的宽度的最小值,并且再取selfSize.width和前面比较结果的最大值。 + if (lsc.widthSizeInner.dimeWrapVal) + { + if (limitedSelfWidth == CGFLOAT_MAX) + selfSize.width = _myCGFloatMax(xPos + paddingTrailing, [self myGetBoundLimitMeasure:lsc.widthSizeInner.uBoundValInner sbv:self dimeType:lsc.widthSizeInner.dime sbvSize:selfSize selfLayoutSize:self.superview.bounds.size isUBound:NO]); + else + selfSize.width = _myCGFloatMax(_myCGFloatMin(xPos + paddingTrailing, limitedSelfWidth), selfSize.width); + } + [self myVertLayout:lsc adjustSingleline:lineIndex lineSpareWidth:selfSize.width - paddingTrailing - xPos lineTotalWeight:lineTotalWeight horzGravity:horzGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; xPos = paddingLeading; @@ -1139,8 +1163,6 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont rect.size.height = 0; } - - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) @@ -1150,13 +1172,13 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont } //计算xPos的值加上leadingSpace + rect.size.width + trailingSpace 的值要小于整体的宽度。 - maxWidth= xPos + leadingSpace + rect.size.width + trailingSpace; + maxWidth = xPos + leadingSpace + rect.size.width + trailingSpace; if (itemIndex != 0) maxWidth += horzSpace; maxWidth += paddingTrailing; NSUInteger lineFirstIndex = [lineFirstSubviewIndexSet indexLessThanOrEqualToIndex:i]; - if (!lsc.widthSizeInner.dimeWrapVal && oldLineFirstIndex != lineFirstIndex) + if (oldLineFirstIndex != lineFirstIndex) { oldLineFirstIndex = lineFirstIndex; @@ -1166,7 +1188,6 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont [self myVertLayout:lsc calcSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; - lineMaxHeight = 0.0; lineMaxWidth = 0.0; itemIndex = 0; @@ -1197,10 +1218,10 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont //内容填充约束布局的宽度包裹计算。 if (lsc.widthSizeInner.dimeWrapVal) - selfSize.width = maxWidth; + selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:maxWidth sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; if (lsc.heightSizeInner.dimeWrapVal) - selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:yPos sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:yPos sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; NSInteger arranges = lineFirstSubviewIndexSet.count; //根据flex规则:如果只有一行则整个高度都作为子视图的拉伸和停靠区域。 @@ -1846,6 +1867,17 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont CGFloat lineMaxHeight = 0.0; //某一列的最高值 CGFloat maxHeight = 0.0; //所有列的最宽行 + //limitedSelfHeight是用来限制子视图换行的高度,默认是selfSize.height + //但是一种特殊情况就是布局视图高度自适应,但是设置了最高高度的情况。 + //这种情况下当子视图超过最高高度时还是需要进行换行处理。 + //而如果没有设置最高高度的话那么默认限制的高度就是最大值CGFLOAT_MAX + CGFloat limitedSelfHeight = selfSize.height; + if (lsc.heightSizeInner.dimeWrapVal) + { + limitedSelfHeight = [self myGetBoundLimitMeasure:lsc.heightSizeInner.uBoundValInner sbv:self dimeType:lsc.heightSizeInner.dime sbvSize:selfSize selfLayoutSize:self.superview.bounds.size isUBound:YES]; + limitedSelfHeight = _myCGFloatMin(limitedSelfHeight, CGFLOAT_MAX); + } + if (lsc.autoArrange) { //计算出每个子视图的宽度。 @@ -1956,9 +1988,11 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont place += vertSpace; place += paddingBottom; - //sbv所占据的宽度要超过了视图的整体宽度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的宽度和布局视图保持一致。 - if (!lsc.heightSizeInner.dimeWrapVal && (place - selfSize.height > 0.0001)) + //sbv所占据的高度要超过了视图的整体高度,因此需要换行。但是如果arrangedIndex为0的话表示这个控件的整行的高度和布局视图保持一致。 + if (place - limitedSelfHeight > 0.0001) { + selfSize.height = limitedSelfHeight; + [lineFirstSubviewIndexSet addIndex:i - itemIndex]; //拉伸以及调整行内子视图的高度。 @@ -1994,6 +2028,16 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont //最后一行的行首索引 [lineFirstSubviewIndexSet addIndex:i - itemIndex]; + //在高度为自适应时,如果没有设置最大高度限制,那么就一定是单行,因此高度就是子视图的总和。 + //如果设置了最大高度限制时,那就要区分最后一行是单行还是多行,所以我们取限高和当前计算出的高度的最小值,并且再取selfSize.height和前面比较结果的最大值。 + if (lsc.heightSizeInner.dimeWrapVal) + { + if (limitedSelfHeight == CGFLOAT_MAX) + selfSize.height = _myCGFloatMax(yPos + paddingBottom, [self myGetBoundLimitMeasure:lsc.heightSizeInner.uBoundValInner sbv:self dimeType:lsc.heightSizeInner.dime sbvSize:selfSize selfLayoutSize:self.superview.bounds.size isUBound:NO]); + else + selfSize.height = _myCGFloatMax(_myCGFloatMin(yPos + paddingBottom, limitedSelfHeight), selfSize.height); + } + [self myHorzLayout:lsc adjustSingleline:lineIndex lineSpareHeight:selfSize.height - paddingBottom - yPos lineTotalWeight:lineTotalWeight vertGravity:vertGravity sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; @@ -2031,7 +2075,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont maxHeight += paddingBottom; NSUInteger lineFirstIndex = [lineFirstSubviewIndexSet indexLessThanOrEqualToIndex:i]; - if (!lsc.heightSizeInner.dimeWrapVal && oldLineFirstIndex != lineFirstIndex) + if (oldLineFirstIndex != lineFirstIndex) { oldLineFirstIndex = lineFirstIndex; @@ -2070,8 +2114,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont xPos += lineMaxWidth + paddingTrailing; if (lsc.heightSizeInner.dimeWrapVal) - selfSize.height = maxHeight; - + selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:maxHeight sbvSize:selfSize selfLayoutSize:self.superview.bounds.size];; if (lsc.widthSizeInner.dimeWrapVal) selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:xPos sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; @@ -2523,7 +2566,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG lineMaxHeight = yPos - paddingTop; if (_myCGFloatLess(maxHeight, yPos)) - maxHeight = yPos; + maxHeight = yPos; //不是最后一行以及非自动排列时才添加布局视图设置的行间距。自动排列的情况下上面已经有添加行间距了。 if (itemIndex != (arrangedCount - 1) && !autoArrange) yPos += vertSpace; diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index a0f8bf7..ae290e4 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -77,6 +77,8 @@ -(CGFloat)mySubview:(MyViewSizeClass*)sbvsc wrapHeightSizeFits:(CGFloat)width; +-(CGFloat)myGetBoundLimitMeasure:(MyLayoutSize*)boundDime sbv:(UIView*)sbv dimeType:(MyGravity)dimeType sbvSize:(CGSize)sbvSize selfLayoutSize:(CGSize)selfLayoutSize isUBound:(BOOL)isUBound; + -(CGFloat)myValidMeasure:(MyLayoutSize*)dime sbv:(UIView*)sbv calcSize:(CGFloat)calcSize sbvSize:(CGSize)sbvSize selfLayoutSize:(CGSize)selfLayoutSize; -(CGFloat)myValidMargin:(MyLayoutPos*)pos sbv:(UIView*)sbv calcPos:(CGFloat)calcPos selfLayoutSize:(CGSize)selfLayoutSize; diff --git a/MyLayoutDemo/FLXTest1ViewController.m b/MyLayoutDemo/FLXTest1ViewController.m index dccdcd2..54888ab 100644 --- a/MyLayoutDemo/FLXTest1ViewController.m +++ b/MyLayoutDemo/FLXTest1ViewController.m @@ -234,7 +234,7 @@ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { -(void)updateStyleDesc { NSString *strFlexDirection = @""; - switch (self.contentLayout.flex.flex_direction_val) { + switch (self.contentLayout.flex.attrs.flex_direction) { case MyFlexDirection_Row: strFlexDirection =@"row;"; break; @@ -252,7 +252,7 @@ -(void)updateStyleDesc } NSString *strFlexWrap = @""; - switch (self.contentLayout.flex.flex_wrap_val) { + switch (self.contentLayout.flex.attrs.flex_wrap) { case MyFlexWrap_NoWrap: strFlexWrap = @"nowrap;"; break; @@ -267,7 +267,7 @@ -(void)updateStyleDesc } NSString *strJustifyContent = @""; - switch (self.contentLayout.flex.justify_content_val) { + switch (self.contentLayout.flex.attrs.justify_content) { case MyFlexGravity_Flex_Start: strJustifyContent = @"flex-start;"; break; @@ -287,7 +287,7 @@ -(void)updateStyleDesc } NSString *strAlignItems = @""; - switch (self.contentLayout.flex.align_items_val) { + switch (self.contentLayout.flex.attrs.align_items) { case MyFlexGravity_Flex_End: strAlignItems = @"flex-end;"; break; @@ -307,7 +307,7 @@ -(void)updateStyleDesc } NSString *strAlignContent = @""; - switch (self.contentLayout.flex.align_content_val) { + switch (self.contentLayout.flex.attrs.align_content) { case MyFlexGravity_Flex_End: strAlignContent = @"flex-end;"; break; @@ -520,40 +520,40 @@ -(void)editFlexItem:(UIView*)itemView if (itemView != nil) { - if (itemView.flexItem.width_val == MyLayoutSize.wrap) + if (itemView.flexItem.attrs.width == MyLayoutSize.wrap) widthTextField.text = @"wrap"; - else if (itemView.flexItem.width_val == MyLayoutSize.fill) + else if (itemView.flexItem.attrs.width == MyLayoutSize.fill) widthTextField.text = @"fill"; - else if (itemView.flexItem.width_val != 0) - widthTextField.text = [@(itemView.flexItem.width_val) stringValue]; + else if (itemView.flexItem.attrs.width != 0) + widthTextField.text = [@(itemView.flexItem.attrs.width) stringValue]; else widthTextField.text = @""; - if (itemView.flexItem.height_val == MyLayoutSize.wrap) + if (itemView.flexItem.attrs.height == MyLayoutSize.wrap) heightTextField.text = @"wrap"; - else if (itemView.flexItem.height_val == MyLayoutSize.fill) + else if (itemView.flexItem.attrs.height == MyLayoutSize.fill) heightTextField.text = @"fill"; - else if (itemView.flexItem.height_val != 0) - heightTextField.text = [@(itemView.flexItem.height_val) stringValue]; + else if (itemView.flexItem.attrs.height != 0) + heightTextField.text = [@(itemView.flexItem.attrs.height) stringValue]; else heightTextField.text = @""; - if (itemView.flexItem.order_val != 0) - orderTextField.text = [@(itemView.flexItem.order_val) stringValue]; + if (itemView.flexItem.attrs.order != 0) + orderTextField.text = [@(itemView.flexItem.attrs.order) stringValue]; - if (itemView.flexItem.flex_grow_val != 0) - flex_growTextField.text = [@(itemView.flexItem.flex_grow_val) stringValue]; + if (itemView.flexItem.attrs.flex_grow != 0) + flex_growTextField.text = [@(itemView.flexItem.attrs.flex_grow) stringValue]; - if (itemView.flexItem.flex_shrink_val != 1) - flex_shrinkTextField.text = [@(itemView.flexItem.flex_shrink_val) stringValue]; + if (itemView.flexItem.attrs.flex_shrink != 1) + flex_shrinkTextField.text = [@(itemView.flexItem.attrs.flex_shrink) stringValue]; - if (itemView.flexItem.flex_basis_val != MyFlex_Auto) - flex_basisTextField.text = [@(itemView.flexItem.flex_basis_val) stringValue]; + if (itemView.flexItem.attrs.flex_basis != MyFlex_Auto) + flex_basisTextField.text = [@(itemView.flexItem.attrs.flex_basis) stringValue]; - switch (itemView.flexItem.align_self_val) { + switch (itemView.flexItem.attrs.align_self) { case MyFlexGravity_Flex_Start: align_selfTextField.text = @"flex-start"; break; @@ -590,7 +590,7 @@ -(IBAction)handleFlexLayoutAttributeChange:(UISegmentedControl*)sender case 0: { self.flex_directionSeg.flexItem.visibility(MyVisibility_Visible); - switch (self.contentLayout.flex.flex_direction_val) { + switch (self.contentLayout.flex.attrs.flex_direction) { case MyFlexDirection_Row: self.flex_directionSeg.selectedSegmentIndex = 0; break; @@ -610,7 +610,7 @@ -(IBAction)handleFlexLayoutAttributeChange:(UISegmentedControl*)sender case 1: { self.flex_wrapSeg.flexItem.visibility(MyVisibility_Visible); - switch (self.contentLayout.flex.flex_wrap_val) { + switch (self.contentLayout.flex.attrs.flex_wrap) { case MyFlexWrap_Wrap: self.flex_wrapSeg.selectedSegmentIndex = 1; break; @@ -628,7 +628,7 @@ -(IBAction)handleFlexLayoutAttributeChange:(UISegmentedControl*)sender case 2: { self.justify_contentSeg.flexItem.visibility(MyVisibility_Visible); - switch (self.contentLayout.flex.justify_content_val) { + switch (self.contentLayout.flex.attrs.justify_content) { case MyFlexGravity_Flex_Start: self.justify_contentSeg.selectedSegmentIndex = 0; break; @@ -651,7 +651,7 @@ -(IBAction)handleFlexLayoutAttributeChange:(UISegmentedControl*)sender case 3: { self.align_itemsSeg.flexItem.visibility(MyVisibility_Visible); - switch (self.contentLayout.flex.align_items_val) { + switch (self.contentLayout.flex.attrs.align_items) { case MyFlexGravity_Flex_Start: self.align_itemsSeg.selectedSegmentIndex = 0; break; @@ -675,7 +675,7 @@ -(IBAction)handleFlexLayoutAttributeChange:(UISegmentedControl*)sender case 4: { self.align_contentSeg.flexItem.visibility(MyVisibility_Visible); - switch (self.contentLayout.flex.align_content_val) { + switch (self.contentLayout.flex.attrs.align_content) { case MyFlexGravity_Flex_Start: self.align_contentSeg.selectedSegmentIndex = 0; break; @@ -890,56 +890,57 @@ -(IBAction)handleSaveItem:(UIButton*)sender NSString *widthStr = widthTextField.text; if ([widthStr isEqualToString:@"wrap"]) - itemView.flexItem.width_val = MyLayoutSize.wrap; + itemView.flexItem.attrs.width = MyLayoutSize.wrap; else if ([widthStr isEqualToString:@"fill"]) - itemView.flexItem.width_val = MyLayoutSize.fill; + itemView.flexItem.attrs.width = MyLayoutSize.fill; else - itemView.flexItem.width_val = widthStr.doubleValue; + itemView.flexItem.attrs.width = widthStr.doubleValue; NSString *heightStr = heightTextField.text; if ([heightStr isEqualToString:@"wrap"]) - itemView.flexItem.height_val = MyLayoutSize.wrap; + itemView.flexItem.attrs.height = MyLayoutSize.wrap; else if ([heightStr isEqualToString:@"fill"]) - itemView.flexItem.height_val = MyLayoutSize.fill; + itemView.flexItem.attrs.height = MyLayoutSize.fill; else - itemView.flexItem.height_val = heightStr.doubleValue; + itemView.flexItem.attrs.height = heightStr.doubleValue; [itemView setTitle:orderTextField.text forState:UIControlStateNormal]; - itemView.flexItem.order_val = orderTextField.text.integerValue; + itemView.flexItem.attrs.order = orderTextField.text.integerValue; - itemView.flexItem.flex_grow_val = flex_growTextField.text.doubleValue; + itemView.flexItem.attrs.flex_grow = flex_growTextField.text.doubleValue; if (flex_shrinkTextField.text.length > 0) - itemView.flexItem.flex_shrink_val = flex_shrinkTextField.text.doubleValue; + itemView.flexItem.attrs.flex_shrink = flex_shrinkTextField.text.doubleValue; else - itemView.flexItem.flex_shrink_val = 1; + itemView.flexItem.attrs.flex_shrink = 1; if (flex_basisTextField.text.length > 0) - itemView.flexItem.flex_basis_val = flex_basisTextField.text.doubleValue; + itemView.flexItem.attrs.flex_basis = flex_basisTextField.text.doubleValue; else - itemView.flexItem.flex_basis_val = MyFlex_Auto; + itemView.flexItem.attrs.flex_basis = MyFlex_Auto; if (align_selfTextField.text.length > 0) { if ([align_selfTextField.text isEqualToString:@"flex-start"]) - itemView.flexItem.align_self_val = MyFlexGravity_Flex_Start; + itemView.flexItem.attrs.align_self = MyFlexGravity_Flex_Start; else if ([align_selfTextField.text isEqualToString:@"flex-end"]) - itemView.flexItem.align_self_val = MyFlexGravity_Flex_End; + itemView.flexItem.attrs.align_self = MyFlexGravity_Flex_End; else if ([align_selfTextField.text isEqualToString:@"center"]) - itemView.flexItem.align_self_val = MyFlexGravity_Center; + itemView.flexItem.attrs.align_self = MyFlexGravity_Center; else if ([align_selfTextField.text isEqualToString:@"baseline"]) - itemView.flexItem.align_self_val = MyFlexGravity_Baseline; + itemView.flexItem.attrs.align_self = MyFlexGravity_Baseline; else if ([align_selfTextField.text isEqualToString:@"stretch"]) - itemView.flexItem.align_self_val = MyFlexGravity_Stretch; + itemView.flexItem.attrs.align_self = MyFlexGravity_Stretch; else - itemView.flexItem.align_self_val = MyFlex_Auto; + itemView.flexItem.attrs.align_self = MyFlex_Auto; } else { - itemView.flexItem.align_self_val = MyFlex_Auto; + itemView.flexItem.attrs.align_self = MyFlex_Auto; } + //销毁对话框。 [sender.superview removeFromSuperview]; From b1173b2e8259202fd133f9dfc2e65897b6fd6507 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Tue, 12 Nov 2019 09:32:45 +0800 Subject: [PATCH 079/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlexLayout.h | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/MyLayout/Lib/MyFlexLayout.h b/MyLayout/Lib/MyFlexLayout.h index 3f71de6..582689e 100644 --- a/MyLayout/Lib/MyFlexLayout.h +++ b/MyLayout/Lib/MyFlexLayout.h @@ -37,7 +37,8 @@ typedef enum : int { extern const int MyFlex_Auto; -//条目的属性,用于设置和获取。 + +//条目的属性,用于条目视图的属性设置和获取。 @interface MyFlexItemAttrs:NSObject @property(nonatomic, assign) NSInteger order; @@ -96,15 +97,19 @@ extern const int MyFlex_Auto; -(MyFlexItem* (^)(CGFloat))margin_left; -(MyFlexItem* (^)(CGFloat))margin_right; -(MyFlexItem* (^)(CGFloat))margin; + //是否可见 -(MyFlexItem* (^)(MyVisibility))visibility; + //添加到父视图中 -(__kindof UIView* (^)(UIView*))addTo; @end -//条目的属性,用于设置和获取。 + + +//布局的属性,用于布局视图的属性设置和获取。 @interface MyFlexAttrs:MyFlexItemAttrs @property(nonatomic, assign) MyFlexDirection flex_direction; @@ -112,6 +117,9 @@ extern const int MyFlex_Auto; @property(nonatomic, assign) MyFlexGravity justify_content; @property(nonatomic, assign) MyFlexGravity align_items; @property(nonatomic, assign) MyFlexGravity align_content; +@property(nonatomic, assign) UIEdgeInsets padding; +@property(nonatomic, assign) CGFloat vert_space; +@property(nonatomic, assign) CGFloat horz_space; @end @@ -127,11 +135,6 @@ extern const int MyFlex_Auto; */ @interface MyFlex:MyFlexItem -@property(nonatomic, assign) UIEdgeInsets padding_val; -@property(nonatomic, assign) CGFloat vert_space_val; -@property(nonatomic, assign) CGFloat horz_space_val; - - //方向设置 -(MyFlex* (^)(MyFlexDirection))flex_direction; //换行设置 @@ -152,6 +155,11 @@ extern const int MyFlex_Auto; @end + + + + + //条目视图在应用flexbox时的分类扩展,只有MyFlexLayout中的子视图才有用。 @interface UIView(MyFlexLayout) @@ -163,7 +171,7 @@ extern const int MyFlex_Auto; /* * 弹性布局是为了兼容flexbox语法而建立了一个布局,它是从MyFlowLayout派生。在MyFlowLayout中也是支持类似flexbox的一些特性的 - * 但是它的属性和flexbox不兼容和一致,因此提供一个新的类MyFlexLayout来完全支持flexbox. + * 因为它的属性和flexbox不兼容,所以提供一个新的类MyFlexLayout来完全支持flexbox. */ @interface MyFlexLayout:MyFlowLayout From a3f027a62db88152a43cf8fd0dd1d121e3c0155f Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Tue, 12 Nov 2019 20:40:09 +0800 Subject: [PATCH 080/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayoutTests/MyFlowLayoutTestCase.m | 120 +++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index ba508bf..bd925fd 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -913,4 +913,124 @@ -(void)testRightAndBottomGravity } } +-(void)testFlex1 +{ + { + MyFlexLayout *flexLayout = MyFlexLayout.new.flex + .align_items(MyFlexGravity_Center) + .justify_content(MyFlexGravity_Center) + .margin(0) + .view; + + flexLayout.frame = CGRectMake(0, 0, 300, 300); + flexLayout.backgroundColor = [UIColor redColor]; + + + MyFlexLayout *contentLayout = MyFlexLayout.new.flex + .flex_wrap(MyFlexWrap_Wrap) + .width(MyLayoutSize.wrap) + .max_width(100) + .height(MyLayoutSize.wrap) + .addTo(flexLayout); + + contentLayout.backgroundColor = [UIColor greenColor]; + + UILabel *lb1 = UILabel.new.flexItem + .width(30) + .height(30) + .addTo(contentLayout); + + lb1.backgroundColor = [UIColor blueColor]; + + UILabel *lb2 = UILabel.new.flexItem + .width(40) + .height(40) + .addTo(contentLayout); + + lb2.backgroundColor = [UIColor yellowColor]; + + UILabel *lb3 = UILabel.new.flexItem + .width(50) + .height(50) + .addTo(contentLayout); + + lb3.backgroundColor = [UIColor grayColor]; + + [flexLayout layoutIfNeeded]; + [contentLayout layoutIfNeeded]; + + MyRectAssert(contentLayout, CGRectMake((300-100)/2.0, (300-90)/2.0, 100, 90)); + MyRectAssert(lb3, CGRectMake(0, 40, 50, 50)); + + contentLayout.flex.height(30); + [flexLayout setNeedsLayout]; + [contentLayout setNeedsLayout]; + [contentLayout layoutIfNeeded]; + [flexLayout layoutIfNeeded]; + + MyRectAssert(contentLayout, CGRectMake((300-100)/2.0, (300-30)/2.0, 100, 30)); + MyRectAssert(lb3, CGRectMake(0, 40, 50, 50)); + + } + + { + MyFlexLayout *flexLayout = MyFlexLayout.new.flex + .align_items(MyFlexGravity_Center) + .justify_content(MyFlexGravity_Center) + .margin(0) + .view; + + flexLayout.frame = CGRectMake(0, 0, 300, 300); + flexLayout.backgroundColor = [UIColor redColor]; + + + MyFlexLayout *contentLayout = MyFlexLayout.new.flex + .flex_wrap(MyFlexWrap_Wrap) + .flex_direction(MyFlexDirection_Column) + .width(MyLayoutSize.wrap) + .max_height(100) + .height(MyLayoutSize.wrap) + .addTo(flexLayout); + + contentLayout.backgroundColor = [UIColor greenColor]; + + UILabel *lb1 = UILabel.new.flexItem + .width(30) + .height(30) + .addTo(contentLayout); + + lb1.backgroundColor = [UIColor blueColor]; + + UILabel *lb2 = UILabel.new.flexItem + .width(40) + .height(40) + .addTo(contentLayout); + + lb2.backgroundColor = [UIColor yellowColor]; + + UILabel *lb3 = UILabel.new.flexItem + .width(50) + .height(50) + .addTo(contentLayout); + + lb3.backgroundColor = [UIColor grayColor]; + + [flexLayout layoutIfNeeded]; + [contentLayout layoutIfNeeded]; + + MyRectAssert(contentLayout, CGRectMake((300-90)/2.0,(300-100)/2.0,90,100)); + MyRectAssert(lb3, CGRectMake(40, 0, 50, 50)); + + contentLayout.flex.width(30); + [flexLayout setNeedsLayout]; + [contentLayout setNeedsLayout]; + [contentLayout layoutIfNeeded]; + [flexLayout layoutIfNeeded]; + + MyRectAssert(contentLayout, CGRectMake((300-30)/2.0, (300-100)/2.0, 30, 100)); + MyRectAssert(lb3, CGRectMake(40, 0, 50, 50)); + } + +} + @end From f0c474276cff9ee825edbbdbcc70d6dc95c04971 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Wed, 13 Nov 2019 16:51:03 +0800 Subject: [PATCH 081/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- MyLayout/Lib/MyBaseLayout.m | 4 +- MyLayout/Lib/MyFlowLayout.m | 134 +++++++++++++++++--------- MyLayout/Lib/MyLinearLayout.m | 8 +- MyLayoutTests/MyFrameLayoutTestCase.m | 16 +++ 5 files changed, 113 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f7b006..a705ee9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,7 +65,7 @@ 4. 修复了布局视图的尺寸自适应能力和AutoLayout结合后,布局视图添加删除子视图后要手动代码进行布局视图尺寸自适应的刷新问题。[issue#95](https://github.com/youngsoft/MyLinearLayout/issues/95) 5. 修复相对布局子视图隐藏时,其他依赖这个子视图的子视图的位置和尺寸不正确更新的问题。 6. 修复UIImageView的宽度固定高度自适应的问题。 -7. 支持通过对isLayouting进行KVO监听来实现布局的通知处理机制,我们可以通过KVO布局视图的isLayouting属性来或者布局完成后子视图的frame以及布局视图的frame值了。 +7. 支持通过对isMyLayouting进行KVO监听来实现布局的通知处理机制,我们可以通过KVO布局视图的isMyLayouting属性来或者布局完成后子视图的frame以及布局视图的frame值了。 8. 下列方法或属性名被列为过期,并推荐使用新的方法名和属性名: ``` diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index cc9240c..6eea760 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -3390,7 +3390,7 @@ -(void)myLayout:(MyLayoutViewSizeClass*)lsc } //宽度不依赖布局并且没有同时设置左右边距则参与最大宽度计算。 - if (sbvsc.widthSizeInner.dimeVal != nil && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner)) + if (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) { if (_myCGFloatLess(pMaxWrapSize->width, sbvmyFrame.width + sbvsc.leadingPosInner.absVal + sbvsc.centerXPosInner.absVal + sbvsc.trailingPosInner.absVal + paddingLeading + paddingTrailing)) @@ -3416,7 +3416,7 @@ -(void)myLayout:(MyLayoutViewSizeClass*)lsc } //高度不依赖布局并且没有同时设置上下边距则参与最大高度计算。 - if (sbvsc.heightSizeInner.dimeVal != nil && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner)) + if (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) { if (_myCGFloatLess(pMaxWrapSize->height, sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.centerYPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom)) pMaxWrapSize->height = sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.centerYPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom; diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 5fda8a1..1a5abbb 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -1353,7 +1353,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG CGFloat yPos = paddingTop; CGFloat lineMaxHeight = 0.0; //某一行的最高值。 CGFloat lineMaxWidth = 0.0; //某一行的最宽值 - CGFloat maxWidth = paddingLeading; //全部行的最大宽度 + CGFloat maxWidth = 0.0; //全部行的最大宽度 CGFloat maxHeight = paddingTop; //最大的高度 #if TARGET_OS_IOS @@ -1371,7 +1371,6 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG if (lsc.pagedCount > 0 && self.superview != nil) { NSInteger rows = lsc.pagedCount / arrangedCount; //每页的行数。 - //对于垂直流式布局来说,要求要有明确的宽度。因此如果我们启用了分页又设置了宽度包裹时则我们的分页是从左到右的排列。否则分页是从上到下的排列。 if (lsc.widthSizeInner.dimeWrapVal) { @@ -1399,53 +1398,70 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG else pagingItemHeight = (selfSize.height - paddingVert - (rows - 1) * vertSpace) / rows; } - } - } + //在宽度自适应的情况下有可能有最小宽度的约束。 + if (lsc.widthSizeInner.dimeWrapVal) + selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:0 sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + //平均宽度,当布局的gravity设置为Horz_Fill时指定这个平均宽度值。 CGFloat averageWidth = 0.0; if (horzGravity == MyGravity_Horz_Fill) + { averageWidth = (selfSize.width - paddingHorz - (arrangedCount - 1) * horzSpace) / arrangedCount; + if (averageWidth < 0.0) + averageWidth = 0.0; + } - //行内子视图的索引号 - NSInteger itemIndex = 0; - NSInteger i = 0; + //得到行数 + NSInteger arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); + CGFloat lineTotalFixedWidths[arranges]; //所有行的固定宽度。 + CGFloat lineTotalShrinks[arranges]; //所有行的总压缩 + CGFloat lineTotalWeights[arranges]; //所有行的总比重 + + CGFloat lineTotalFixedWidth = 0.0; CGFloat lineTotalShrink = 0.0; //某一行的总压缩比重。 CGFloat lineTotalWeight = 0.0; - CGFloat lineTotalFixedWidth = 0.0; + BOOL hasTotalWeight = NO; //是否有比重计算,这个标志用于加快处理速度 + BOOL hasTotalShrink = NO; //是否有压缩计算,这个标志用于加快处理速度 + //行内子视图的索引号 + NSInteger i = 0; + NSInteger itemIndex = 0; + NSInteger lineIndex = 0; //行索引 for (; i < sbs.count; i++) { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; + CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; + CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; + CGFloat topSpace = sbvsc.topPosInner.absVal; + CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; + CGRect rect = sbvmyFrame.frame; + if (itemIndex >= arrangedCount) { - itemIndex = 0; - - if (lineTotalWeight != 0 && horzGravity != MyGravity_Horz_Fill) - { - [self myVertLayout:lsc calcSinglelineWeight:lineTotalWeight lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount inSelfSize:selfSize]; - } + lineTotalFixedWidths[lineIndex] = lineTotalFixedWidth; + lineTotalWeights[lineIndex] = lineTotalWeight; + lineTotalShrinks[lineIndex] = lineTotalShrink; - if (lineTotalShrink != 0 && horzGravity != MyGravity_Horz_Fill) - { - [self myVertLayout:lsc calcSinglelineShrink:lineTotalShrink lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount inSelfSize:selfSize]; - } + if(!hasTotalWeight) + hasTotalWeight = lineTotalWeight > 0; + if (!hasTotalShrink) + hasTotalShrink = lineTotalShrink > 0; + + if (lineTotalFixedWidth > maxWidth) + maxWidth = lineTotalFixedWidth; - lineTotalWeight = 0.0; lineTotalFixedWidth = 0.0; + lineTotalWeight = 0.0; lineTotalShrink = 0.0; + itemIndex = 0; + lineIndex++; } - CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; - CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; - CGFloat topSpace = sbvsc.topPosInner.absVal; - CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; - CGRect rect = sbvmyFrame.frame; - //计算每行的宽度。 if (averageWidth != 0.0) { @@ -1482,9 +1498,11 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG rect.size.width = 0.0; } - rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; - + sbvmyFrame.frame = rect; + itemIndex++; + + //计算总拉伸比。 if (sbvsc.weight != 0.0) lineTotalWeight += sbvsc.weight; @@ -1494,29 +1512,59 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG lineTotalFixedWidth += rect.size.width; lineTotalFixedWidth += leadingSpace + trailingSpace; - if (itemIndex != (arrangedCount - 1)) + if (itemIndex < arrangedCount) lineTotalFixedWidth += horzSpace; - - sbvmyFrame.frame = rect; - itemIndex++; - } //最后一行。 - if (itemIndex < arrangedCount) - lineTotalFixedWidth -= horzSpace; - - if (lineTotalWeight != 0.0 && horzGravity != MyGravity_Horz_Fill) + if (arranges > 0) { - [self myVertLayout:lsc calcSinglelineWeight:lineTotalWeight lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; + if (itemIndex < arrangedCount) + lineTotalFixedWidth -= horzSpace; + + lineTotalWeights[lineIndex] = lineTotalWeight; + lineTotalShrinks[lineIndex] = lineTotalShrink; + lineTotalFixedWidths[lineIndex] = lineTotalFixedWidth; + + if(!hasTotalWeight) + hasTotalWeight = lineTotalWeight > 0; + if (!hasTotalShrink) + hasTotalShrink = lineTotalShrink > 0; + + if (lineTotalFixedWidth > maxWidth) + maxWidth = lineTotalFixedWidth; } - //如果有压缩子视图的处理则需要压缩子视图。 - if (lineTotalShrink != 0.0 && horzGravity != MyGravity_Horz_Fill) + maxWidth += paddingLeading + paddingTrailing; + if (lsc.widthSizeInner.dimeWrapVal) + selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:maxWidth sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + + //进行所有行的宽度拉伸和压缩。 + if (horzGravity != MyGravity_Horz_Fill && (hasTotalShrink || hasTotalWeight)) { - [self myVertLayout:lsc calcSinglelineShrink:lineTotalShrink lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; + NSInteger remainedCount = sbs.count; + lineIndex = 0; + for (;lineIndex < arranges; lineIndex++) + { + lineTotalFixedWidth = lineTotalFixedWidths[lineIndex]; + lineTotalWeight = lineTotalWeights[lineIndex]; + lineTotalShrink = lineTotalShrinks[lineIndex]; + + if (lineTotalWeight != 0) + { + [self myVertLayout:lsc calcSinglelineWeight:lineTotalWeight lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:lineIndex*arrangedCount count:MIN(arrangedCount,remainedCount) inSelfSize:selfSize]; + } + + if (lineTotalShrink != 0) + { + [self myVertLayout:lsc calcSinglelineShrink:lineTotalShrink lineSpareWidth:selfSize.width - paddingHorz - lineTotalFixedWidth sbs:sbs startItemIndex:lineIndex*arrangedCount count:MIN(arrangedCount,remainedCount) inSelfSize:selfSize]; + } + + remainedCount -= arrangedCount; + } } + //初始化每行的下一个子视图的位置。 NSMutableArray *nextPointOfRows = nil; if (autoArrange) @@ -1528,8 +1576,9 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG } } - NSInteger lineIndex = 0; //行索引 CGFloat pageWidth = 0.0; //页宽。 + maxWidth = paddingLeading; + lineIndex = 0; //行索引 itemIndex = 0; lineTotalShrink = 0.0; i = 0; @@ -1584,7 +1633,6 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG lineIndex++; } - CGFloat topSpace = sbvsc.topPosInner.absVal; CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; @@ -1728,8 +1776,6 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:selfSize.height sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; } - //得到行数 - NSInteger arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); //行数 //根据flex规则:如果只有一行则整个高度都作为子视图的拉伸和停靠区域。 if (lsc.isFlex && arranges == 1) lineMaxHeight = selfSize.height - paddingVert; diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 9c4f4c3..09bbed2 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -358,7 +358,7 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub //左右依赖的,或者依赖父视图宽度的不参数最宽计算!! if ((tempSelfWidth > maxSelfWidth) && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) && - (sbvsc.leadingPosInner == nil || sbvsc.trailingPosInner == nil || sbvsc.widthSizeInner.dimeVal != nil)) + (sbvsc.leadingPosInner.posVal == nil || sbvsc.trailingPosInner.posVal == nil || sbvsc.widthSizeInner.dimeVal != nil)) { maxSelfWidth = tempSelfWidth; } @@ -677,7 +677,7 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub if ((tempSelfWidth > maxSelfWidth) && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) && - (sbvsc.leadingPosInner == nil || sbvsc.trailingPosInner == nil || sbvsc.widthSizeInner.dimeVal != nil)) + (sbvsc.leadingPosInner.posVal == nil || sbvsc.trailingPosInner.posVal == nil || sbvsc.widthSizeInner.dimeVal != nil)) { maxSelfWidth = tempSelfWidth; } @@ -827,7 +827,7 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub if ((tempSelfHeight > maxSelfHeight) && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) && - (sbvsc.topPosInner == nil || sbvsc.bottomPosInner == nil || sbvsc.heightSizeInner.dimeVal != nil)) + (sbvsc.topPosInner.posVal == nil || sbvsc.bottomPosInner.posVal == nil || sbvsc.heightSizeInner.dimeVal != nil)) { maxSelfHeight = tempSelfHeight; } @@ -1201,7 +1201,7 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub if ((tempSelfHeight > maxSelfHeight) && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) && - (sbvsc.topPosInner == nil || sbvsc.bottomPosInner == nil || sbvsc.heightSizeInner.dimeVal != nil)) + (sbvsc.topPosInner.posVal == nil || sbvsc.bottomPosInner.posVal == nil || sbvsc.heightSizeInner.dimeVal != nil )) { maxSelfHeight = tempSelfHeight; } diff --git a/MyLayoutTests/MyFrameLayoutTestCase.m b/MyLayoutTests/MyFrameLayoutTestCase.m index 2f46588..9898100 100644 --- a/MyLayoutTests/MyFrameLayoutTestCase.m +++ b/MyLayoutTests/MyFrameLayoutTestCase.m @@ -324,6 +324,22 @@ -(void)testWrapContent3 } +-(void)testWrapContent4 +{ + //没有约束,原生的frame值设置。 + MyFrameLayout *rootLayout = [MyFrameLayout new]; + rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10); + rootLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + + UIView *v = [UIView new]; + v.frame = CGRectMake(0, 0, 150, 150); + [rootLayout addSubview:v]; + + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 170, 170)); + +} + -(void)testPerformanceExample { [self measureBlock:^{ From eb1013656a25c9936d4600e02112e22e16773618 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Wed, 13 Nov 2019 20:10:17 +0800 Subject: [PATCH 082/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 +- MyLayout/Lib/MyFloatLayout.m | 12 +- MyLayout/Lib/MyFlowLayout.m | 175 +++++++++++++++------- MyLayoutDemo/FLLTest5ViewController.m | 42 +++++- MyLayoutTests/MyFloatLayoutTestCase.m | 62 ++++++++ MyLayoutTests/MyFlowLayoutTestCase.m | 191 ++++++++++++++++++++++++- MyLayoutTests/MyLinearLayoutTestCase.m | 41 ++++++ 7 files changed, 463 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a705ee9..36c2e22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,8 +31,9 @@ 10. 浮动布局添加对尺寸自适应的支持。您可以在垂直浮动布局中将布局视图的宽度设置为自适应,同时可以在水平浮动布局中将布局视图的高度设置为自适应。 - 11. 在线性布局、流式布局、浮动布局中实现了可以在尺寸自适应的模式下gravity的停靠属性生效的能力。解决了[issue#102](https://github.com/youngsoft/MyLinearLayout/issues/102) +12. 在线性布局、流式布局、浮动布局中实现了设置尺寸自适应并且设置了最大最小值约束的情况下子视图被正确布局的功能。 +13. 扩充的流式布局中的pagedCount的能力,由原先的必须是在滚动视图的子视图下生效改为可以在任意时刻生效。 ### Update 1. 更新了对尺寸自适应属性的设置方式。不再建议使用wrapContentWidth进行宽度自适应设置,而是改为`myWidth = MyLayoutSize.wrap`或者`widthSize.equalTo(@(MyLayoutSize.wrap))`进行宽度自适应设置。不再建议使用wrapContentHeight进行高度尺寸自适应设置,而是改为`myHeight= MyLayoutSize.wrap`或者`heightSize.equalTo(@(MyLayoutSize.wrap))`进行高度自适应设置。 对于宽度是否自适应的判断则可以用`myWidth == MyLayoutSize.wrap`或widthSize.iswrap进行判断,高度也是一样的。 @@ -43,12 +44,13 @@ 3. 线性布局中的shrinkType属性用于控制所有子视图的压缩特性,如果子视图的尺寸设置shrink属性值则以子视图的设置优先,布局视图的shrinkType将不再起作用。 + ### Fixed 1. 修复在使用sizeclass时对位置对象进行克隆的一个BUG。这个BUG可能导致在不同sizeclass下位置设置被覆盖的问题。 2. 修复相对布局下一组视图在高度或者宽度自适应下无法垂直居中或者水平居中的[BUG#103](https://github.com/youngsoft/MyLinearLayout/issues/103) 3. 修复框架布局MyFrameLayout设置高度自适应时,当其中的子视图隐藏或者恢复隐藏时自适应高度无法更新的[BUG#99](https://github.com/youngsoft/MyLinearLayout/issues/99) - +4. 修复了流式布局在设置了子视图水平间距和垂直间距的情况下右对齐和底部对齐的BUG。 diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 5ebfaf5..ef4d357 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -406,9 +406,12 @@ -(CGSize)myVertOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv CGFloat paddingHorz = paddingLeading + paddingTrailing; // CGFloat paddingVert = paddingTop + paddingBottom; - //如果没有边界限制我们将高度设置为最大。。 + //如果没有边界限制我们将宽度设置为最大。。 if (lsc.widthSizeInner.dimeWrapVal) - selfSize.width = CGFLOAT_MAX; + { + //如果有最大限制则取最大值,解决那种宽度自适应,但是有最大值需要换行的情况。 + selfSize.width = [self myGetBoundLimitMeasure:lsc.widthSizeInner.uBoundValInner sbv:self dimeType:lsc.widthSizeInner.dime sbvSize:selfSize selfLayoutSize:self.superview.bounds.size isUBound:YES]; + } //支持浮动水平间距。 CGFloat vertSpace = lsc.subviewVSpace; @@ -874,7 +877,10 @@ -(CGSize)myHorzOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv //如果没有边界限制我们将高度设置为最大。。 if (lsc.heightSizeInner.dimeWrapVal) - selfSize.height = CGFLOAT_MAX; + { + //如果有最大限制则取最大值,解决那种高度自适应,但是有最大值需要换行的情况。 + selfSize.height = [self myGetBoundLimitMeasure:lsc.heightSizeInner.uBoundValInner sbv:self dimeType:lsc.heightSizeInner.dime sbvSize:selfSize selfLayoutSize:self.superview.bounds.size isUBound:YES]; + } //支持浮动垂直间距。 CGFloat horzSpace = lsc.subviewHSpace; diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 1a5abbb..20903e0 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -210,6 +210,9 @@ -(id)createSizeClassInstance //计算垂直流式布局下每行的比重值。 - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSinglelineWeight:(CGFloat)lineTotalWeight lineSpareWidth:(CGFloat)lineSpareWidth sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count inSelfSize:(CGSize)selfSize { + if (count == 0) + return; + //如果浮动宽度都是小于等于0因为没有拉升必要,所以直接返回 if (lineSpareWidth <= 0.0) return; @@ -238,6 +241,9 @@ - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSinglelineWeight:(CGFlo //计算水平流式布局下每行的比重值。 - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSinglelineWeight:(CGFloat)lineTotalWeight lineSpareHeight:(CGFloat)lineSpareHeight sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count inSelfSize:(CGSize)selfSize { + if (count == 0) + return; + if (lineSpareHeight <= 0.0) return; @@ -270,6 +276,9 @@ - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSinglelineWeight:(CGFlo //调整内容约束垂直流式布局的每行的宽度 - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc adjustSingleline:(NSInteger)lineIndex lineSpareWidth:(CGFloat)lineSpareWidth lineTotalWeight:(CGFloat)lineTotalWeight horzGravity:(MyGravity)horzGravity sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count inSelfSize:(CGSize)selfSize { + if (count == 0) + return; + if (lineSpareWidth <= 0.0) return; @@ -320,6 +329,9 @@ - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc adjustSingleline:(NSInteger //调整内容约束水平流式布局的每行的高度 - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc adjustSingleline:(NSInteger)lineIndex lineSpareHeight:(CGFloat)lineSpareHeight lineTotalWeight:(CGFloat)lineTotalWeight vertGravity:(MyGravity)vertGravity sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count inSelfSize:(CGSize)selfSize { + if (count == 0) + return; + if (lineSpareHeight <= 0.0) return; @@ -368,6 +380,9 @@ - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc adjustSingleline:(NSInteger - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSinglelineShrink:(CGFloat)lineTotalShrink lineSpareWidth:(CGFloat)lineSpareWidth sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count inSelfSize:(CGSize)selfSize { + if (count == 0) + return; + if (_myCGFloatGreatOrEqual(lineSpareWidth, 0.0)) lineTotalShrink = 0.0; @@ -396,6 +411,9 @@ - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSinglelineShrink:(CGFlo - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSinglelineShrink:(CGFloat)lineTotalShrink lineSpareHeight:(CGFloat)lineSpareHeight sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count inSelfSize:(CGSize)selfSize { + if (count == 0) + return; + if (_myCGFloatGreatOrEqual(lineSpareHeight, 0.0)) lineTotalShrink = 0.0; @@ -425,6 +443,9 @@ - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSinglelineShrink:(CGFlo - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)lineIndex vertAlignment:(MyGravity)vertAlignment horzGravity:(MyGravity)horzGravity lineMaxHeight:(CGFloat)lineMaxHeight lineMaxWidth:(CGFloat)lineMaxWidth lineTotalShrink:(CGFloat)lineTotalShrink sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate inSelfSize:(CGSize)selfSize { + if (count == 0) + return; + CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; CGFloat paddingHorz = paddingLeading + paddingTrailing; @@ -624,6 +645,9 @@ - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)lineIndex horzAlignment:(MyGravity)horzAlignment vertGravity:(MyGravity)vertGravity lineMaxWidth:(CGFloat)lineMaxWidth lineMaxHeight:(CGFloat)lineMaxHeight lineTotalShrink:(CGFloat)lineTotalShrink sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate inSelfSize:(CGSize)selfSize { + if (count == 0) + return; + CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingVert = paddingTop + paddingBottom; @@ -1417,12 +1441,12 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG //得到行数 NSInteger arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); CGFloat lineTotalFixedWidths[arranges]; //所有行的固定宽度。 - CGFloat lineTotalShrinks[arranges]; //所有行的总压缩 CGFloat lineTotalWeights[arranges]; //所有行的总比重 + CGFloat lineTotalShrinks[arranges]; //所有行的总压缩 CGFloat lineTotalFixedWidth = 0.0; - CGFloat lineTotalShrink = 0.0; //某一行的总压缩比重。 CGFloat lineTotalWeight = 0.0; + CGFloat lineTotalShrink = 0.0; //某一行的总压缩比重。 BOOL hasTotalWeight = NO; //是否有比重计算,这个标志用于加快处理速度 BOOL hasTotalShrink = NO; //是否有压缩计算,这个标志用于加快处理速度 //行内子视图的索引号 @@ -1502,6 +1526,11 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG sbvmyFrame.frame = rect; itemIndex++; + lineTotalFixedWidth += rect.size.width; + lineTotalFixedWidth += leadingSpace + trailingSpace; + if (itemIndex < arrangedCount) + lineTotalFixedWidth += horzSpace; + //计算总拉伸比。 if (sbvsc.weight != 0.0) lineTotalWeight += sbvsc.weight; @@ -1509,11 +1538,6 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG //计算总的压缩比 lineTotalShrink += sbvsc.leadingPosInner.shrink + sbvsc.trailingPosInner.shrink; lineTotalShrink += sbvsc.widthSizeInner.shrink; - - lineTotalFixedWidth += rect.size.width; - lineTotalFixedWidth += leadingSpace + trailingSpace; - if (itemIndex < arrangedCount) - lineTotalFixedWidth += horzSpace; } //最后一行。 @@ -1523,8 +1547,8 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG lineTotalFixedWidth -= horzSpace; lineTotalWeights[lineIndex] = lineTotalWeight; - lineTotalShrinks[lineIndex] = lineTotalShrink; lineTotalFixedWidths[lineIndex] = lineTotalFixedWidth; + lineTotalShrinks[lineIndex] = lineTotalShrink; if(!hasTotalWeight) hasTotalWeight = lineTotalWeight > 0; @@ -1540,7 +1564,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:maxWidth sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; //进行所有行的宽度拉伸和压缩。 - if (horzGravity != MyGravity_Horz_Fill && (hasTotalShrink || hasTotalWeight)) + if (horzGravity != MyGravity_Horz_Fill && (hasTotalWeight || hasTotalShrink)) { NSInteger remainedCount = sbs.count; lineIndex = 0; @@ -1564,7 +1588,6 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG } } - //初始化每行的下一个子视图的位置。 NSMutableArray *nextPointOfRows = nil; if (autoArrange) @@ -2294,7 +2317,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG CGFloat yPos = paddingTop; CGFloat lineMaxWidth = 0.0; //每一列的最大宽度 CGFloat lineMaxHeight = 0.0; //每一列的最大高度 - CGFloat maxHeight = paddingTop; //全列的最大高度 + CGFloat maxHeight = 0.0; //全列的最大高度 CGFloat maxWidth = paddingLeading; //最大的宽度。 //父滚动视图是否分页滚动。 @@ -2346,48 +2369,62 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG } + //在高度自适应的情况下有可能有最大最小高度约束。 + if (lsc.heightSizeInner.dimeWrapVal) + selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:0 sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + //平均高度,当布局的gravity设置为Vert_Fill时指定这个平均高度值。 CGFloat averageHeight = 0.0; if (vertGravity == MyGravity_Vert_Fill) averageHeight = (selfSize.height - paddingVert - (arrangedCount - 1) * vertSpace) / arrangedCount; - NSInteger itemIndex = 0; - NSInteger i = 0; - CGFloat lineTotalShrink = 0.0; //某一行的总压缩比重。 - CGFloat lineTotalWeight = 0.0; + //得到行数 + NSInteger arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); + CGFloat lineTotalFixedHeights[arranges]; //所有行的固定高度。 + CGFloat lineTotalWeights[arranges]; //所有行的总比重 + CGFloat lineTotalShrinks[arranges]; //所有行的总压缩 + CGFloat lineTotalFixedHeight = 0.0; + CGFloat lineTotalWeight = 0.0; + CGFloat lineTotalShrink = 0.0; //某一行的总压缩比重。 + BOOL hasTotalWeight = NO; //是否有比重计算,这个标志用于加快处理速度 + BOOL hasTotalShrink = NO; //是否有压缩计算,这个标志用于加快处理速度 + + NSInteger i = 0; + NSInteger itemIndex = 0; + NSInteger lineIndex = 0; //行索引 for (; i < sbs.count; i++) { UIView *sbv = sbs[i]; MyFrame *sbvmyFrame = sbv.myFrame; MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; + CGFloat topSpace = sbvsc.topPosInner.absVal; + CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; + CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; + CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; + CGRect rect = sbvmyFrame.frame; + if (itemIndex >= arrangedCount) { - itemIndex = 0; + lineTotalFixedHeights[lineIndex] = lineTotalFixedHeight; + lineTotalWeights[lineIndex] = lineTotalWeight; + lineTotalShrinks[lineIndex] = lineTotalShrink; - if (lineTotalWeight != 0 && vertGravity != MyGravity_Vert_Fill) - { - [self myHorzLayout:lsc calcSinglelineWeight:lineTotalWeight lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount inSelfSize:selfSize]; - } + if(!hasTotalWeight) + hasTotalWeight = lineTotalWeight > 0; + if (!hasTotalShrink) + hasTotalShrink = lineTotalShrink > 0; - if (lineTotalShrink != 0 && vertGravity != MyGravity_Vert_Fill) - { - [self myHorzLayout:lsc calcSinglelineShrink:lineTotalShrink lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount inSelfSize:selfSize]; - } + if (lineTotalFixedHeight > maxHeight) + maxHeight = lineTotalFixedHeight; - lineTotalWeight = 0.0; lineTotalFixedHeight = 0.0; + lineTotalWeight = 0.0; lineTotalShrink = 0.0; - + itemIndex = 0; + lineIndex++; } - - CGFloat topSpace = sbvsc.topPosInner.absVal; - CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; - CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; - CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; - CGRect rect = sbvmyFrame.frame; - //水平流式布局因为高度依赖宽度自适应的情况比较少,所以这里直接先计算宽度 if (pagingItemWidth != 0.0) rect.size.width = pagingItemWidth - leadingSpace - trailingSpace; @@ -2438,34 +2475,69 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; } + sbvmyFrame.frame = rect; + itemIndex++; + + lineTotalFixedHeight += rect.size.height; + lineTotalFixedHeight += topSpace + bottomSpace; + if (itemIndex < arrangedCount) + lineTotalFixedHeight += vertSpace; + if (sbvsc.weight != 0) lineTotalWeight += sbvsc.weight; //计算总的压缩比 lineTotalShrink += sbvsc.topPosInner.shrink + sbvsc.bottomPosInner.shrink; lineTotalShrink += sbvsc.heightSizeInner.shrink; + } + + //最后一行。 + if (arranges > 0) + { + if (itemIndex < arrangedCount) + lineTotalFixedHeight -= vertSpace; - lineTotalFixedHeight += rect.size.height; - lineTotalFixedHeight += topSpace + bottomSpace; - if (itemIndex != (arrangedCount - 1)) - lineTotalFixedHeight += vertSpace; + lineTotalFixedHeights[lineIndex] = lineTotalFixedHeight; + lineTotalWeights[lineIndex] = lineTotalWeight; + lineTotalShrinks[lineIndex] = lineTotalShrink; - sbvmyFrame.frame = rect; - itemIndex++; + if(!hasTotalWeight) + hasTotalWeight = lineTotalWeight > 0; + if (!hasTotalShrink) + hasTotalShrink = lineTotalShrink > 0; + + if (lineTotalFixedHeight > maxHeight) + maxHeight = lineTotalFixedHeight; } - //最后一行。 - if (itemIndex < arrangedCount) - lineTotalFixedHeight -= vertSpace; + maxHeight += paddingTop + paddingBottom; + if (lsc.heightSizeInner.dimeWrapVal) + selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:maxHeight sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; - if (lineTotalWeight != 0.0 && vertGravity != MyGravity_Vert_Fill) - { - [self myHorzLayout:lsc calcSinglelineWeight:lineTotalWeight lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; - } - if (lineTotalShrink != 0.0 && vertGravity != MyGravity_Vert_Fill) + //进行所有行的宽度拉伸和压缩。 + if (vertGravity != MyGravity_Vert_Fill && (hasTotalWeight || hasTotalShrink)) { - [self myHorzLayout:lsc calcSinglelineShrink:lineTotalShrink lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:i - itemIndex count:itemIndex inSelfSize:selfSize]; + NSInteger remainedCount = sbs.count; + lineIndex = 0; + for (;lineIndex < arranges; lineIndex++) + { + lineTotalFixedHeight = lineTotalFixedHeights[lineIndex]; + lineTotalWeight = lineTotalWeights[lineIndex]; + lineTotalShrink = lineTotalShrinks[lineIndex]; + + if (lineTotalWeight != 0) + { + [self myHorzLayout:lsc calcSinglelineWeight:lineTotalWeight lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:lineIndex*arrangedCount count:MIN(arrangedCount,remainedCount) inSelfSize:selfSize]; + } + + if (lineTotalShrink != 0) + { + [self myHorzLayout:lsc calcSinglelineShrink:lineTotalShrink lineSpareHeight:selfSize.height - paddingVert - lineTotalFixedHeight sbs:sbs startItemIndex:lineIndex*arrangedCount count:MIN(arrangedCount,remainedCount) inSelfSize:selfSize]; + } + + remainedCount -= arrangedCount; + } } //初始化每行的下一个子视图的位置。 @@ -2479,8 +2551,9 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG } } - NSInteger lineIndex = 0; CGFloat pageHeight = 0.0; //页高 + maxHeight = paddingTop; + lineIndex = 0; itemIndex = 0; lineTotalShrink = 0.0; i = 0; @@ -2642,9 +2715,6 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:selfSize.width sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; } - - //得到行数 - NSInteger arranges = floor((sbs.count + arrangedCount - 1.0) / arrangedCount); //行数 //根据flex规则:如果只有一行则整个高度都作为子视图的拉伸和停靠区域。 if (lsc.isFlex && arranges == 1) lineMaxWidth = selfSize.width - paddingHorz; @@ -2652,7 +2722,6 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG //最后一行 [self myHorzLayout:lsc calcSingleline:lineIndex horzAlignment:horzAlignment vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; - //整体的停靠。 if (horzGravity != MyGravity_None && selfSize.width != maxWidth && !(isHorzPaging && isPagingScroll)) { diff --git a/MyLayoutDemo/FLLTest5ViewController.m b/MyLayoutDemo/FLLTest5ViewController.m index 5aa1607..dd142cc 100644 --- a/MyLayoutDemo/FLLTest5ViewController.m +++ b/MyLayoutDemo/FLLTest5ViewController.m @@ -12,6 +12,11 @@ @interface FLLTest5ViewController () +@property(nonatomic, strong) UIScrollView *scrollView1; +@property(nonatomic, strong) UIScrollView *scrollView2; +@property(nonatomic, strong) UIScrollView *scrollView3; +@property(nonatomic, strong) UIScrollView *scrollView4; + @end @@ -46,16 +51,13 @@ -(void)loadView //创建一个垂直数量流式布局分页从左到右滚动 [self createVertPagingFlowLayout2:rootLayout]; - - - - } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. - + UIBarButtonItem *bar =[[UIBarButtonItem alloc] initWithTitle:@"paging" style:UIBarButtonItemStylePlain target:self action:@selector(handlePagingSwitch:)]; + self.navigationItem.rightBarButtonItem = bar; } @@ -101,6 +103,7 @@ -(void)createHorzPagingFlowLayout1:(UIView*)rootLayout scrollView.pagingEnabled = YES; //开启分页滚动模式!!您可以注释这句话看看非分页滚动的布局滚动效果。 scrollView.myHeight = 200; //设置明确的高度为200,因为宽度已经由父线性布局的gravity属性确定了,所以不需要设置了。 [rootLayout addSubview:scrollView]; + self.scrollView1 = scrollView; //建立一个水平数量约束流式布局:每列展示3个子视图,每页展示9个子视图,整体从左往右滚动。 @@ -141,7 +144,7 @@ -(void)createHorzPagingFlowLayout2:(UIView*)rootLayout scrollView.pagingEnabled = YES; //开启分页滚动模式!!您可以注释这句话看看非分页滚动的布局滚动效果。 scrollView.myHeight = 250; //设置明确的高度为250,因为宽度已经由父线性布局的gravity属性确定了,所以不需要设置了。 [rootLayout addSubview:scrollView]; - + self.scrollView2 = scrollView; //建立一个水平数量约束流式布局:每列展示3个子视图,每页展示9个子视图,整体从上往下滚动。 MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:3]; @@ -183,7 +186,8 @@ -(void)createVertPagingFlowLayout1:(UIView*)rootLayout scrollView.pagingEnabled = YES; //开启分页滚动模式!!您可以注释这句话看看非分页滚动的布局滚动效果。 scrollView.myHeight = 250; //设置明确的高度为250,因为宽度已经由父线性布局的gravity属性确定了,所以不需要设置了。 [rootLayout addSubview:scrollView]; - + self.scrollView3 = scrollView; + //建立一个垂直数量约束流式布局:每列展示3个子视图,每页展示9个子视图,整体从上往下滚动。 MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; flowLayout.pagedCount = 9; //pagedCount设置为非0时表示开始分页展示的功能,这里表示每页展示9个子视图,这个数量必须是arrangedCount的倍数。 @@ -227,6 +231,7 @@ -(void)createVertPagingFlowLayout2:(UIView*)rootLayout scrollView.pagingEnabled = YES; //开启分页滚动模式!!您可以注释这句话看看非分页滚动的布局滚动效果。 scrollView.myHeight = 200; //设置明确的高度为200,因为宽度已经由父线性布局的gravity属性确定了,所以不需要设置了。 [rootLayout addSubview:scrollView]; + self.scrollView4 = scrollView; //建立一个垂直数量约束流式布局:每列展示3个子视图,每页展示9个子视图,整体从左往右滚动。 MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; @@ -256,6 +261,29 @@ -(void)createVertPagingFlowLayout2:(UIView*)rootLayout #pragma mark -- Handle Method +-(void)handlePagingSwitch:(UIBarButtonItem*)sender +{ + if ([sender.title isEqualToString:@"paging"]) + { + sender.title = @"scroll"; + } + else + { + self.title = @"paging"; + } + + self.scrollView1.pagingEnabled = !self.scrollView1.pagingEnabled; + self.scrollView2.pagingEnabled = !self.scrollView2.pagingEnabled; + self.scrollView3.pagingEnabled = !self.scrollView3.pagingEnabled; + self.scrollView4.pagingEnabled = !self.scrollView4.pagingEnabled; + + [self.scrollView1.subviews.firstObject setNeedsLayout]; + [self.scrollView2.subviews.firstObject setNeedsLayout]; + [self.scrollView3.subviews.firstObject setNeedsLayout]; + [self.scrollView4.subviews.firstObject setNeedsLayout]; + +} + /* #pragma mark - Navigation diff --git a/MyLayoutTests/MyFloatLayoutTestCase.m b/MyLayoutTests/MyFloatLayoutTestCase.m index 5c6380e..b3ed9bc 100644 --- a/MyLayoutTests/MyFloatLayoutTestCase.m +++ b/MyLayoutTests/MyFloatLayoutTestCase.m @@ -389,6 +389,68 @@ -(void)testWrapAndGravity } } +-(void)testWrapAndMaxMinLimit +{ + { + MyFloatLayout *rootLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Vert]; + rootLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + rootLayout.widthSize.max(80); + rootLayout.padding = UIEdgeInsetsMake(10, 5, 5, 10); + rootLayout.subviewSpace = 20; + + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 15, 15)); + + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(30, 30); + [rootLayout addSubview:v1]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 5+30+10, 10+30+5)); + + UIView *v2 = [UIView new]; + v2.mySize = CGSizeMake(10, 10); + [rootLayout addSubview:v2]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 5+30+20+10+10, 10+30+5)); + + UIView *v3 = [UIView new]; + v3.mySize = CGSizeMake(50, 50); + [rootLayout addSubview:v3]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 75, 10+30+20+50+5)); + } + + { + MyFloatLayout *rootLayout = [MyFloatLayout floatLayoutWithOrientation:MyOrientation_Horz]; + rootLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + rootLayout.heightSize.max(80); + rootLayout.padding = UIEdgeInsetsMake(5, 10, 10, 5); + rootLayout.subviewSpace = 20; + + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 15, 15)); + + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(30, 30); + [rootLayout addSubview:v1]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 10+30+5,5+30+10)); + + UIView *v2 = [UIView new]; + v2.mySize = CGSizeMake(10, 10); + [rootLayout addSubview:v2]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 10+30+5,5+30+20+10+10)); + + UIView *v3 = [UIView new]; + v3.mySize = CGSizeMake(50, 50); + [rootLayout addSubview:v3]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 10+30+20+50+5,75)); + } + +} + - (void)testPerformanceExample { // This is an example of a performance test case. diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index bd925fd..3ae92f7 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -719,8 +719,195 @@ -(void)testWeight } --(void)testWrapAndGravity +-(void)testWrapAndWeightAndShrink { + //测试数量约束布局的宽度和高度是自适应,并且有最大,最小值约束下的用例。 + { + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:1]; + rootLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + rootLayout.padding = UIEdgeInsetsMake(10, 5, 5, 10); + rootLayout.subviewHSpace = 20; + rootLayout.subviewVSpace = 20; + + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 15, 15)); + + { + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(30, 30); + [rootLayout addSubview:v1]; + } + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 15+30, 15+30)); + + { + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(30, 30); + [rootLayout addSubview:v1]; + } + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 15+30, 15+30+20+30)); + + rootLayout.arrangedCount = 2; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 10+30+20+30+5, 10+30+5)); + + { + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(30, 30); + [rootLayout addSubview:v1]; + } + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 10+30+20+30+5, 10+30+20+30+5)); + + { + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(40, 40); + [rootLayout addSubview:v1]; + } + rootLayout.subviews.firstObject.weight = 1; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 10+30+20+40+5, 10+30+20+40+5)); + MyRectAssert(rootLayout.subviews.firstObject, CGRectMake(5,10, 40, 30)); + + rootLayout.widthSize.max(70); + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 70, 10+30+20+40+5)); + MyRectAssert(rootLayout.subviews.firstObject, CGRectMake(5,10, 30, 30)); + MyRectAssert(rootLayout.subviews.lastObject, CGRectMake(5+30+20, 10+30+20, 40, 40)); + + rootLayout.subviews.lastObject.widthSize.shrink = 1; + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout.subviews.lastObject, CGRectMake(5+30+20, 10+30+20, 5, 40)); + } + + { + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:1]; + rootLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + rootLayout.padding = UIEdgeInsetsMake(5, 10, 10, 5); + rootLayout.subviewHSpace = 20; + rootLayout.subviewVSpace = 20; + + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 15, 15)); + + { + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(30, 30); + [rootLayout addSubview:v1]; + } + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 15+30, 15+30)); + + { + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(30, 30); + [rootLayout addSubview:v1]; + } + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 15+30+20+30, 15+30)); + + rootLayout.arrangedCount = 2; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0,10+30+5,10+30+20+30+5)); + + { + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(30, 30); + [rootLayout addSubview:v1]; + } + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 10+30+20+30+5, 10+30+20+30+5)); + + { + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(40, 40); + [rootLayout addSubview:v1]; + } + rootLayout.subviews.firstObject.weight = 1; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 10+30+20+40+5,10+30+20+40+5)); + MyRectAssert(rootLayout.subviews.firstObject, CGRectMake(10,5,30,40)); + + rootLayout.heightSize.max(70); + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 10+30+20+40+5, 70)); + MyRectAssert(rootLayout.subviews.firstObject, CGRectMake(10,5,30, 30)); + MyRectAssert(rootLayout.subviews.lastObject, CGRectMake(10+30+20,5+30+20,40, 40)); + + rootLayout.subviews.lastObject.heightSize.shrink = 1; + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout.subviews.lastObject, CGRectMake(10+30+20,5+30+20,40,5)); + } +} + +-(void)testWrapAndMinSize +{ + //测试自适应并且是最小高宽约束的情况。 + { + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:2]; + rootLayout.widthSize.equalTo(@(MyLayoutSize.wrap)).min(50); + rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)); + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0,0,50,0)); + + UIView *v = [UIView new]; + v.mySize = CGSizeMake(20, 20); + [rootLayout addSubview:v]; + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0,0,50,20)); + + rootLayout.subviews.firstObject.weight = 1; + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0,0,50,20)); + MyRectAssert(rootLayout.subviews.firstObject, CGRectMake(0,0,50,20)); + + UIView *v2 = [UIView new]; + v2.mySize = CGSizeMake(40, 40); + [rootLayout addSubview:v2]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0,0,20+40,40)); + MyRectAssert(rootLayout.subviews.firstObject, CGRectMake(0,0,20,20)); + } + { + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:2]; + rootLayout.widthSize.equalTo(@(MyLayoutSize.wrap)); + rootLayout.heightSize.equalTo(@(MyLayoutSize.wrap)).min(50); + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0,0,0,50)); + + UIView *v = [UIView new]; + v.mySize = CGSizeMake(20, 20); + [rootLayout addSubview:v]; + + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0,0,20,50)); + + rootLayout.subviews.firstObject.weight = 1; + [rootLayout setNeedsLayout]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0,0,20,50)); + MyRectAssert(rootLayout.subviews.firstObject, CGRectMake(0,0,20,50)); + + UIView *v2 = [UIView new]; + v2.mySize = CGSizeMake(40, 40); + [rootLayout addSubview:v2]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0,0,40,20+40)); + MyRectAssert(rootLayout.subviews.firstObject, CGRectMake(0,0,20,20)); + } } @@ -915,6 +1102,8 @@ -(void)testRightAndBottomGravity -(void)testFlex1 { + //测试内容约束布局下的尺寸自适应,以及最大最小值设置的场景。 + { MyFlexLayout *flexLayout = MyFlexLayout.new.flex .align_items(MyFlexGravity_Center) diff --git a/MyLayoutTests/MyLinearLayoutTestCase.m b/MyLayoutTests/MyLinearLayoutTestCase.m index 0ba093d..4c4ffe7 100644 --- a/MyLayoutTests/MyLinearLayoutTestCase.m +++ b/MyLayoutTests/MyLinearLayoutTestCase.m @@ -880,6 +880,47 @@ -(void)testMaxAndMin XCTAssertTrue(CGRectEqualToRect(backLinear.frame, CGRectMake(0,0,375,500)), @"the backLinear.frame = %@",NSStringFromCGRect(backLinear.frame)); XCTAssertTrue(CGRectEqualToRect(v.frame, CGRectMake(0,0,100,500)), @"the v.frame = %@",NSStringFromCGRect(v.frame)); +} + +-(void)testNoLayoutConstraint1 +{ + //这用来测试没有设置约束,直接通过frame来得到布局尺寸自适应的情况。 + { + MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + rootLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + + UIView *v1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; + [rootLayout addSubview:v1]; + + UIView *v2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)]; + [rootLayout addSubview:v2]; + + UIView *v3 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)]; + [rootLayout addSubview:v3]; + + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 300, 100+200+300)); + } + + { + MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + rootLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + + UIView *v1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; + [rootLayout addSubview:v1]; + + UIView *v2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)]; + [rootLayout addSubview:v2]; + + UIView *v3 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)]; + [rootLayout addSubview:v3]; + + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 100+200+300,300)); + } + + + } - (void)testPerformanceExample { From 2873e427531d1d00679302eff2dad1cc628a3170 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Thu, 14 Nov 2019 09:07:32 +0800 Subject: [PATCH 083/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlexLayout.h | 7 +- MyLayout/Lib/MyFlexLayout.m | 139 ++++++++++- MyLayoutDemo/AllTestExampleViewController.m | 10 +- MyLayoutDemo/FLXTest1ViewController.m | 248 ++++++++++---------- 4 files changed, 255 insertions(+), 149 deletions(-) diff --git a/MyLayout/Lib/MyFlexLayout.h b/MyLayout/Lib/MyFlexLayout.h index 582689e..0c25e14 100644 --- a/MyLayout/Lib/MyFlexLayout.h +++ b/MyLayout/Lib/MyFlexLayout.h @@ -64,7 +64,6 @@ extern const int MyFlex_Auto; - /* flexbox中项目的设置类。 */ @@ -163,8 +162,8 @@ extern const int MyFlex_Auto; //条目视图在应用flexbox时的分类扩展,只有MyFlexLayout中的子视图才有用。 @interface UIView(MyFlexLayout) -//我们可以借助视图的flexItem来设置条目视图在弹性布局视图中的一些属性。 -@property(nonatomic, readonly, strong) MyFlexItem *flexItem; +//我们可以借助视图的myFlex来设置条目视图在弹性布局视图中的一些属性。 +@property(nonatomic, readonly, strong) MyFlexItem *myFlex; @end @@ -176,6 +175,6 @@ extern const int MyFlex_Auto; @interface MyFlexLayout:MyFlowLayout //用于flexbox约束的设置。 -@property(nonatomic, readonly, strong, readonly) MyFlex *flex; +@property(nonatomic, readonly, strong) MyFlex *myFlex; @end diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index 1569858..633d61e 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -38,6 +38,69 @@ -(instancetype)init return self; } +-(void)setOrder:(NSInteger)order +{ + if (_order != order) + { + _order = order; + [self.view.superview setNeedsLayout]; + } +} + +-(void)setFlex_grow:(CGFloat)flex_grow +{ + if (_flex_grow != flex_grow) + { + _flex_grow = flex_grow; + [self.view.superview setNeedsLayout]; + } +} + +-(void)setFlex_shrink:(CGFloat)flex_shrink +{ + if (_flex_shrink != flex_shrink) + { + _flex_shrink = flex_shrink; + [self.view.superview setNeedsLayout]; + } +} + +-(void)setFlex_basis:(CGFloat)flex_basis +{ + if (_flex_basis != flex_basis) + { + _flex_basis = flex_basis; + [self.view.superview setNeedsLayout]; + } +} + +-(void)setAlign_self:(MyFlexGravity)align_self +{ + if (_align_self != align_self) + { + _align_self = align_self; + [self.view.superview setNeedsLayout]; + } +} + +-(void)setWidth:(CGFloat)width +{ + if (_width != width) + { + _width = width; + [self.view.superview setNeedsLayout]; + } +} + +-(void)setHeight:(CGFloat)height +{ + if (_height != height) + { + _height = height; + [self.view.superview setNeedsLayout]; + } +} + -(CGFloat)margin_top { return self.view.myTop; @@ -108,9 +171,7 @@ -(instancetype)initWithView:(UIView*)view attrs:(MyFlexItemAttrs*)attrs _view = view; _attrs = attrs; _attrs.view = view; - // _attrs = [MyFlexItemAttrs new]; - // _attrs.view = view; - } + } return self; } @@ -318,6 +379,58 @@ -(instancetype)init return self; } +//@property(nonatomic, assign) MyFlexDirection flex_direction; +//@property(nonatomic, assign) MyFlexWrap flex_wrap; +//@property(nonatomic, assign) MyFlexGravity justify_content; +//@property(nonatomic, assign) MyFlexGravity align_items; +//@property(nonatomic, assign) MyFlexGravity align_content; + + +-(void)setFlex_direction:(MyFlexDirection)flex_direction +{ + if (_flex_direction != flex_direction) + { + _flex_direction = flex_direction; + [self.view setNeedsLayout]; + } +} + +-(void)setFlex_wrap:(MyFlexWrap)flex_wrap +{ + if (_flex_wrap != flex_wrap) + { + _flex_wrap = flex_wrap; + [self.view setNeedsLayout]; + } +} + +-(void)setJustify_content:(MyFlexGravity)justify_content +{ + if (_justify_content != justify_content) + { + _justify_content = justify_content; + [self.view setNeedsLayout]; + } +} + +-(void)setAlign_items:(MyFlexGravity)align_items +{ + if (_align_items != align_items) + { + _align_items = align_items; + [self.view setNeedsLayout]; + } +} + +-(void)setAlign_content:(MyFlexGravity)align_content +{ + if (_align_content != align_content) + { + _align_content = align_content; + [self.view setNeedsLayout]; + } +} + -(UIEdgeInsets)padding { return ((MyFlexLayout*)self.view).padding; @@ -437,12 +550,12 @@ -(MyFlexAttrs*)attrs @implementation UIView(MyFlexLayout) --(MyFlexItem*)flexItem +-(MyFlexItem*)myFlex { MyFlexItem *obj = nil; if ([self isKindOfClass:[MyFlexLayout class]] ) { - obj = ((MyFlexLayout*)self).flex; + obj = ((MyFlexLayout*)self).myFlex; } else { @@ -466,7 +579,7 @@ -(instancetype)init self = [super init]; if (self != nil) { - _flex = [[MyFlex alloc] initWithView:self attrs:[MyFlexAttrs new]]; + _myFlex = [[MyFlex alloc] initWithView:self attrs:[MyFlexAttrs new]]; self.orientation = MyOrientation_Vert; //默认row self.arrangedCount = NSIntegerMax; //默认单行 self.isFlex = YES; //满足flexbox的需求。 @@ -480,7 +593,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( MyFlexLayout *lsc = self.myCurrentSizeClass; //最先设置方向。 - switch (self.flex.attrs.flex_direction) { + switch (self.myFlex.attrs.flex_direction) { case MyFlexDirection_Column_Reverse: //column_reverse lsc.orientation = MyOrientation_Horz; lsc.layoutTransform = CGAffineTransformMake(1,0,0,-1,0,0); //垂直翻转 @@ -501,7 +614,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( } //设置换行. - switch (self.flex.attrs.flex_wrap) { + switch (self.myFlex.attrs.flex_wrap) { case MyFlexWrap_Wrap: lsc.arrangedCount = 0; break; @@ -522,12 +635,12 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //按order排序。 [sbs sortWithOptions:NSSortStable usingComparator:^NSComparisonResult(UIView* _Nonnull obj1, UIView* _Nonnull obj2) { - return obj1.flexItem.attrs.order - obj2.flexItem.attrs.order; + return obj1.myFlex.attrs.order - obj2.myFlex.attrs.order; }]; for (UIView *sbv in sbs) { - MyFlexItem *flexItem = sbv.flexItem; + MyFlexItem *flexItem = sbv.myFlex; UIView *sbvsc = sbv.myCurrentSizeClass; //flex_grow,如果子视图有设置grow则父视图的换行不起作用。 @@ -589,7 +702,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //设置主轴的水平对齐和拉伸 MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = lsc.gravity & MyGravity_Vert_Mask; - switch (self.flex.attrs.justify_content) { + switch (self.myFlex.attrs.justify_content) { case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Vert) lsc.gravity = MyGravity_Horz_Trailing | vertGravity; @@ -626,7 +739,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //次轴的对齐处理。 MyGravity vertArrangedGravity = lsc.arrangedGravity & MyGravity_Horz_Mask; MyGravity horzArrangedGravity = lsc.arrangedGravity & MyGravity_Vert_Mask; - switch (self.flex.attrs.align_items) { + switch (self.myFlex.attrs.align_items) { case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Vert) lsc.arrangedGravity = MyGravity_Vert_Bottom | horzArrangedGravity; @@ -663,7 +776,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //多行下的整体停靠处理。 vertGravity = lsc.gravity & MyGravity_Horz_Mask; horzGravity = lsc.gravity & MyGravity_Vert_Mask; - switch (self.flex.attrs.align_content) { + switch (self.myFlex.attrs.align_content) { case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Horz) lsc.gravity = MyGravity_Horz_Trailing | vertGravity; diff --git a/MyLayoutDemo/AllTestExampleViewController.m b/MyLayoutDemo/AllTestExampleViewController.m index a745543..4642797 100644 --- a/MyLayoutDemo/AllTestExampleViewController.m +++ b/MyLayoutDemo/AllTestExampleViewController.m @@ -132,7 +132,7 @@ -(void)example2 -(void)example3 { //用链式语法创建一个弹性布局,宽度和父视图一致,高度为100 - MyFlexLayout *layout = MyFlexLayout.new.flex + MyFlexLayout *layout = MyFlexLayout.new.myFlex .flex_direction(MyFlexDirection_Row) .flex_wrap(MyFlexWrap_Wrap) .align_content(MyFlexGravity_Center) @@ -146,23 +146,23 @@ -(void)example3 .addTo(self.view); - UILabel *itemA = UILabel.new.flexItem + UILabel *itemA = UILabel.new.myFlex .width(MyLayoutSize.fill) .height(30) .addTo(layout); - UILabel *itemB = UILabel.new.flexItem + UILabel *itemB = UILabel.new.myFlex .flex_grow(1) .align_self(MyFlexGravity_Flex_Start) .height(30) .addTo(layout); - UILabel *itemC = UILabel.new.flexItem + UILabel *itemC = UILabel.new.myFlex .flex_grow(1) .height(40) .addTo(layout); - UILabel *itemD = UILabel.new.flexItem + UILabel *itemD = UILabel.new.myFlex .flex_grow(1) .height(50) .addTo(layout); diff --git a/MyLayoutDemo/FLXTest1ViewController.m b/MyLayoutDemo/FLXTest1ViewController.m index 54888ab..05c503e 100644 --- a/MyLayoutDemo/FLXTest1ViewController.m +++ b/MyLayoutDemo/FLXTest1ViewController.m @@ -29,29 +29,30 @@ @implementation FLXTest1ViewController -(void)loadView { + //根视图为flexbox布局视图。 - MyFlexLayout *rootLayout = MyFlexLayout.new.flex + MyFlexLayout *rootLayout = MyFlexLayout.new.myFlex .flex_direction(MyFlexDirection_Column) .vert_space(10) .view; self.view = rootLayout; //布局属性设置。 - MyFlexLayout *flexAttrLayout = MyFlexLayout.new.flex + MyFlexLayout *flexAttrLayout = MyFlexLayout.new.myFlex .flex_direction(MyFlexDirection_Row) .align_items(MyFlexGravity_Center) .width(MyLayoutSize.fill) .height(MyLayoutSize.wrap) .addTo(rootLayout); - UILabel *flexAttrTitleLabel = UILabel.new.flexItem + UILabel *flexAttrTitleLabel = UILabel.new.myFlex .width(MyLayoutSize.wrap) .height(MyLayoutSize.wrap) .addTo(flexAttrLayout); flexAttrTitleLabel.text = @"flex:"; - UISegmentedControl *flexAttrSeg = UISegmentedControl.new.flexItem + UISegmentedControl *flexAttrSeg = UISegmentedControl.new.myFlex .flex_grow(1) .height(MyLayoutSize.wrap) .addTo(flexAttrLayout); @@ -63,7 +64,7 @@ -(void)loadView [flexAttrSeg insertSegmentWithTitle:@"align_content" atIndex:4 animated:NO]; [flexAttrSeg addTarget:self action:@selector(handleFlexLayoutAttributeChange:) forControlEvents:UIControlEventValueChanged]; - UISegmentedControl *flex_directionSeg = UISegmentedControl.new.flexItem + UISegmentedControl *flex_directionSeg = UISegmentedControl.new.myFlex .width(MyLayoutSize.fill) .height(MyLayoutSize.wrap) .addTo(rootLayout); @@ -76,7 +77,7 @@ -(void)loadView [flex_directionSeg addTarget:self action:@selector(handleFlex_Direction:) forControlEvents:UIControlEventValueChanged]; self.flex_directionSeg = flex_directionSeg; - UISegmentedControl *flex_wrapSeg = UISegmentedControl.new.flexItem + UISegmentedControl *flex_wrapSeg = UISegmentedControl.new.myFlex .width(MyLayoutSize.fill) .height(MyLayoutSize.wrap) .visibility(MyVisibility_Gone) @@ -88,7 +89,7 @@ -(void)loadView [flex_wrapSeg addTarget:self action:@selector(handleFlex_Wrap:) forControlEvents:UIControlEventValueChanged]; self.flex_wrapSeg = flex_wrapSeg; - UISegmentedControl *justify_contentSeg = UISegmentedControl.new.flexItem + UISegmentedControl *justify_contentSeg = UISegmentedControl.new.myFlex .width(MyLayoutSize.fill) .height(MyLayoutSize.wrap) .visibility(MyVisibility_Gone) @@ -102,7 +103,7 @@ -(void)loadView [justify_contentSeg addTarget:self action:@selector(handleJustify_Content:) forControlEvents:UIControlEventValueChanged]; self.justify_contentSeg = justify_contentSeg; - UISegmentedControl *align_itemsSeg = UISegmentedControl.new.flexItem + UISegmentedControl *align_itemsSeg = UISegmentedControl.new.myFlex .width(MyLayoutSize.fill) .height(MyLayoutSize.wrap) .visibility(MyVisibility_Gone) @@ -117,7 +118,7 @@ -(void)loadView self.align_itemsSeg = align_itemsSeg; - UISegmentedControl *align_contentSeg = UISegmentedControl.new.flexItem + UISegmentedControl *align_contentSeg = UISegmentedControl.new.myFlex .width(MyLayoutSize.fill) .height(MyLayoutSize.wrap) .visibility(MyVisibility_Gone) @@ -133,42 +134,42 @@ -(void)loadView self.align_contentSeg = align_contentSeg; - MyFlexLayout *paddingLayout = MyFlexLayout.new.flex + MyFlexLayout *paddingLayout = MyFlexLayout.new.myFlex .flex_direction(MyFlexDirection_Row) .align_items(MyFlexGravity_Center) .width(MyLayoutSize.fill) .height(MyLayoutSize.wrap) .addTo(rootLayout); - UILabel *paddingTitleLabel = UILabel.new.flexItem + UILabel *paddingTitleLabel = UILabel.new.myFlex .width(MyLayoutSize.wrap) .height(MyLayoutSize.wrap) .addTo(paddingLayout); paddingTitleLabel.text = @"padding:"; - UISwitch *paddingSwitch = UISwitch.new.flexItem + UISwitch *paddingSwitch = UISwitch.new.myFlex .width(MyLayoutSize.wrap) .height(MyLayoutSize.wrap) .addTo(paddingLayout); [paddingSwitch addTarget:self action:@selector(handlePaddingChange:) forControlEvents:UIControlEventValueChanged]; - MyFlexLayout *spaceLayout = MyFlexLayout.new.flex + MyFlexLayout *spaceLayout = MyFlexLayout.new.myFlex .flex_direction(MyFlexDirection_Row) .align_items(MyFlexGravity_Center) .width(MyLayoutSize.fill) .height(MyLayoutSize.wrap) .addTo(rootLayout); - UILabel *spaceTitleLabel = UILabel.new.flexItem + UILabel *spaceTitleLabel = UILabel.new.myFlex .width(MyLayoutSize.wrap) .height(MyLayoutSize.wrap) .addTo(spaceLayout); spaceTitleLabel.text = @"space:"; - UISwitch *spaceSwitch = UISwitch.new.flexItem + UISwitch *spaceSwitch = UISwitch.new.myFlex .width(MyLayoutSize.wrap) .height(MyLayoutSize.wrap) .addTo(spaceLayout); @@ -176,7 +177,7 @@ -(void)loadView [spaceSwitch addTarget:self action:@selector(handleSpaceChange:) forControlEvents:UIControlEventValueChanged]; - UILabel *flexlayoutStyleDescLabel = UILabel.new.flexItem + UILabel *flexlayoutStyleDescLabel = UILabel.new.myFlex .width(MyLayoutSize.fill) .height(MyLayoutSize.wrap) .addTo(rootLayout); @@ -185,7 +186,7 @@ -(void)loadView flexlayoutStyleDescLabel.textColor = [CFTool color:6]; self.flexlayoutStyleDescLabel = flexlayoutStyleDescLabel; - UIButton *button = UIButton.new.flexItem + UIButton *button = UIButton.new.myFlex .width(MyLayoutSize.fill) .height(MyLayoutSize.wrap) .addTo(rootLayout); @@ -195,7 +196,7 @@ -(void)loadView [button addTarget:self action:@selector(handleAddItem:) forControlEvents:UIControlEventTouchUpInside]; - MyFlexLayout *contentLayout = MyFlexLayout.new.flex + MyFlexLayout *contentLayout = MyFlexLayout.new.myFlex .width(MyLayoutSize.fill) .flex_grow(1) .addTo(rootLayout); @@ -234,7 +235,7 @@ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { -(void)updateStyleDesc { NSString *strFlexDirection = @""; - switch (self.contentLayout.flex.attrs.flex_direction) { + switch (self.contentLayout.myFlex.attrs.flex_direction) { case MyFlexDirection_Row: strFlexDirection =@"row;"; break; @@ -252,7 +253,7 @@ -(void)updateStyleDesc } NSString *strFlexWrap = @""; - switch (self.contentLayout.flex.attrs.flex_wrap) { + switch (self.contentLayout.myFlex.attrs.flex_wrap) { case MyFlexWrap_NoWrap: strFlexWrap = @"nowrap;"; break; @@ -267,7 +268,7 @@ -(void)updateStyleDesc } NSString *strJustifyContent = @""; - switch (self.contentLayout.flex.attrs.justify_content) { + switch (self.contentLayout.myFlex.attrs.justify_content) { case MyFlexGravity_Flex_Start: strJustifyContent = @"flex-start;"; break; @@ -287,7 +288,7 @@ -(void)updateStyleDesc } NSString *strAlignItems = @""; - switch (self.contentLayout.flex.attrs.align_items) { + switch (self.contentLayout.myFlex.attrs.align_items) { case MyFlexGravity_Flex_End: strAlignItems = @"flex-end;"; break; @@ -307,7 +308,7 @@ -(void)updateStyleDesc } NSString *strAlignContent = @""; - switch (self.contentLayout.flex.attrs.align_content) { + switch (self.contentLayout.myFlex.attrs.align_content) { case MyFlexGravity_Flex_End: strAlignContent = @"flex-end;"; break; @@ -342,7 +343,7 @@ -(void)updateStyleDesc -(void)editFlexItem:(UIView*)itemView { //创建一个 - MyFlexLayout *dialogLayout = MyFlexLayout.new.flex + MyFlexLayout *dialogLayout = MyFlexLayout.new.myFlex .flex_direction(MyFlexDirection_Row) .align_items(MyFlexGravity_Center) .flex_wrap(MyFlexWrap_Wrap) @@ -357,14 +358,14 @@ -(void)editFlexItem:(UIView*)itemView dialogLayout.backgroundColor = [CFTool color:2]; - UILabel *widthLabel = UILabel.new.flexItem + UILabel *widthLabel = UILabel.new.myFlex .width(MyLayoutSize.wrap) .height(MyLayoutSize.wrap) .addTo(dialogLayout); widthLabel.text = @"width:"; - UITextField *widthTextField = UITextField.new.flexItem + UITextField *widthTextField = UITextField.new.myFlex .width(100) .flex_grow(1) .height(30) @@ -374,14 +375,14 @@ -(void)editFlexItem:(UIView*)itemView widthTextField.borderStyle = UITextBorderStyleRoundedRect; widthTextField.placeholder = @"数字|wrap|fill|空"; - UILabel *heightLabel = UILabel.new.flexItem + UILabel *heightLabel = UILabel.new.myFlex .width(MyLayoutSize.wrap) .height(MyLayoutSize.wrap) .addTo(dialogLayout); heightLabel.text = @"height:"; - UITextField *heightTextField = UITextField.new.flexItem + UITextField *heightTextField = UITextField.new.myFlex .width(100) .flex_grow(1) .height(30) @@ -392,14 +393,14 @@ -(void)editFlexItem:(UIView*)itemView heightTextField.placeholder = @"数字|wrap|fill|空"; - UILabel *orderLabel = UILabel.new.flexItem + UILabel *orderLabel = UILabel.new.myFlex .width(MyLayoutSize.wrap) .height(MyLayoutSize.wrap) .addTo(dialogLayout); orderLabel.text = @"order:"; - UITextField *orderTextField = UITextField.new.flexItem + UITextField *orderTextField = UITextField.new.myFlex .width(100) .flex_grow(1) .height(30) @@ -410,14 +411,14 @@ -(void)editFlexItem:(UIView*)itemView orderTextField.placeholder = @"数字|空"; - UILabel *flex_growLabel = UILabel.new.flexItem + UILabel *flex_growLabel = UILabel.new.myFlex .width(MyLayoutSize.wrap) .height(MyLayoutSize.wrap) .addTo(dialogLayout); flex_growLabel.text = @"flex-grow:"; - UITextField *flex_growTextField = UITextField.new.flexItem + UITextField *flex_growTextField = UITextField.new.myFlex .width(100) .flex_grow(1) .height(30) @@ -428,14 +429,14 @@ -(void)editFlexItem:(UIView*)itemView flex_growTextField.placeholder = @"数字|空"; - UILabel *flex_shrinkLabel = UILabel.new.flexItem + UILabel *flex_shrinkLabel = UILabel.new.myFlex .width(MyLayoutSize.wrap) .height(MyLayoutSize.wrap) .addTo(dialogLayout); flex_shrinkLabel.text = @"flex-shrink:"; - UITextField *flex_shrinkTextField = UITextField.new.flexItem + UITextField *flex_shrinkTextField = UITextField.new.myFlex .width(100) .flex_grow(1) .height(30) @@ -446,14 +447,14 @@ -(void)editFlexItem:(UIView*)itemView flex_shrinkTextField.placeholder = @"数字|空"; - UILabel *flex_basisLabel = UILabel.new.flexItem + UILabel *flex_basisLabel = UILabel.new.myFlex .width(MyLayoutSize.wrap) .height(MyLayoutSize.wrap) .addTo(dialogLayout); flex_basisLabel.text = @"flex-basis:"; - UITextField *flex_basisTextField = UITextField.new.flexItem + UITextField *flex_basisTextField = UITextField.new.myFlex .width(100) .flex_grow(1) .height(30) @@ -464,14 +465,14 @@ -(void)editFlexItem:(UIView*)itemView flex_basisTextField.placeholder = @"数字|空"; - UILabel *align_selfLabel = UILabel.new.flexItem + UILabel *align_selfLabel = UILabel.new.myFlex .width(MyLayoutSize.wrap) .height(MyLayoutSize.wrap) .addTo(dialogLayout); align_selfLabel.text = @"align-self:"; - UITextField *align_selfTextField = UITextField.new.flexItem + UITextField *align_selfTextField = UITextField.new.myFlex .width(100) .flex_grow(1) .height(30) @@ -482,7 +483,7 @@ -(void)editFlexItem:(UIView*)itemView align_selfTextField.placeholder = @"flex-start|flex-end|center|stretch|baseline|auto"; - UIButton *addButton = UIButton.new.flexItem + UIButton *addButton = UIButton.new.myFlex .flex_grow(1) .width(50) .height(30) @@ -500,7 +501,7 @@ -(void)editFlexItem:(UIView*)itemView [addButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [addButton addTarget:self action:@selector(handleSaveItem:) forControlEvents:UIControlEventTouchUpInside]; - UIButton *closeButton = UIButton.new.flexItem + UIButton *closeButton = UIButton.new.myFlex .flex_grow(1) .width(50) .height(30) @@ -511,7 +512,7 @@ -(void)editFlexItem:(UIView*)itemView [closeButton addTarget:self action:@selector(handleCloseDialog:) forControlEvents:UIControlEventTouchUpInside]; - UILabel *tipLabel = UILabel.new.flexItem + UILabel *tipLabel = UILabel.new.myFlex .width(MyLayoutSize.fill) .height(MyLayoutSize.wrap) .addTo(dialogLayout); @@ -520,40 +521,40 @@ -(void)editFlexItem:(UIView*)itemView if (itemView != nil) { - if (itemView.flexItem.attrs.width == MyLayoutSize.wrap) + if (itemView.myFlex.attrs.width == MyLayoutSize.wrap) widthTextField.text = @"wrap"; - else if (itemView.flexItem.attrs.width == MyLayoutSize.fill) + else if (itemView.myFlex.attrs.width == MyLayoutSize.fill) widthTextField.text = @"fill"; - else if (itemView.flexItem.attrs.width != 0) - widthTextField.text = [@(itemView.flexItem.attrs.width) stringValue]; + else if (itemView.myFlex.attrs.width != 0) + widthTextField.text = [@(itemView.myFlex.attrs.width) stringValue]; else widthTextField.text = @""; - if (itemView.flexItem.attrs.height == MyLayoutSize.wrap) + if (itemView.myFlex.attrs.height == MyLayoutSize.wrap) heightTextField.text = @"wrap"; - else if (itemView.flexItem.attrs.height == MyLayoutSize.fill) + else if (itemView.myFlex.attrs.height == MyLayoutSize.fill) heightTextField.text = @"fill"; - else if (itemView.flexItem.attrs.height != 0) - heightTextField.text = [@(itemView.flexItem.attrs.height) stringValue]; + else if (itemView.myFlex.attrs.height != 0) + heightTextField.text = [@(itemView.myFlex.attrs.height) stringValue]; else heightTextField.text = @""; - if (itemView.flexItem.attrs.order != 0) - orderTextField.text = [@(itemView.flexItem.attrs.order) stringValue]; + if (itemView.myFlex.attrs.order != 0) + orderTextField.text = [@(itemView.myFlex.attrs.order) stringValue]; - if (itemView.flexItem.attrs.flex_grow != 0) - flex_growTextField.text = [@(itemView.flexItem.attrs.flex_grow) stringValue]; + if (itemView.myFlex.attrs.flex_grow != 0) + flex_growTextField.text = [@(itemView.myFlex.attrs.flex_grow) stringValue]; - if (itemView.flexItem.attrs.flex_shrink != 1) - flex_shrinkTextField.text = [@(itemView.flexItem.attrs.flex_shrink) stringValue]; + if (itemView.myFlex.attrs.flex_shrink != 1) + flex_shrinkTextField.text = [@(itemView.myFlex.attrs.flex_shrink) stringValue]; - if (itemView.flexItem.attrs.flex_basis != MyFlex_Auto) - flex_basisTextField.text = [@(itemView.flexItem.attrs.flex_basis) stringValue]; + if (itemView.myFlex.attrs.flex_basis != MyFlex_Auto) + flex_basisTextField.text = [@(itemView.myFlex.attrs.flex_basis) stringValue]; - switch (itemView.flexItem.attrs.align_self) { + switch (itemView.myFlex.attrs.align_self) { case MyFlexGravity_Flex_Start: align_selfTextField.text = @"flex-start"; break; @@ -580,17 +581,17 @@ -(void)editFlexItem:(UIView*)itemView -(IBAction)handleFlexLayoutAttributeChange:(UISegmentedControl*)sender { - self.flex_directionSeg.flexItem.visibility(MyVisibility_Gone); - self.flex_wrapSeg.flexItem.visibility(MyVisibility_Gone); - self.justify_contentSeg.flexItem.visibility(MyVisibility_Gone); - self.align_itemsSeg.flexItem.visibility(MyVisibility_Gone); - self.align_contentSeg.flexItem.visibility(MyVisibility_Gone); + self.flex_directionSeg.myFlex.visibility(MyVisibility_Gone); + self.flex_wrapSeg.myFlex.visibility(MyVisibility_Gone); + self.justify_contentSeg.myFlex.visibility(MyVisibility_Gone); + self.align_itemsSeg.myFlex.visibility(MyVisibility_Gone); + self.align_contentSeg.myFlex.visibility(MyVisibility_Gone); switch (sender.selectedSegmentIndex) { case 0: { - self.flex_directionSeg.flexItem.visibility(MyVisibility_Visible); - switch (self.contentLayout.flex.attrs.flex_direction) { + self.flex_directionSeg.myFlex.visibility(MyVisibility_Visible); + switch (self.contentLayout.myFlex.attrs.flex_direction) { case MyFlexDirection_Row: self.flex_directionSeg.selectedSegmentIndex = 0; break; @@ -609,8 +610,8 @@ -(IBAction)handleFlexLayoutAttributeChange:(UISegmentedControl*)sender break; case 1: { - self.flex_wrapSeg.flexItem.visibility(MyVisibility_Visible); - switch (self.contentLayout.flex.attrs.flex_wrap) { + self.flex_wrapSeg.myFlex.visibility(MyVisibility_Visible); + switch (self.contentLayout.myFlex.attrs.flex_wrap) { case MyFlexWrap_Wrap: self.flex_wrapSeg.selectedSegmentIndex = 1; break; @@ -627,8 +628,8 @@ -(IBAction)handleFlexLayoutAttributeChange:(UISegmentedControl*)sender break; case 2: { - self.justify_contentSeg.flexItem.visibility(MyVisibility_Visible); - switch (self.contentLayout.flex.attrs.justify_content) { + self.justify_contentSeg.myFlex.visibility(MyVisibility_Visible); + switch (self.contentLayout.myFlex.attrs.justify_content) { case MyFlexGravity_Flex_Start: self.justify_contentSeg.selectedSegmentIndex = 0; break; @@ -650,8 +651,8 @@ -(IBAction)handleFlexLayoutAttributeChange:(UISegmentedControl*)sender break; case 3: { - self.align_itemsSeg.flexItem.visibility(MyVisibility_Visible); - switch (self.contentLayout.flex.attrs.align_items) { + self.align_itemsSeg.myFlex.visibility(MyVisibility_Visible); + switch (self.contentLayout.myFlex.attrs.align_items) { case MyFlexGravity_Flex_Start: self.align_itemsSeg.selectedSegmentIndex = 0; break; @@ -674,8 +675,8 @@ -(IBAction)handleFlexLayoutAttributeChange:(UISegmentedControl*)sender break; case 4: { - self.align_contentSeg.flexItem.visibility(MyVisibility_Visible); - switch (self.contentLayout.flex.attrs.align_content) { + self.align_contentSeg.myFlex.visibility(MyVisibility_Visible); + switch (self.contentLayout.myFlex.attrs.align_content) { case MyFlexGravity_Flex_Start: self.align_contentSeg.selectedSegmentIndex = 0; break; @@ -707,95 +708,91 @@ -(void)handleFlex_Direction:(UISegmentedControl*)sender { switch (sender.selectedSegmentIndex) { case 0: - self.contentLayout.flex.flex_direction(MyFlexDirection_Row); + self.contentLayout.myFlex.flex_direction(MyFlexDirection_Row); break; case 1: - self.contentLayout.flex.flex_direction(MyFlexDirection_Row_Reverse); + self.contentLayout.myFlex.flex_direction(MyFlexDirection_Row_Reverse); break; case 2: - self.contentLayout.flex.flex_direction(MyFlexDirection_Column); + self.contentLayout.myFlex.flex_direction(MyFlexDirection_Column); break; case 3: - self.contentLayout.flex.flex_direction(MyFlexDirection_Column_Reverse); + self.contentLayout.myFlex.flex_direction(MyFlexDirection_Column_Reverse); case 4: default: break; } [self updateStyleDesc]; - [self.contentLayout setNeedsLayout]; } -(void)handleFlex_Wrap:(UISegmentedControl*)sender { switch (sender.selectedSegmentIndex) { case 0: - self.contentLayout.flex.flex_wrap(MyFlexWrap_NoWrap); + self.contentLayout.myFlex.flex_wrap(MyFlexWrap_NoWrap); break; case 1: - self.contentLayout.flex.flex_wrap(MyFlexWrap_Wrap); + self.contentLayout.myFlex.flex_wrap(MyFlexWrap_Wrap); break; case 2: - self.contentLayout.flex.flex_wrap(MyFlexWrap_Wrap_Reverse); + self.contentLayout.myFlex.flex_wrap(MyFlexWrap_Wrap_Reverse); break; default: break; } [self updateStyleDesc]; - [self.contentLayout setNeedsLayout]; } -(void)handleJustify_Content:(UISegmentedControl*)sender { switch (sender.selectedSegmentIndex) { case 0: - self.contentLayout.flex.justify_content(MyFlexGravity_Flex_Start); + self.contentLayout.myFlex.justify_content(MyFlexGravity_Flex_Start); break; case 1: - self.contentLayout.flex.justify_content(MyFlexGravity_Flex_End); + self.contentLayout.myFlex.justify_content(MyFlexGravity_Flex_End); break; case 2: - self.contentLayout.flex.justify_content(MyFlexGravity_Center); + self.contentLayout.myFlex.justify_content(MyFlexGravity_Center); break; case 3: - self.contentLayout.flex.justify_content(MyFlexGravity_Space_Between); + self.contentLayout.myFlex.justify_content(MyFlexGravity_Space_Between); break; case 4: - self.contentLayout.flex.justify_content(MyFlexGravity_Space_Around); + self.contentLayout.myFlex.justify_content(MyFlexGravity_Space_Around); break; default: break; } [self updateStyleDesc]; - [self.contentLayout setNeedsLayout]; } -(void)handleAlign_Items:(UISegmentedControl*)sender { switch (sender.selectedSegmentIndex) { case 0: - self.contentLayout.flex.align_items(MyFlexGravity_Flex_Start); + self.contentLayout.myFlex.align_items(MyFlexGravity_Flex_Start); break; case 1: - self.contentLayout.flex.align_items(MyFlexGravity_Flex_End); + self.contentLayout.myFlex.align_items(MyFlexGravity_Flex_End); break; case 2: - self.contentLayout.flex.align_items(MyFlexGravity_Center); + self.contentLayout.myFlex.align_items(MyFlexGravity_Center); break; case 3: - self.contentLayout.flex.align_items(MyFlexGravity_Stretch); + self.contentLayout.myFlex.align_items(MyFlexGravity_Stretch); break; case 4: - self.contentLayout.flex.align_items(MyFlexGravity_Baseline); + self.contentLayout.myFlex.align_items(MyFlexGravity_Baseline); break; default: break; } [self updateStyleDesc]; - [self.contentLayout setNeedsLayout]; } @@ -803,46 +800,45 @@ -(void)handleAlign_Content:(UISegmentedControl*)sender { switch (sender.selectedSegmentIndex) { case 0: - self.contentLayout.flex.align_content(MyFlexGravity_Flex_Start); + self.contentLayout.myFlex.align_content(MyFlexGravity_Flex_Start); break; case 1: - self.contentLayout.flex.align_content(MyFlexGravity_Flex_End); + self.contentLayout.myFlex.align_content(MyFlexGravity_Flex_End); break; case 2: - self.contentLayout.flex.align_content(MyFlexGravity_Center); + self.contentLayout.myFlex.align_content(MyFlexGravity_Center); break; case 3: - self.contentLayout.flex.align_content(MyFlexGravity_Space_Between); + self.contentLayout.myFlex.align_content(MyFlexGravity_Space_Between); break; case 4: - self.contentLayout.flex.align_content(MyFlexGravity_Space_Around); + self.contentLayout.myFlex.align_content(MyFlexGravity_Space_Around); break; case 5: - self.contentLayout.flex.align_content(MyFlexGravity_Stretch); + self.contentLayout.myFlex.align_content(MyFlexGravity_Stretch); break; default: break; } [self updateStyleDesc]; - [self.contentLayout setNeedsLayout]; } -(IBAction)handleSpaceChange:(UISwitch*)sender { if (sender.isOn) - self.contentLayout.flex.vert_space(10).horz_space(10); + self.contentLayout.myFlex.vert_space(10).horz_space(10); else - self.contentLayout.flex.vert_space(0).horz_space(0); + self.contentLayout.myFlex.vert_space(0).horz_space(0); } -(IBAction)handlePaddingChange:(UISwitch*)sender { if (sender.isOn) - self.contentLayout.flex.padding(UIEdgeInsetsMake(20, 20, 20, 20)); + self.contentLayout.myFlex.padding(UIEdgeInsetsMake(20, 20, 20, 20)); else - self.contentLayout.flex.padding(UIEdgeInsetsZero); + self.contentLayout.myFlex.padding(UIEdgeInsetsZero); } @@ -890,61 +886,59 @@ -(IBAction)handleSaveItem:(UIButton*)sender NSString *widthStr = widthTextField.text; if ([widthStr isEqualToString:@"wrap"]) - itemView.flexItem.attrs.width = MyLayoutSize.wrap; + itemView.myFlex.attrs.width = MyLayoutSize.wrap; else if ([widthStr isEqualToString:@"fill"]) - itemView.flexItem.attrs.width = MyLayoutSize.fill; + itemView.myFlex.attrs.width = MyLayoutSize.fill; else - itemView.flexItem.attrs.width = widthStr.doubleValue; + itemView.myFlex.attrs.width = widthStr.doubleValue; NSString *heightStr = heightTextField.text; if ([heightStr isEqualToString:@"wrap"]) - itemView.flexItem.attrs.height = MyLayoutSize.wrap; + itemView.myFlex.attrs.height = MyLayoutSize.wrap; else if ([heightStr isEqualToString:@"fill"]) - itemView.flexItem.attrs.height = MyLayoutSize.fill; + itemView.myFlex.attrs.height = MyLayoutSize.fill; else - itemView.flexItem.attrs.height = heightStr.doubleValue; + itemView.myFlex.attrs.height = heightStr.doubleValue; [itemView setTitle:orderTextField.text forState:UIControlStateNormal]; - itemView.flexItem.attrs.order = orderTextField.text.integerValue; + itemView.myFlex.attrs.order = orderTextField.text.integerValue; - itemView.flexItem.attrs.flex_grow = flex_growTextField.text.doubleValue; + itemView.myFlex.attrs.flex_grow = flex_growTextField.text.doubleValue; if (flex_shrinkTextField.text.length > 0) - itemView.flexItem.attrs.flex_shrink = flex_shrinkTextField.text.doubleValue; + itemView.myFlex.attrs.flex_shrink = flex_shrinkTextField.text.doubleValue; else - itemView.flexItem.attrs.flex_shrink = 1; + itemView.myFlex.attrs.flex_shrink = 1; if (flex_basisTextField.text.length > 0) - itemView.flexItem.attrs.flex_basis = flex_basisTextField.text.doubleValue; + itemView.myFlex.attrs.flex_basis = flex_basisTextField.text.doubleValue; else - itemView.flexItem.attrs.flex_basis = MyFlex_Auto; + itemView.myFlex.attrs.flex_basis = MyFlex_Auto; if (align_selfTextField.text.length > 0) { if ([align_selfTextField.text isEqualToString:@"flex-start"]) - itemView.flexItem.attrs.align_self = MyFlexGravity_Flex_Start; + itemView.myFlex.attrs.align_self = MyFlexGravity_Flex_Start; else if ([align_selfTextField.text isEqualToString:@"flex-end"]) - itemView.flexItem.attrs.align_self = MyFlexGravity_Flex_End; + itemView.myFlex.attrs.align_self = MyFlexGravity_Flex_End; else if ([align_selfTextField.text isEqualToString:@"center"]) - itemView.flexItem.attrs.align_self = MyFlexGravity_Center; + itemView.myFlex.attrs.align_self = MyFlexGravity_Center; else if ([align_selfTextField.text isEqualToString:@"baseline"]) - itemView.flexItem.attrs.align_self = MyFlexGravity_Baseline; + itemView.myFlex.attrs.align_self = MyFlexGravity_Baseline; else if ([align_selfTextField.text isEqualToString:@"stretch"]) - itemView.flexItem.attrs.align_self = MyFlexGravity_Stretch; + itemView.myFlex.attrs.align_self = MyFlexGravity_Stretch; else - itemView.flexItem.attrs.align_self = MyFlex_Auto; + itemView.myFlex.attrs.align_self = MyFlex_Auto; } else { - itemView.flexItem.attrs.align_self = MyFlex_Auto; + itemView.myFlex.attrs.align_self = MyFlex_Auto; } //销毁对话框。 - [sender.superview removeFromSuperview]; - - [self.contentLayout setNeedsLayout]; + [sender.superview removeFromSuperview]; } -(IBAction)handleModifyItemView:(UITapGestureRecognizer*)sender From c103e2f34d9711c76877a838a71881edd5f24882 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Thu, 14 Nov 2019 09:12:52 +0800 Subject: [PATCH 084/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlexLayout.m | 9 --------- 1 file changed, 9 deletions(-) diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index 633d61e..f9662cc 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -159,10 +159,8 @@ @implementation MyFlexItem __weak UIView *_view; MyFlexItemAttrs *_attrs; } - @dynamic attrs; - -(instancetype)initWithView:(UIView*)view attrs:(MyFlexItemAttrs*)attrs { self = [super init]; @@ -379,13 +377,6 @@ -(instancetype)init return self; } -//@property(nonatomic, assign) MyFlexDirection flex_direction; -//@property(nonatomic, assign) MyFlexWrap flex_wrap; -//@property(nonatomic, assign) MyFlexGravity justify_content; -//@property(nonatomic, assign) MyFlexGravity align_items; -//@property(nonatomic, assign) MyFlexGravity align_content; - - -(void)setFlex_direction:(MyFlexDirection)flex_direction { if (_flex_direction != flex_direction) From 2953028c33d19a7b9bcd4a495eb0e7b2d7f16734 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Thu, 14 Nov 2019 13:24:23 +0800 Subject: [PATCH 085/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyRelativeLayout.m | 2 + MyLayoutDemo/AllTestExampleViewController.m | 58 +++++++++++++-------- MyLayoutTests/MyFlowLayoutTestCase.m | 24 ++++----- MyLayoutTests/MyRelativeLayoutTestCase.m | 43 +++++++++++++++ 4 files changed, 92 insertions(+), 35 deletions(-) diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 45bb4c6..2c2ef8b 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -65,6 +65,8 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( sbvmyFrame.sizeClass = [sbv myBestSizeClass:sizeClass myFrame:sbvmyFrame]; } } + else + [sbvmyFrame reset]; } else { diff --git a/MyLayoutDemo/AllTestExampleViewController.m b/MyLayoutDemo/AllTestExampleViewController.m index 4642797..0e8c2fe 100644 --- a/MyLayoutDemo/AllTestExampleViewController.m +++ b/MyLayoutDemo/AllTestExampleViewController.m @@ -232,33 +232,45 @@ -(void)example4 -(void)example5 { - MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; + MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + rootLayout.myHeight = MyLayoutSize.wrap; rootLayout.myHorzMargin = 0; - rootLayout.tag = 100; - [self.view addSubview:rootLayout]; + rootLayout.padding = UIEdgeInsetsMake(12, 12, 12, 12); -// UIView * v = [UIView new]; -// v.mySize = CGSizeMake(100, 100); -// [rootLayout addSubview:v]; + MyLinearLayout *headerLayout = [MyLinearLayout linearLayoutWithOrientation:(MyOrientation_Horz)]; + headerLayout.topPos.equalTo(rootLayout.topPos); + headerLayout.leftPos.equalTo(rootLayout.leftPos); + headerLayout.wrapContentHeight = YES; + [rootLayout addSubview:headerLayout]; - MyLinearLayout *v = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; - v.tag = 200; - v.hidden = YES; - v.backgroundColor = [UIColor redColor]; - v.mySize = CGSizeMake(100, 100); - // v.myHorzMargin = 0; - // v.myHeight = 100; - [rootLayout addSubview:v]; + UIImageView *headerView = UIImageView.alloc.init; + headerView.mySize = CGSizeMake(32, 32); + [headerLayout addSubview:headerView]; + + UILabel *nameLabel = [UILabel new]; + nameLabel.text = @"欧阳大哥"; + nameLabel.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + nameLabel.alignment = MyGravity_Vert_Center; + nameLabel.myLeft = 5; + [headerLayout addSubview:nameLabel]; + + UILabel *titleLabel = [UILabel new]; + titleLabel.text = @"大师傅阿萨德阿斯蒂芬阿斯蒂芬"; + titleLabel.myHeight = MyLayoutSize.wrap; + titleLabel.leftPos.equalTo(headerLayout.leftPos).offset(32 + 5); + titleLabel.topPos.equalTo(headerLayout.bottomPos).offset(5); + titleLabel.rightPos.equalTo(rootLayout.rightPos); + [rootLayout addSubview:titleLabel]; + + MyLinearLayout *barView = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + barView.myHeight = 20; + barView.leftPos.equalTo(titleLabel.leftPos); + barView.rightPos.equalTo(rootLayout.rightPos); + barView.topPos.equalTo(titleLabel.bottomPos); + [rootLayout addSubview:barView]; + + [self.view addSubview:rootLayout]; - [NSTimer scheduledTimerWithTimeInterval:30 repeats:NO block:^(NSTimer * _Nonnull timer) { - - v.hidden = NO; - -// UIView *vv1 = [UIView new]; -// vv1.mySize = CGSizeMake(100, 100); -// [v addSubview:vv1]; - - }]; } @end diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index 3ae92f7..1677719 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -1105,7 +1105,7 @@ -(void)testFlex1 //测试内容约束布局下的尺寸自适应,以及最大最小值设置的场景。 { - MyFlexLayout *flexLayout = MyFlexLayout.new.flex + MyFlexLayout *flexLayout = MyFlexLayout.new.myFlex .align_items(MyFlexGravity_Center) .justify_content(MyFlexGravity_Center) .margin(0) @@ -1115,7 +1115,7 @@ -(void)testFlex1 flexLayout.backgroundColor = [UIColor redColor]; - MyFlexLayout *contentLayout = MyFlexLayout.new.flex + MyFlexLayout *contentLayout = MyFlexLayout.new.myFlex .flex_wrap(MyFlexWrap_Wrap) .width(MyLayoutSize.wrap) .max_width(100) @@ -1124,21 +1124,21 @@ -(void)testFlex1 contentLayout.backgroundColor = [UIColor greenColor]; - UILabel *lb1 = UILabel.new.flexItem + UILabel *lb1 = UILabel.new.myFlex .width(30) .height(30) .addTo(contentLayout); lb1.backgroundColor = [UIColor blueColor]; - UILabel *lb2 = UILabel.new.flexItem + UILabel *lb2 = UILabel.new.myFlex .width(40) .height(40) .addTo(contentLayout); lb2.backgroundColor = [UIColor yellowColor]; - UILabel *lb3 = UILabel.new.flexItem + UILabel *lb3 = UILabel.new.myFlex .width(50) .height(50) .addTo(contentLayout); @@ -1151,7 +1151,7 @@ -(void)testFlex1 MyRectAssert(contentLayout, CGRectMake((300-100)/2.0, (300-90)/2.0, 100, 90)); MyRectAssert(lb3, CGRectMake(0, 40, 50, 50)); - contentLayout.flex.height(30); + contentLayout.myFlex.height(30); [flexLayout setNeedsLayout]; [contentLayout setNeedsLayout]; [contentLayout layoutIfNeeded]; @@ -1163,7 +1163,7 @@ -(void)testFlex1 } { - MyFlexLayout *flexLayout = MyFlexLayout.new.flex + MyFlexLayout *flexLayout = MyFlexLayout.new.myFlex .align_items(MyFlexGravity_Center) .justify_content(MyFlexGravity_Center) .margin(0) @@ -1173,7 +1173,7 @@ -(void)testFlex1 flexLayout.backgroundColor = [UIColor redColor]; - MyFlexLayout *contentLayout = MyFlexLayout.new.flex + MyFlexLayout *contentLayout = MyFlexLayout.new.myFlex .flex_wrap(MyFlexWrap_Wrap) .flex_direction(MyFlexDirection_Column) .width(MyLayoutSize.wrap) @@ -1183,21 +1183,21 @@ -(void)testFlex1 contentLayout.backgroundColor = [UIColor greenColor]; - UILabel *lb1 = UILabel.new.flexItem + UILabel *lb1 = UILabel.new.myFlex .width(30) .height(30) .addTo(contentLayout); lb1.backgroundColor = [UIColor blueColor]; - UILabel *lb2 = UILabel.new.flexItem + UILabel *lb2 = UILabel.new.myFlex .width(40) .height(40) .addTo(contentLayout); lb2.backgroundColor = [UIColor yellowColor]; - UILabel *lb3 = UILabel.new.flexItem + UILabel *lb3 = UILabel.new.myFlex .width(50) .height(50) .addTo(contentLayout); @@ -1210,7 +1210,7 @@ -(void)testFlex1 MyRectAssert(contentLayout, CGRectMake((300-90)/2.0,(300-100)/2.0,90,100)); MyRectAssert(lb3, CGRectMake(40, 0, 50, 50)); - contentLayout.flex.width(30); + contentLayout.myFlex.width(30); [flexLayout setNeedsLayout]; [contentLayout setNeedsLayout]; [contentLayout layoutIfNeeded]; diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index 65763e9..08edb5d 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -1389,6 +1389,49 @@ -(void)testExample1 XCTAssertTrue(CGRectEqualToRect(v7.frame, CGRectMake(0,-16,100,100)), @"the v7.frame = %@",NSStringFromCGRect(v7.frame)); } +-(void)testWrapContentHeight4 +{ + MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + rootLayout.myHeight = MyLayoutSize.wrap; + rootLayout.padding = UIEdgeInsetsMake(12, 12, 12, 12); + + MyLinearLayout *headerLayout = [MyLinearLayout linearLayoutWithOrientation:(MyOrientation_Horz)]; + headerLayout.topPos.equalTo(rootLayout.topPos); + headerLayout.leftPos.equalTo(rootLayout.leftPos); + headerLayout.wrapContentHeight = YES; + [rootLayout addSubview:headerLayout]; + + UIImageView *headerView = UIImageView.alloc.init; + headerView.mySize = CGSizeMake(32, 32); + [headerLayout addSubview:headerView]; + + UILabel *nameLabel = [UILabel new]; + nameLabel.text = @"欧阳大哥"; + nameLabel.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + nameLabel.alignment = MyGravity_Vert_Center; + nameLabel.myLeft = 5; + [headerLayout addSubview:nameLabel]; + + UILabel *titleLabel = [UILabel new]; + titleLabel.text = @"大师傅阿萨德阿斯蒂芬阿斯蒂芬"; + titleLabel.myHeight = MyLayoutSize.wrap; + titleLabel.leftPos.equalTo(headerLayout.leftPos).offset(32 + 5); + titleLabel.topPos.equalTo(headerLayout.bottomPos).offset(5); + titleLabel.rightPos.equalTo(rootLayout.rightPos); + [rootLayout addSubview:titleLabel]; + + MyLinearLayout *barView = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; + barView.myHeight = 20; + barView.leftPos.equalTo(titleLabel.leftPos); + barView.rightPos.equalTo(rootLayout.rightPos); + barView.topPos.equalTo(titleLabel.bottomPos); + [rootLayout addSubview:barView]; + + CGSize sz = [rootLayout sizeThatFits:CGSizeMake(375, 0)]; + MySizeAssert(rootLayout,sz,CGSizeMake(375, 101.5)); + //MyRectAssert(rootLayout, CGRectMake(0, 0, sz.width, sz.height)); +} + - (void)testPerformanceExample { // This is an example of a performance test case. [self measureBlock:^{ From bcccffeb9b5c80d9d4a5d41d52ce85baedc93cc4 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Thu, 14 Nov 2019 16:03:28 +0800 Subject: [PATCH 086/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyRelativeLayout.m | 13 +++-- MyLayoutTests/MyRelativeLayoutTestCase.m | 61 ++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 2c2ef8b..568575d 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -263,17 +263,17 @@ -(void)myLayout:(MyRelativeLayoutViewSizeClass*)lsc if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) sbvmyFrame.leading -= sbvsc.leadingPosInner.absVal; - sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; + sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width + sbvsc.trailingPosInner.absVal; } else if (sbvsc.leadingPosInner.posMostVal != nil) { sbvmyFrame.leading = sbvsc.leadingPosInner.posMostVal.doubleValue + sbvsc.leadingPosInner.absVal; - sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; + sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width + sbvsc.trailingPosInner.absVal; } else if (sbvsc.leadingPosInner.posNumVal != nil) { sbvmyFrame.leading = sbvsc.leadingPosInner.absVal + lsc.myLayoutLeadingPadding; - sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width; + sbvmyFrame.trailing = sbvmyFrame.leading + sbvmyFrame.width + sbvsc.trailingPosInner.absVal; } else if (sbvsc.trailingPosInner.posRelaVal != nil) { @@ -531,17 +531,17 @@ -(void)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcTopBottomOfSubview:(MyVi if (relaView != nil && relaView != self && [self myIsNoLayoutSubview:relaView]) sbvmyFrame.top -= sbvsc.topPosInner.absVal; - sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; + sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height + sbvsc.bottomPosInner.absVal; } else if (sbvsc.topPosInner.posMostVal != nil) { sbvmyFrame.top = sbvsc.topPosInner.posMostVal.doubleValue + sbvsc.topPosInner.absVal; - sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; + sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height + sbvsc.bottomPosInner.absVal; } else if (sbvsc.topPosInner.posNumVal != nil) { sbvmyFrame.top = sbvsc.topPosInner.absVal + lsc.myLayoutTopPadding; - sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height; + sbvmyFrame.bottom = sbvmyFrame.top + sbvmyFrame.height + sbvsc.bottomPosInner.absVal; } else if (sbvsc.bottomPosInner.posRelaVal != nil) { @@ -787,7 +787,6 @@ -(BOOL)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcWidthOfSubview:(MyViewSi { if (sbvsc.widthSizeInner.dimeArrVal != nil) { - NSArray *dimeArray = sbvsc.widthSizeInner.dimeArrVal; BOOL isViewHidden = [self myIsNoLayoutSubview:sbv]; diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index 08edb5d..cfb8fde 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -1432,6 +1432,67 @@ -(void)testWrapContentHeight4 //MyRectAssert(rootLayout, CGRectMake(0, 0, sz.width, sz.height)); } +-(void)testWrapContentHeight5 +{ + MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + rootLayout.myWidth = MyLayoutSize.wrap; + rootLayout.myHeight = MyLayoutSize.wrap; + + //放一个高宽都是wrap的子布局视图。 + MyRelativeLayout *layout1 = [MyRelativeLayout new]; + layout1.myWidth = MyLayoutSize.wrap; + layout1.myHeight = MyLayoutSize.wrap; + layout1.myMargin = 10; + [rootLayout addSubview:layout1]; + + MyRelativeLayout *layout11 = [MyRelativeLayout new]; + layout11.myWidth = MyLayoutSize.wrap; + layout11.myHeight = MyLayoutSize.wrap; + layout11.myMargin = 10; + [layout1 addSubview:layout11]; + + UIView *v111 = [UIView new]; + v111.mySize = CGSizeMake(10, 10); + v111.myMargin = 10; + [layout11 addSubview:v111]; + + CGSize sz = [rootLayout sizeThatFits:CGSizeMake(0, 0)]; + MySizeAssert(rootLayout,sz,CGSizeMake(70, 70)); + + v111.visibility = MyVisibility_Gone; + sz = [rootLayout sizeThatFits:CGSizeMake(0, 0)]; + MySizeAssert(rootLayout,sz,CGSizeMake(40, 40)); + + v111.visibility = MyVisibility_Visible; + + + MyFlowLayout *layout2 = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; + layout2.widthSize.equalTo(@(MyLayoutSize.wrap)).max(80); + layout2.myHeight = MyLayoutSize.wrap; + layout2.topPos.equalTo(layout1.centerYPos); + layout2.leftPos.equalTo(layout1.rightPos); + layout2.rightPos.equalTo(rootLayout.rightPos).offset(20); + [rootLayout addSubview:layout2]; + + UIView *v21 = [UIView new]; + v21.mySize = CGSizeMake(60, 60); + [layout2 addSubview:v21]; + + sz = [rootLayout sizeThatFits:CGSizeMake(0, 0)]; + MySizeAssert(rootLayout,sz,CGSizeMake(150, 95)); + + + UIView *v22 = [UIView new]; + v22.mySize = CGSizeMake(60, 60); + [layout2 addSubview:v22]; + + sz = [rootLayout sizeThatFits:CGSizeMake(0, 0)]; + MySizeAssert(rootLayout,sz,CGSizeMake(170, 35+60+60)); + + +} + + - (void)testPerformanceExample { // This is an example of a performance test case. [self measureBlock:^{ From cc0fd65caae644ea0bd075c8d699e9f632f751c8 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Thu, 14 Nov 2019 20:52:00 +0800 Subject: [PATCH 087/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlexLayout.m | 5 +- MyLayout/Lib/MyFloatLayout.m | 4 +- MyLayout/Lib/MyFlowLayout.m | 13 ++-- MyLayout/Lib/MyLayoutDef.h | 4 +- MyLayout/Lib/MyLinearLayout.m | 121 ++++++++++++++++++---------------- 5 files changed, 78 insertions(+), 69 deletions(-) diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index f9662cc..75017d8 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -31,8 +31,9 @@ -(instancetype)init _flex_shrink = 1; _flex_basis = MyFlex_Auto; _align_self = MyFlex_Auto; - _width = 0; - _height = 0; + //默认子视图的宽高都是自适应的。 + _width = MyLayoutSize.wrap; + _height = MyLayoutSize.wrap; } return self; diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index ef4d357..5654992 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -840,7 +840,7 @@ -(CGSize)myVertOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv break; case MyGravity_Vert_Stretch: { - if (sbvsc.heightSizeInner.dimeVal == nil) + if (sbvsc.heightSizeInner.dimeVal == nil || (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]])) sbvmyFrame.height = lineMaxHeight; } break; @@ -1284,7 +1284,7 @@ -(CGSize)myHorzOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv break; case MyGravity_Horz_Stretch: { - if (sbvsc.widthSizeInner.dimeVal == nil) + if (sbvsc.widthSizeInner.dimeVal == nil || (sbvsc.widthSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]])) sbvmyFrame.width = lineMaxWidth; } break; diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index 20903e0..bca4209 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -622,7 +622,7 @@ - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l break; case MyGravity_Vert_Stretch: { - if (sbvsc.heightSizeInner.dimeVal == nil) + if (sbvsc.heightSizeInner.dimeVal == nil || (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]])) { sbvmyFrame.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:lineMaxHeight - sbvsc.topPosInner.absVal - sbvsc.bottomPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } @@ -813,7 +813,7 @@ - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l break; case MyGravity_Horz_Stretch: { - if (sbvsc.widthSizeInner.dimeVal == nil) + if (sbvsc.widthSizeInner.dimeVal == nil || (sbvsc.widthSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]])) { sbvmyFrame.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:lineMaxWidth - sbvsc.leadingPosInner.absVal - sbvsc.trailingPosInner.absVal sbvSize:sbvmyFrame.frame.size selfLayoutSize:selfSize]; } @@ -1316,7 +1316,8 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont if (vertGravity == MyGravity_Vert_Stretch) { MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.heightSizeInner.dimeVal == nil) + //只有在没有约束,或者非布局视图下的高度自适应约束才会被拉伸。 + if (sbvsc.heightSizeInner.dimeVal == nil || (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]])) { sbvmyFrame.height += fill; } @@ -1857,7 +1858,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG if (vertGravity == MyGravity_Vert_Stretch) { MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.heightSizeInner.dimeVal == nil) + if (sbvsc.heightSizeInner.dimeVal == nil || (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]])) { sbvmyFrame.height += fill; } @@ -2255,7 +2256,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont if (horzGravity == MyGravity_Horz_Stretch) { MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.widthSizeInner.dimeVal == nil) + if (sbvsc.widthSizeInner.dimeVal == nil || (sbvsc.widthSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]])) { sbvmyFrame.width += fill; } @@ -2773,7 +2774,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG if (horzGravity == MyGravity_Horz_Stretch) { MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.widthSizeInner.dimeVal == nil) + if (sbvsc.widthSizeInner.dimeVal == nil || (sbvsc.widthSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]])) { sbvmyFrame.width += fill; } diff --git a/MyLayout/Lib/MyLayoutDef.h b/MyLayout/Lib/MyLayoutDef.h index 7a2535b..8bef1cd 100644 --- a/MyLayout/Lib/MyLayoutDef.h +++ b/MyLayout/Lib/MyLayoutDef.h @@ -88,7 +88,7 @@ typedef enum : unsigned short { MyGravity_Horz_Around = 128, /**水平宽度填充*/ MyGravity_Horz_Fill = MyGravity_Horz_Left | MyGravity_Horz_Center | MyGravity_Horz_Right, - /**水平宽度拉伸,它跟宽度填充的区别是如果子视图指定了宽度则不会被拉伸*/ + /**水平宽度拉伸,它跟宽度填充的区别是如果子视图指定了宽度(非布局子视图宽度自适应除外)则不会被拉伸*/ MyGravity_Horz_Stretch = MyGravity_Horz_Left | MyGravity_Horz_Right, /**水平掩码,用来获取水平方向的枚举值*/ MyGravity_Horz_Mask = 0xFF00, @@ -110,7 +110,7 @@ typedef enum : unsigned short { MyGravity_Vert_Around = 64 << 8, /**垂直高度填充*/ MyGravity_Vert_Fill = MyGravity_Vert_Top | MyGravity_Vert_Center | MyGravity_Vert_Bottom, - /**垂直高度拉伸,它跟高度填充的区别是如果子视图指定了高度则不会被拉伸*/ + /**垂直高度拉伸,它跟高度填充的区别是如果子视图指定了高度(非布局子视图高度自适应除外)则不会被拉伸*/ MyGravity_Vert_Stretch = MyGravity_Vert_Top | MyGravity_Vert_Bottom, /**垂直掩码,用来获取垂直方向的枚举值*/ MyGravity_Vert_Mask = 0x00FF, diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 09bbed2..78964a3 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -293,10 +293,10 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub CGFloat addSpace = 0.0; //用于压缩时的间距压缩增量。 CGFloat maxSelfWidth = 0.0; - //高度不是包裹的子视图集合 - NSMutableSet *noWrapsbsSet = [NSMutableSet new]; - //固定高度尺寸的子视图集合 - NSMutableArray *fixedSizeSbs = [NSMutableArray new]; + //高度可以被伸缩的子视图集合 + NSMutableSet *flexSbsSet = [NSMutableSet new]; + //高度是固定尺寸的子视图集合 + NSMutableArray *fixedSbsSet = [NSMutableArray new]; CGFloat fixedSizeHeight = 0.0; NSInteger fixedSpaceCount = 0.0; //固定间距的子视图数量。 CGFloat fixedSpaceHeight = 0.0; //固定间距的子视图的高度。 @@ -309,29 +309,32 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) { - BOOL canAddToNoWrapSbs = YES; + BOOL isFlexSbv = YES; + //比重高度的子视图不能被伸缩。 if (sbvsc.weight != 0.0) - canAddToNoWrapSbs = NO; + isFlexSbv = NO; - //判断是否是添加到参与布局视图包裹计算的子视图。 + //高度依赖于父视图的不能被伸缩 if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) - canAddToNoWrapSbs = NO; + isFlexSbv = NO; - //如果子视图高度是包裹的也不进行扩展 - if (sbvsc.heightSizeInner.dimeWrapVal) - canAddToNoWrapSbs = NO; + //布局视图的高度自适应尺寸的不能被伸缩。 + if (sbvsc.heightSizeInner.dimeWrapVal && [sbv isKindOfClass:[MyBaseLayout class]]) + isFlexSbv = NO; - //如果子视图的最小高度就是自身则也不进行扩展。 + //高度最小是自身尺寸的不能被伸缩。 if (sbvsc.heightSizeInner.lBoundValInner.dimeWrapVal) - canAddToNoWrapSbs = NO; + isFlexSbv = NO; - //对于尺寸拉升来说,只要设置了高度约束就都不拉升。 - if (vertGravity == MyGravity_Vert_Stretch && sbvsc.heightSizeInner.dimeVal != nil) - canAddToNoWrapSbs = NO; + //对于拉伸来说,只要是设置了高度约束(除了非布局子视图的高度自适应除外)都不会被伸缩 + if (vertGravity == MyGravity_Vert_Stretch && + sbvsc.heightSizeInner.dimeVal != nil && + (!sbvsc.heightSizeInner.dimeWrapVal || [sbv isKindOfClass:[MyBaseLayout class]])) + isFlexSbv = NO; - if (canAddToNoWrapSbs) - [noWrapsbsSet addObject:sbv]; + if (isFlexSbv) + [flexSbsSet addObject:sbv]; //在计算拉伸时,如果没有设置宽度约束则将宽度设置为0 if (sbvsc.heightSizeInner.dimeVal == nil && !sbvsc.heightSizeInner.lBoundValInner.dimeWrapVal) @@ -412,7 +415,7 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub if (!sbvsc.heightSizeInner.lBoundValInner.dimeWrapVal) { fixedSizeHeight += rect.size.height; - [fixedSizeSbs addObject:sbv]; + [fixedSbsSet addObject:sbv]; } } @@ -495,20 +498,20 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub { if (sstContent == MySubviewsShrink_Size) {//压缩尺寸 - if (fixedSizeSbs.count > 0 && spareHeight < 0 && selfSize.height > 0) + if (fixedSbsSet.count > 0 && spareHeight < 0 && selfSize.height > 0) { if (sstMode == MySubviewsShrink_Average) {//均分。 - CGFloat averageHeight = spareHeight / fixedSizeSbs.count; + CGFloat averageHeight = spareHeight / fixedSbsSet.count; - for (UIView *fsbv in fixedSizeSbs) + for (UIView *fsbv in fixedSbsSet) { fsbv.myFrame.height += averageHeight; } } else if (_myCGFloatNotEqual(fixedSizeHeight, 0)) {//按比例分配。 - for (UIView *fsbv in fixedSizeSbs) + for (UIView *fsbv in fixedSbsSet) { fsbv.myFrame.height += spareHeight * (fsbv.myFrame.height / fixedSizeHeight); } @@ -596,8 +599,8 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) { pos = paddingTop; - if (noWrapsbsSet.count > 0) - fill = (selfSize.height - fixedHeight - paddingVert) / noWrapsbsSet.count; + if (flexSbsSet.count > 0) + fill = (selfSize.height - fixedHeight - paddingVert) / flexSbsSet.count; } else { @@ -651,7 +654,7 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub } //加上扩充的宽度。 - if (fill != 0 && [noWrapsbsSet containsObject:sbv]) + if (fill != 0 && [flexSbsSet containsObject:sbv]) rect.size.height += fill; if (totalShrink != 0.0 && sbvsc.heightSizeInner.shrink != 0.0) @@ -756,12 +759,12 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub CGFloat totalShrink = 0.0; //总的压缩比重 CGFloat addSpace = 0.0; //用于压缩时的间距压缩增量。 - //宽度不是包裹的子视图集合 - NSMutableSet *noWrapsbsSet = [NSMutableSet new]; - //固定宽度尺寸的子视图集合 - NSMutableArray *fixedSizeSbs = [NSMutableArray new]; - //浮动宽度尺寸的子视图集合 - NSMutableArray *flexedSizeSbs = [NSMutableArray new]; + //宽度是可伸缩的子视图集合 + NSMutableSet *flexSbsSet = [NSMutableSet new]; + //宽度是固定尺寸的子视图集合 + NSMutableArray *fixedSbsSet = [NSMutableArray new]; + //左右拉伸宽度尺寸的子视图集合 + NSMutableArray *leftRightFlexSbs = [NSMutableArray new]; CGFloat fixedSizeWidth = 0.0; //固定尺寸视图的宽度 NSInteger fixedSpaceCount = 0.0; //固定间距的子视图数量。 CGFloat fixedSpaceWidth = 0.0; //固定间距的子视图的宽度。 @@ -778,28 +781,32 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) { - BOOL canAddToNoWrapSbs = YES; + BOOL isFlexSbv = YES; + //设置了比重宽度的子视图不伸缩 if (sbvsc.weight != 0.0) - canAddToNoWrapSbs = NO; + isFlexSbv = NO; - //判断是否是添加到参与布局视图包裹计算的子视图。 + //宽度依赖父视图宽度的不伸缩 if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner) - canAddToNoWrapSbs = NO; + isFlexSbv = NO; - //如果子视图宽度是包裹的也不进行扩展 - if (sbvsc.widthSizeInner.dimeWrapVal) - canAddToNoWrapSbs = NO; + //布局子视图宽度自适应时不伸缩 + if (sbvsc.widthSizeInner.dimeWrapVal && [sbv isKindOfClass:[MyBaseLayout class]]) + isFlexSbv = NO; - //如果子视图的最小宽度就是自身则也不进行扩展。 + //子视图宽度最小为自身宽度时不伸缩。 if (sbvsc.widthSizeInner.lBoundValInner.dimeWrapVal) - canAddToNoWrapSbs = NO; + isFlexSbv = NO; - if (horzGravity == MyGravity_Horz_Stretch && sbvsc.widthSizeInner.dimeVal != nil) - canAddToNoWrapSbs = NO; + //对于拉伸来说,只要是设置了宽度约束(除了非布局子视图的宽度自适应除外)都不会被伸缩 + if (horzGravity == MyGravity_Horz_Stretch && + sbvsc.widthSizeInner.dimeVal != nil && + (!sbvsc.widthSizeInner.dimeWrapVal || [sbv isKindOfClass:[MyBaseLayout class]])) + isFlexSbv = NO; - if (canAddToNoWrapSbs) - [noWrapsbsSet addObject:sbv]; + if (isFlexSbv) + [flexSbsSet addObject:sbv]; //在计算拉伸时,如果没有设置宽度约束则将宽度设置为0 if (sbvsc.widthSizeInner.dimeVal == nil && !sbvsc.widthSizeInner.lBoundValInner.dimeWrapVal) @@ -884,12 +891,12 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub if (!sbvsc.widthSizeInner.lBoundValInner.dimeWrapVal) { fixedSizeWidth += rect.size.width; - [fixedSizeSbs addObject:sbv]; + [fixedSbsSet addObject:sbv]; } if (sbvsc.widthSizeInner.dimeWrapVal) { - [flexedSizeSbs addObject:sbv]; + [leftRightFlexSbs addObject:sbv]; } } @@ -971,29 +978,29 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub if (_myCGFloatLessOrEqual(spareWidth, 0.0)) { //如果压缩方式为自动,但是浮动宽度子视图数量不为2则压缩类型无效。 - if (sstMode == MySubviewsShrink_Auto && flexedSizeSbs.count != 2) + if (sstMode == MySubviewsShrink_Auto && leftRightFlexSbs.count != 2) sstMode = MySubviewsShrink_None; if (sstMode != MySubviewsShrink_None) { if (sstContent == MySubviewsShrink_Size) { - if (fixedSizeSbs.count > 0 && spareWidth < 0 && selfSize.width > 0) + if (fixedSbsSet.count > 0 && spareWidth < 0 && selfSize.width > 0) { //均分。 if (sstMode == MySubviewsShrink_Average) { - CGFloat averageWidth = spareWidth / fixedSizeSbs.count; + CGFloat averageWidth = spareWidth / fixedSbsSet.count; - for (UIView *fsbv in fixedSizeSbs) + for (UIView *fsbv in fixedSbsSet) { fsbv.myFrame.width += averageWidth; } } else if (sstMode == MySubviewsShrink_Auto) { - UIView *leadingView = flexedSizeSbs[0]; - UIView *trailingView = flexedSizeSbs[1]; + UIView *leadingView = leftRightFlexSbs[0]; + UIView *trailingView = leftRightFlexSbs[1]; CGFloat leadingWidth = leadingView.myFrame.width; CGFloat trailingWidth = trailingView.myFrame.width; @@ -1027,7 +1034,7 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub } else if (_myCGFloatNotEqual(fixedSizeWidth, 0)) {//按比例分配。 - for (UIView *fsbv in fixedSizeSbs) + for (UIView *fsbv in fixedSbsSet) { fsbv.myFrame.width += spareWidth * (fsbv.myFrame.width / fixedSizeWidth); } @@ -1115,8 +1122,8 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) { pos = paddingLeading; - if (noWrapsbsSet.count > 0) - fill = (selfSize.width - fixedWidth - paddingHorz) / noWrapsbsSet.count; + if (flexSbsSet.count > 0) + fill = (selfSize.width - fixedWidth - paddingHorz) / flexSbsSet.count; } else { @@ -1174,7 +1181,7 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub } //加上扩充的宽度。 - if (fill != 0.0 && [noWrapsbsSet containsObject:sbv]) + if (fill != 0.0 && [flexSbsSet containsObject:sbv]) rect.size.width += fill; if (totalShrink != 0.0 && sbvsc.widthSizeInner.shrink != 0.0) From 01c88a9298e02083d5c0551786e18733d03399d0 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Fri, 15 Nov 2019 08:54:53 +0800 Subject: [PATCH 088/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFloatLayout.m | 21 +++++++++++++-- MyLayoutTests/MyFloatLayoutTestCase.m | 18 +++++++++++-- MyLayoutTests/MyFlowLayoutTestCase.m | 7 +++++ MyLayoutTests/MyLinearLayoutTestCase.m | 36 +++++++++++++------------- 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 5654992..76a377a 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -407,6 +407,7 @@ -(CGSize)myVertOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv // CGFloat paddingVert = paddingTop + paddingBottom; //如果没有边界限制我们将宽度设置为最大。。 + BOOL isBeyondFlag = NO; //子视图是否超出剩余空间需要换行。 if (lsc.widthSizeInner.dimeWrapVal) { //如果有最大限制则取最大值,解决那种宽度自适应,但是有最大值需要换行的情况。 @@ -630,6 +631,10 @@ -(CGSize)myVertOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv trailingCandidateXBoundary = trailingPoint.x; break; } + else + {//这里表明剩余空间放不下了。 + isBeyondFlag = YES; + } nextPoint.y = CGRectGetMaxY(candidateRect); } @@ -750,7 +755,11 @@ -(CGSize)myVertOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv maxWidth += paddingTrailing; if (lsc.widthSizeInner.dimeWrapVal) - selfSize.width = maxWidth; + { + //只有在设置了最大宽度限制并且超出了才认为最大宽度是限制宽度,否则是最大子视图宽度。 + if (selfSize.width == CGFLOAT_MAX || !isBeyondFlag) + selfSize.width = maxWidth; + } maxHeight += paddingBottom; if (lsc.heightSizeInner.dimeWrapVal) @@ -876,6 +885,7 @@ -(CGSize)myHorzOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv CGFloat paddingVert = paddingTop + paddingBottom; //如果没有边界限制我们将高度设置为最大。。 + BOOL isBeyondFlag = NO; //子视图是否超出剩余空间需要换行。 if (lsc.heightSizeInner.dimeWrapVal) { //如果有最大限制则取最大值,解决那种高度自适应,但是有最大值需要换行的情况。 @@ -1092,6 +1102,10 @@ -(CGSize)myHorzOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv bottomCandidateYBoundary = bottomPoint.y; break; } + else + { + isBeyondFlag = YES; + } nextPoint.x = CGRectGetMaxX(candidateRect); } @@ -1204,7 +1218,10 @@ -(CGSize)myHorzOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv maxHeight += paddingBottom; if (lsc.heightSizeInner.dimeWrapVal) - selfSize.height = maxHeight; + { + if (selfSize.height == CGFLOAT_MAX || !isBeyondFlag) + selfSize.height = maxHeight; + } maxWidth += paddingTrailing; if (lsc.widthSizeInner.dimeWrapVal) diff --git a/MyLayoutTests/MyFloatLayoutTestCase.m b/MyLayoutTests/MyFloatLayoutTestCase.m index b3ed9bc..de9f557 100644 --- a/MyLayoutTests/MyFloatLayoutTestCase.m +++ b/MyLayoutTests/MyFloatLayoutTestCase.m @@ -414,10 +414,17 @@ -(void)testWrapAndMaxMinLimit MyRectAssert(rootLayout, CGRectMake(0, 0, 5+30+20+10+10, 10+30+5)); UIView *v3 = [UIView new]; + v3.clearFloat = YES; v3.mySize = CGSizeMake(50, 50); [rootLayout addSubview:v3]; [rootLayout layoutIfNeeded]; - MyRectAssert(rootLayout, CGRectMake(0, 0, 75, 10+30+20+50+5)); + MyRectAssert(rootLayout, CGRectMake(0, 0, 5+30+20+10+10, 10+30+20+50+5)); + + UIView *v4 = [UIView new]; + v4.mySize = CGSizeMake(50, 50); + [rootLayout addSubview:v4]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 80, 10+30+20+50+20+50+5)); } { @@ -443,10 +450,17 @@ -(void)testWrapAndMaxMinLimit MyRectAssert(rootLayout, CGRectMake(0, 0, 10+30+5,5+30+20+10+10)); UIView *v3 = [UIView new]; + v3.clearFloat = YES; v3.mySize = CGSizeMake(50, 50); [rootLayout addSubview:v3]; [rootLayout layoutIfNeeded]; - MyRectAssert(rootLayout, CGRectMake(0, 0, 10+30+20+50+5,75)); + MyRectAssert(rootLayout, CGRectMake(0, 0,10+30+20+50+5,5+30+20+10+10)); + + UIView *v4 = [UIView new]; + v4.mySize = CGSizeMake(50, 50); + [rootLayout addSubview:v4]; + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 10+30+20+50+20+50+5,80)); } } diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index 1677719..407d6a5 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -1100,6 +1100,13 @@ -(void)testRightAndBottomGravity } } +-(void)testFillAndStretch +{ + //测试填充和拉伸。垂直数量约束流式布局的行内拉升和填充。以及整体 + + +} + -(void)testFlex1 { //测试内容约束布局下的尺寸自适应,以及最大最小值设置的场景。 diff --git a/MyLayoutTests/MyLinearLayoutTestCase.m b/MyLayoutTests/MyLinearLayoutTestCase.m index 4c4ffe7..4c8db8a 100644 --- a/MyLayoutTests/MyLinearLayoutTestCase.m +++ b/MyLayoutTests/MyLinearLayoutTestCase.m @@ -503,11 +503,11 @@ -(void)testFillAndStretch XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,190,400)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); - XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(20,10,140,20.5)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); - XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(100,30.5,50,67.5)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); - XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(55,98,70,107.5)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); - XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(40,205.5,100,67.5)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); - XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(10,272.5,80,107.5)), @"the v5 .frame = %@",NSStringFromCGRect(v5.frame)); + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(20,10,140,74.5)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(100,84.5,50,54)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(55,138.5,70,94)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(40,232,100,54)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(10,286,80,94)), @"the v5 .frame = %@",NSStringFromCGRect(v5.frame)); } if (1){ @@ -553,10 +553,10 @@ -(void)testFillAndStretch XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,190,400)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); - XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(20,10,140,20.5)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); - XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(100,30.5,50,135)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); - XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(55,165.5,70,40)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); - XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(40,205.5,100,135)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(20,10,140,110.5)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(100,120.5,50,90)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(55,210,70,40)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(40,250,100,90)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(10,340,80,40)), @"the v5 .frame = %@",NSStringFromCGRect(v5.frame)); } @@ -604,11 +604,11 @@ -(void)testFillAndStretch XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,400,190)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); - XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(10,20,35,140)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); - XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(45,100,64,50)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); - XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(109,55,104,70)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); - XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(212.5,40,64,100)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); - XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(276.5,10,104,80)), @"the v5 .frame = %@",NSStringFromCGRect(v5.frame)); + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(10,20,86,140)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(96,100,51,50)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(147,55,91,70)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(238,40,51,100)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); + XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(289,10,91,80)), @"the v5 .frame = %@",NSStringFromCGRect(v5.frame)); } if (1){ @@ -654,10 +654,10 @@ -(void)testFillAndStretch XCTAssertTrue(CGRectEqualToRect(rootLayout.frame, CGRectMake(0,0,400,190)), @"the rootLayout.frame = %@",NSStringFromCGRect(rootLayout.frame)); - XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(10,20,35,140)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); - XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(45,100,127.5,50)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); - XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(172.5,55,40,70)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); - XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(212.5,40,127.5,100)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); + XCTAssertTrue(CGRectEqualToRect(v1.frame, CGRectMake(10,20,120,140)), @"the v1.frame = %@",NSStringFromCGRect(v1.frame)); + XCTAssertTrue(CGRectEqualToRect(v2.frame, CGRectMake(130,100,85,50)), @"the v2.frame = %@",NSStringFromCGRect(v2.frame)); + XCTAssertTrue(CGRectEqualToRect(v3.frame, CGRectMake(215,55,40,70)), @"the v3.frame = %@",NSStringFromCGRect(v3.frame)); + XCTAssertTrue(CGRectEqualToRect(v4.frame, CGRectMake(255,40,85,100)), @"the v4 .frame = %@",NSStringFromCGRect(v4.frame)); XCTAssertTrue(CGRectEqualToRect(v5.frame, CGRectMake(340,10,40,80)), @"the v5 .frame = %@",NSStringFromCGRect(v5.frame)); } From a956d49e4858f62be5fb5e0440001a93f2db365b Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Mon, 18 Nov 2019 13:32:56 +0800 Subject: [PATCH 089/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout.xcodeproj/project.pbxproj | 14 + MyLayout/Lib/MyBaseLayout.h | 35 +- MyLayout/Lib/MyBaseLayout.m | 220 ++++++++--- MyLayout/Lib/MyFlexLayout.h | 212 ++++++----- MyLayout/Lib/MyFlexLayout.m | 518 +++++++++++--------------- MyLayout/Lib/MyFrameLayout.m | 5 +- MyLayout/Lib/MyLayout.h | 1 - MyLayout/Lib/MyLayoutInner.h | 16 + MyLayout/Lib/MyLayoutMath.h | 3 +- MyLayout/Lib/MyLayoutSize.h | 16 +- MyLayout/Lib/MyLayoutSize.m | 13 +- MyLayout/Lib/MyLayoutSizeClass.m | 4 + MyLayout/Lib/MyLayoutSizeInner.h | 1 + MyLayout/Lib/MyLayoutUI.h | 104 ++++++ MyLayout/Lib/MyLayoutUI.m | 244 ++++++++++++ MyLayout/Lib/MyLayoutUIInner.h | 19 + MyLayout/Lib/MyLinearLayout.m | 8 +- MyLayout/Lib/MyRelativeLayout.m | 19 +- MyLayoutDemo/FLXTest1ViewController.m | 26 +- MyLayoutTests/MyFlowLayoutTestCase.m | 2 - 20 files changed, 967 insertions(+), 513 deletions(-) create mode 100644 MyLayout/Lib/MyLayoutUI.h create mode 100644 MyLayout/Lib/MyLayoutUI.m create mode 100644 MyLayout/Lib/MyLayoutUIInner.h diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index ce750b5..d97d033 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -171,6 +171,10 @@ 20DF42422318F4EA0078CAA0 /* MyFlexLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DF42402318F4EA0078CAA0 /* MyFlexLayout.m */; }; 20F0DFFD2111749A00CFCE8C /* AllTest11ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F0DFFC2111749A00CFCE8C /* AllTest11ViewController.m */; }; 20F0E00021120A8D00CFCE8C /* FLLTest8ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F0DFFF21120A8D00CFCE8C /* FLLTest8ViewController.m */; }; + 20F4A803237EF0E000D464E7 /* MyLayoutUI.h in Headers */ = {isa = PBXBuildFile; fileRef = 20F4A801237EF0E000D464E7 /* MyLayoutUI.h */; }; + 20F4A804237EF0E000D464E7 /* MyLayoutUI.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F4A802237EF0E000D464E7 /* MyLayoutUI.m */; }; + 20F4A805237EF46200D464E7 /* MyLayoutUI.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F4A802237EF0E000D464E7 /* MyLayoutUI.m */; }; + 20F4A807237FC40900D464E7 /* MyLayoutUIInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 20F4A806237FC40900D464E7 /* MyLayoutUIInner.h */; }; 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F783551F60399700BE5B31 /* GLTest3ViewController.m */; }; 4411977B1F6AE78E00C22557 /* GridLayoutDemo5.json in Resources */ = {isa = PBXBuildFile; fileRef = 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */; }; 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */; }; @@ -426,6 +430,9 @@ 20F0DFFC2111749A00CFCE8C /* AllTest11ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest11ViewController.m; sourceTree = ""; }; 20F0DFFE21120A8D00CFCE8C /* FLLTest8ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLLTest8ViewController.h; sourceTree = ""; }; 20F0DFFF21120A8D00CFCE8C /* FLLTest8ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLLTest8ViewController.m; sourceTree = ""; }; + 20F4A801237EF0E000D464E7 /* MyLayoutUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyLayoutUI.h; sourceTree = ""; }; + 20F4A802237EF0E000D464E7 /* MyLayoutUI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyLayoutUI.m; sourceTree = ""; }; + 20F4A806237FC40900D464E7 /* MyLayoutUIInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutUIInner.h; sourceTree = ""; }; 20F783541F60398C00BE5B31 /* GLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest3ViewController.h; sourceTree = ""; }; 20F783551F60399700BE5B31 /* GLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest3ViewController.m; sourceTree = ""; }; 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo5.json; sourceTree = ""; }; @@ -815,6 +822,9 @@ 182225B41E77E5930081AA4B /* MyFlowLayout.m */, 20DF423F2318F4EA0078CAA0 /* MyFlexLayout.h */, 20DF42402318F4EA0078CAA0 /* MyFlexLayout.m */, + 20F4A801237EF0E000D464E7 /* MyLayoutUI.h */, + 20F4A802237EF0E000D464E7 /* MyLayoutUI.m */, + 20F4A806237FC40900D464E7 /* MyLayoutUIInner.h */, 182225AC1E77E5930081AA4B /* MyLinearLayout.h */, 182225B21E77E5930081AA4B /* MyLinearLayout.m */, 182225AD1E77E5930081AA4B /* MyFloatLayout.h */, @@ -929,6 +939,7 @@ 18C15AF21EDF13F900AADEAC /* MyPathLayout.h in Headers */, 205643161F55A03000E8BDDE /* MyLayoutMath.h in Headers */, 18C15AF31EDF13FF00AADEAC /* MyFrameLayout.h in Headers */, + 20F4A803237EF0E000D464E7 /* MyLayoutUI.h in Headers */, 18C15AF41EDF140400AADEAC /* MyBaseLayout.h in Headers */, 18C15AF51EDF140D00AADEAC /* MyLayoutPos.h in Headers */, 18C15AF61EDF141000AADEAC /* MyLayoutSize.h in Headers */, @@ -942,6 +953,7 @@ 18C15AFA1EDF142300AADEAC /* MyLayoutDef.h in Headers */, 205E0C6020B907CC001A8B99 /* MyLayoutPosInner.h in Headers */, 205E0C6120B907D1001A8B99 /* MyLayoutSizeInner.h in Headers */, + 20F4A807237FC40900D464E7 /* MyLayoutUIInner.h in Headers */, 205E0C6220B907DB001A8B99 /* MyLayoutInner.h in Headers */, 205E0C6320B907EC001A8B99 /* MyLayoutDelegate.h in Headers */, ); @@ -1151,6 +1163,7 @@ 20DF42422318F4EA0078CAA0 /* MyFlexLayout.m in Sources */, 182DB6441EF7876200E2D65D /* MyGridLayout.m in Sources */, 18C15B001EDF144B00AADEAC /* MyPathLayout.m in Sources */, + 20F4A804237EF0E000D464E7 /* MyLayoutUI.m in Sources */, 18C15B011EDF144B00AADEAC /* MyFrameLayout.m in Sources */, 18C15B021EDF144B00AADEAC /* MyBaseLayout.m in Sources */, 18C15B031EDF144B00AADEAC /* MyLayoutPos.m in Sources */, @@ -1182,6 +1195,7 @@ 18D3C9731EDF082800D3DE43 /* AllTest2TableViewCell.m in Sources */, 18D3C95F1EDF07F800D3DE43 /* FOLTest6ViewController.m in Sources */, 182225D51E77E5930081AA4B /* MyLayoutSize.m in Sources */, + 20F4A805237EF46200D464E7 /* MyLayoutUI.m in Sources */, 6740E20120A52DC100AFBC5A /* AllTest10Cell.m in Sources */, 18D3C93A1EDF07C000D3DE43 /* FLLTest2ViewController.m in Sources */, 467E63CF228CDA660065D080 /* AllTest1TableViewCellForAutoLayout.m in Sources */, diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index 433184f..515a7ac 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -789,7 +789,6 @@ @property(nonatomic,getter=isSelected) BOOL selected; // default is NO may be used by some subclasses or by application - /** *设置布局视图在布局开始之前的处理块。系统会在每次布局完成前调用对应的处理块后将处理块清空为nil。系统会在调用layoutSubviews方法前执行beginLayoutBlock。 */ @@ -799,36 +798,12 @@ */ @property(nonatomic,copy) void (^endLayoutBlock)(void); - - - /** - 删除所有子视图的方便方法 - */ --(void)removeAllSubviews; - - -/** - *设置布局时的动画。并指定时间。这个函数是下面方法的简单实现: - - @code - self.beginLayoutBlock = ^{ - - [UIView beginAnimations:nil context:nil]; - [UIView setAnimationDuration:duration]; - }; - - self.endLayoutBlock = ^{ - - [UIView commitAnimations]; - }; - -@endcode - + *设置布局时的动画。并指定时间,选项,和完成时的处理,这个动画只会在调用后的下次布局时执行一次。 @param duration 指定动画的时间间隔 */ -(void)layoutAnimationWithDuration:(NSTimeInterval)duration; - +-(void)layoutAnimationWithDuration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion; /** 设置布局视图在第一次布局完成之后或者有横竖屏切换时进行处理的block。这个block不像beginLayoutBlock以及endLayoutBlock那样只会执行一次,而是会一直存在 @@ -844,6 +819,12 @@ @property(nonatomic,copy) void (^rotationToDeviceOrientationBlock)(MyBaseLayout *layout, BOOL isFirst, BOOL isPortrait); +/** + 删除所有子视图的方便方法 + */ +-(void)removeAllSubviews; + + /** *判断当前是否正在布局中,如果正在布局中则返回YES,否则返回NO。 我们可以通过KVO的方式来监听这个属性的变化,以便获取布局完成后的真实frame值。 */ diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 6eea760..a0b1702 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -717,16 +717,14 @@ @implementation MyBaseLayout MyLayoutTouchEventDelegate *_touchEventDelegate; MyBorderlineLayerDelegate *_borderlineLayerDelegate; BOOL _isAddSuperviewKVO; - int _lastScreenOrientation; //为0为初始状态,为1为竖屏,为2为横屏。内部使用。 BOOL _useCacheRects; + MyBaseLayoutOptionalData *_optionalData; } -(void)dealloc { //如果您在使用时出现了KVO的异常崩溃,原因是您将这个视图被多次加入为子视图,请检查您的代码,是否这个视图被多次加入!! - _endLayoutBlock = nil; - _beginLayoutBlock = nil; - _rotationToDeviceOrientationBlock = nil; + _optionalData = nil; } #pragma mark -- Public Methods @@ -997,19 +995,7 @@ -(void)removeAllSubviews [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; } --(void)layoutAnimationWithDuration:(NSTimeInterval)duration -{ - self.beginLayoutBlock = ^{ - - [UIView beginAnimations:nil context:nil]; - [UIView setAnimationDuration:duration]; - }; - - self.endLayoutBlock = ^{ - - [UIView commitAnimations]; - }; -} + -(MyBorderline*)topBorderline { @@ -1203,6 +1189,55 @@ -(MyLayoutDragger*)createLayoutDragger return dragger; } +-(void)setBeginLayoutBlock:(void (^)(void))beginLayoutBlock +{ + if (_optionalData == nil) + _optionalData = [MyBaseLayoutOptionalData new]; + _optionalData.beginLayoutBlock = beginLayoutBlock; +} + +-(void (^)(void))beginLayoutBlock +{ + return _optionalData.beginLayoutBlock; +} + +-(void)setEndLayoutBlock:(void (^)(void))endLayoutBlock +{ + if (_optionalData == nil) + _optionalData = [MyBaseLayoutOptionalData new]; + _optionalData.endLayoutBlock = endLayoutBlock; +} + +-(void (^)(void))endLayoutBlock +{ + return _optionalData.endLayoutBlock; +} + +-(void)setRotationToDeviceOrientationBlock:(void (^)(MyBaseLayout *, BOOL, BOOL))rotationToDeviceOrientationBlock +{ + if (_optionalData == nil) + _optionalData = [MyBaseLayoutOptionalData new]; + _optionalData.rotationToDeviceOrientationBlock = rotationToDeviceOrientationBlock; +} + +-(void (^)(MyBaseLayout *, BOOL, BOOL))rotationToDeviceOrientationBlock +{ + return _optionalData.rotationToDeviceOrientationBlock; +} + +-(void)layoutAnimationWithDuration:(NSTimeInterval)duration +{ + [self layoutAnimationWithDuration:duration options:0 completion:nil]; +} +-(void)layoutAnimationWithDuration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion +{ + if (_optionalData == nil) + _optionalData = [MyBaseLayoutOptionalData new]; + _optionalData.aniDuration = duration; + _optionalData.aniOptions = options; + _optionalData.aniCompletion = completion; +} + #pragma mark -- Touches Event @@ -1576,8 +1611,11 @@ - (void)willMoveToSuperview:(UIView*)newSuperview } else { - self.beginLayoutBlock = nil; - self.endLayoutBlock = nil; + _optionalData.aniDuration = 0.0; + _optionalData.beginLayoutBlock = nil; + _optionalData.endLayoutBlock = nil; + if (_optionalData.rotationToDeviceOrientationBlock == nil) + _optionalData = nil; } } @@ -1745,21 +1783,15 @@ -(CGSize)intrinsicContentSize return sz; } --(void)layoutSubviews -{ - if (!self.autoresizesSubviews) - return; - - if (self.beginLayoutBlock != nil) - self.beginLayoutBlock(); - self.beginLayoutBlock = nil; +-(void)doLayoutSubviews +{ int currentScreenOrientation = 0; if (!self.isMyLayouting) { self.isMyLayouting = YES; - + if (self.priorAutoresizingMask) [super layoutSubviews]; @@ -1782,9 +1814,9 @@ -(void)layoutSubviews if (!sbvmyFrame.hasObserver && sbvmyFrame.sizeClass != nil && !sbvmyFrame.sizeClass.useFrame) [self myAddSubviewObserver:sbv sbvmyFrame:sbvmyFrame]; } - + MyBaseLayout *lsc = (MyBaseLayout*)selfMyFrame.sizeClass; - + //计算布局 CGSize oldSelfSize = self.bounds.size; CGSize newSelfSize; @@ -1799,13 +1831,13 @@ -(void)layoutSubviews static CGFloat sSizeError = 0; if (sSizeError == 0) sSizeError = 1 / [UIScreen mainScreen].scale + 0.0001; //误差量。 - + //设置子视图的frame并还原 for (UIView *sbv in self.subviews) { CGRect sbvOldBounds = sbv.bounds; CGPoint sbvOldCenter = sbv.center; - + MyFrame *sbvmyFrame = sbv.myFrame; MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; @@ -1824,7 +1856,7 @@ -(void)layoutSubviews CGRect rc; if ([sbv isKindOfClass:[MyBaseLayout class]]) { - rc = _myLayoutCGRectRound(sbvmyFrame.frame); + rc = _myLayoutCGRectRound(sbvmyFrame.frame); CGRect sbvTempBounds = CGRectMake(sbvOldBounds.origin.x, sbvOldBounds.origin.y, rc.size.width, rc.size.height); @@ -1928,10 +1960,10 @@ -(void)layoutSubviews currentBounds.size.height = newSelfSize.height; currentCenter.y += (newSelfSize.height - oldSelfSize.height) * self.layer.anchorPoint.y * superViewZoomScale; } - + self.bounds = currentBounds; self.center = currentCenter; - } + } } } @@ -1949,9 +1981,9 @@ -(void)layoutSubviews //比如一些表格或者其他的情况。默认情况下这个函数什么也不做。 [((MyBaseLayout*)supv) myHookSublayout:self borderlineRect:&borderlineRect]; } - + [_borderlineLayerDelegate setNeedsLayoutIn:borderlineRect withLayer:self.layer]; - + } //如果自己的父视图是非UIScrollView以及非布局视图。以及自己的宽度或者高度是包裹的,并且如果设置了在父视图居中或者居下或者居右时要在父视图中更新自己的位置。 if (supv != nil && ![supv isKindOfClass:[MyBaseLayout class]]) @@ -1959,7 +1991,7 @@ -(void)layoutSubviews CGPoint centerPonintSelf = self.center; CGRect rectSelf = self.bounds; CGRect rectSuper = supv.bounds; - + //特殊处理低版本下的top和bottom的两种安全区域的场景。 if ((lsc.topPosInner.isSafeAreaPos || lsc.bottomPosInner.isSafeAreaPos) && [UIDevice currentDevice].systemVersion.doubleValue < 11 ) { @@ -1968,7 +2000,7 @@ -(void)layoutSubviews else centerPonintSelf.y = rectSuper.size.height - rectSelf.size.height - [lsc.bottomPosInner realPosIn:rectSuper.size.height] + self.layer.anchorPoint.y * rectSelf.size.height; } - + //如果自己的父视图是非UIScrollView以及非布局视图。以及自己的宽度或者高度是包裹的时,并且如果设置了在父视图居中或者居下或者居右时要在父视图中更新自己的位置。 if (![supv isKindOfClass:[UIScrollView class]] && (lsc.widthSizeInner.dimeWrapVal || lsc.heightSizeInner.dimeWrapVal)) { @@ -2045,35 +2077,68 @@ -(void)layoutSubviews //处理父视图是滚动视图时动态调整滚动视图的contentSize [self myLayout:lsc adjustScrollViewContentWithSize:newSelfSize]; } - + if (selfMyFrame.multiple) selfMyFrame.sizeClass = [self myDefaultSizeClass]; self.isMyLayouting = NO; } - if (self.endLayoutBlock != nil) - self.endLayoutBlock(); - self.endLayoutBlock = nil; - //执行屏幕旋转的处理逻辑。 - if (currentScreenOrientation != 0 && self.rotationToDeviceOrientationBlock != nil) + if (currentScreenOrientation != 0 && _optionalData.rotationToDeviceOrientationBlock != nil) { - if (_lastScreenOrientation == 0) + if (_optionalData.lastScreenOrientation == 0) { - _lastScreenOrientation = currentScreenOrientation; - self.rotationToDeviceOrientationBlock(self,YES, currentScreenOrientation == 1); + _optionalData.lastScreenOrientation = currentScreenOrientation; + _optionalData.rotationToDeviceOrientationBlock(self,YES, currentScreenOrientation == 1); } else { - if (_lastScreenOrientation != currentScreenOrientation) + if (_optionalData.lastScreenOrientation != currentScreenOrientation) { - _lastScreenOrientation = currentScreenOrientation; - self.rotationToDeviceOrientationBlock(self, NO, currentScreenOrientation == 1); + _optionalData.lastScreenOrientation = currentScreenOrientation; + _optionalData.rotationToDeviceOrientationBlock(self, NO, currentScreenOrientation == 1); } } - _lastScreenOrientation = currentScreenOrientation; + _optionalData.lastScreenOrientation = currentScreenOrientation; + } +} + +-(void)layoutSubviews +{ + if (!self.autoresizesSubviews) + return; + + if (_optionalData.beginLayoutBlock != nil) + { + _optionalData.beginLayoutBlock(); + _optionalData.beginLayoutBlock = nil; + } + + if (_optionalData == nil || _optionalData.aniDuration <= 0) + { + [self doLayoutSubviews]; + } + else + { + [UIView animateWithDuration:_optionalData.aniDuration delay:0 options:_optionalData.aniOptions animations:^{ + [self doLayoutSubviews]; + } completion:_optionalData.aniCompletion]; + + _optionalData.aniDuration = 0.0; + _optionalData.aniCompletion = nil; + } + + if (_optionalData.endLayoutBlock != nil) + { + _optionalData.endLayoutBlock(); + _optionalData.endLayoutBlock = nil; } + + //因为rotationToDeviceOrientationBlock设置后不会在内部被清除,而其他的都会被清除。 + //所有只要rotationToDeviceOrientationBlock为空就可以将可选的多余数据给清除掉了。 + if (_optionalData != nil && _optionalData.rotationToDeviceOrientationBlock == nil) + _optionalData = nil; } -(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection @@ -2414,6 +2479,10 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize size.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:size.width sbvSize:size selfLayoutSize:rectSuper.size]; } + else if (lsc.widthSizeInner.dimeFillVal) + { + size.width = [lsc.widthSizeInner measureWith:rectSuper.size.width]; + } if (lsc.leadingPosInner.posVal != nil && lsc.trailingPosInner.posVal != nil) { @@ -2441,6 +2510,10 @@ -(CGSize)myCalcSizeInNoLayoutSuperview:(UIView*)newSuperview currentSize:(CGSize size.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:size.height sbvSize:size selfLayoutSize:rectSuper.size]; } + else if (lsc.heightSizeInner.dimeFillVal) + { + size.height = [lsc.heightSizeInner measureWith:rectSuper.size.height]; + } if (lsc.topPosInner.posVal != nil && lsc.bottomPosInner.posVal != nil) { @@ -2507,9 +2580,14 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview { rectSelf.size.width = lsc.widthSizeInner.measure; } + else if (lsc.widthSizeInner.dimeFillVal) + { + isAdjust = YES; + rectSelf.size.width = [lsc.widthSizeInner measureWith:rectSuper.size.width]; + } else { - //do nothing... + } } @@ -2607,6 +2685,11 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview { rectSelf.size.height = lsc.heightSizeInner.measure; } + else if (lsc.heightSizeInner.dimeFillVal) + { + isAdjust = YES; + rectSelf.size.height = [lsc.heightSizeInner measureWith:rectSuper.size.height]; + } else { // do nothing... @@ -3278,6 +3361,10 @@ -(CGFloat)myLayout:(MyLayoutViewSizeClass*)lsc retVal = [sbvWidthSizeInner measureWith:sbvWidthSizeInner.dimeRelaVal.view.myEstimatedHeight]; } } + else if (sbvWidthSizeInner.dimeFillVal) + { + retVal = [sbvWidthSizeInner measureWith:selfSize.width - paddingLeading - paddingTrailing]; + } else if (sbvWidthSizeInner.dimeWrapVal) { if (![sbvsc.view isKindOfClass:[MyBaseLayout class]]) @@ -3321,10 +3408,16 @@ -(CGFloat)myLayout:(MyLayoutViewSizeClass*)lsc retVal = [sbvHeightSizeInner measureWith:sbvHeightSizeInner.dimeRelaVal.view.myEstimatedHeight]; } } + else if (sbvHeightSizeInner.dimeFillVal) + { + retVal = [sbvHeightSizeInner measureWith:selfSize.height - paddingTop - paddingBottom]; + } + else if (sbvHeightSizeInner.dimeWrapVal) + { + if (![sbvsc.view isKindOfClass:[MyBaseLayout class]]) + retVal = [self mySubview:sbvsc wrapHeightSizeFits:sbvSize.width]; + } - //高度等于内容的高度,特殊处理。 - if (sbvsc.heightSizeInner.dimeWrapVal && ![sbvsc.view isKindOfClass:[MyBaseLayout class]]) - retVal = [self mySubview:sbvsc wrapHeightSizeFits:sbvSize.width]; return retVal; } @@ -3389,10 +3482,9 @@ -(void)myLayout:(MyLayoutViewSizeClass*)lsc pMaxWrapSize->width = sbvsc.leadingPosInner.absVal + sbvsc.trailingPosInner.absVal + paddingLeading + paddingTrailing; } - //宽度不依赖布局并且没有同时设置左右边距则参与最大宽度计算。 - if (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) + //宽度不依赖布局则参与最大宽度计算。 + if ((sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) && !sbvsc.widthSizeInner.dimeFillVal) { - if (_myCGFloatLess(pMaxWrapSize->width, sbvmyFrame.width + sbvsc.leadingPosInner.absVal + sbvsc.centerXPosInner.absVal + sbvsc.trailingPosInner.absVal + paddingLeading + paddingTrailing)) pMaxWrapSize->width = sbvmyFrame.width + sbvsc.leadingPosInner.absVal + sbvsc.centerXPosInner.absVal + sbvsc.trailingPosInner.absVal + paddingLeading + paddingTrailing; @@ -3415,8 +3507,8 @@ -(void)myLayout:(MyLayoutViewSizeClass*)lsc pMaxWrapSize->height = sbvsc.topPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom; } - //高度不依赖布局并且没有同时设置上下边距则参与最大高度计算。 - if (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) + //高度不依赖布局则参与最大高度计算。 + if ((sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) && !sbvsc.heightSizeInner.dimeFillVal) { if (_myCGFloatLess(pMaxWrapSize->height, sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.centerYPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom)) pMaxWrapSize->height = sbvmyFrame.height + sbvsc.topPosInner.absVal + sbvsc.centerYPosInner.absVal + sbvsc.bottomPosInner.absVal + paddingTop + paddingBottom; @@ -3481,6 +3573,12 @@ -(void)myCalcSubviewsWrapContentSize:(NSArray*)sbs isEstimate:(BOOL)is @end +@implementation MyBaseLayoutOptionalData + + +@end + + @implementation MyFrame -(id)init diff --git a/MyLayout/Lib/MyFlexLayout.h b/MyLayout/Lib/MyFlexLayout.h index 0c25e14..dcccf83 100644 --- a/MyLayout/Lib/MyFlexLayout.h +++ b/MyLayout/Lib/MyFlexLayout.h @@ -7,39 +7,57 @@ // #import "MyFlowLayout.h" +#import "MyLayoutUI.h" - -//定义flex的方向类型。 +/**定义flex的方向类型*/ typedef enum : int { + /**横向从左到右排列(左对齐),默认的排列方式*/ MyFlexDirection_Row, + /**纵向排列*/ MyFlexDirection_Column, + /**反转横向排列(右对齐,从后往前排,最后一项排在最前面*/ MyFlexDirection_Row_Reverse, + /**反转纵向排列,从后往前排,最后一项排在最上面*/ MyFlexDirection_Column_Reverse } MyFlexDirection; -//定义flex的换行类型 +/**定义flex的换行类型*/ typedef enum : int { + /**当子元素溢出父容器时不换行*/ MyFlexWrap_NoWrap = 0, + /**当子元素溢出父容器时自动换行*/ MyFlexWrap_Wrap = 4, + /**反转 wrap 排列*/ MyFlexWrap_Wrap_Reverse = 12 }MyFlexWrap; -//定义flex的停靠对齐 +/**定义弹性盒以及条目的停靠对齐类型*/ typedef enum : int { + /**开始位置对齐或停靠*/ MyFlexGravity_Flex_Start, + /**结束位置对齐或停靠*/ MyFlexGravity_Flex_End, + /**居中位置对齐或停靠*/ MyFlexGravity_Center, + /**拉伸行或者列之间的间距*/ MyFlexGravity_Space_Between, + /**拉伸行或者列之间的间距,头尾间距是其他间距的一半*/ MyFlexGravity_Space_Around, + /**基线对齐*/ MyFlexGravity_Baseline, + /**拉伸条目尺寸*/ MyFlexGravity_Stretch }MyFlexGravity; +/**默认自动值*/ extern const int MyFlex_Auto; -//条目的属性,用于条目视图的属性设置和获取。 -@interface MyFlexItemAttrs:NSObject + +/** + 条目视图属性 + */ +@protocol MyFlexItemAttrs @property(nonatomic, assign) NSInteger order; @property(nonatomic, assign) CGFloat flex_grow; @@ -48,122 +66,125 @@ extern const int MyFlex_Auto; @property(nonatomic, assign) MyFlexGravity align_self; @property(nonatomic, assign) CGFloat width; @property(nonatomic, assign) CGFloat height; -@property(nonatomic, assign) CGFloat margin_top; -@property(nonatomic, assign) CGFloat margin_bottom; -@property(nonatomic, assign) CGFloat margin_left; -@property(nonatomic, assign) CGFloat margin_right; -@property(nonatomic, assign) MyVisibility visibility; - -@end - -@protocol MyFlexItemAttrsContainer - -@property(nonatomic, strong, readonly) MyFlexItemAttrs *attrs; @end - -/* - flexbox中项目的设置类。 - */ -@interface MyFlexItem:NSObject - -//您可以用链式语法进行属性设置,也可以直接通过属性赋值进行设置和获取。 -@property(nonatomic, weak, readonly) __kindof UIView *view; - -//条目的顺序设置 --(MyFlexItem* (^)(NSInteger))order; -//条目的尺寸比重设置,默认为0表示不按比重 --(MyFlexItem* (^)(CGFloat))flex_grow; -//条目的压缩比重设置,默认为1,表示当会进行压缩 --(MyFlexItem* (^)(CGFloat))flex_shrink; -//条目的尺寸设置,可以设置为MyFlex_Auto,固定值,相对值。你可以使用这个属性也可以通过width/height来设置。 --(MyFlexItem* (^)(CGFloat))flex_basis; -//行内条目自身的对齐方式。 --(MyFlexItem* (^)(MyFlexGravity))align_self; -//设置具体的宽度或高度值,当宽度值大于0小于1是表明的是相对宽度或高度,你也可以设置MyLayoutSize.wrap和MyLayoutSize.fill来设置特殊宽度或高度。 --(MyFlexItem* (^)(CGFloat))width; --(MyFlexItem* (^)(CGFloat))min_width; --(MyFlexItem* (^)(CGFloat))max_width; --(MyFlexItem* (^)(CGFloat))height; --(MyFlexItem* (^)(CGFloat))min_height; --(MyFlexItem* (^)(CGFloat))max_height; - -//条目的外间距设置。 --(MyFlexItem* (^)(CGFloat))margin_top; --(MyFlexItem* (^)(CGFloat))margin_bottom; --(MyFlexItem* (^)(CGFloat))margin_left; --(MyFlexItem* (^)(CGFloat))margin_right; --(MyFlexItem* (^)(CGFloat))margin; - -//是否可见 --(MyFlexItem* (^)(MyVisibility))visibility; - -//添加到父视图中 --(__kindof UIView* (^)(UIView*))addTo; - -@end - - - - -//布局的属性,用于布局视图的属性设置和获取。 -@interface MyFlexAttrs:MyFlexItemAttrs +/** + 布局视图属性 + */ +@protocol MyFlexBoxAttrs @property(nonatomic, assign) MyFlexDirection flex_direction; @property(nonatomic, assign) MyFlexWrap flex_wrap; @property(nonatomic, assign) MyFlexGravity justify_content; @property(nonatomic, assign) MyFlexGravity align_items; @property(nonatomic, assign) MyFlexGravity align_content; +@property(nonatomic, assign) NSInteger item_size; @property(nonatomic, assign) UIEdgeInsets padding; @property(nonatomic, assign) CGFloat vert_space; @property(nonatomic, assign) CGFloat horz_space; @end -@protocol MyFlexAttrsContainer -@property(nonatomic, strong, readonly) MyFlexAttrs *attrs; -@end +@protocol MyFlexItem +@property(nonatomic, strong, readonly) id attrs; -/* - flexbox的设置类。 - */ -@interface MyFlex:MyFlexItem - -//方向设置 --(MyFlex* (^)(MyFlexDirection))flex_direction; -//换行设置 --(MyFlex* (^)(MyFlexWrap))flex_wrap; -//通过 | 运算来结合 wrap 和direction --(MyFlex* (^)(int))flex_flow; -//行的停靠设置 --(MyFlex* (^)(MyFlexGravity))justify_content; -//行内条目的对齐设置 --(MyFlex* (^)(MyFlexGravity))align_items; -//整体的停靠设置 --(MyFlex* (^)(MyFlexGravity))align_content; -//内边距设置 --(MyFlex* (^)(UIEdgeInsets))padding; -//条目之间的垂直和水平间距设置 --(MyFlex* (^)(CGFloat))vert_space; --(MyFlex* (^)(CGFloat))horz_space; +/** + 条目在弹盒中的排列顺序,值越大越往后排。 + */ +-(id (^)(NSInteger))order; +/** + 设置或检索弹性盒的扩展比率。默认值为0表示不扩展 + */ +-(id (^)(CGFloat))flex_grow; +/** + 设置或检索弹性盒的收缩比率。默认值为1表示当条目尺寸超过弹性盒尺寸后会进行压缩。值越大压缩比越大 + */ +-(id (^)(CGFloat))flex_shrink; +/** + 设置或检索弹性盒伸缩基准值。默认值为MyFlex_Auto表示由其他属性决定,如果值为大于0小于1则表示相对值,其他为一个固定的尺寸值。 + */ +-(id (^)(CGFloat))flex_basis; +/** + 设置或检索弹性盒子元素自身在侧轴(纵轴)方向上的对齐方式。可选值为:MyFlexGravity_Flex_Start | MyFlexGravity_Flex_End | MyFlexGravity_Center | MyFlexGravity_Baseline | MyFlexGravity_Stretch中的一个,默认值为MyFlex_Auto + */ +-(id (^)(MyFlexGravity))align_self; @end +@protocol MyFlexBox +@property(nonatomic, strong) id attrs; + +/** + 设置或检索伸缩盒对象的子元素在父容器中的位置。默认值:MyFlexDirection_Row + */ +-(id (^)(MyFlexDirection))flex_direction; +/** + 设置或检索伸缩盒对象的子元素超出父容器时是否换行。默认值:MyFlexWrap_NoWrap + */ +-(id (^)(MyFlexWrap))flex_wrap; +/** + 同时设置检索伸缩盒对象的子元素在父容器中的位置和伸缩盒对象的子元素超出父容器时是否换行。二者通过 | 运算进行组合 + */ +-(id (^)(int))flex_flow; +/** + 设置或检索弹性盒子元素在主轴(横轴)方向上的对齐方式。可选值为:MyFlexGravity_Flex_Start | MyFlexGravity_Flex_End | MyFlexGravity_Center | MyFlexGravity_Space_Between | MyFlexGravity_Space_Around 中的一个,默认值为MyFlexGravity_Flex_Start + */ +-(id (^)(MyFlexGravity))justify_content; +/** + 设置或检索弹性盒子元素在侧轴(纵轴)方向上的对齐方式。可选值为:MyFlexGravity_Flex_Start | MyFlexGravity_Flex_End | MyFlexGravity_Center | MyFlexGravity_Baseline | MyFlexGravity_Stretch中的一个,默认值为MyFlexGravity_Flex_Start + */ +-(id (^)(MyFlexGravity))align_items; +/** + 设置或检索弹性盒堆叠伸缩行的对齐方式。可选值为:MyFlexGravity_Flex_Start | MyFlexGravity_Flex_End | MyFlexGravity_Center | MyFlexGravity_Between | MyFlexGravity_Around | MyFlexGravity_Stretch中的一个,默认值为MyFlexGravity_Stretch + */ +-(id (^)(MyFlexGravity))align_content; + + +/** + 指定主轴的子条目的数量。只有在flex_wrap设置为wrap时才有效。默认值是0表示会根据条目的尺寸自动进行换行。 + */ +-(id (^)(NSInteger))item_size; +/** + 指定布局视图中每页的条目数量。这个值必须是item_size的倍数。 + */ +-(id (^)(NSInteger))page_size; +/** + 指定布局会根据条目的尺寸自动排列,默认值是NO。 + */ +-(id (^)(BOOL))auto_arrange; + + +/** + 设置弹性盒的内边距 + */ +-(id (^)(UIEdgeInsets))padding; +/** + 设置弹性盒内所有条目视图之间的垂直间距 + */ +-(id (^)(CGFloat))vert_space; +/** + 设置弹性盒内所有条目视图之间的水平间距 + */ +-(id (^)(CGFloat))horz_space; + +@end -//条目视图在应用flexbox时的分类扩展,只有MyFlexLayout中的子视图才有用。 @interface UIView(MyFlexLayout) -//我们可以借助视图的myFlex来设置条目视图在弹性布局视图中的一些属性。 -@property(nonatomic, readonly, strong) MyFlexItem *myFlex; + +/** + 用于弹盒视图中的子视图的布局设置。 + */ +@property(nonatomic, strong, readonly) id myFlex; @end @@ -174,7 +195,10 @@ extern const int MyFlex_Auto; */ @interface MyFlexLayout:MyFlowLayout -//用于flexbox约束的设置。 -@property(nonatomic, readonly, strong) MyFlex *myFlex; + +/** + 用于弹盒布局视图自身的布局设置 + */ +@property(nonatomic, strong, readonly) id myFlex; @end diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index 75017d8..b0e65e8 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -7,16 +7,23 @@ // #import "MyFlexLayout.h" +#import "MyLayoutUIInner.h" #import "MyLayoutInner.h" #import const char * const ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM = "ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM"; const int MyFlex_Auto = -1; -@interface MyFlexItemAttrs() -@property(nonatomic, weak) UIView *view; +#pragma mark -- MyFlexItemAttrs +@interface MyFlexItemAttrs:NSObject +@property(nonatomic, weak) UIView *view; +@property(nonatomic, assign) NSInteger order; +@property(nonatomic, assign) CGFloat flex_grow; +@property(nonatomic, assign) CGFloat flex_shrink; +@property(nonatomic, assign) CGFloat flex_basis; +@property(nonatomic, assign) MyFlexGravity align_self; @end @implementation MyFlexItemAttrs @@ -31,11 +38,7 @@ -(instancetype)init _flex_shrink = 1; _flex_basis = MyFlex_Auto; _align_self = MyFlex_Auto; - //默认子视图的宽高都是自适应的。 - _width = MyLayoutSize.wrap; - _height = MyLayoutSize.wrap; } - return self; } @@ -84,284 +87,64 @@ -(void)setAlign_self:(MyFlexGravity)align_self } } --(void)setWidth:(CGFloat)width -{ - if (_width != width) - { - _width = width; - [self.view.superview setNeedsLayout]; - } -} - --(void)setHeight:(CGFloat)height -{ - if (_height != height) - { - _height = height; - [self.view.superview setNeedsLayout]; - } -} - --(CGFloat)margin_top -{ - return self.view.myTop; -} - --(void)setMargin_top:(CGFloat)margin_top -{ - self.view.myTop = margin_top; -} - --(CGFloat)margin_bottom -{ - return self.view.myBottom; -} - --(void)setMargin_bottom:(CGFloat)margin_bottom -{ - self.view.myBottom = margin_bottom; -} - --(CGFloat)margin_left -{ - return self.view.myLeft; -} - --(void)setMargin_left:(CGFloat)margin_left -{ - self.view.myLeft = margin_left; -} - --(CGFloat)margin_right +-(CGFloat)width { - return self.view.myRight; + if (self.view.widthSizeInner.isWrap) + return MyLayoutSize.wrap; + else if (self.view.widthSizeInner.isFill) + return self.view.widthSizeInner.multiVal == 1 ? MyLayoutSize.fill : self.view.widthSizeInner.multiVal; + else if (self.view.widthSizeInner.dimeNumVal != nil) + return self.view.widthSizeInner.dimeNumVal.doubleValue; + else + return MyLayoutSize.wrap; } --(void)setMargin_right:(CGFloat)margin_right +-(void)setWidth:(CGFloat)width { - self.view.myRight = margin_right; + if (width > 0 && width < 1) + self.view.widthSize.equalTo(@(MyLayoutSize.fill)).multiply(width); + else + self.view.widthSize.equalTo(@(width)); } --(MyVisibility)visibility +-(CGFloat)height { - return self.view.visibility; + if (self.view.heightSizeInner.isWrap) + return MyLayoutSize.wrap; + else if (self.view.heightSizeInner.isFill) + return self.view.heightSizeInner.multiVal == 1 ? MyLayoutSize.fill : self.view.heightSizeInner.multiVal; + else if (self.view.heightSizeInner.dimeNumVal != nil) + return self.view.heightSizeInner.dimeNumVal.doubleValue; + else + return MyLayoutSize.wrap; } --(void)setVisibility:(MyVisibility)visibility +-(void)setHeight:(CGFloat)height { - self.view.visibility = visibility; + if (height > 0 && height < 1) + self.view.heightSize.equalTo(@(MyLayoutSize.fill)).multiply(height); + else + self.view.heightSize.equalTo(@(height)); } @end -@implementation MyFlexItem -{ - @package - __weak UIView *_view; - MyFlexItemAttrs *_attrs; -} -@dynamic attrs; - --(instancetype)initWithView:(UIView*)view attrs:(MyFlexItemAttrs*)attrs -{ - self = [super init]; - if (self != nil) - { - _view = view; - _attrs = attrs; - _attrs.view = view; - } - return self; -} - --(MyFlexItemAttrs*)attrs -{ - return _attrs; -} - --(MyFlexItem* (^)(NSInteger))order -{ - return ^id(NSInteger val) { - self.attrs.order = val; - return self; - }; -} - --(MyFlexItem* (^)(CGFloat))flex_grow -{ - return ^id(CGFloat val) { - self.attrs.flex_grow = val; - return self; - }; -} - --(MyFlexItem* (^)(CGFloat))flex_shrink -{ - return ^id(CGFloat val) { - self.attrs.flex_shrink = val; - return self; - }; -} - --(MyFlexItem* (^)(CGFloat))flex_basis -{ - return ^id(CGFloat val) { - self.attrs.flex_basis = val; - return self; - }; -} - --(MyFlexItem* (^)(MyFlexGravity))align_self -{ - return ^id(MyFlexGravity val) { - self.attrs.align_self = val; - return self; - }; -} - --(__kindof UIView* (^)(UIView*))addTo -{ - return ^(UIView *val) { - - //当前是布局视图,并且父视图是非布局视图则特殊设置。 - if ([self.view isKindOfClass:[MyFlexLayout class]] && ![val isKindOfClass:[MyBaseLayout class]]) - [self setSizeConstraintWithSuperview:val]; - - [val addSubview:self.view]; - return self.view; - }; -} - --(MyFlexItem* (^)(CGFloat))width -{ - return ^id(CGFloat val) { - self.attrs.width = val; - return self; - }; -} - --(MyFlexItem* (^)(CGFloat))min_width -{ - return ^id(CGFloat val) { - self.view.widthSize.min(val); - return self; - }; -} - --(MyFlexItem* (^)(CGFloat))max_width -{ - return ^id(CGFloat val) { - self.view.widthSize.max(val); - return self; - }; -} - --(MyFlexItem* (^)(CGFloat))height -{ - return ^id(CGFloat val) { - self.attrs.height = val; - return self; - }; -} - --(MyFlexItem* (^)(CGFloat))min_height -{ - return ^id(CGFloat val) { - self.view.heightSize.min(val); - return self; - }; -} - --(MyFlexItem* (^)(CGFloat))max_height -{ - return ^id(CGFloat val) { - self.view.heightSize.max(val); - return self; - }; -} - --(MyFlexItem* (^)(CGFloat))margin_top -{ - return ^id(CGFloat val) { - self.view.myTop = val; - return self; - }; -} - --(MyFlexItem* (^)(CGFloat))margin_bottom -{ - return ^id(CGFloat val) { - self.view.myBottom = val; - return self; - }; -} - --(MyFlexItem* (^)(CGFloat))margin_left -{ - return ^id(CGFloat val) { - self.view.myLeft = val; - return self; - }; -} - --(MyFlexItem* (^)(CGFloat))margin_right -{ - return ^id(CGFloat val) { - self.view.myRight = val; - return self; - }; -} - --(MyFlexItem* (^)(CGFloat))margin -{ - return ^id(CGFloat val) { - self.view.myLeft = val; - self.view.myRight = val; - self.view.myTop = val; - self.view.myBottom = val; - return self; - }; -} - --(MyFlexItem* (^)(MyVisibility))visibility -{ - return ^id(MyVisibility val) { - self.view.visibility = val; - return self; - }; -} --(void)setSizeConstraintWithSuperview:(UIView*)superview -{ - //宽度设置 - if (self.attrs.width == MyLayoutSize.wrap) - [self.view.widthSize __equalTo:@(MyLayoutSize.wrap)]; - else if (self.attrs.width == MyLayoutSize.fill) - [self.view.widthSize __equalTo:superview.widthSize]; - else if (self.attrs.width > 0 && self.attrs.width < 1) - [[self.view.widthSize __equalTo:superview.widthSize] __multiply:self.attrs.width]; - else if (self.attrs.width == 0.0) - [self.view.widthSize __equalTo:nil]; - else - [self.view.widthSize __equalTo:@(self.attrs.width)]; - - //高度设置 - if (self.attrs.height == MyLayoutSize.wrap) - [self.view.heightSize __equalTo:@(MyLayoutSize.wrap)]; - else if (self.attrs.height == MyLayoutSize.fill) - [self.view.heightSize __equalTo:superview.heightSize]; - else if (self.attrs.height > 0 && self.attrs.height < 1) - [[self.view.heightSize __equalTo:superview.heightSize] __multiply:self.attrs.height]; - else if (self.attrs.height == 0.0) - [self.view.heightSize __equalTo:nil]; - else - [self.view.heightSize __equalTo:@(self.attrs.height)]; -} +#pragma mark -- MyFlexBoxAttrs +@interface MyFlexBoxAttrs :MyFlexItemAttrs +@property(nonatomic, assign) MyFlexDirection flex_direction; +@property(nonatomic, assign) MyFlexWrap flex_wrap; +@property(nonatomic, assign) MyFlexGravity justify_content; +@property(nonatomic, assign) MyFlexGravity align_items; +@property(nonatomic, assign) MyFlexGravity align_content; +@property(nonatomic, assign) NSInteger item_size; +@property(nonatomic, assign) UIEdgeInsets padding; +@property(nonatomic, assign) CGFloat vert_space; +@property(nonatomic, assign) CGFloat horz_space; @end - -@implementation MyFlexAttrs +@implementation MyFlexBoxAttrs -(instancetype)init { @@ -373,6 +156,7 @@ -(instancetype)init _justify_content = MyFlexGravity_Flex_Start; _align_items = MyFlexGravity_Stretch; _align_content = MyFlexGravity_Stretch; + _item_size = 0; } return self; @@ -423,6 +207,15 @@ -(void)setAlign_content:(MyFlexGravity)align_content } } +-(void)setItem_size:(NSInteger)item_size +{ + if (_item_size != item_size) + { + _item_size = item_size; + [self.view setNeedsLayout]; + } +} + -(UIEdgeInsets)padding { return ((MyFlexLayout*)self.view).padding; @@ -456,14 +249,92 @@ -(void)setHorz_space:(CGFloat)horz_space @end -@implementation MyFlex +#pragma mark -- MyFlexItem +@interface MyFlexItem:NSObject +@property(nonatomic, weak, readonly) UIView *view; +@end + +@implementation MyFlexItem +{ + @package + id _attrs; +} +@dynamic attrs; + +-(instancetype)initWithView:(UIView*)view attrs:(id)attrs +{ + self = [super init]; + if (self != nil) + { + _attrs = attrs; + _view = view; + } + return self; +} --(MyFlexAttrs*)attrs +-(id)attrs { - return (MyFlexAttrs*)_attrs; + return _attrs; } --(MyFlex* (^)(MyFlexDirection))flex_direction +-(id (^)(NSInteger))order +{ + return ^id(NSInteger val) { + self.attrs.order = val; + return self; + }; +} + +-(id (^)(CGFloat))flex_grow +{ + return ^id(CGFloat val) { + self.attrs.flex_grow = val; + return self; + }; +} + +-(id (^)(CGFloat))flex_shrink +{ + return ^id(CGFloat val) { + self.attrs.flex_shrink = val; + return self; + }; +} + +-(id (^)(CGFloat))flex_basis +{ + return ^id(CGFloat val) { + self.attrs.flex_basis = val; + return self; + }; +} + +-(id (^)(MyFlexGravity))align_self +{ + return ^id(MyFlexGravity val) { + self.attrs.align_self = val; + return self; + }; +} + +//其他请求跳转到myUI中去。 +-(id)forwardingTargetForSelector:(SEL)aSelector +{ + return self.view.myUI; +} + +@end + + +#pragma mark -- MyFlexBox + +@interface MyFlexBox:MyFlexItem + +@end + +@implementation MyFlexBox + +-(id (^)(MyFlexDirection))flex_direction { return ^id(MyFlexDirection val){ self.attrs.flex_direction = val; @@ -471,7 +342,7 @@ -(MyFlexAttrs*)attrs }; } --(MyFlex* (^)(MyFlexWrap))flex_wrap +-(id (^)(MyFlexWrap))flex_wrap { return ^id(MyFlexWrap val){ self.attrs.flex_wrap = val; @@ -479,7 +350,7 @@ -(MyFlexAttrs*)attrs }; } --(MyFlex* (^)(int))flex_flow +-(id (^)(int))flex_flow { return ^id(int val) { //取方向值。 @@ -490,7 +361,7 @@ -(MyFlexAttrs*)attrs }; } --(MyFlex* (^)(MyFlexGravity))justify_content +-(id (^)(MyFlexGravity))justify_content { return ^id(MyFlexGravity val) { self.attrs.justify_content = val; @@ -498,7 +369,7 @@ -(MyFlexAttrs*)attrs }; } --(MyFlex* (^)(MyFlexGravity))align_items +-(id (^)(MyFlexGravity))align_items { return ^id(MyFlexGravity val) { self.attrs.align_items = val; @@ -506,7 +377,32 @@ -(MyFlexAttrs*)attrs }; } --(MyFlex* (^)(MyFlexGravity))align_content + +-(id (^)(NSInteger))item_size +{ + return ^id(NSInteger val) { + self.attrs.item_size = val; + return self; + }; +} + +-(id (^)(NSInteger))page_size +{ + return ^id(NSInteger val) { + ((MyFlexLayout*)self.view).pagedCount = val; + return self; + }; +} + +-(id (^)(BOOL))auto_arrange +{ + return ^id(BOOL val) { + ((MyFlexLayout*)self.view).autoArrange = val; + return self; + }; +} + +-(id (^)(MyFlexGravity))align_content { return ^id(MyFlexGravity val) { self.attrs.align_content = val; @@ -514,7 +410,7 @@ -(MyFlexAttrs*)attrs }; } --(MyFlex* (^)(UIEdgeInsets))padding +-(id (^)(UIEdgeInsets))padding { return ^id(UIEdgeInsets val) { ((MyFlexLayout*)self.view).padding = val; @@ -522,7 +418,7 @@ -(MyFlexAttrs*)attrs }; } --(MyFlex* (^)(CGFloat))vert_space +-(id (^)(CGFloat))vert_space { return ^id(CGFloat val) { ((MyFlexLayout*)self.view).subviewVSpace = val; @@ -530,7 +426,7 @@ -(MyFlexAttrs*)attrs }; } --(MyFlex* (^)(CGFloat))horz_space +-(id (^)(CGFloat))horz_space { return ^id(CGFloat val) { ((MyFlexLayout*)self.view).subviewHSpace = val; @@ -540,25 +436,31 @@ -(MyFlexAttrs*)attrs @end + +#pragma mark - UIView + @implementation UIView(MyFlexLayout) --(MyFlexItem*)myFlex +-(id)myFlex { - MyFlexItem *obj = nil; - if ([self isKindOfClass:[MyFlexLayout class]] ) + if ([self isKindOfClass:[MyFlexLayout class]]) { - obj = ((MyFlexLayout*)self).myFlex; + return ((MyFlexLayout*)self).myFlex; } else { - obj = (MyFlexItem*)objc_getAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM); + id obj = (id)objc_getAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM); if (obj == nil) { - obj = [[MyFlexItem alloc] initWithView:self attrs:[MyFlexItemAttrs new]]; - objc_setAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + MyFlexItemAttrs *attrs = [MyFlexItemAttrs new]; + attrs.view = self; + obj = [[MyFlexItem alloc] initWithView:self attrs:attrs]; } + + objc_setAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_FLEXITEM, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + return obj; } - return obj; } @end @@ -571,10 +473,13 @@ -(instancetype)init self = [super init]; if (self != nil) { - _myFlex = [[MyFlex alloc] initWithView:self attrs:[MyFlexAttrs new]]; self.orientation = MyOrientation_Vert; //默认row self.arrangedCount = NSIntegerMax; //默认单行 self.isFlex = YES; //满足flexbox的需求。 + + MyFlexBoxAttrs *attrs = [MyFlexBoxAttrs new]; + attrs.view = self; + _myFlex = [[MyFlexBox alloc] initWithView:self attrs:attrs]; } return self; } @@ -583,9 +488,10 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( { //将flexbox中的属性映射为MyFlowLayout中的属性。 MyFlexLayout *lsc = self.myCurrentSizeClass; - + id myFlex = self.myFlex; + //最先设置方向。 - switch (self.myFlex.attrs.flex_direction) { + switch (myFlex.attrs.flex_direction) { case MyFlexDirection_Column_Reverse: //column_reverse lsc.orientation = MyOrientation_Horz; lsc.layoutTransform = CGAffineTransformMake(1,0,0,-1,0,0); //垂直翻转 @@ -605,13 +511,13 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( break; } - //设置换行. - switch (self.myFlex.attrs.flex_wrap) { + //设置换行 + switch (myFlex.attrs.flex_wrap) { case MyFlexWrap_Wrap: - lsc.arrangedCount = 0; + lsc.arrangedCount = myFlex.attrs.item_size; break; case MyFlexWrap_Wrap_Reverse: - lsc.arrangedCount = 0; + lsc.arrangedCount = myFlex.attrs.item_size; lsc.layoutTransform = CGAffineTransformConcat(lsc.layoutTransform, (lsc.orientation == MyOrientation_Vert)? CGAffineTransformMake(1,0,0,-1,0,0):CGAffineTransformMake(-1,0,0,1,0,0)); break; case MyFlexWrap_NoWrap: @@ -632,7 +538,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( for (UIView *sbv in sbs) { - MyFlexItem *flexItem = sbv.myFlex; + id flexItem = sbv.myFlex; UIView *sbvsc = sbv.myCurrentSizeClass; //flex_grow,如果子视图有设置grow则父视图的换行不起作用。 @@ -644,22 +550,26 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( else sbvsc.heightSize.shrink = flexItem.attrs.flex_shrink != MyFlex_Auto? flexItem.attrs.flex_shrink:0; - [flexItem setSizeConstraintWithSuperview:self]; - + //如果没有设置尺寸约束则默认是自适应。 + if (sbvsc.widthSizeInner.dimeVal == nil) + [sbvsc.widthSize __equalTo:@(MyLayoutSize.wrap)]; + if (sbvsc.heightSizeInner.dimeVal == nil) + [sbvsc.heightSize __equalTo:@(MyLayoutSize.wrap)]; + //基准值设置。 if (flexItem.attrs.flex_basis != MyFlex_Auto) { if (lsc.orientation == MyOrientation_Vert) { - if (flexItem.attrs.flex_basis < 1 && flexItem.attrs.flex_basis > 0) - [[sbvsc.widthSize __equalTo:lsc.widthSize] __multiply:flexItem.attrs.flex_basis]; + if (flexItem.attrs.flex_basis > 0 && flexItem.attrs.flex_basis < 1) + [[sbvsc.widthSize __equalTo:@(MyLayoutSize.fill)] __multiply:flexItem.attrs.flex_basis]; else [sbvsc.widthSize __equalTo:@(flexItem.attrs.flex_basis)]; } else { - if (flexItem.attrs.flex_basis < 1 && flexItem.attrs.flex_basis > 0) - [[sbvsc.heightSize __equalTo:lsc.heightSize] __multiply:flexItem.attrs.flex_basis]; + if (flexItem.attrs.flex_basis > 0 && flexItem.attrs.flex_basis < 1) + [[sbvsc.heightSize __equalTo:@(MyLayoutSize.fill)] __multiply:flexItem.attrs.flex_basis]; else [sbvsc.heightSize __equalTo:@(flexItem.attrs.flex_basis)]; } @@ -668,7 +578,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //对齐方式设置。 int align_self = flexItem.attrs.align_self; switch (align_self) { - case MyFlex_Auto: + case -1: sbvsc.alignment = MyGravity_None; break; case MyFlexGravity_Flex_Start: @@ -694,7 +604,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //设置主轴的水平对齐和拉伸 MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = lsc.gravity & MyGravity_Vert_Mask; - switch (self.myFlex.attrs.justify_content) { + switch (myFlex.attrs.justify_content) { case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Vert) lsc.gravity = MyGravity_Horz_Trailing | vertGravity; @@ -731,7 +641,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //次轴的对齐处理。 MyGravity vertArrangedGravity = lsc.arrangedGravity & MyGravity_Horz_Mask; MyGravity horzArrangedGravity = lsc.arrangedGravity & MyGravity_Vert_Mask; - switch (self.myFlex.attrs.align_items) { + switch (myFlex.attrs.align_items) { case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Vert) lsc.arrangedGravity = MyGravity_Vert_Bottom | horzArrangedGravity; @@ -768,7 +678,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( //多行下的整体停靠处理。 vertGravity = lsc.gravity & MyGravity_Horz_Mask; horzGravity = lsc.gravity & MyGravity_Vert_Mask; - switch (self.myFlex.attrs.align_content) { + switch (myFlex.attrs.align_content) { case MyFlexGravity_Flex_End: if (lsc.orientation == MyOrientation_Horz) lsc.gravity = MyGravity_Horz_Trailing | vertGravity; diff --git a/MyLayout/Lib/MyFrameLayout.m b/MyLayout/Lib/MyFrameLayout.m index e655e04..11a04ef 100644 --- a/MyLayout/Lib/MyFrameLayout.m +++ b/MyLayout/Lib/MyFrameLayout.m @@ -66,8 +66,9 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( (sbvsc.centerXPosInner.posVal != nil) || (sbvsc.centerYPosInner.posVal != nil) || (sbvsc.widthSizeInner.dimeRelaVal.view == self) || - (sbvsc.heightSizeInner.dimeRelaVal.view == self) - ) + (sbvsc.heightSizeInner.dimeRelaVal.view == self) || + sbvsc.widthSizeInner.dimeFillVal || + sbvsc.heightSizeInner.dimeFillVal) { [self myLayout:lsc calcRectOfSubview:sbvsc sbvmyFrame:sbvmyFrame vertGravity:vertGravity horzGravity:horzGravity inSelfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing pMaxWrapSize:NULL]; } diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index dc0ed55..166d13d 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -58,5 +58,4 @@ #import "MyPathLayout.h" #import "MyGridLayout.h" #import "MyMaker.h" - #endif diff --git a/MyLayout/Lib/MyLayoutInner.h b/MyLayout/Lib/MyLayoutInner.h index ae290e4..50810d1 100644 --- a/MyLayout/Lib/MyLayoutInner.h +++ b/MyLayout/Lib/MyLayoutInner.h @@ -214,3 +214,19 @@ paddingTrailing:(CGFloat)paddingTrailing @property(nonatomic, readonly) CGFloat myEstimatedHeight; @end + +//为了减少布局视图不必要的内存占用,这里将一些可选数据保存到这个类中来 +@interface MyBaseLayoutOptionalData:NSObject + +//特定场景处理的回调block +@property(nonatomic,copy) void (^beginLayoutBlock)(void); +@property(nonatomic,copy) void (^endLayoutBlock)(void); +@property(nonatomic,copy) void (^rotationToDeviceOrientationBlock)(MyBaseLayout *layout, BOOL isFirst, BOOL isPortrait); +@property(nonatomic, assign) int lastScreenOrientation; //为0为初始状态,为1为竖屏,为2为横屏。内部使用。 + +//动画扩展 +@property(nonatomic, assign) NSTimeInterval aniDuration; +@property(nonatomic, assign) UIViewAnimationOptions aniOptions; +@property(nonatomic, copy) void (^aniCompletion)(BOOL finished); + +@end diff --git a/MyLayout/Lib/MyLayoutMath.h b/MyLayout/Lib/MyLayoutMath.h index 1cecf41..da8cd3c 100644 --- a/MyLayout/Lib/MyLayoutMath.h +++ b/MyLayout/Lib/MyLayoutMath.h @@ -59,7 +59,6 @@ typedef enum : unsigned char MyLayoutValueType_SafeArea, MyLayoutValueType_Most, MyLayoutValueType_LayoutDimeClone, - MyLayoutValueType_Weight, - MyLayoutValueType_Wrap, MyLayoutValueType_Fill, + MyLayoutValueType_Wrap, }MyLayoutValueType; diff --git a/MyLayout/Lib/MyLayoutSize.h b/MyLayout/Lib/MyLayoutSize.h index b9ceac6..9ab81a3 100644 --- a/MyLayout/Lib/MyLayoutSize.h +++ b/MyLayout/Lib/MyLayoutSize.h @@ -26,14 +26,14 @@ @interface MyLayoutSize : NSObject #if UIKIT_DEFINE_AS_PROPERTIES -/**特殊的尺寸,表示尺寸由子视图决定或者由内容决定。目前只用在表格布局MyTableLayout和栅格布局MyGridLayout中。*/ +/**特殊的尺寸,表示尺寸由子视图决定或者由内容决定,也就是说尺寸自适应*/ @property(class, nonatomic, assign,readonly) NSInteger wrap; #else +(NSInteger)wrap; #endif #if UIKIT_DEFINE_AS_PROPERTIES -/**特殊的尺寸,表示尺寸会填充满父视图的剩余空间。目前只用在表格布局MyTableLayout和栅格布局MyGridLayout中。*/ +/**特殊的尺寸,表示尺寸会填充满父视图的剩余空间。*/ @property(class, nonatomic, assign,readonly) NSInteger fill; #else +(NSInteger)fill; @@ -65,7 +65,7 @@ /** 设置尺寸的具体值,这个具体值可以设置为NSNumber, MyLayoutSize以及NSArray数组,UIView, MyLayoutMostSize和nil值。 - 1. 设置为NSNumber值表示指定具体的宽度或者高度数值 + 1. 设置为NSNumber值表示指定具体的宽度或者高度数值,如果设置为特殊值MyLayoutSize.wrap则表示尺寸自适应,如果设置为LayoutSize.fill则表示等于父视图的尺寸。 2. 设置为MyLayoutSize值表示宽度和高度与设置的对象有依赖关系, 甚至可以依赖对象本身 @@ -216,9 +216,17 @@ @property(nonatomic, assign, readonly) CGFloat minVal; @property(nonatomic, assign, readonly) CGFloat maxVal; -//判断尺寸值是否是自适应值。 +/** + 判断尺寸值是否是自适应值。 + */ @property(nonatomic, assign, readonly) BOOL isWrap; + +/** + 判断尺寸是不是填充比重值。 + */ +@property(nonatomic, assign, readonly) BOOL isFill; + @end diff --git a/MyLayout/Lib/MyLayoutSize.m b/MyLayout/Lib/MyLayoutSize.m index c193b35..5984bf3 100644 --- a/MyLayout/Lib/MyLayoutSize.m +++ b/MyLayout/Lib/MyLayoutSize.m @@ -219,6 +219,11 @@ -(BOOL)isWrap return [self dimeWrapVal]; } +-(BOOL)isFill +{ + return [self dimeFillVal]; +} + #pragma mark -- NSCopying -(id)copyWithZone:(NSZone *)zone @@ -291,6 +296,12 @@ -(BOOL)dimeWrapVal return self.isActive && _dimeValType == MyLayoutValueType_Wrap; } +-(BOOL)dimeFillVal +{ + return self.isActive && _dimeValType == MyLayoutValueType_Fill; +} + + -(MyLayoutSize*)lBoundVal { if (_lBoundVal == nil) @@ -342,7 +353,7 @@ -(MyLayoutSize*)__equalTo:(id)val priority:(NSInteger)priority if ([val integerValue] == MyLayoutSize.wrap) _dimeValType = MyLayoutValueType_Wrap; else if ([val integerValue] == MyLayoutSize.fill) - NSAssert(0, @"oops! 暂时不支持"); + _dimeValType = MyLayoutValueType_Fill; else _dimeValType = MyLayoutValueType_NSNumber; } diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index ce91418..147c71b 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -341,6 +341,8 @@ -(CGFloat)myWidth //特殊处理设置为MyLayoutSize.wrap的返回 if (self.widthSizeInner.dimeValType == MyLayoutValueType_Wrap) return MyLayoutSize.wrap; + else if (self.widthSizeInner.dimeValType == MyLayoutValueType_Fill) + return MyLayoutSize.fill; else return self.widthSizeInner.measure; } @@ -354,6 +356,8 @@ -(CGFloat)myHeight { if (self.heightSizeInner.dimeValType == MyLayoutValueType_Wrap) return MyLayoutSize.wrap; + else if (self.heightSizeInner.dimeValType == MyLayoutValueType_Fill) + return MyLayoutSize.fill; else return self.heightSizeInner.measure; } diff --git a/MyLayout/Lib/MyLayoutSizeInner.h b/MyLayout/Lib/MyLayoutSizeInner.h index 97f910f..7ba5785 100644 --- a/MyLayout/Lib/MyLayoutSizeInner.h +++ b/MyLayout/Lib/MyLayoutSizeInner.h @@ -23,6 +23,7 @@ @property(nonatomic, readonly, strong) NSArray *dimeArrVal; @property(nonatomic, readonly, assign) BOOL dimeWrapVal; +@property(nonatomic, readonly, assign) BOOL dimeFillVal; @property(nonatomic, readonly, strong) MyLayoutSize *lBoundVal; @property(nonatomic, readonly, strong) MyLayoutSize *uBoundVal; diff --git a/MyLayout/Lib/MyLayoutUI.h b/MyLayout/Lib/MyLayoutUI.h new file mode 100644 index 0000000..21fe768 --- /dev/null +++ b/MyLayout/Lib/MyLayoutUI.h @@ -0,0 +1,104 @@ +// +// MyFlexItem.h +// MyLayout +// +// Created by oubaiquan on 2019/11/15. +// Copyright © 2019 YoungSoft. All rights reserved. +// + +#import +#import "MyLayoutDef.h" + + +@protocol MyUIViewUI +@optional + +//您可以用链式语法进行属性设置,也可以直接通过属性赋值进行设置和获取。 +@property(nonatomic, weak, readonly) __kindof UIView *view; + + +/** + 视图的宽度设置,如果宽度设置为大于0小于1则表明是相对于父视图宽度的比重值,如果是MyLayoutSize.wrap则表明宽度自适应,如果是MyLayoutSize.fill则表明宽度和父视图相等,其他的值就是一个固定宽度值。 + */ +-(id (^)(CGFloat))width; + +/** + 最小宽度限制设置 + */ +-(id (^)(CGFloat))min_width; + +/** + 最大宽度限制设置 + */ +-(id (^)(CGFloat))max_width; +/** + 视图的高度设置,如果高度设置为大于0小于1则表明是相对于父视图高度的比重值,如果是MyLayoutSize.wrap则表明高度自适应,如果是MyLayoutSize.fill则表明高度和父视图相等,其他的值就是一个固定高度值。 + */ +-(id (^)(CGFloat))height; + +/** + 最小高度限制设置 + */ +-(id (^)(CGFloat))min_height; + +/** + 最大高度限制设置 + */ +-(id (^)(CGFloat))max_height; + +//视图的外间距设置。 +/** + 视图的顶部外间距设置 + */ +-(id (^)(CGFloat))margin_top; +/** + 视图的底部外间距设置 + */ +-(id (^)(CGFloat))margin_bottom; +/** + 视图的左边外间距设置 + */ +-(id (^)(CGFloat))margin_left; +/** + 视图的右边外间距设置 + */ +-(id (^)(CGFloat))margin_right; +/** + 视图的四周外间距设置 + */ +-(id (^)(CGFloat))margin; +/** + 视图的可视设置 + */ +-(id (^)(MyVisibility))visibility; + +//视图特有的属性。 +-(id (^)(CGAffineTransform))transform; +-(id (^)(BOOL))clipsToBounds; +-(id (^)(UIColor*))backgroundColor; +-(id (^)(CGFloat))alpha; +-(id (^)(NSInteger))tag; +-(id (^)(BOOL))userInteractionEnabled; +-(id (^)( UIColor *color,CGFloat width))border; +-(id (^)(CGFloat))cornerRadius; +-(id (^)(UIColor* color, CGSize offset, CGFloat radius))shadow; + +//添加到父视图中 +-(__kindof UIView* (^)(UIView*))addTo; + +//添加子视图 +-(id (^)(UIView*))add; + +@end + + +@protocol MyUIViewUICategory + +@property(nonatomic, strong, readonly) id myUI; + +@end + + +@interface UIView(MyLayoutUI) +@end + diff --git a/MyLayout/Lib/MyLayoutUI.m b/MyLayout/Lib/MyLayoutUI.m new file mode 100644 index 0000000..f70c3fa --- /dev/null +++ b/MyLayout/Lib/MyLayoutUI.m @@ -0,0 +1,244 @@ +// +// MyFlexItem.m +// MyLayout +// +// Created by oubaiquan on 2019/11/15. +// Copyright © 2019 YoungSoft. All rights reserved. +// + +#import "MyBaseLayout.h" +#import "MyLayoutInner.h" +#import "MyLayoutUIInner.h" +#import + +const char * const ASSOCIATEDOBJECT_KEY_MYLAYOUT_MYUI = "ASSOCIATEDOBJECT_KEY_MYLAYOUT_MYUI"; + + +#pragma mark -- MyUIViewUI + +@implementation MyUIViewUI + +-(instancetype)initWithView:(UIView*)view +{ + self = [self init]; + if (self != nil) + { + _view = view; + } + return self; +} + +-(id (^)(CGFloat))width +{ + return ^id(CGFloat val) { + if (val > 0 && val < 1) + self.view.widthSize.equalTo(@(MyLayoutSize.fill)).multiply(val); + else + self.view.widthSize.equalTo(@(val)); + return self; + }; +} + +-(id (^)(CGFloat))min_width +{ + return ^id(CGFloat val) { + self.view.widthSize.min(val); + return self; + }; +} + +-(id (^)(CGFloat))max_width +{ + return ^id(CGFloat val) { + self.view.widthSize.max(val); + return self; + }; +} + +-(id (^)(CGFloat))height +{ + return ^id(CGFloat val) { + if (val > 0 && val < 1) + self.view.heightSize.equalTo(@(MyLayoutSize.fill)).multiply(val); + else + self.view.heightSize.equalTo(@(val)); + return self; + }; +} + +-(id (^)(CGFloat))min_height +{ + return ^id(CGFloat val) { + self.view.heightSize.min(val); + return self; + }; +} + +-(id (^)(CGFloat))max_height +{ + return ^id(CGFloat val) { + self.view.heightSize.max(val); + return self; + }; +} + +-(id (^)(CGFloat))margin_top +{ + return ^id(CGFloat val) { + self.view.myTop = val; + return self; + }; +} + +-(id (^)(CGFloat))margin_bottom +{ + return ^id(CGFloat val) { + self.view.myBottom = val; + return self; + }; +} + +-(id (^)(CGFloat))margin_left +{ + return ^id(CGFloat val) { + self.view.myLeft = val; + return self; + }; +} + +-(id (^)(CGFloat))margin_right +{ + return ^id(CGFloat val) { + self.view.myRight = val; + return self; + }; +} + +-(id (^)(CGFloat))margin +{ + return ^id(CGFloat val) { + self.view.myLeft = val; + self.view.myRight = val; + self.view.myTop = val; + self.view.myBottom = val; + return self; + }; +} + +-(id (^)(MyVisibility))visibility +{ + return ^id(MyVisibility val) { + self.view.visibility = val; + return self; + }; +} + +-(id (^)(CGAffineTransform))transform +{ + return ^id(CGAffineTransform val) { + self.view.transform = val; + return self; + }; +} + +-(id (^)(BOOL))clipsToBounds +{ + return ^id(BOOL val) { + self.view.clipsToBounds = val; + return self; + }; +} + +-(id (^)(UIColor*))backgroundColor +{ + return ^id(UIColor *val) { + self.view.backgroundColor = val; + return self; + }; +} + +-(id (^)(CGFloat))alpha +{ + return ^id(CGFloat val) { + self.view.alpha = val; + return self; + }; +} + +-(id (^)(NSInteger))tag +{ + return ^id(NSInteger val) { + self.view.tag = val; + return self; + }; +} + +-(id (^)(BOOL))userInteractionEnabled +{ + return ^id(BOOL val) { + self.view.userInteractionEnabled = val; + return self; + }; +} + +-(id (^)(UIColor *color, CGFloat width))border +{ + return ^id(UIColor *color, CGFloat width) { + self.view.layer.borderColor = color.CGColor; + self.view.layer.borderWidth = width; + return self; + }; +} + +-(id (^)(CGFloat))cornerRadius +{ + return ^id(CGFloat val) { + self.view.layer.cornerRadius = val; + return self; + }; +} + +-(id (^)(UIColor* color, CGSize offset, CGFloat radius))shadow +{ + return ^id(UIColor *color, CGSize offset, CGFloat radius) { + self.view.layer.shadowColor = color.CGColor; + self.view.layer.shadowOffset = offset; + self.view.layer.shadowRadius = radius; + return self; + }; +} + +-(__kindof UIView* (^)(UIView*))addTo +{ + return ^(UIView *val) { + [val addSubview:self.view]; + return self.view; + }; +} + +-(id (^)(UIView*))add +{ + return ^(UIView *val) { + [self.view addSubview:val]; + return self; + }; +} + + +@end + + +@implementation UIView(MyLayoutUI) + +-(id)myUI +{ + id obj = (id)objc_getAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_MYUI); + if (obj == nil) + { + obj = [[MyUIViewUI alloc] initWithView:self]; + objc_setAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_MYUI, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return obj; +} + +@end diff --git a/MyLayout/Lib/MyLayoutUIInner.h b/MyLayout/Lib/MyLayoutUIInner.h new file mode 100644 index 0000000..2ee05eb --- /dev/null +++ b/MyLayout/Lib/MyLayoutUIInner.h @@ -0,0 +1,19 @@ +// +// MyFlexItem.h +// MyLayout +// +// Created by oubaiquan on 2019/11/15. +// Copyright © 2019 YoungSoft. All rights reserved. +// + +#import "MyLayoutUI.h" + +#pragma mark -- MyUIViewUI + +@interface MyUIViewUI : NSObject + +@property(nonatomic, weak, readonly) __kindof UIView *view; + +-(instancetype)initWithView:(UIView*)view; + +@end diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 78964a3..3ecc884 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -316,7 +316,7 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub isFlexSbv = NO; //高度依赖于父视图的不能被伸缩 - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) + if ((sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == lsc.heightSizeInner) || sbvsc.heightSizeInner.dimeFillVal) isFlexSbv = NO; //布局视图的高度自适应尺寸的不能被伸缩。 @@ -361,6 +361,7 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub //左右依赖的,或者依赖父视图宽度的不参数最宽计算!! if ((tempSelfWidth > maxSelfWidth) && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) && + !sbvsc.widthSizeInner.dimeFillVal && (sbvsc.leadingPosInner.posVal == nil || sbvsc.trailingPosInner.posVal == nil || sbvsc.widthSizeInner.dimeVal != nil)) { maxSelfWidth = tempSelfWidth; @@ -680,6 +681,7 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub if ((tempSelfWidth > maxSelfWidth) && (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) && + !sbvsc.widthSizeInner.dimeFillVal && (sbvsc.leadingPosInner.posVal == nil || sbvsc.trailingPosInner.posVal == nil || sbvsc.widthSizeInner.dimeVal != nil)) { maxSelfWidth = tempSelfWidth; @@ -788,7 +790,7 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub isFlexSbv = NO; //宽度依赖父视图宽度的不伸缩 - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner) + if ((sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == lsc.widthSizeInner) || sbvsc.widthSizeInner.dimeFillVal) isFlexSbv = NO; //布局子视图宽度自适应时不伸缩 @@ -834,6 +836,7 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub if ((tempSelfHeight > maxSelfHeight) && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) && + !sbvsc.heightSizeInner.dimeFillVal && (sbvsc.topPosInner.posVal == nil || sbvsc.bottomPosInner.posVal == nil || sbvsc.heightSizeInner.dimeVal != nil)) { maxSelfHeight = tempSelfHeight; @@ -1208,6 +1211,7 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub if ((tempSelfHeight > maxSelfHeight) && (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) && + !sbvsc.heightSizeInner.dimeFillVal && (sbvsc.topPosInner.posVal == nil || sbvsc.bottomPosInner.posVal == nil || sbvsc.heightSizeInner.dimeVal != nil )) { maxSelfHeight = tempSelfHeight; diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 568575d..9ad2379 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -862,13 +862,16 @@ -(BOOL)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcWidthOfSubview:(MyViewSi } else if (sbvsc.widthSizeInner.dimeRelaVal != nil) { - sbvmyFrame.width = [sbvsc.widthSizeInner measureWith:[self myLayout:lsc calcSizeOrPosOfSubview:sbvsc.widthSizeInner.dimeRelaVal.view gravity:sbvsc.widthSizeInner.dimeRelaVal.dime selfSize:selfSize] ]; } else if (sbvsc.widthSizeInner.dimeNumVal != nil) { sbvmyFrame.width = sbvsc.widthSizeInner.measure; } + else if (sbvsc.widthSizeInner.dimeFillVal) + { + sbvmyFrame.width = [sbvsc.widthSizeInner measureWith:selfSize.width - lsc.myLayoutLeadingPadding - lsc.myLayoutTrailingPadding]; + } else if (sbvsc.widthSizeInner.dimeWrapVal) { //对于非布局视图进行宽度自适应计算。 @@ -1037,6 +1040,10 @@ -(BOOL)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcHeightOfSubview:(MyViewS { sbvmyFrame.height = sbvsc.heightSizeInner.measure; } + else if (sbvsc.heightSizeInner.dimeFillVal) + { + sbvmyFrame.height = [sbvsc.heightSizeInner measureWith:selfSize.height - lsc.myLayoutTopPadding - lsc.myLayoutBottomPadding]; + } else if (sbvsc.heightSizeInner.dimeWrapVal) { if (![sbv isKindOfClass:[MyBaseLayout class]]) @@ -1156,7 +1163,8 @@ -(CGSize)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcSelfSize:(CGSize)selfS sbvsc.trailingPosInner.posRelaVal.view == self || sbvsc.centerXPosInner.posRelaVal.view == self || sbvsc.centerXPosInner.posNumVal != nil || - sbvsc.widthSizeInner.dimeRelaVal.view == self + sbvsc.widthSizeInner.dimeRelaVal.view == self || + sbvsc.widthSizeInner.dimeFillVal ) { *pRecalcWidth = YES; @@ -1168,7 +1176,7 @@ -(CGSize)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcSelfSize:(CGSize)selfS maxWidth = sbvsc.leadingPosInner.absVal + sbvsc.trailingPosInner.absVal + lsc.myLayoutLeadingPadding + lsc.myLayoutTrailingPadding; } - if ( sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) + if ( (sbvsc.widthSizeInner.dimeRelaVal == nil || sbvsc.widthSizeInner.dimeRelaVal != lsc.widthSizeInner) && !sbvsc.widthSizeInner.dimeFillVal) { if (sbvsc.centerXPosInner.posVal != nil) { @@ -1198,7 +1206,8 @@ -(CGSize)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcSelfSize:(CGSize)selfS sbvsc.bottomPosInner.posRelaVal.view == self || sbvsc.centerYPosInner.posRelaVal.view == self || sbvsc.centerYPosInner.posNumVal != nil || - sbvsc.heightSizeInner.dimeRelaVal.view == self + sbvsc.heightSizeInner.dimeRelaVal.view == self || + sbvsc.heightSizeInner.dimeFillVal ) { *pRecalcHeight = YES; @@ -1211,7 +1220,7 @@ -(CGSize)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcSelfSize:(CGSize)selfS } //高度不依赖父视图 - if (sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) + if ((sbvsc.heightSizeInner.dimeRelaVal == nil || sbvsc.heightSizeInner.dimeRelaVal != lsc.heightSizeInner) && !sbvsc.heightSizeInner.dimeFillVal) { if (sbvsc.centerYPosInner.posVal != nil) { diff --git a/MyLayoutDemo/FLXTest1ViewController.m b/MyLayoutDemo/FLXTest1ViewController.m index 05c503e..79f33e6 100644 --- a/MyLayoutDemo/FLXTest1ViewController.m +++ b/MyLayoutDemo/FLXTest1ViewController.m @@ -37,6 +37,8 @@ -(void)loadView .view; self.view = rootLayout; + + //布局属性设置。 MyFlexLayout *flexAttrLayout = MyFlexLayout.new.myFlex .flex_direction(MyFlexDirection_Row) @@ -148,6 +150,13 @@ -(void)loadView paddingTitleLabel.text = @"padding:"; + + + + + + + UISwitch *paddingSwitch = UISwitch.new.myFlex .width(MyLayoutSize.wrap) .height(MyLayoutSize.wrap) @@ -195,10 +204,11 @@ -(void)loadView [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [button addTarget:self action:@selector(handleAddItem:) forControlEvents:UIControlEventTouchUpInside]; + MyFlexLayout *contentLayout = MyFlexLayout.new.myFlex - .width(MyLayoutSize.fill) .flex_grow(1) + .width(MyLayoutSize.fill) .addTo(rootLayout); contentLayout.backgroundColor = [UIColor lightGrayColor]; @@ -366,8 +376,8 @@ -(void)editFlexItem:(UIView*)itemView widthLabel.text = @"width:"; UITextField *widthTextField = UITextField.new.myFlex - .width(100) .flex_grow(1) + .width(100) .height(30) .addTo(dialogLayout); @@ -383,8 +393,8 @@ -(void)editFlexItem:(UIView*)itemView heightLabel.text = @"height:"; UITextField *heightTextField = UITextField.new.myFlex - .width(100) .flex_grow(1) + .width(100) .height(30) .addTo(dialogLayout); @@ -401,8 +411,8 @@ -(void)editFlexItem:(UIView*)itemView orderLabel.text = @"order:"; UITextField *orderTextField = UITextField.new.myFlex - .width(100) .flex_grow(1) + .width(100) .height(30) .addTo(dialogLayout); @@ -419,8 +429,8 @@ -(void)editFlexItem:(UIView*)itemView flex_growLabel.text = @"flex-grow:"; UITextField *flex_growTextField = UITextField.new.myFlex - .width(100) .flex_grow(1) + .width(100) .height(30) .addTo(dialogLayout); @@ -437,8 +447,8 @@ -(void)editFlexItem:(UIView*)itemView flex_shrinkLabel.text = @"flex-shrink:"; UITextField *flex_shrinkTextField = UITextField.new.myFlex - .width(100) .flex_grow(1) + .width(100) .height(30) .addTo(dialogLayout); @@ -455,8 +465,8 @@ -(void)editFlexItem:(UIView*)itemView flex_basisLabel.text = @"flex-basis:"; UITextField *flex_basisTextField = UITextField.new.myFlex - .width(100) .flex_grow(1) + .width(100) .height(30) .addTo(dialogLayout); @@ -473,8 +483,8 @@ -(void)editFlexItem:(UIView*)itemView align_selfLabel.text = @"align-self:"; UITextField *align_selfTextField = UITextField.new.myFlex - .width(100) .flex_grow(1) + .width(100) .height(30) .addTo(dialogLayout); diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index 407d6a5..35fb92c 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -1124,9 +1124,7 @@ -(void)testFlex1 MyFlexLayout *contentLayout = MyFlexLayout.new.myFlex .flex_wrap(MyFlexWrap_Wrap) - .width(MyLayoutSize.wrap) .max_width(100) - .height(MyLayoutSize.wrap) .addTo(flexLayout); contentLayout.backgroundColor = [UIColor greenColor]; From 6823a2b010af6a2470003e4f228f3648b39d2468 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Mon, 18 Nov 2019 15:36:02 +0800 Subject: [PATCH 090/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 +++ MyLayout/Lib/MyRelativeLayout.m | 4 +++ MyLayoutTests/MyFlowLayoutTestCase.m | 34 ++++++++++++++++++++++++ MyLayoutTests/MyRelativeLayoutTestCase.m | 31 +++++++++++++++++++++ 4 files changed, 72 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36c2e22..da5dbfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ 11. 在线性布局、流式布局、浮动布局中实现了可以在尺寸自适应的模式下gravity的停靠属性生效的能力。解决了[issue#102](https://github.com/youngsoft/MyLinearLayout/issues/102) 12. 在线性布局、流式布局、浮动布局中实现了设置尺寸自适应并且设置了最大最小值约束的情况下子视图被正确布局的功能。 13. 扩充的流式布局中的pagedCount的能力,由原先的必须是在滚动视图的子视图下生效改为可以在任意时刻生效。 +14. 改变对布局动画方法:`layoutAnimationWithDuration:`的实现逻辑,并新增加了动画的选项以及动画完成后的处理block机制,具体使用请参见方法:`layoutAnimationWithDuration:options:completion:` ### Update 1. 更新了对尺寸自适应属性的设置方式。不再建议使用wrapContentWidth进行宽度自适应设置,而是改为`myWidth = MyLayoutSize.wrap`或者`widthSize.equalTo(@(MyLayoutSize.wrap))`进行宽度自适应设置。不再建议使用wrapContentHeight进行高度尺寸自适应设置,而是改为`myHeight= MyLayoutSize.wrap`或者`heightSize.equalTo(@(MyLayoutSize.wrap))`进行高度自适应设置。 对于宽度是否自适应的判断则可以用`myWidth == MyLayoutSize.wrap`或widthSize.iswrap进行判断,高度也是一样的。 @@ -42,6 +43,8 @@ 2. 将浮动布局的noBoundaryLimit属性设置为过期,这个属性将不再生效,而是直接将布局的宽度或者高度设置为自适应即可实现相同的功能。 3. 线性布局中的shrinkType属性用于控制所有子视图的压缩特性,如果子视图的尺寸设置shrink属性值则以子视图的设置优先,布局视图的shrinkType将不再起作用。 +4. 修改布局视图监听子布局视图frame和center变化的实现,由原来的KVO形式变化为直接调用。这样就可以减少布局计算的耗时处理。 +5. 重构了流式布局、相对布局,加快了布局计算时间,尤其是相对布局的重构。 diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 9ad2379..2a66cc8 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -20,6 +20,10 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( CGSize selfSize = [super calcLayoutSize:size isEstimate:isEstimate pHasSubLayout:pHasSubLayout sizeClass:sizeClass sbs:sbs]; MyRelativeLayoutViewSizeClass *lsc = (MyRelativeLayoutViewSizeClass*)self.myCurrentSizeClass; + if (lsc.widthSizeInner.dimeWrapVal) + selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:0 sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; + if (lsc.heightSizeInner.dimeWrapVal) + selfSize.height = [self myValidMeasure:lsc.heightSizeInner sbv:self calcSize:0 sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; for (UIView *sbv in self.subviews) { diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index 35fb92c..c2d82e8 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -1104,6 +1104,40 @@ -(void)testFillAndStretch { //测试填充和拉伸。垂直数量约束流式布局的行内拉升和填充。以及整体 + //垂直流式布局主要是高度的填充和拉伸。 + + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:4]; + rootLayout.gravity = MyGravity_Vert_Fill; + rootLayout.arrangedGravity = MyGravity_Vert_Fill; + rootLayout.frame = CGRectMake(0, 0, 200, 200); + + //一个子视图高度有约束, 一个高度为自适应, 一个没有设置任何高度约束。一个标杆高度视图。 + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(40, 40); + [rootLayout addSubview:v1]; + + UILabel *v2 = [UILabel new]; + v2.text = @"hello"; + v2.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + [rootLayout addSubview:v2]; + + UIView *v3 = [UIView new]; + v3.frame = CGRectMake(0, 0, 30, 30); + [rootLayout addSubview:v3]; + + UIView *v4 = [UIView new]; + v4.mySize = CGSizeMake(50, 50); + [rootLayout addSubview:v4]; + + UIView *v5 = [UIView new]; + v5.mySize = CGSizeMake(60, 60); + + + + + //水平流式布局主要是宽度和填充和拉伸 + + } diff --git a/MyLayoutTests/MyRelativeLayoutTestCase.m b/MyLayoutTests/MyRelativeLayoutTestCase.m index cfb8fde..0f5ebab 100644 --- a/MyLayoutTests/MyRelativeLayoutTestCase.m +++ b/MyLayoutTests/MyRelativeLayoutTestCase.m @@ -1490,6 +1490,37 @@ -(void)testWrapContentHeight5 MySizeAssert(rootLayout,sz,CGSizeMake(170, 35+60+60)); +} + +-(void)testWrapContentHeight6 +{ + MyRelativeLayout* _layoutRoot = [[MyRelativeLayout alloc] init]; + _layoutRoot.myTop = + _layoutRoot.myLeft = + _layoutRoot.myRight = 0; + _layoutRoot.wrapContentHeight = YES; + _layoutRoot.bottomPadding = 12; + // _layoutRoot.backgroundColor = [UIColor whiteColor]; + //_layoutRoot.clipsToBounds = YES; + _layoutRoot.frame = CGRectMake(0, 0, 100, 0); + + UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)]; + imageView.myLeft = + imageView.myRight = 0; + imageView.myBottom = -12; + [_layoutRoot addSubview:imageView]; + + [_layoutRoot layoutIfNeeded]; + + MyRectAssert(_layoutRoot, CGRectMake(0, 0, 100, 50)); + + + [_layoutRoot setNeedsLayout]; + [_layoutRoot layoutIfNeeded]; + + MyRectAssert(_layoutRoot, CGRectMake(0, 0, 100, 50)); + + } From e9f09bcd450450598274e2d22d77a29f1675c976 Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Mon, 18 Nov 2019 18:15:37 +0800 Subject: [PATCH 091/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyFlowLayout.m | 20 +++- MyLayoutDemo/FLLTest5ViewController.m | 47 ++++++++ MyLayoutTests/MyFlowLayoutTestCase.m | 153 +++++++++++++++++++++----- MyLayoutTests/MyFrameLayoutTestCase.m | 30 +++++ 4 files changed, 215 insertions(+), 35 deletions(-) diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index bca4209..e8a36a1 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -1405,7 +1405,9 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG else pagingItemWidth = (CGRectGetWidth(self.superview.bounds) - paddingLeading - arrangedCount * horzSpace ) / arrangedCount; - pagingItemHeight = (selfSize.height - paddingVert - (rows - 1) * vertSpace) / rows; + //如果是水平滚动则如果布局不是高度自适应才让条目的高度生效。 + if (!lsc.heightSizeInner.dimeWrapVal) + pagingItemHeight = (selfSize.height - paddingVert - (rows - 1) * vertSpace) / rows; } else { @@ -1680,7 +1682,11 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG //再算一次宽度,只有比重为0并且不压缩的情况下计算。否则有可能前面被压缩或者被拉升而又会在这里重置了 - if (sbvsc.weight == 0.0 && sbvsc.widthSizeInner.shrink == 0 && horzGravity != MyGravity_Horz_Fill) + if (sbvsc.weight == 0.0 && + sbvsc.widthSizeInner.shrink == 0 && + horzGravity != MyGravity_Horz_Fill && + pagingItemWidth == 0.0 && + subviewSize == 0.0) { rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; } @@ -1759,7 +1765,8 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG else {//正常排列。 //这里的最大其实就是最后一个视图的位置加上最高的子视图的尺寸。 - maxHeight = yPos + lineMaxHeight; + if (_myCGFloatLess(maxHeight, yPos + lineMaxHeight)) + maxHeight = yPos + lineMaxHeight; } rect.origin.x = xPos + leadingSpace; @@ -2347,7 +2354,9 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG else pagingItemHeight = (CGRectGetHeight(self.superview.bounds) - paddingTop - arrangedCount * vertSpace ) / arrangedCount; - pagingItemWidth = (selfSize.width - paddingHorz - (cols - 1) * horzSpace) / cols; + //如果是水平滚动则如果布局不是高度自适应才让条目的高度生效。 + if (!lsc.widthSizeInner.dimeWrapVal) + pagingItemWidth = (selfSize.width - paddingHorz - (cols - 1) * horzSpace) / cols; } else { @@ -2675,7 +2684,8 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG else {//正常排列。 //这里的最大其实就是最后一个视图的位置加上最宽的子视图的尺寸。 - maxWidth = xPos + lineMaxWidth; + if (_myCGFloatLess(maxWidth, xPos + lineMaxWidth)) + maxWidth = xPos + lineMaxWidth; } rect.origin.x = xPos + leadingSpace; diff --git a/MyLayoutDemo/FLLTest5ViewController.m b/MyLayoutDemo/FLLTest5ViewController.m index dd142cc..5b40529 100644 --- a/MyLayoutDemo/FLLTest5ViewController.m +++ b/MyLayoutDemo/FLLTest5ViewController.m @@ -51,6 +51,9 @@ -(void)loadView //创建一个垂直数量流式布局分页从左到右滚动 [self createVertPagingFlowLayout2:rootLayout]; + //创建一个垂直数量流式布局分页从左到右滚动,这里高度自适应。 + [self createVertPagingFlowLayout3:rootLayout]; + } - (void)viewDidLoad { @@ -79,6 +82,7 @@ -(void)addAllItemSubviews:(MyFlowLayout*)flowLayout label.backgroundColor = [CFTool color:random() % 14 + 1]; label.text = [NSString stringWithFormat:@"%d",i]; label.myMargin = 5; //同时带有四边的间距! + label.mySize = CGSizeMake(60, 60); //在分页的情况下一般不需要设置条目视图的尺寸。而且即使设置了也无效。 [flowLayout addSubview:label]; } @@ -258,6 +262,49 @@ -(void)createVertPagingFlowLayout2:(UIView*)rootLayout } +/** + * 创建一个垂直分页从左向右滚动的流式布局,高度自适应。 + */ +-(void)createVertPagingFlowLayout3:(UIView*)rootLayout +{ + UILabel *titleLabel = [UILabel new]; + titleLabel.text = @"垂直流式布局分页从左往右滚动(高度自适应):➡︎"; + [titleLabel sizeToFit]; + [rootLayout addSubview:titleLabel]; + titleLabel.myTop = 20; + + //要开启分页功能,必须要将流式布局加入到一个滚动视图里面作为子视图!!! + UIScrollView *scrollView = [UIScrollView new]; + scrollView.pagingEnabled = YES; //开启分页滚动模式!!您可以注释这句话看看非分页滚动的布局滚动效果。 + scrollView.myHeight = MyLayoutSize.wrap; //高度自适应 + [rootLayout addSubview:scrollView]; + self.scrollView4 = scrollView; + + //建立一个垂直数量约束流式布局:每列展示3个子视图,每页展示9个子视图,整体从左往右滚动。 + MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:3]; + flowLayout.pagedCount = 9; //pagedCount设置为非0时表示开始分页展示的功能,这里表示每页展示9个子视图,这个数量必须是arrangedCount的倍数。 + + //设置流式布局的高度和宽度都是自适应。 + flowLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + /* + 上面是实现一个垂直流式布局分页且从左往右滚动的标准属性设置方法。 + */ + + + flowLayout.subviewHSpace = 10; + flowLayout.subviewVSpace = 10; //设置子视图的水平和垂直间距。 + flowLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); //布局视图的内边距设置!您可以注释掉这句话看看效果!如果设置内边距且也有分页时请将这个值设置和子视图间距相等。 + [scrollView addSubview:flowLayout]; + flowLayout.backgroundColor = [CFTool color:0]; + + [self addAllItemSubviews:flowLayout]; + + //获取流式布局的横屏size classes,并且设置设备处于横屏时,每排数量由3个变为6个,每页的数量由9个变为18个。您可以注释掉这段代码,然后横竖屏切换看看效果。 + MyFlowLayout *flowLayoutSC = [flowLayout fetchLayoutSizeClass:MySizeClass_Landscape copyFrom:MySizeClass_wAny | MySizeClass_hAny]; + flowLayoutSC.arrangedCount = 6; + flowLayoutSC.pagedCount = 18; +} + #pragma mark -- Handle Method diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index c2d82e8..8be2237 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -1105,38 +1105,131 @@ -(void)testFillAndStretch //测试填充和拉伸。垂直数量约束流式布局的行内拉升和填充。以及整体 //垂直流式布局主要是高度的填充和拉伸。 - - MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:4]; - rootLayout.gravity = MyGravity_Vert_Fill; - rootLayout.arrangedGravity = MyGravity_Vert_Fill; - rootLayout.frame = CGRectMake(0, 0, 200, 200); - - //一个子视图高度有约束, 一个高度为自适应, 一个没有设置任何高度约束。一个标杆高度视图。 - UIView *v1 = [UIView new]; - v1.mySize = CGSizeMake(40, 40); - [rootLayout addSubview:v1]; - - UILabel *v2 = [UILabel new]; - v2.text = @"hello"; - v2.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); - [rootLayout addSubview:v2]; - - UIView *v3 = [UIView new]; - v3.frame = CGRectMake(0, 0, 30, 30); - [rootLayout addSubview:v3]; - - UIView *v4 = [UIView new]; - v4.mySize = CGSizeMake(50, 50); - [rootLayout addSubview:v4]; - - UIView *v5 = [UIView new]; - v5.mySize = CGSizeMake(60, 60); - - - + { + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:4]; + rootLayout.arrangedGravity = MyGravity_Vert_Fill; + rootLayout.frame = CGRectMake(0, 0, 200, 200); + + //一个子视图高度有约束, 一个高度为自适应, 一个没有设置任何高度约束。一个标杆高度视图。 + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(40, 40); + [rootLayout addSubview:v1]; + + UILabel *v2 = [UILabel new]; + v2.text = @"hello"; + v2.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + [rootLayout addSubview:v2]; + + UIView *v3 = [UIView new]; + v3.frame = CGRectMake(0, 0, 30, 30); + [rootLayout addSubview:v3]; + + UIView *v4 = [UIView new]; + v4.mySize = CGSizeMake(50, 50); + [rootLayout addSubview:v4]; + + UIView *v5 = [UIView new]; + v5.mySize = CGSizeMake(60, 60); + [rootLayout addSubview:v5]; + + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 200, 200)); + + MyRectAssert(v1, CGRectMake(0, 0, 40, 50)); + MyRectAssert(v2, CGRectMake(40, 0, 36.5, 50)); + MyRectAssert(v3, CGRectMake(76.5, 0, 30, 50)); + MyRectAssert(v4, CGRectMake(106.5, 0, 50, 50)); + MyRectAssert(v5, CGRectMake(0, 50, 60, 60)); + + rootLayout.arrangedGravity = MyGravity_Vert_Stretch; + [rootLayout layoutIfNeeded]; + MyRectAssert(v1, CGRectMake(0, 0, 40, 40)); + MyRectAssert(v2, CGRectMake(40, 0, 36.5, 50)); + MyRectAssert(v3, CGRectMake(76.5, 0, 30, 50)); + MyRectAssert(v4, CGRectMake(106.5, 0, 50, 50)); + MyRectAssert(v5, CGRectMake(0, 50, 60, 60)); + + + rootLayout.gravity = MyGravity_Vert_Fill; + [rootLayout layoutIfNeeded]; + MyRectAssert(v1, CGRectMake(0, 0, 40, 85)); + MyRectAssert(v2, CGRectMake(40, 0, 36.5, 95)); + MyRectAssert(v3, CGRectMake(76.5, 0, 30, 95)); + MyRectAssert(v4, CGRectMake(106.5, 0, 50, 95)); + MyRectAssert(v5, CGRectMake(0, 95, 60, 105)); + + + rootLayout.gravity = MyGravity_Vert_Stretch; + [rootLayout layoutIfNeeded]; + MyRectAssert(v1, CGRectMake(0, 0, 40, 40)); + MyRectAssert(v2, CGRectMake(40, 0, 36.5, 95)); + MyRectAssert(v3, CGRectMake(76.5, 0, 30, 95)); + MyRectAssert(v4, CGRectMake(106.5, 0, 50, 50)); + MyRectAssert(v5, CGRectMake(0, 95, 60, 60)); + } //水平流式布局主要是宽度和填充和拉伸 - + { + MyFlowLayout *rootLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:4]; + rootLayout.arrangedGravity = MyGravity_Horz_Fill; + rootLayout.frame = CGRectMake(0, 0, 200, 200); + + //一个子视图高度有约束, 一个高度为自适应, 一个没有设置任何高度约束。一个标杆高度视图。 + UIView *v1 = [UIView new]; + v1.mySize = CGSizeMake(40, 40); + [rootLayout addSubview:v1]; + + UILabel *v2 = [UILabel new]; + v2.text = @"hello"; + v2.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); + [rootLayout addSubview:v2]; + + UIView *v3 = [UIView new]; + v3.frame = CGRectMake(0, 0, 30, 30); + [rootLayout addSubview:v3]; + + UIView *v4 = [UIView new]; + v4.mySize = CGSizeMake(50, 50); + [rootLayout addSubview:v4]; + + UIView *v5 = [UIView new]; + v5.mySize = CGSizeMake(60, 60); + [rootLayout addSubview:v5]; + + [rootLayout layoutIfNeeded]; + MyRectAssert(rootLayout, CGRectMake(0, 0, 200, 200)); + + MyRectAssert(v1, CGRectMake(0, 0, 50, 40)); + MyRectAssert(v2, CGRectMake(0, 40,50,20.5)); + MyRectAssert(v3, CGRectMake(0,60.5, 50, 30)); + MyRectAssert(v4, CGRectMake(0,90.5, 50, 50)); + MyRectAssert(v5, CGRectMake(50, 0, 60, 60)); + + rootLayout.arrangedGravity = MyGravity_Horz_Stretch; + [rootLayout layoutIfNeeded]; + MyRectAssert(v1, CGRectMake(0, 0, 40, 40)); + MyRectAssert(v2, CGRectMake(0, 40, 50,20.5)); + MyRectAssert(v3, CGRectMake(0,60.5, 50, 30)); + MyRectAssert(v4, CGRectMake(0,90.5, 50, 50)); + MyRectAssert(v5, CGRectMake(50, 0, 60, 60)); + + + rootLayout.gravity = MyGravity_Horz_Fill; + [rootLayout layoutIfNeeded]; + MyRectAssert(v1, CGRectMake(0, 0, 85, 40)); + MyRectAssert(v2, CGRectMake(0, 40, 95, 20.5)); + MyRectAssert(v3, CGRectMake(0,60.5, 50+45, 30)); + MyRectAssert(v4, CGRectMake(0,90.5, 50+45, 50)); + MyRectAssert(v5, CGRectMake(50+45, 0, 60+45, 60)); + + rootLayout.gravity = MyGravity_Horz_Stretch; + [rootLayout layoutIfNeeded]; + MyRectAssert(v1, CGRectMake(0, 0, 40, 40)); + MyRectAssert(v2, CGRectMake(0, 40, 95, 20.5)); + MyRectAssert(v3, CGRectMake(0,60.5, 50+45, 30)); + MyRectAssert(v4, CGRectMake(0,90.5, 50, 50)); + MyRectAssert(v5, CGRectMake(95, 0, 60, 60)); + } } diff --git a/MyLayoutTests/MyFrameLayoutTestCase.m b/MyLayoutTests/MyFrameLayoutTestCase.m index 9898100..e0e76b7 100644 --- a/MyLayoutTests/MyFrameLayoutTestCase.m +++ b/MyLayoutTests/MyFrameLayoutTestCase.m @@ -340,6 +340,36 @@ -(void)testWrapContent4 } +-(void)testWrapContent5 +{ + MyFrameLayout* _layoutRoot = [[MyFrameLayout alloc] init]; + _layoutRoot.myTop = + _layoutRoot.myLeft = + _layoutRoot.myRight = 0; + _layoutRoot.wrapContentHeight = YES; + _layoutRoot.bottomPadding = 12; + // _layoutRoot.backgroundColor = [UIColor whiteColor]; + //_layoutRoot.clipsToBounds = YES; + _layoutRoot.frame = CGRectMake(0, 0, 100, 0); + + UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)]; + imageView.myLeft = + imageView.myRight = 0; + imageView.myBottom = -12; + [_layoutRoot addSubview:imageView]; + + [_layoutRoot layoutIfNeeded]; + + MyRectAssert(_layoutRoot, CGRectMake(0, 0, 100, 50)); + + + [_layoutRoot setNeedsLayout]; + [_layoutRoot layoutIfNeeded]; + + MyRectAssert(_layoutRoot, CGRectMake(0, 0, 100, 50)); + +} + -(void)testPerformanceExample { [self measureBlock:^{ From 6eb09ffbd86a8ff5eb0adab174b4354e2af3d88d Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Mon, 18 Nov 2019 19:52:32 +0800 Subject: [PATCH 092/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.h | 4 ++-- MyLayout/Lib/MyFlowLayout.h | 4 ++-- MyLayoutDemo/FLXTest1ViewController.m | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index 515a7ac..540d04b 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -741,8 +741,8 @@ 8. MyGravity_Horz_Fill 表示布局会拉伸子视图的宽度,以便使里面的子视图水平方向填充满整个布局视图的宽度或者子视图平分布局视图的宽度。 (支持:框架布局,垂直线性布局,垂直表格布局,流式布局) 9. MyGravity_Vert_Baseline 表示布局里面的子视图都基线对齐,目前只支持水平线性布局。 - 10.MyGravity_Vert_Stretch 表示当布局中的子视图没有设置高度约束时,会拉伸子视图的高度。(支持:线性布局、流式布局) - 11.MyGravity_Horz_Stretch 表示当布局中的子视图没有设置宽度约束时,会拉伸子视图的宽度。(支持:线性布局、流式布局) + 10.MyGravity_Vert_Stretch 表示当布局中的子视图没有设置高度约束时或者非布局子视图高度自适应时,会拉伸子视图的高度。(支持:线性布局、流式布局) + 11.MyGravity_Horz_Stretch 表示当布局中的子视图没有设置宽度约束或者非布局子视图宽度自适应时,会拉伸子视图的宽度。(支持:线性布局、流式布局) */ @property(nonatomic, assign) IBInspectable MyGravity gravity; diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index 7e052de..eebf3c6 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -202,7 +202,7 @@ MyGravity_Vert_Center 垂直居中对齐 MyGravity_Vert_Bottom 底部对齐 MyGravity_Vert_Fill 两端对齐 - MyGravity_Vert_Stretch 如果子视图未设置约束则子视图高度被拉伸 + MyGravity_Vert_Stretch 如果子视图未设置约束或者非布局子视图高度自适应则子视图高度被拉伸 MyGravity_Vert_Baseline 基线对齐,以每一行的第一个带有文字的视图作为基线进行对齐。 MyGravity_Vert_Between 数量约束垂直流式布局有效,子视图会紧凑进行排列,当设置为这个属性值时,子视图的y轴的位置总是从对应列的上一行的结尾开始,而不是上一行的最高位置开始。 MyGravity_Vert_Around 如果行内子视图没有设置高度约束,则子视图的高度填充整行,否则按子视图的高度是高度约束决定。 @@ -213,7 +213,7 @@ MyGravity_Horz_Center 水平居中对齐 MyGravity_Horz_Right 右边对齐 MyGravity_Horz_Fill 两端对齐 - MyGravity_Horz_Stretch 如果子视图未设置约束则子视图宽度被拉伸 + MyGravity_Horz_Stretch 如果子视图未设置约束或者非布局子视图宽度自适应则子视图宽度被拉伸 MyGravity_Horz_Between 数量约束垂直流式布局有效,子视图会紧凑进行排列,当设置为这个属性值时,子视图的x轴的位置总是从对应行的上一列的结尾开始,而不是上一列的最宽位置开始。 MyGravity_Horz_Around 如果列内子视图没有设置宽度约束,则子视图的宽度填充整行,否则按子视图的宽度是宽度约束决定。 @endcode diff --git a/MyLayoutDemo/FLXTest1ViewController.m b/MyLayoutDemo/FLXTest1ViewController.m index 79f33e6..34feb97 100644 --- a/MyLayoutDemo/FLXTest1ViewController.m +++ b/MyLayoutDemo/FLXTest1ViewController.m @@ -899,6 +899,8 @@ -(IBAction)handleSaveItem:(UIButton*)sender itemView.myFlex.attrs.width = MyLayoutSize.wrap; else if ([widthStr isEqualToString:@"fill"]) itemView.myFlex.attrs.width = MyLayoutSize.fill; + else if (widthStr.length == 0) + itemView.myFlex.attrs.width = MyLayoutSize.wrap; else itemView.myFlex.attrs.width = widthStr.doubleValue; @@ -907,6 +909,8 @@ -(IBAction)handleSaveItem:(UIButton*)sender itemView.myFlex.attrs.height = MyLayoutSize.wrap; else if ([heightStr isEqualToString:@"fill"]) itemView.myFlex.attrs.height = MyLayoutSize.fill; + else if (heightStr.length == 0) + itemView.myFlex.attrs.height = MyLayoutSize.wrap; else itemView.myFlex.attrs.height = heightStr.doubleValue; From bb97f2cecc9461a48fc4b7055e8aa3668527a83f Mon Sep 17 00:00:00 2001 From: oubaiquan Date: Tue, 19 Nov 2019 11:36:43 +0800 Subject: [PATCH 093/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout.podspec | 2 +- MyLayout.xcodeproj/project.pbxproj | 12 +++++++++--- .../xcshareddata/xcschemes/MyLayout.xcscheme | 4 +--- MyLayout/Lib/MyBaseLayout.m | 12 ++++++++---- MyLayout/Lib/MyFloatLayout.m | 10 ---------- MyLayout/Lib/MyLayout.h | 2 +- MyLayout/Lib/MyLayoutSize.m | 4 ++-- .../AppIcon.appiconset/Contents.json | 3 ++- .../AppIcon.appiconset/appicon1024.png | Bin 0 -> 336999 bytes MyLayoutDemo/PLTest5ViewController.m | 6 +++--- MyLayoutDemo/TLTest4ViewController.m | 8 ++++---- 11 files changed, 31 insertions(+), 32 deletions(-) create mode 100644 MyLayoutDemo/Images.xcassets/AppIcon.appiconset/appicon1024.png diff --git a/MyLayout.podspec b/MyLayout.podspec index db12297..9d2abfd 100644 --- a/MyLayout.podspec +++ b/MyLayout.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "MyLayout" - s.version = "1.8.0" + s.version = "1.9.0beta" s.summary = "MyLayout is an iOS UI framework integrates the functions with Android,AutoLayout,SizeClass,HTML CSS float and flexbox,UIView UITableView." s.description = <<-DESC diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index d97d033..9fd7100 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -1039,7 +1039,7 @@ 184082851B2C46E8003F378B /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0920; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = YoungSoft; TargetAttributes = { 181A10B41EDF12CF00996203 = { @@ -1067,12 +1067,12 @@ }; buildConfigurationList = 184082881B2C46E8003F378B /* Build configuration list for PBXProject "MyLayout" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - English, Base, "zh-Hans", + en, ); mainGroup = 184082841B2C46E8003F378B; productRefGroup = 1840828E1B2C46E8003F378B /* Products */; @@ -1434,6 +1434,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -1442,12 +1443,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -1487,6 +1490,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -1495,12 +1499,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; diff --git a/MyLayout.xcodeproj/xcshareddata/xcschemes/MyLayout.xcscheme b/MyLayout.xcodeproj/xcshareddata/xcschemes/MyLayout.xcscheme index f25ed80..45a8ea8 100644 --- a/MyLayout.xcodeproj/xcshareddata/xcschemes/MyLayout.xcscheme +++ b/MyLayout.xcodeproj/xcshareddata/xcschemes/MyLayout.xcscheme @@ -1,6 +1,6 @@ @@ -37,7 +36,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index a0b1702..2327ff4 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -1448,6 +1448,7 @@ - (void)willMoveToSuperview:(UIView*)newSuperview MyBaseLayout *lsc = self.myCurrentSizeClass; //特殊处理如果视图是控制器根视图则取消高度或者宽度包裹,以及adjustScrollViewContentSizeMode的设置。 + //但是有一种特殊情况是控制器是子视图控制器。因此还需要添加判断父视图是否是非布局父视图,只有是非布局父视图下才将自适应设置清除 @try { if (newSuperview != nil) @@ -1456,10 +1457,13 @@ - (void)willMoveToSuperview:(UIView*)newSuperview id vc = [self valueForKey:@"viewDelegate"]; if (vc != nil) { - if (lsc.widthSizeInner.dimeWrapVal) - [lsc.widthSizeInner __equalTo:nil]; - if (lsc.heightSizeInner.dimeWrapVal) - [lsc.heightSizeInner __equalTo:nil]; + if (![newSuperview isKindOfClass:[MyBaseLayout class]]) + { + if (lsc.widthSizeInner.dimeWrapVal) + [lsc.widthSizeInner __equalTo:nil]; + if (lsc.heightSizeInner.dimeWrapVal) + [lsc.heightSizeInner __equalTo:nil]; + } if (lsc.insetsPaddingFromSafeArea == defRectEdge) lsc.insetsPaddingFromSafeArea = ~UIRectEdgeTop; diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 76a377a..1edc96d 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -86,16 +86,6 @@ -(MyOrientation)orientation return self.myCurrentSizeClass.orientation; } --(void)setNoBoundaryLimit:(BOOL)noBoundaryLimit -{ - NSLog(@"属性已经过期!请直接设置宽度或者高度值为MyLayoutSize.wrap"); -} - --(BOOL)noBoundaryLimit -{ - return NO; -} - -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace { [self setSubviewsSize:subviewSize minSpace:minSpace maxSpace:maxSpace inSizeClass:MySizeClass_hAny | MySizeClass_wAny]; diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index 166d13d..4da0f7c 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -37,7 +37,7 @@ */ -//Current version is 1.9.0, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.9.0beta, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. #ifndef MyLayout_MyLayout_h diff --git a/MyLayout/Lib/MyLayoutSize.m b/MyLayout/Lib/MyLayoutSize.m index 5984bf3..cb7ed1a 100644 --- a/MyLayout/Lib/MyLayoutSize.m +++ b/MyLayout/Lib/MyLayoutSize.m @@ -67,9 +67,9 @@ -(id)init //如果尺寸是自适应,并且当前视图是布局视图则直接布局视图自身刷新布局,否则由视图的父视图来刷新布局,这里特殊处理。 if ([val isKindOfClass:[NSNumber class]]) { - if ([val integerValue] == MyLayoutSize.wrap && [_view isKindOfClass:[MyBaseLayout class]]) + if ([val integerValue] == MyLayoutSize.wrap && [self->_view isKindOfClass:[MyBaseLayout class]]) { - [_view setNeedsLayout]; + [self->_view setNeedsLayout]; return self; } } diff --git a/MyLayoutDemo/Images.xcassets/AppIcon.appiconset/Contents.json b/MyLayoutDemo/Images.xcassets/AppIcon.appiconset/Contents.json index d9e47dd..cdf278d 100644 --- a/MyLayoutDemo/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/MyLayoutDemo/Images.xcassets/AppIcon.appiconset/Contents.json @@ -100,8 +100,9 @@ "scale" : "2x" }, { - "idiom" : "ios-marketing", "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "appicon1024.png", "scale" : "1x" } ], diff --git a/MyLayoutDemo/Images.xcassets/AppIcon.appiconset/appicon1024.png b/MyLayoutDemo/Images.xcassets/AppIcon.appiconset/appicon1024.png new file mode 100644 index 0000000000000000000000000000000000000000..f79781478dba06d3e4c9d7f016a68b832c0267f7 GIT binary patch literal 336999 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

5agO9}6&#;iC&|?M&TE>EejBP_P9v!dbf$~&% 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

-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%0D65&~S9XeU_gwA_-dbq7YQ$=a9g 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

#K;@aCgChZ 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℞z-<(ua?ik4 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 Date: Tue, 26 Nov 2019 19:21:15 +0800 Subject: [PATCH 094/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout.podspec | 3 +- MyLayout/Lib/MyBaseLayout.m | 1 + MyLayout/Lib/MyFlexLayout.m | 8 +- MyLayout/Lib/MyFlowLayout.m | 49 ++++- MyLayout/Lib/MyLayoutPos.h | 3 - MyLayout/Lib/MyLayoutPos.m | 11 -- MyLayout/Lib/MyLayoutPosInner.h | 2 +- MyLayout/Lib/MyLayoutSize.h | 14 +- MyLayout/Lib/MyLayoutSize.m | 29 ++- MyLayout/Lib/MyLayoutSizeClass.m | 3 +- MyLayout/Lib/MyLayoutSizeInner.h | 1 + MyLayout/Lib/MyLayoutUI.h | 17 +- MyLayout/Lib/MyLayoutUI.m | 16 ++ MyLayout/Lib/MyRelativeLayout.m | 4 +- MyLayoutDemo/AllTestExampleViewController.m | 24 ++- MyLayoutDemo/FLXTest1ViewController.m | 14 +- MyLayoutTests/MyFlowLayoutTestCase.m | 4 +- MyLayoutTests/MyLayoutPerformanceTestCase.m | 203 ++++++++++++++++++++ 18 files changed, 344 insertions(+), 62 deletions(-) diff --git a/MyLayout.podspec b/MyLayout.podspec index 9d2abfd..d346170 100644 --- a/MyLayout.podspec +++ b/MyLayout.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "MyLayout" - s.version = "1.9.0beta" + s.version = "1.9.0" s.summary = "MyLayout is an iOS UI framework integrates the functions with Android,AutoLayout,SizeClass,HTML CSS float and flexbox,UIView UITableView." s.description = <<-DESC @@ -90,6 +90,7 @@ Pod::Spec.new do |s| #s.exclude_files = "Classes/Exclude" s.public_header_files = "MyLayout/Lib/*.h" + s.private_header_files = "MyLayout/Lib/{*Inner.h,MyLayoutDelegate.h,MyLayoutMath.h,MyGridNode.h,MyLayoutSizeClass.h}" end diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index 2327ff4..a794bd8 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -3550,6 +3550,7 @@ -(void)myCalcSubviewsWrapContentSize:(NSArray*)sbs isEstimate:(BOOL)is MyFrame *sbvmyFrame = sbv.myFrame; MyViewSizeClass *sbvsc = (MyViewSizeClass *)[sbv myCurrentSizeClassFrom:sbvmyFrame]; + if (customSetting != nil) customSetting(sbvsc); diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index b0e65e8..40c801c 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -93,6 +93,8 @@ -(CGFloat)width return MyLayoutSize.wrap; else if (self.view.widthSizeInner.isFill) return self.view.widthSizeInner.multiVal == 1 ? MyLayoutSize.fill : self.view.widthSizeInner.multiVal; + else if (self.view.widthSizeInner != nil && self.view.widthSizeInner.dimeValType == MyLayoutValueType_Nil) + return MyLayoutSize.empty; else if (self.view.widthSizeInner.dimeNumVal != nil) return self.view.widthSizeInner.dimeNumVal.doubleValue; else @@ -113,6 +115,8 @@ -(CGFloat)height return MyLayoutSize.wrap; else if (self.view.heightSizeInner.isFill) return self.view.heightSizeInner.multiVal == 1 ? MyLayoutSize.fill : self.view.heightSizeInner.multiVal; + else if (self.view.heightSizeInner != nil && self.view.heightSizeInner.dimeValType == MyLayoutValueType_Nil) + return MyLayoutSize.empty; else if (self.view.heightSizeInner.dimeNumVal != nil) return self.view.heightSizeInner.dimeNumVal.doubleValue; else @@ -551,9 +555,9 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( sbvsc.heightSize.shrink = flexItem.attrs.flex_shrink != MyFlex_Auto? flexItem.attrs.flex_shrink:0; //如果没有设置尺寸约束则默认是自适应。 - if (sbvsc.widthSizeInner.dimeVal == nil) + if (sbvsc.widthSizeInner == nil) [sbvsc.widthSize __equalTo:@(MyLayoutSize.wrap)]; - if (sbvsc.heightSizeInner.dimeVal == nil) + if (sbvsc.heightSizeInner == nil) [sbvsc.heightSize __equalTo:@(MyLayoutSize.wrap)]; //基准值设置。 diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index e8a36a1..f9aae10 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -161,9 +161,11 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbvsc.widthSizeInner.dimeWrapVal) { - if (lsc.pagedCount > 0 || - (orientation == MyOrientation_Horz && (arrangedGravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill) || - (orientation == MyOrientation_Vert && ((gravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill || sbvsc.weight != 0))) + if (lsc.pagedCount > 0 || + (orientation == MyOrientation_Vert && sbvsc.weight != 0.0) || + (arrangedGravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill || + (arrangedGravity & MyGravity_Vert_Mask) == MyGravity_Horz_Stretch || + (gravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill ) { if ([sbvsc.view isKindOfClass:[MyBaseLayout class]]) [sbvsc.widthSizeInner __setActive:NO]; @@ -173,8 +175,10 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbvsc.heightSizeInner.dimeWrapVal) { if (lsc.pagedCount > 0 || - (orientation == MyOrientation_Vert && (arrangedGravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill) || - (orientation == MyOrientation_Horz && ((gravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill || sbvsc.weight != 0))) + (orientation == MyOrientation_Horz && sbvsc.weight != 0.0) || + (arrangedGravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill || + (arrangedGravity & MyGravity_Horz_Mask) == MyGravity_Vert_Stretch || + (gravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill) { if ([sbvsc.view isKindOfClass:[MyBaseLayout class]]) [sbvsc.heightSizeInner __setActive:NO]; @@ -1317,7 +1321,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont { MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; //只有在没有约束,或者非布局视图下的高度自适应约束才会被拉伸。 - if (sbvsc.heightSizeInner.dimeVal == nil || (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]])) + if (sbvsc.heightSizeInner.dimeVal == nil) { sbvmyFrame.height += fill; } @@ -1865,7 +1869,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG if (vertGravity == MyGravity_Vert_Stretch) { MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.heightSizeInner.dimeVal == nil || (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]])) + if (sbvsc.heightSizeInner.dimeVal == nil) { sbvmyFrame.height += fill; } @@ -2000,13 +2004,27 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; CGFloat topSpace = sbvsc.topPosInner.absVal; + CGFloat leadingSpace = sbvsc.leadingPosInner.absVal; CGFloat bottomSpace = sbvsc.bottomPosInner.absVal; + CGFloat trailingSpace = sbvsc.trailingPosInner.absVal; CGRect rect = sbvmyFrame.frame; //这里先计算一下宽度,因为有可能有宽度固定,高度自适应的情况。 if (sbvsc.widthSizeInner.dimeVal != nil) { rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; + + //当只有一行而且是flex标准并且是stretch时会把所有子视图的宽度都强制拉伸为布局视图的宽度 + //所以如果这里是宽度自适应时需要将宽度强制设置为和布局等宽,以便解决同时高度自适应时高度计算不正确的问题。 + if (lineIndex == 0 && + sbvsc.widthSizeInner.dimeWrapVal && + lsc.isFlex && + horzGravity == MyGravity_Horz_Stretch && + rect.size.width > selfSize.width - paddingHorz - leadingSpace - trailingSpace) + { + rect.size.width = selfSize.width - paddingHorz - leadingSpace - trailingSpace; + } + rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; } else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) @@ -2263,7 +2281,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont if (horzGravity == MyGravity_Horz_Stretch) { MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.widthSizeInner.dimeVal == nil || (sbvsc.widthSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]])) + if (sbvsc.widthSizeInner.dimeVal == nil) { sbvmyFrame.width += fill; } @@ -2441,6 +2459,17 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG else if (sbvsc.widthSizeInner.dimeVal != nil) { rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; + + // 当只有一行而且是flex标准并且是stretch时会把所有子视图的宽度都强制拉伸为布局视图的宽度 + // 所以如果这里是宽度自适应时需要将宽度强制设置为和布局等宽,以便解决同时高度自适应时高度计算不正确的问题。 + if (arranges == 1 && + sbvsc.widthSizeInner.dimeWrapVal && + lsc.isFlex && + horzGravity == MyGravity_Horz_Stretch && + rect.size.width > selfSize.width - paddingHorz - leadingSpace - trailingSpace) + { + rect.size.width = selfSize.width - paddingHorz - leadingSpace - trailingSpace; + } } else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) { @@ -2726,7 +2755,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG selfSize.width = [self myValidMeasure:lsc.widthSizeInner sbv:self calcSize:selfSize.width sbvSize:selfSize selfLayoutSize:self.superview.bounds.size]; } - //根据flex规则:如果只有一行则整个高度都作为子视图的拉伸和停靠区域。 + //根据flex规则:如果只有一行则整个宽度都作为子视图的拉伸和停靠区域。 if (lsc.isFlex && arranges == 1) lineMaxWidth = selfSize.width - paddingHorz; @@ -2784,7 +2813,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG if (horzGravity == MyGravity_Horz_Stretch) { MyViewSizeClass *sbvsc = (MyViewSizeClass*)[sbv myCurrentSizeClassFrom:sbvmyFrame]; - if (sbvsc.widthSizeInner.dimeVal == nil || (sbvsc.widthSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]])) + if (sbvsc.widthSizeInner.dimeVal == nil) { sbvmyFrame.width += fill; } diff --git a/MyLayout/Lib/MyLayoutPos.h b/MyLayout/Lib/MyLayoutPos.h index 512b55e..b2301c3 100644 --- a/MyLayout/Lib/MyLayoutPos.h +++ b/MyLayout/Lib/MyLayoutPos.h @@ -248,10 +248,7 @@ //通过如下属性获取上面方法设置的值。 -@property(nonatomic, strong, readonly) id posVal; @property(nonatomic, assign, readonly) CGFloat offsetVal; -@property(nonatomic, assign, readonly) CGFloat minVal; -@property(nonatomic, assign, readonly) CGFloat maxVal; @end diff --git a/MyLayout/Lib/MyLayoutPos.m b/MyLayout/Lib/MyLayoutPos.m index c7b402a..f7ba0a7 100644 --- a/MyLayout/Lib/MyLayoutPos.m +++ b/MyLayout/Lib/MyLayoutPos.m @@ -170,17 +170,6 @@ -(CGFloat)offsetVal return self.isActive? _offsetVal : 0; } --(CGFloat)minVal -{ - return self.isActive && _lBoundVal != nil ? _lBoundVal.posNumVal.doubleValue : -CGFLOAT_MAX; -} - --(CGFloat)maxVal -{ - return self.isActive && _uBoundVal != nil ? _uBoundVal.posNumVal.doubleValue : CGFLOAT_MAX; -} - - #pragma mark -- NSCopying -(id)copyWithZone:(NSZone *)zone diff --git a/MyLayout/Lib/MyLayoutPosInner.h b/MyLayout/Lib/MyLayoutPosInner.h index 75da7b1..3a8e516 100644 --- a/MyLayout/Lib/MyLayoutPosInner.h +++ b/MyLayout/Lib/MyLayoutPosInner.h @@ -16,7 +16,7 @@ @property(nonatomic, weak) UIView *view; @property(nonatomic, assign) MyGravity pos; @property(nonatomic, assign) MyLayoutValueType posValType; - +@property(nonatomic, strong, readonly) id posVal; @property(nonatomic, readonly, strong) NSNumber *posNumVal; @property(nonatomic, readonly, strong) MyLayoutPos *posRelaVal; @property(nonatomic, readonly, strong) NSArray *posArrVal; diff --git a/MyLayout/Lib/MyLayoutSize.h b/MyLayout/Lib/MyLayoutSize.h index 9ab81a3..ed9b82b 100644 --- a/MyLayout/Lib/MyLayoutSize.h +++ b/MyLayout/Lib/MyLayoutSize.h @@ -39,6 +39,14 @@ +(NSInteger)fill; #endif + +#if UIKIT_DEFINE_AS_PROPERTIES +/**特殊的尺寸,表示清除尺寸的约束设置,等价于:equalTo(nil)*/ +@property(class, nonatomic, assign,readonly) NSInteger empty; +#else ++(NSInteger)empty; +#endif + #if UIKIT_DEFINE_AS_PROPERTIES /**特殊的尺寸,表示尺寸会均分父视图的剩余空间。目前只用在表格布局MyTableLayout */ @property(class, nonatomic, assign,readonly) NSInteger average; @@ -65,7 +73,7 @@ /** 设置尺寸的具体值,这个具体值可以设置为NSNumber, MyLayoutSize以及NSArray数组,UIView, MyLayoutMostSize和nil值。 - 1. 设置为NSNumber值表示指定具体的宽度或者高度数值,如果设置为特殊值MyLayoutSize.wrap则表示尺寸自适应,如果设置为LayoutSize.fill则表示等于父视图的尺寸。 + 1. 设置为NSNumber值表示指定具体的宽度或者高度数值,如果设置为特殊值MyLayoutSize.wrap则表示尺寸自适应,如果设置为MyLayoutSize.fill则表示等于父视图的尺寸,如果设置为MyLayoutSize.empty则表示清空尺寸约束。 2. 设置为MyLayoutSize值表示宽度和高度与设置的对象有依赖关系, 甚至可以依赖对象本身 @@ -210,11 +218,9 @@ //上面方法设置的属性的获取。 -@property(nonatomic, strong, readonly) id dimeVal; @property(nonatomic, assign, readonly) CGFloat addVal; @property(nonatomic, assign, readonly) CGFloat multiVal; -@property(nonatomic, assign, readonly) CGFloat minVal; -@property(nonatomic, assign, readonly) CGFloat maxVal; + /** 判断尺寸值是否是自适应值。 diff --git a/MyLayout/Lib/MyLayoutSize.m b/MyLayout/Lib/MyLayoutSize.m index cb7ed1a..5485e5b 100644 --- a/MyLayout/Lib/MyLayoutSize.m +++ b/MyLayout/Lib/MyLayoutSize.m @@ -21,6 +21,10 @@ @implementation MyLayoutSize MyLayoutSize *_uBoundVal; } ++(NSInteger)empty +{ + return -100000; //这么定义存粹是一个数字没有其他意义 +} +(NSInteger)wrap { @@ -82,7 +86,6 @@ -(id)init -(MyLayoutSize* (^)(CGFloat val))myAdd { return ^id(CGFloat val){ - [self __add:val]; [self setNeedsLayout]; return self; @@ -92,7 +95,6 @@ -(id)init -(MyLayoutSize* (^)(CGFloat val))myMultiply { return ^id(CGFloat val){ - [self __multiply:val]; [self setNeedsLayout]; return self; @@ -102,7 +104,6 @@ -(id)init -(MyLayoutSize* (^)(CGFloat val))myMin { return ^id(CGFloat val){ - [self __min:val]; [self setNeedsLayout]; return self; @@ -112,7 +113,6 @@ -(id)init -(MyLayoutSize* (^)(id sizeVal, CGFloat addVal, CGFloat multiVal))myLBound { return ^id(id sizeVal, CGFloat addVal, CGFloat multiVal){ - [self __lBound:sizeVal addVal:addVal multiVal:multiVal]; [self setNeedsLayout]; return self; @@ -122,7 +122,6 @@ -(id)init -(MyLayoutSize* (^)(CGFloat val))myMax { return ^id(CGFloat val){ - [self __max:val]; [self setNeedsLayout]; return self; @@ -132,7 +131,6 @@ -(id)init -(MyLayoutSize* (^)(id sizeVal, CGFloat addVal, CGFloat multiVal))myUBound { return ^id(id sizeVal, CGFloat addVal, CGFloat multiVal){ - [self __uBound:sizeVal addVal:addVal multiVal:multiVal]; [self setNeedsLayout]; return self; @@ -204,24 +202,14 @@ -(id)dimeVal return self.isActive ? _dimeVal : nil; } --(CGFloat)minVal -{ - return (self.isActive && _lBoundVal != nil) ? _lBoundVal.dimeNumVal.doubleValue : -CGFLOAT_MAX; -} - --(CGFloat)maxVal -{ - return (self.isActive && _uBoundVal != nil) ? _uBoundVal.dimeNumVal.doubleValue : CGFLOAT_MAX; -} - -(BOOL)isWrap { - return [self dimeWrapVal]; + return _dimeValType == MyLayoutValueType_Wrap; } -(BOOL)isFill { - return [self dimeFillVal]; + return _dimeValType == MyLayoutValueType_Fill; } #pragma mark -- NSCopying @@ -354,6 +342,11 @@ -(MyLayoutSize*)__equalTo:(id)val priority:(NSInteger)priority _dimeValType = MyLayoutValueType_Wrap; else if ([val integerValue] == MyLayoutSize.fill) _dimeValType = MyLayoutValueType_Fill; + else if ([val integerValue] == MyLayoutSize.empty) + { + _dimeValType = MyLayoutValueType_Nil; + val = nil; + } else _dimeValType = MyLayoutValueType_NSNumber; } diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index 147c71b..99597c7 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -99,7 +99,6 @@ -(MyLayoutPos*)topPos _topPos = [MyLayoutPos new]; _topPos.view = self.view; _topPos.pos = MyGravity_Vert_Top; - } return _topPos; } @@ -338,7 +337,7 @@ -(MyLayoutSize*)heightSize -(CGFloat)myWidth { - //特殊处理设置为MyLayoutSize.wrap的返回 + //特殊处理设置为MyLayoutSize.wrap和MyLayoutSize.fill的返回。 if (self.widthSizeInner.dimeValType == MyLayoutValueType_Wrap) return MyLayoutSize.wrap; else if (self.widthSizeInner.dimeValType == MyLayoutValueType_Fill) diff --git a/MyLayout/Lib/MyLayoutSizeInner.h b/MyLayout/Lib/MyLayoutSizeInner.h index 7ba5785..8cd898e 100644 --- a/MyLayout/Lib/MyLayoutSizeInner.h +++ b/MyLayout/Lib/MyLayoutSizeInner.h @@ -18,6 +18,7 @@ @property(nonatomic, assign) MyGravity dime; @property(nonatomic, assign) MyLayoutValueType dimeValType; +@property(nonatomic, strong, readonly) id dimeVal; @property(nonatomic, readonly, strong) NSNumber *dimeNumVal; @property(nonatomic, readonly, strong) MyLayoutSize *dimeRelaVal; @property(nonatomic, readonly, strong) NSArray *dimeArrVal; diff --git a/MyLayout/Lib/MyLayoutUI.h b/MyLayout/Lib/MyLayoutUI.h index 21fe768..1becd05 100644 --- a/MyLayout/Lib/MyLayoutUI.h +++ b/MyLayout/Lib/MyLayoutUI.h @@ -18,10 +18,17 @@ /** - 视图的宽度设置,如果宽度设置为大于0小于1则表明是相对于父视图宽度的比重值,如果是MyLayoutSize.wrap则表明宽度自适应,如果是MyLayoutSize.fill则表明宽度和父视图相等,其他的值就是一个固定宽度值。 + 视图的宽度设置,如果宽度设置为大于0小于1则表明是相对于父视图宽度的比重值,如果是MyLayoutSize.wrap则表明宽度自适应,如果是MyLayoutSize.fill则表明宽度和父视图相等,如果是MyLayoutSize.empty则表明不设置宽度值。 其他的值就是一个固定宽度值。 */ -(id (^)(CGFloat))width; + +/** + 视图的宽度设置,percent表明占用父视图宽度的百分比值,inc表明在百分比值的基础上的增量值。 + */ +-(id (^)(CGFloat percent, CGFloat inc))width_percent; + + /** 最小宽度限制设置 */ @@ -32,10 +39,16 @@ */ -(id (^)(CGFloat))max_width; /** - 视图的高度设置,如果高度设置为大于0小于1则表明是相对于父视图高度的比重值,如果是MyLayoutSize.wrap则表明高度自适应,如果是MyLayoutSize.fill则表明高度和父视图相等,其他的值就是一个固定高度值。 + 视图的高度设置,如果高度设置为大于0小于1则表明是相对于父视图高度的比重值,如果是MyLayoutSize.wrap则表明高度自适应,如果是MyLayoutSize.fill则表明高度和父视图相等,如果是MyLayoutSize.empty则表明不设置高度值,其他的值就是一个固定高度值。 */ -(id (^)(CGFloat))height; +/** + 视图的高度设置,percent表明占用父视图高度的百分比值,inc表明在百分比值的基础上的增量值。 + */ +-(id (^)(CGFloat percent, CGFloat inc))height_percent; + + /** 最小高度限制设置 */ diff --git a/MyLayout/Lib/MyLayoutUI.m b/MyLayout/Lib/MyLayoutUI.m index f70c3fa..6359827 100644 --- a/MyLayout/Lib/MyLayoutUI.m +++ b/MyLayout/Lib/MyLayoutUI.m @@ -39,6 +39,14 @@ -(instancetype)initWithView:(UIView*)view }; } +-(id (^)(CGFloat percent, CGFloat inc))width_percent +{ + return ^id(CGFloat percent, CGFloat inc) { + self.view.widthSize.equalTo(@(MyLayoutSize.fill)).multiply(percent).add(inc); + return self; + }; +} + -(id (^)(CGFloat))min_width { return ^id(CGFloat val) { @@ -66,6 +74,14 @@ -(instancetype)initWithView:(UIView*)view }; } +-(id (^)(CGFloat percent, CGFloat inc))height_percent +{ + return ^id(CGFloat percent, CGFloat inc) { + self.view.heightSize.equalTo(@(MyLayoutSize.fill)).multiply(percent).add(inc); + return self; + }; +} + -(id (^)(CGFloat))min_height { return ^id(CGFloat val) { diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 2a66cc8..295cf25 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -855,7 +855,7 @@ -(BOOL)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcWidthOfSubview:(MyViewSi } - dime.view.myFrame.width = [self myValidMeasure:dime.view.widthSize sbv:dime.view calcSize:dime.view.myFrame.width sbvSize:dime.view.myFrame.frame.size selfLayoutSize:selfSize]; + dime.view.myFrame.width = [self myValidMeasure:dime.view.widthSizeInner sbv:dime.view calcSize:dime.view.myFrame.width sbvSize:dime.view.myFrame.frame.size selfLayoutSize:selfSize]; } else { @@ -1026,7 +1026,7 @@ -(BOOL)myLayout:(MyRelativeLayoutViewSizeClass*)lsc calcHeightOfSubview:(MyViewS dime.view.myFrame.height = tempHeight; } - dime.view.myFrame.height = [self myValidMeasure:dime.view.heightSize sbv:dime.view calcSize:dime.view.myFrame.height sbvSize:dime.view.myFrame.frame.size selfLayoutSize:selfSize]; + dime.view.myFrame.height = [self myValidMeasure:dime.view.heightSizeInner sbv:dime.view calcSize:dime.view.myFrame.height sbvSize:dime.view.myFrame.frame.size selfLayoutSize:selfSize]; } else diff --git a/MyLayoutDemo/AllTestExampleViewController.m b/MyLayoutDemo/AllTestExampleViewController.m index 0e8c2fe..fbd8b30 100644 --- a/MyLayoutDemo/AllTestExampleViewController.m +++ b/MyLayoutDemo/AllTestExampleViewController.m @@ -232,7 +232,27 @@ -(void)example4 -(void)example5 { - MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + //一个row 下两个宽度均分高度为填充的子视图。 + + MyFlexLayout *rootLayout = MyFlexLayout.new.myFlex + .margin(0) + .addTo(self.view); + + UIView *v1 = MyFlexLayout.new.myFlex + .flex_grow(1) + .margin_top(30) + .backgroundColor(UIColor.redColor) + .addTo(rootLayout); + + UIView *v2 = MyFlexLayout.new.myFlex + .flex_grow(1) + .margin_top(30) + .backgroundColor(UIColor.greenColor) + .addTo(rootLayout); + + + + /*MyRelativeLayout *rootLayout = [MyRelativeLayout new]; rootLayout.myHeight = MyLayoutSize.wrap; rootLayout.myHorzMargin = 0; rootLayout.padding = UIEdgeInsetsMake(12, 12, 12, 12); @@ -270,7 +290,7 @@ -(void)example5 [rootLayout addSubview:barView]; [self.view addSubview:rootLayout]; - + */ } @end diff --git a/MyLayoutDemo/FLXTest1ViewController.m b/MyLayoutDemo/FLXTest1ViewController.m index 34feb97..3a3b149 100644 --- a/MyLayoutDemo/FLXTest1ViewController.m +++ b/MyLayoutDemo/FLXTest1ViewController.m @@ -383,7 +383,8 @@ -(void)editFlexItem:(UIView*)itemView widthTextField.tag = 100; widthTextField.borderStyle = UITextBorderStyleRoundedRect; - widthTextField.placeholder = @"数字|wrap|fill|空"; + widthTextField.placeholder = @"数字|wrap|fill|empty"; + widthTextField.autocapitalizationType = UITextAutocapitalizationTypeNone; UILabel *heightLabel = UILabel.new.myFlex .width(MyLayoutSize.wrap) @@ -400,7 +401,8 @@ -(void)editFlexItem:(UIView*)itemView heightTextField.tag = 200; heightTextField.borderStyle = UITextBorderStyleRoundedRect; - heightTextField.placeholder = @"数字|wrap|fill|空"; + heightTextField.placeholder = @"数字|wrap|fill|empty"; + heightTextField.autocapitalizationType = UITextAutocapitalizationTypeNone; UILabel *orderLabel = UILabel.new.myFlex @@ -535,6 +537,8 @@ -(void)editFlexItem:(UIView*)itemView widthTextField.text = @"wrap"; else if (itemView.myFlex.attrs.width == MyLayoutSize.fill) widthTextField.text = @"fill"; + else if (itemView.myFlex.attrs.width == MyLayoutSize.empty) + widthTextField.text = @"empty"; else if (itemView.myFlex.attrs.width != 0) widthTextField.text = [@(itemView.myFlex.attrs.width) stringValue]; else @@ -545,6 +549,8 @@ -(void)editFlexItem:(UIView*)itemView heightTextField.text = @"wrap"; else if (itemView.myFlex.attrs.height == MyLayoutSize.fill) heightTextField.text = @"fill"; + else if (itemView.myFlex.attrs.height == MyLayoutSize.empty) + heightTextField.text = @"empty"; else if (itemView.myFlex.attrs.height != 0) heightTextField.text = [@(itemView.myFlex.attrs.height) stringValue]; else @@ -899,6 +905,8 @@ -(IBAction)handleSaveItem:(UIButton*)sender itemView.myFlex.attrs.width = MyLayoutSize.wrap; else if ([widthStr isEqualToString:@"fill"]) itemView.myFlex.attrs.width = MyLayoutSize.fill; + else if ([widthStr isEqualToString:@"empty"]) + itemView.myFlex.attrs.width = MyLayoutSize.empty; else if (widthStr.length == 0) itemView.myFlex.attrs.width = MyLayoutSize.wrap; else @@ -909,6 +917,8 @@ -(IBAction)handleSaveItem:(UIButton*)sender itemView.myFlex.attrs.height = MyLayoutSize.wrap; else if ([heightStr isEqualToString:@"fill"]) itemView.myFlex.attrs.height = MyLayoutSize.fill; + else if ([heightStr isEqualToString:@"empty"]) + itemView.myFlex.attrs.height = MyLayoutSize.empty; else if (heightStr.length == 0) itemView.myFlex.attrs.height = MyLayoutSize.wrap; else diff --git a/MyLayoutTests/MyFlowLayoutTestCase.m b/MyLayoutTests/MyFlowLayoutTestCase.m index 8be2237..5a957a1 100644 --- a/MyLayoutTests/MyFlowLayoutTestCase.m +++ b/MyLayoutTests/MyFlowLayoutTestCase.m @@ -1162,7 +1162,7 @@ -(void)testFillAndStretch rootLayout.gravity = MyGravity_Vert_Stretch; [rootLayout layoutIfNeeded]; MyRectAssert(v1, CGRectMake(0, 0, 40, 40)); - MyRectAssert(v2, CGRectMake(40, 0, 36.5, 95)); + MyRectAssert(v2, CGRectMake(40, 0, 36.5, 50)); MyRectAssert(v3, CGRectMake(76.5, 0, 30, 95)); MyRectAssert(v4, CGRectMake(106.5, 0, 50, 50)); MyRectAssert(v5, CGRectMake(0, 95, 60, 60)); @@ -1225,7 +1225,7 @@ -(void)testFillAndStretch rootLayout.gravity = MyGravity_Horz_Stretch; [rootLayout layoutIfNeeded]; MyRectAssert(v1, CGRectMake(0, 0, 40, 40)); - MyRectAssert(v2, CGRectMake(0, 40, 95, 20.5)); + MyRectAssert(v2, CGRectMake(0, 40, 50, 20.5)); MyRectAssert(v3, CGRectMake(0,60.5, 50+45, 30)); MyRectAssert(v4, CGRectMake(0,90.5, 50, 50)); MyRectAssert(v5, CGRectMake(95, 0, 60, 60)); diff --git a/MyLayoutTests/MyLayoutPerformanceTestCase.m b/MyLayoutTests/MyLayoutPerformanceTestCase.m index 9836520..c4d0c86 100644 --- a/MyLayoutTests/MyLayoutPerformanceTestCase.m +++ b/MyLayoutTests/MyLayoutPerformanceTestCase.m @@ -7,6 +7,8 @@ // #import "MyLayoutTestCaseBase.h" +//#import "FlexBoxLayout.h" +//#import "FBFeedView.h" //对SDAutoLayout和Masonry的测试请单独引入这两个第三方库进行测试。 @@ -1900,6 +1902,207 @@ - (void)testPerformance_linearlayout_layoutUIStackView { }]; } +-(void)testPerformance_flexlayout { + + [self measureBlock:^{ + + UIScrollView *contentView = [UIScrollView new]; + contentView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-44); + + + MyFlexLayout *root = MyFlexLayout.new.myFlex + .justify_content(MyFlexGravity_Space_Around) + .align_items(MyFlexGravity_Center) + .width([UIScreen mainScreen].bounds.size.width) + .height([UIScreen mainScreen].bounds.size.height) + .addTo(contentView); + + + MyFlexLayout *div1 = MyFlexLayout.new.myFlex + .flex_direction(MyFlexDirection_Column) + .justify_content(MyFlexGravity_Space_Between) + .align_items(MyFlexGravity_Center) + .width(150) + .margin_top(20) + .addTo(root); + + UIView *child1 = UIView.new.myFlex + .width(100) + .height(100) + .addTo(div1); + + child1.backgroundColor = [UIColor blueColor]; + + + UIView *child2 = UIView.new.myFlex + .width(100) + .height(100) + .addTo(div1); + + child2.backgroundColor = [UIColor greenColor]; + + UILabel *child3 = UILabel.new.myFlex + .addTo(div1); + + child3.numberOfLines = 0; + child3.backgroundColor = [UIColor yellowColor]; + [child3 setAttributedText:[[NSAttributedString alloc] initWithString:@"testfdsfdsfdsfdsfdsfdsafdsafdsafasdkkk" attributes:@{NSFontAttributeName :[UIFont systemFontOfSize:18]}] ]; + + + + MyFlexLayout *div2 = MyFlexLayout.new.myFlex + .flex_direction(MyFlexDirection_Column) + .justify_content(MyFlexGravity_Space_Around) + .align_items(MyFlexGravity_Center) + .width(150) + .margin_top(20) + .addTo(root); + + UIView *child5 = UIView.new.myFlex + .flex_grow(1) + .width(50) + .height(50) + .margin_bottom(10) + .addTo(div2); + + child5.backgroundColor = [UIColor blueColor]; + + + + UIView *child6 = UIView.new.myFlex + .flex_grow(2) + .width(50) + .height(50) + .margin(10) + .addTo(div2); + + child6.backgroundColor = [UIColor greenColor]; + + + UIView *child7 = UIView.new.myFlex + .flex_grow(1) + .width(50) + .height(50) + .margin_bottom(10) + .addTo(div2); + + child7.backgroundColor = [UIColor yellowColor]; + + + UIView *child8 = UIView.new.myFlex + .flex_grow(1) + .width(50) + .height(50) + .margin_bottom(10) + .addTo(div2); + + child8.backgroundColor = [UIColor blackColor]; + + [root layoutIfNeeded]; + + }]; + +} + +//-(void)testPerformance_yoga { +// +// [self measureBlock:^{ +// UIScrollView *contentView = [UIScrollView new]; +// contentView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-44); +// +// +// UIView *child1 = [UIView new]; +// child1.backgroundColor = [UIColor blueColor]; +// +// [child1 fb_makeLayout:^(FBLayout *layout) { +// layout.width.height.equalTo(@100); +// }]; +// +// UIView *child2 = [UIView new]; +// child2.backgroundColor = [UIColor greenColor]; +// [child2 fb_makeLayout:^(FBLayout *layout) { +// layout.equalTo(child1); +// }]; +// +// +// UILabel *child3 = [UILabel new]; +// child3.numberOfLines = 0; +// child3.backgroundColor = [UIColor yellowColor]; +// [child3 fb_wrapContent]; +// [child3 setAttributedText:[[NSAttributedString alloc] initWithString:@"testfdsfdsfdsfdsfdsfdsafdsafdsafasdkkk" attributes:@{NSFontAttributeName :[UIFont systemFontOfSize:18]}] ]; +// +// [contentView addSubview:child1]; +// [contentView addSubview:child2]; +// [contentView addSubview:child3]; +// +// +// FBLayoutDiv *div1 = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionColumn +// justifyContent:FBJustifySpaceBetween +// alignItems:FBAlignCenter +// children:@[child1, child2,child3]]; +// +// +// +// [div1 fb_makeLayout:^(FBLayout *layout) { +// layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(20, 0, 0, 0)); +// layout.width.equalTo(@(150)); +// }]; +// +// +// UIView *child5 = [UIView new]; +// child5.backgroundColor = [UIColor blueColor]; +// [child5 fb_makeLayout:^(FBLayout *layout) { +// layout.width.height.equalTo(@(50)).margin.equalToEdgeInsets(UIEdgeInsetsMake(0, 0, 10, 0)).flexGrow.equalTo(@1.0); +// }]; +// +// UIView *child6 = [UIView new]; +// child6.backgroundColor = [UIColor greenColor]; +// [child6 fb_makeLayout:^(FBLayout *layout) { +// layout.equalTo(child5); +// layout.flexGrow.equalTo(@(2.0)); +// layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 10, 10, 10)); +// }]; +// +// +// UIView *child7 = [UIView new]; +// child7.backgroundColor = [UIColor yellowColor]; +// [child7 fb_makeLayout:^(FBLayout *layout) { +// layout.equalTo(child5); +// }]; +// +// UIView *child8 = [UIView new]; +// child8.backgroundColor = [UIColor blackColor]; +// +// [child8 fb_makeLayout:^(FBLayout *layout) { +// layout.equalTo(child5); +// }]; +// +// FBLayoutDiv *div2 =[FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionColumn +// justifyContent:FBJustifySpaceAround +// alignItems:FBAlignCenter +// children:@[child5,child6,child7,child8]]; +// [div2 fb_makeLayout:^(FBLayout *layout) { +// layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(20, 0, 0, 0)); +// layout.width.equalTo(@(150)); +// }]; +// +// [contentView addSubview:child5]; +// [contentView addSubview:child6]; +// [contentView addSubview:child7]; +// [contentView addSubview:child8]; +// +// FBLayoutDiv *root = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionRow +// justifyContent:FBJustifySpaceAround +// alignItems:FBAlignCenter +// children:@[div1,div2]]; +// +// contentView.fb_contentDiv = root; +// +// [root fb_applyLayouWithSize:[UIScreen mainScreen].bounds.size]; +// }]; +// +//} + @end From cd73266bd8bde5677bf20e241a3ada3a3e87f1d3 Mon Sep 17 00:00:00 2001 From: youngsoft Date: Sat, 30 Nov 2019 08:41:58 +0800 Subject: [PATCH 095/115] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8CBUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- MyLayout.xcodeproj/project.pbxproj | 14 -- MyLayout/Lib/MyBaseLayout.h | 10 +- MyLayout/Lib/MyFlexLayout.h | 80 +++++- MyLayout/Lib/MyFlexLayout.m | 145 ++++++++++- MyLayout/Lib/MyLayout.h | 2 +- MyLayout/Lib/MyLayoutUI.h | 117 --------- MyLayout/Lib/MyLayoutUI.m | 260 -------------------- MyLayout/Lib/MyLayoutUIInner.h | 19 -- MyLayoutDemo/AllTestExampleViewController.m | 24 +- MyLayoutDemo/FLLTest3ViewController.m | 2 + 11 files changed, 230 insertions(+), 445 deletions(-) delete mode 100644 MyLayout/Lib/MyLayoutUI.h delete mode 100644 MyLayout/Lib/MyLayoutUI.m delete mode 100644 MyLayout/Lib/MyLayoutUIInner.h diff --git a/CHANGELOG.md b/CHANGELOG.md index da5dbfe..9524878 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ **MyLayout**的所有版本的变更日志都将会在这里记录. --- -## [V1.9.0](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.9.0)(2019/10/21) +## [V1.9.0](https://github.com/youngsoft/MyLinearLayout/releases/tag/1.9.0)(2019/11/30) ### Added diff --git a/MyLayout.xcodeproj/project.pbxproj b/MyLayout.xcodeproj/project.pbxproj index 9fd7100..aa59aa0 100644 --- a/MyLayout.xcodeproj/project.pbxproj +++ b/MyLayout.xcodeproj/project.pbxproj @@ -171,10 +171,6 @@ 20DF42422318F4EA0078CAA0 /* MyFlexLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DF42402318F4EA0078CAA0 /* MyFlexLayout.m */; }; 20F0DFFD2111749A00CFCE8C /* AllTest11ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F0DFFC2111749A00CFCE8C /* AllTest11ViewController.m */; }; 20F0E00021120A8D00CFCE8C /* FLLTest8ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F0DFFF21120A8D00CFCE8C /* FLLTest8ViewController.m */; }; - 20F4A803237EF0E000D464E7 /* MyLayoutUI.h in Headers */ = {isa = PBXBuildFile; fileRef = 20F4A801237EF0E000D464E7 /* MyLayoutUI.h */; }; - 20F4A804237EF0E000D464E7 /* MyLayoutUI.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F4A802237EF0E000D464E7 /* MyLayoutUI.m */; }; - 20F4A805237EF46200D464E7 /* MyLayoutUI.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F4A802237EF0E000D464E7 /* MyLayoutUI.m */; }; - 20F4A807237FC40900D464E7 /* MyLayoutUIInner.h in Headers */ = {isa = PBXBuildFile; fileRef = 20F4A806237FC40900D464E7 /* MyLayoutUIInner.h */; }; 20F783561F60399700BE5B31 /* GLTest3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 20F783551F60399700BE5B31 /* GLTest3ViewController.m */; }; 4411977B1F6AE78E00C22557 /* GridLayoutDemo5.json in Resources */ = {isa = PBXBuildFile; fileRef = 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */; }; 444B71911F6A3E3F00331872 /* GLTest5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 444B71901F6A3E3F00331872 /* GLTest5ViewController.m */; }; @@ -430,9 +426,6 @@ 20F0DFFC2111749A00CFCE8C /* AllTest11ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AllTest11ViewController.m; sourceTree = ""; }; 20F0DFFE21120A8D00CFCE8C /* FLLTest8ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLLTest8ViewController.h; sourceTree = ""; }; 20F0DFFF21120A8D00CFCE8C /* FLLTest8ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLLTest8ViewController.m; sourceTree = ""; }; - 20F4A801237EF0E000D464E7 /* MyLayoutUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyLayoutUI.h; sourceTree = ""; }; - 20F4A802237EF0E000D464E7 /* MyLayoutUI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyLayoutUI.m; sourceTree = ""; }; - 20F4A806237FC40900D464E7 /* MyLayoutUIInner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLayoutUIInner.h; sourceTree = ""; }; 20F783541F60398C00BE5B31 /* GLTest3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTest3ViewController.h; sourceTree = ""; }; 20F783551F60399700BE5B31 /* GLTest3ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTest3ViewController.m; sourceTree = ""; }; 4411977A1F6AE78E00C22557 /* GridLayoutDemo5.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GridLayoutDemo5.json; sourceTree = ""; }; @@ -822,9 +815,6 @@ 182225B41E77E5930081AA4B /* MyFlowLayout.m */, 20DF423F2318F4EA0078CAA0 /* MyFlexLayout.h */, 20DF42402318F4EA0078CAA0 /* MyFlexLayout.m */, - 20F4A801237EF0E000D464E7 /* MyLayoutUI.h */, - 20F4A802237EF0E000D464E7 /* MyLayoutUI.m */, - 20F4A806237FC40900D464E7 /* MyLayoutUIInner.h */, 182225AC1E77E5930081AA4B /* MyLinearLayout.h */, 182225B21E77E5930081AA4B /* MyLinearLayout.m */, 182225AD1E77E5930081AA4B /* MyFloatLayout.h */, @@ -939,7 +929,6 @@ 18C15AF21EDF13F900AADEAC /* MyPathLayout.h in Headers */, 205643161F55A03000E8BDDE /* MyLayoutMath.h in Headers */, 18C15AF31EDF13FF00AADEAC /* MyFrameLayout.h in Headers */, - 20F4A803237EF0E000D464E7 /* MyLayoutUI.h in Headers */, 18C15AF41EDF140400AADEAC /* MyBaseLayout.h in Headers */, 18C15AF51EDF140D00AADEAC /* MyLayoutPos.h in Headers */, 18C15AF61EDF141000AADEAC /* MyLayoutSize.h in Headers */, @@ -953,7 +942,6 @@ 18C15AFA1EDF142300AADEAC /* MyLayoutDef.h in Headers */, 205E0C6020B907CC001A8B99 /* MyLayoutPosInner.h in Headers */, 205E0C6120B907D1001A8B99 /* MyLayoutSizeInner.h in Headers */, - 20F4A807237FC40900D464E7 /* MyLayoutUIInner.h in Headers */, 205E0C6220B907DB001A8B99 /* MyLayoutInner.h in Headers */, 205E0C6320B907EC001A8B99 /* MyLayoutDelegate.h in Headers */, ); @@ -1163,7 +1151,6 @@ 20DF42422318F4EA0078CAA0 /* MyFlexLayout.m in Sources */, 182DB6441EF7876200E2D65D /* MyGridLayout.m in Sources */, 18C15B001EDF144B00AADEAC /* MyPathLayout.m in Sources */, - 20F4A804237EF0E000D464E7 /* MyLayoutUI.m in Sources */, 18C15B011EDF144B00AADEAC /* MyFrameLayout.m in Sources */, 18C15B021EDF144B00AADEAC /* MyBaseLayout.m in Sources */, 18C15B031EDF144B00AADEAC /* MyLayoutPos.m in Sources */, @@ -1195,7 +1182,6 @@ 18D3C9731EDF082800D3DE43 /* AllTest2TableViewCell.m in Sources */, 18D3C95F1EDF07F800D3DE43 /* FOLTest6ViewController.m in Sources */, 182225D51E77E5930081AA4B /* MyLayoutSize.m in Sources */, - 20F4A805237EF46200D464E7 /* MyLayoutUI.m in Sources */, 6740E20120A52DC100AFBC5A /* AllTest10Cell.m in Sources */, 18D3C93A1EDF07C000D3DE43 /* FLLTest2ViewController.m in Sources */, 467E63CF228CDA660065D080 /* AllTest1TableViewCellForAutoLayout.m in Sources */, diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index 540d04b..f048446 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -336,12 +336,18 @@ */ /** - *视图的宽度布局尺寸,是widthSize.equalTo方法的简化版本。此属性只用于赋值不用于读取! + *视图的宽度布局尺寸,是widthSize.equalTo方法的简化版本。此属性只用于赋值不用于读取!除了设置常规的数字外您还可以设置一些特殊的值: + MyLayoutSize.wrap 表示宽度自适应 + MyLayoutSize.fill 表明宽度填充父视图剩余宽度 + MyLayoutSize.empty 表明清除宽度约束。 */ @property(nonatomic,assign) IBInspectable CGFloat myWidth; /** - *视图的高度布局尺寸,是heightSize.equalTo方法的简化版本。此属性只用于赋值不用于读取! + *视图的高度布局尺寸,是heightSize.equalTo方法的简化版本。此属性只用于赋值不用于读取!除了设置常规的数字外您还可以设置一些特殊的值: + MyLayoutSize.wrap 表示高度自适应 + MyLayoutSize.fill 表明高度填充父视图剩余高度 + MyLayoutSize.empty 表明清除高度约束。 */ @property(nonatomic,assign) IBInspectable CGFloat myHeight; diff --git a/MyLayout/Lib/MyFlexLayout.h b/MyLayout/Lib/MyFlexLayout.h index dcccf83..b508f82 100644 --- a/MyLayout/Lib/MyFlexLayout.h +++ b/MyLayout/Lib/MyFlexLayout.h @@ -7,7 +7,6 @@ // #import "MyFlowLayout.h" -#import "MyLayoutUI.h" /**定义flex的方向类型*/ typedef enum : int { @@ -89,9 +88,86 @@ extern const int MyFlex_Auto; -@protocol MyFlexItem +@protocol MyFlexItem @property(nonatomic, strong, readonly) id attrs; +@property(nonatomic, weak, readonly) __kindof UIView *view; + + +/** + 视图的宽度设置,如果宽度设置为大于0小于1则表明是相对于父视图宽度的比重值,如果是MyLayoutSize.wrap则表明宽度自适应,如果是MyLayoutSize.fill则表明宽度和父视图相等,如果是MyLayoutSize.empty则表明不设置宽度值。 其他的值就是一个固定宽度值。 + */ +-(id (^)(CGFloat))width; + + +/** + 视图的宽度设置,percent表明占用父视图宽度的百分比值,inc表明在百分比值的基础上的增量值。 + */ +-(id (^)(CGFloat percent, CGFloat inc))width_percent; + + +/** + 最小宽度限制设置 + */ +-(id (^)(CGFloat))min_width; + +/** + 最大宽度限制设置 + */ +-(id (^)(CGFloat))max_width; +/** + 视图的高度设置,如果高度设置为大于0小于1则表明是相对于父视图高度的比重值,如果是MyLayoutSize.wrap则表明高度自适应,如果是MyLayoutSize.fill则表明高度和父视图相等,如果是MyLayoutSize.empty则表明不设置高度值,其他的值就是一个固定高度值。 + */ +-(id (^)(CGFloat))height; + +/** + 视图的高度设置,percent表明占用父视图高度的百分比值,inc表明在百分比值的基础上的增量值。 + */ +-(id (^)(CGFloat percent, CGFloat inc))height_percent; + + +/** + 最小高度限制设置 + */ +-(id (^)(CGFloat))min_height; + +/** + 最大高度限制设置 + */ +-(id (^)(CGFloat))max_height; + +//视图的外间距设置。 +/** + 视图的顶部外间距设置 + */ +-(id (^)(CGFloat))margin_top; +/** + 视图的底部外间距设置 + */ +-(id (^)(CGFloat))margin_bottom; +/** + 视图的左边外间距设置 + */ +-(id (^)(CGFloat))margin_left; +/** + 视图的右边外间距设置 + */ +-(id (^)(CGFloat))margin_right; +/** + 视图的四周外间距设置 + */ +-(id (^)(CGFloat))margin; +/** + 视图的可视设置 + */ +-(id (^)(MyVisibility))visibility; + + +//添加到父视图中 +-(__kindof UIView* (^)(UIView*))addTo; + +//添加子视图 +-(id (^)(UIView*))add; /** 条目在弹盒中的排列顺序,值越大越往后排。 diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index 40c801c..095848f 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -7,7 +7,6 @@ // #import "MyFlexLayout.h" -#import "MyLayoutUIInner.h" #import "MyLayoutInner.h" #import @@ -281,6 +280,144 @@ -(instancetype)initWithView:(UIView*)view attrs:(id)attrs return _attrs; } +-(id (^)(CGFloat))width +{ + return ^id(CGFloat val) { + if (val > 0 && val < 1) + self.view.widthSize.equalTo(@(MyLayoutSize.fill)).multiply(val); + else + self.view.widthSize.equalTo(@(val)); + return self; + }; +} + +-(id (^)(CGFloat percent, CGFloat inc))width_percent +{ + return ^id(CGFloat percent, CGFloat inc) { + self.view.widthSize.equalTo(@(MyLayoutSize.fill)).multiply(percent).add(inc); + return self; + }; +} + +-(id (^)(CGFloat))min_width +{ + return ^id(CGFloat val) { + self.view.widthSize.min(val); + return self; + }; +} + +-(id (^)(CGFloat))max_width +{ + return ^id(CGFloat val) { + self.view.widthSize.max(val); + return self; + }; +} + +-(id (^)(CGFloat))height +{ + return ^id(CGFloat val) { + if (val > 0 && val < 1) + self.view.heightSize.equalTo(@(MyLayoutSize.fill)).multiply(val); + else + self.view.heightSize.equalTo(@(val)); + return self; + }; +} + +-(id (^)(CGFloat percent, CGFloat inc))height_percent +{ + return ^id(CGFloat percent, CGFloat inc) { + self.view.heightSize.equalTo(@(MyLayoutSize.fill)).multiply(percent).add(inc); + return self; + }; +} + +-(id (^)(CGFloat))min_height +{ + return ^id(CGFloat val) { + self.view.heightSize.min(val); + return self; + }; +} + +-(id (^)(CGFloat))max_height +{ + return ^id(CGFloat val) { + self.view.heightSize.max(val); + return self; + }; +} + +-(id (^)(CGFloat))margin_top +{ + return ^id(CGFloat val) { + self.view.myTop = val; + return self; + }; +} + +-(id (^)(CGFloat))margin_bottom +{ + return ^id(CGFloat val) { + self.view.myBottom = val; + return self; + }; +} + +-(id (^)(CGFloat))margin_left +{ + return ^id(CGFloat val) { + self.view.myLeft = val; + return self; + }; +} + +-(id (^)(CGFloat))margin_right +{ + return ^id(CGFloat val) { + self.view.myRight = val; + return self; + }; +} + +-(id (^)(CGFloat))margin +{ + return ^id(CGFloat val) { + self.view.myLeft = val; + self.view.myRight = val; + self.view.myTop = val; + self.view.myBottom = val; + return self; + }; +} + +-(id (^)(MyVisibility))visibility +{ + return ^id(MyVisibility val) { + self.view.visibility = val; + return self; + }; +} + +-(__kindof UIView* (^)(UIView*))addTo +{ + return ^(UIView *val) { + [val addSubview:self.view]; + return self.view; + }; +} + +-(id (^)(UIView*))add +{ + return ^(UIView *val) { + [self.view addSubview:val]; + return self; + }; +} + + -(id (^)(NSInteger))order { return ^id(NSInteger val) { @@ -321,12 +458,6 @@ -(instancetype)initWithView:(UIView*)view attrs:(id)attrs }; } -//其他请求跳转到myUI中去。 --(id)forwardingTargetForSelector:(SEL)aSelector -{ - return self.view.myUI; -} - @end diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index 4da0f7c..166d13d 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -37,7 +37,7 @@ */ -//Current version is 1.9.0beta, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.9.0, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. #ifndef MyLayout_MyLayout_h diff --git a/MyLayout/Lib/MyLayoutUI.h b/MyLayout/Lib/MyLayoutUI.h deleted file mode 100644 index 1becd05..0000000 --- a/MyLayout/Lib/MyLayoutUI.h +++ /dev/null @@ -1,117 +0,0 @@ -// -// MyFlexItem.h -// MyLayout -// -// Created by oubaiquan on 2019/11/15. -// Copyright © 2019 YoungSoft. All rights reserved. -// - -#import -#import "MyLayoutDef.h" - - -@protocol MyUIViewUI -@optional - -//您可以用链式语法进行属性设置,也可以直接通过属性赋值进行设置和获取。 -@property(nonatomic, weak, readonly) __kindof UIView *view; - - -/** - 视图的宽度设置,如果宽度设置为大于0小于1则表明是相对于父视图宽度的比重值,如果是MyLayoutSize.wrap则表明宽度自适应,如果是MyLayoutSize.fill则表明宽度和父视图相等,如果是MyLayoutSize.empty则表明不设置宽度值。 其他的值就是一个固定宽度值。 - */ --(id (^)(CGFloat))width; - - -/** - 视图的宽度设置,percent表明占用父视图宽度的百分比值,inc表明在百分比值的基础上的增量值。 - */ --(id (^)(CGFloat percent, CGFloat inc))width_percent; - - -/** - 最小宽度限制设置 - */ --(id (^)(CGFloat))min_width; - -/** - 最大宽度限制设置 - */ --(id (^)(CGFloat))max_width; -/** - 视图的高度设置,如果高度设置为大于0小于1则表明是相对于父视图高度的比重值,如果是MyLayoutSize.wrap则表明高度自适应,如果是MyLayoutSize.fill则表明高度和父视图相等,如果是MyLayoutSize.empty则表明不设置高度值,其他的值就是一个固定高度值。 - */ --(id (^)(CGFloat))height; - -/** - 视图的高度设置,percent表明占用父视图高度的百分比值,inc表明在百分比值的基础上的增量值。 - */ --(id (^)(CGFloat percent, CGFloat inc))height_percent; - - -/** - 最小高度限制设置 - */ --(id (^)(CGFloat))min_height; - -/** - 最大高度限制设置 - */ --(id (^)(CGFloat))max_height; - -//视图的外间距设置。 -/** - 视图的顶部外间距设置 - */ --(id (^)(CGFloat))margin_top; -/** - 视图的底部外间距设置 - */ --(id (^)(CGFloat))margin_bottom; -/** - 视图的左边外间距设置 - */ --(id (^)(CGFloat))margin_left; -/** - 视图的右边外间距设置 - */ --(id (^)(CGFloat))margin_right; -/** - 视图的四周外间距设置 - */ --(id (^)(CGFloat))margin; -/** - 视图的可视设置 - */ --(id (^)(MyVisibility))visibility; - -//视图特有的属性。 --(id (^)(CGAffineTransform))transform; --(id (^)(BOOL))clipsToBounds; --(id (^)(UIColor*))backgroundColor; --(id (^)(CGFloat))alpha; --(id (^)(NSInteger))tag; --(id (^)(BOOL))userInteractionEnabled; --(id (^)( UIColor *color,CGFloat width))border; --(id (^)(CGFloat))cornerRadius; --(id (^)(UIColor* color, CGSize offset, CGFloat radius))shadow; - -//添加到父视图中 --(__kindof UIView* (^)(UIView*))addTo; - -//添加子视图 --(id (^)(UIView*))add; - -@end - - -@protocol MyUIViewUICategory - -@property(nonatomic, strong, readonly) id myUI; - -@end - - -@interface UIView(MyLayoutUI) -@end - diff --git a/MyLayout/Lib/MyLayoutUI.m b/MyLayout/Lib/MyLayoutUI.m deleted file mode 100644 index 6359827..0000000 --- a/MyLayout/Lib/MyLayoutUI.m +++ /dev/null @@ -1,260 +0,0 @@ -// -// MyFlexItem.m -// MyLayout -// -// Created by oubaiquan on 2019/11/15. -// Copyright © 2019 YoungSoft. All rights reserved. -// - -#import "MyBaseLayout.h" -#import "MyLayoutInner.h" -#import "MyLayoutUIInner.h" -#import - -const char * const ASSOCIATEDOBJECT_KEY_MYLAYOUT_MYUI = "ASSOCIATEDOBJECT_KEY_MYLAYOUT_MYUI"; - - -#pragma mark -- MyUIViewUI - -@implementation MyUIViewUI - --(instancetype)initWithView:(UIView*)view -{ - self = [self init]; - if (self != nil) - { - _view = view; - } - return self; -} - --(id (^)(CGFloat))width -{ - return ^id(CGFloat val) { - if (val > 0 && val < 1) - self.view.widthSize.equalTo(@(MyLayoutSize.fill)).multiply(val); - else - self.view.widthSize.equalTo(@(val)); - return self; - }; -} - --(id (^)(CGFloat percent, CGFloat inc))width_percent -{ - return ^id(CGFloat percent, CGFloat inc) { - self.view.widthSize.equalTo(@(MyLayoutSize.fill)).multiply(percent).add(inc); - return self; - }; -} - --(id (^)(CGFloat))min_width -{ - return ^id(CGFloat val) { - self.view.widthSize.min(val); - return self; - }; -} - --(id (^)(CGFloat))max_width -{ - return ^id(CGFloat val) { - self.view.widthSize.max(val); - return self; - }; -} - --(id (^)(CGFloat))height -{ - return ^id(CGFloat val) { - if (val > 0 && val < 1) - self.view.heightSize.equalTo(@(MyLayoutSize.fill)).multiply(val); - else - self.view.heightSize.equalTo(@(val)); - return self; - }; -} - --(id (^)(CGFloat percent, CGFloat inc))height_percent -{ - return ^id(CGFloat percent, CGFloat inc) { - self.view.heightSize.equalTo(@(MyLayoutSize.fill)).multiply(percent).add(inc); - return self; - }; -} - --(id (^)(CGFloat))min_height -{ - return ^id(CGFloat val) { - self.view.heightSize.min(val); - return self; - }; -} - --(id (^)(CGFloat))max_height -{ - return ^id(CGFloat val) { - self.view.heightSize.max(val); - return self; - }; -} - --(id (^)(CGFloat))margin_top -{ - return ^id(CGFloat val) { - self.view.myTop = val; - return self; - }; -} - --(id (^)(CGFloat))margin_bottom -{ - return ^id(CGFloat val) { - self.view.myBottom = val; - return self; - }; -} - --(id (^)(CGFloat))margin_left -{ - return ^id(CGFloat val) { - self.view.myLeft = val; - return self; - }; -} - --(id (^)(CGFloat))margin_right -{ - return ^id(CGFloat val) { - self.view.myRight = val; - return self; - }; -} - --(id (^)(CGFloat))margin -{ - return ^id(CGFloat val) { - self.view.myLeft = val; - self.view.myRight = val; - self.view.myTop = val; - self.view.myBottom = val; - return self; - }; -} - --(id (^)(MyVisibility))visibility -{ - return ^id(MyVisibility val) { - self.view.visibility = val; - return self; - }; -} - --(id (^)(CGAffineTransform))transform -{ - return ^id(CGAffineTransform val) { - self.view.transform = val; - return self; - }; -} - --(id (^)(BOOL))clipsToBounds -{ - return ^id(BOOL val) { - self.view.clipsToBounds = val; - return self; - }; -} - --(id (^)(UIColor*))backgroundColor -{ - return ^id(UIColor *val) { - self.view.backgroundColor = val; - return self; - }; -} - --(id (^)(CGFloat))alpha -{ - return ^id(CGFloat val) { - self.view.alpha = val; - return self; - }; -} - --(id (^)(NSInteger))tag -{ - return ^id(NSInteger val) { - self.view.tag = val; - return self; - }; -} - --(id (^)(BOOL))userInteractionEnabled -{ - return ^id(BOOL val) { - self.view.userInteractionEnabled = val; - return self; - }; -} - --(id (^)(UIColor *color, CGFloat width))border -{ - return ^id(UIColor *color, CGFloat width) { - self.view.layer.borderColor = color.CGColor; - self.view.layer.borderWidth = width; - return self; - }; -} - --(id (^)(CGFloat))cornerRadius -{ - return ^id(CGFloat val) { - self.view.layer.cornerRadius = val; - return self; - }; -} - --(id (^)(UIColor* color, CGSize offset, CGFloat radius))shadow -{ - return ^id(UIColor *color, CGSize offset, CGFloat radius) { - self.view.layer.shadowColor = color.CGColor; - self.view.layer.shadowOffset = offset; - self.view.layer.shadowRadius = radius; - return self; - }; -} - --(__kindof UIView* (^)(UIView*))addTo -{ - return ^(UIView *val) { - [val addSubview:self.view]; - return self.view; - }; -} - --(id (^)(UIView*))add -{ - return ^(UIView *val) { - [self.view addSubview:val]; - return self; - }; -} - - -@end - - -@implementation UIView(MyLayoutUI) - --(id)myUI -{ - id obj = (id)objc_getAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_MYUI); - if (obj == nil) - { - obj = [[MyUIViewUI alloc] initWithView:self]; - objc_setAssociatedObject(self, ASSOCIATEDOBJECT_KEY_MYLAYOUT_MYUI, obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - } - return obj; -} - -@end diff --git a/MyLayout/Lib/MyLayoutUIInner.h b/MyLayout/Lib/MyLayoutUIInner.h deleted file mode 100644 index 2ee05eb..0000000 --- a/MyLayout/Lib/MyLayoutUIInner.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// MyFlexItem.h -// MyLayout -// -// Created by oubaiquan on 2019/11/15. -// Copyright © 2019 YoungSoft. All rights reserved. -// - -#import "MyLayoutUI.h" - -#pragma mark -- MyUIViewUI - -@interface MyUIViewUI : NSObject - -@property(nonatomic, weak, readonly) __kindof UIView *view; - --(instancetype)initWithView:(UIView*)view; - -@end diff --git a/MyLayoutDemo/AllTestExampleViewController.m b/MyLayoutDemo/AllTestExampleViewController.m index fbd8b30..ee4ced6 100644 --- a/MyLayoutDemo/AllTestExampleViewController.m +++ b/MyLayoutDemo/AllTestExampleViewController.m @@ -232,27 +232,8 @@ -(void)example4 -(void)example5 { - //一个row 下两个宽度均分高度为填充的子视图。 - - MyFlexLayout *rootLayout = MyFlexLayout.new.myFlex - .margin(0) - .addTo(self.view); - - UIView *v1 = MyFlexLayout.new.myFlex - .flex_grow(1) - .margin_top(30) - .backgroundColor(UIColor.redColor) - .addTo(rootLayout); - - UIView *v2 = MyFlexLayout.new.myFlex - .flex_grow(1) - .margin_top(30) - .backgroundColor(UIColor.greenColor) - .addTo(rootLayout); - - - - /*MyRelativeLayout *rootLayout = [MyRelativeLayout new]; + + MyRelativeLayout *rootLayout = [MyRelativeLayout new]; rootLayout.myHeight = MyLayoutSize.wrap; rootLayout.myHorzMargin = 0; rootLayout.padding = UIEdgeInsetsMake(12, 12, 12, 12); @@ -290,7 +271,6 @@ -(void)example5 [rootLayout addSubview:barView]; [self.view addSubview:rootLayout]; - */ } @end diff --git a/MyLayoutDemo/FLLTest3ViewController.m b/MyLayoutDemo/FLLTest3ViewController.m index 2de8feb..e5720c9 100644 --- a/MyLayoutDemo/FLLTest3ViewController.m +++ b/MyLayoutDemo/FLLTest3ViewController.m @@ -33,6 +33,8 @@ -(void)loadView 子视图的扩展属性useFrame表示某个子视图不受布局视图的布局控制,而是用最原始的frame属性设置来实现自定义的位置和尺寸的设定。 子视图的扩展属性noLayout表示某个子视图会参与布局,但是并不会正真的调整布局后的frame值。 + 在新版本1.9.0中将这些能力进行了统一的封装,通过一个拖放类来实现这些功能。 + */ MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; From d7ab375e416d63f72cf2ba97d3d839d13019f54e Mon Sep 17 00:00:00 2001 From: youngsoft Date: Sun, 22 Dec 2019 13:13:35 +0800 Subject: [PATCH 096/115] =?UTF-8?q?BUG=E4=BF=AE=E5=A4=8D=EF=BC=8C=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=8D=87=E7=BA=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyLayout/Lib/MyBaseLayout.h | 14 +- MyLayout/Lib/MyBaseLayout.m | 26 +- MyLayout/Lib/MyFlexLayout.m | 5 +- MyLayout/Lib/MyFloatLayout.h | 10 + MyLayout/Lib/MyFloatLayout.m | 77 ++-- MyLayout/Lib/MyFlowLayout.h | 26 +- MyLayout/Lib/MyFlowLayout.m | 359 ++++++++++-------- MyLayout/Lib/MyLayout.h | 2 +- MyLayout/Lib/MyLayoutDef.h | 24 +- MyLayout/Lib/MyLayoutSizeClass.h | 23 +- MyLayout/Lib/MyLayoutSizeClass.m | 86 ++++- MyLayout/Lib/MyLinearLayout.h | 17 + MyLayout/Lib/MyLinearLayout.m | 97 +++-- MyLayout/Lib/MyRelativeLayout.m | 4 +- MyLayoutDemo/FLLTest1ViewController.m | 59 ++- MyLayoutDemo/FLLTest2ViewController.m | 5 +- MyLayoutDemo/FLLTest8ViewController.m | 98 ++++- MyLayoutDemo/LLTest3ViewController.m | 30 +- .../zh-Hans.lproj/FLLTest2ViewController.xib | 2 +- .../zh-Hans.lproj/Localizable.strings | 4 +- 20 files changed, 675 insertions(+), 293 deletions(-) diff --git a/MyLayout/Lib/MyBaseLayout.h b/MyLayout/Lib/MyBaseLayout.h index f048446..be7c34d 100644 --- a/MyLayout/Lib/MyBaseLayout.h +++ b/MyLayout/Lib/MyBaseLayout.h @@ -743,12 +743,16 @@ 6. MyGravity_Horz_Around 表示每列之间的列间距都被拉伸,以便使里面的子视图水平方向填充满整个布局视图,首尾子视图和父视图的间距是子视图兄弟之间的一半。 (支持:水平线性布局,水平表格布局,流式布局) - 7. MyGravity_Vert_Fill 表示布局会拉伸子视图的高度,以便使里面的子视图垂直方向填充满整个布局视图的高度或者子视图平分布局视图的高度。(支持:框架布局,水平线性布局,水平表格布局,流式布局) + 7. MyGravity_Vert_Among 表示每行之间的行间距都被拉伸,以便使里面的子视图垂直方向填充满整个布局视图,首尾子视图和父视图的间距和子视图兄弟之间的间距相等。 (支持:垂直线性布局,垂直表格布局,流式布局) - 8. MyGravity_Horz_Fill 表示布局会拉伸子视图的宽度,以便使里面的子视图水平方向填充满整个布局视图的宽度或者子视图平分布局视图的宽度。 (支持:框架布局,垂直线性布局,垂直表格布局,流式布局) - 9. MyGravity_Vert_Baseline 表示布局里面的子视图都基线对齐,目前只支持水平线性布局。 - 10.MyGravity_Vert_Stretch 表示当布局中的子视图没有设置高度约束时或者非布局子视图高度自适应时,会拉伸子视图的高度。(支持:线性布局、流式布局) - 11.MyGravity_Horz_Stretch 表示当布局中的子视图没有设置宽度约束或者非布局子视图宽度自适应时,会拉伸子视图的宽度。(支持:线性布局、流式布局) + 8. MyGravity_Horz_Among 表示每列之间的列间距都被拉伸,以便使里面的子视图水平方向填充满整个布局视图,首尾子视图和父视图的间距和子视图兄弟之间的间距相等。 (支持:水平线性布局,水平表格布局,流式布局) + + 9. MyGravity_Vert_Fill 表示布局会拉伸子视图的高度,以便使里面的子视图垂直方向填充满整个布局视图的高度或者子视图平分布局视图的高度。(支持:框架布局,水平线性布局,水平表格布局,流式布局) + + 10. MyGravity_Horz_Fill 表示布局会拉伸子视图的宽度,以便使里面的子视图水平方向填充满整个布局视图的宽度或者子视图平分布局视图的宽度。 (支持:框架布局,垂直线性布局,垂直表格布局,流式布局) + 11. MyGravity_Vert_Baseline 表示布局里面的子视图都基线对齐,目前只支持水平线性布局。 + 12.MyGravity_Vert_Stretch 表示当布局中的子视图没有设置高度约束时或者非布局子视图高度自适应时,会拉伸子视图的高度。(支持:线性布局、流式布局) + 13.MyGravity_Horz_Stretch 表示当布局中的子视图没有设置宽度约束或者非布局子视图宽度自适应时,会拉伸子视图的宽度。(支持:线性布局、流式布局) */ @property(nonatomic, assign) IBInspectable MyGravity gravity; diff --git a/MyLayout/Lib/MyBaseLayout.m b/MyLayout/Lib/MyBaseLayout.m index a794bd8..c71a9b5 100644 --- a/MyLayout/Lib/MyBaseLayout.m +++ b/MyLayout/Lib/MyBaseLayout.m @@ -2611,7 +2611,7 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview isAdjust = YES; //如果宽度约束的优先级很低都按左右边距来决定布局视图的宽度。 if (lsc.widthSizeInner.priority == MyPriority_Low) - [lsc.widthSizeInner __setActive:NO]; + [lsc.widthSizeInner __equalTo:nil]; if (lsc.widthSizeInner.dimeVal == nil) { @@ -2713,7 +2713,7 @@ -(BOOL)myUpdateLayoutRectInNoLayoutSuperview:(UIView*)newSuperview isAdjust = YES; //如果高度约束优先级很低则按上下边距来决定布局视图高度。 if (lsc.heightSizeInner.priority == MyPriority_Low) - [lsc.heightSizeInner __setActive:NO]; + [lsc.heightSizeInner __equalTo:nil]; if (lsc.heightSizeInner.dimeVal == nil) { @@ -3175,23 +3175,11 @@ - (void)myLayout:(MyBaseLayout*)lsc adjustScrollViewContentWithSize:(CGSize)newS contsize.height = newSize.height + topMargin + bottomMargin; if (contsize.width != newSize.width + leadingMargin + trailingMargin) contsize.width = newSize.width + leadingMargin + trailingMargin; - - //因为调整contentsize可能会调整contentOffset,所以为了保持一致性这里要还原掉原来的contentOffset - CGPoint oldOffset = scrolv.contentOffset; - + contsize.width *= scrolv.zoomScale; contsize.height *= scrolv.zoomScale; - - if (!CGSizeEqualToSize(scrolv.contentSize, contsize)) scrolv.contentSize = contsize; - - if ((oldOffset.x <= 0 || oldOffset.x <= contsize.width - rectSuper.size.width) && - (oldOffset.y <= 0 || oldOffset.y <= contsize.height - rectSuper.size.height)) - { - if (!CGPointEqualToPoint(scrolv.contentOffset, oldOffset)) - scrolv.contentOffset = oldOffset; - } } } @@ -3299,19 +3287,19 @@ -(void)myLayout:(MyLayoutViewSizeClass*)lsc adjustSizeSettingOfSubview:(MyViewSi //只要子视图是包裹并且布局视图是fill填充,都应该清除子视图的包裹设置。 if (sbvsc.widthSizeInner.dimeWrapVal && horzGravity == MyGravity_Horz_Fill) - [sbvsc.widthSizeInner __setActive:NO]; + [sbvsc.widthSizeInner __equalTo:nil]; if (sbvsc.heightSizeInner.dimeWrapVal && vertGravity == MyGravity_Vert_Fill) - [sbvsc.heightSizeInner __setActive:NO]; + [sbvsc.heightSizeInner __equalTo:nil]; if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil && (sbvsc.widthSizeInner.priority == MyPriority_Low || !lsc.widthSizeInner.dimeWrapVal)) - [sbvsc.widthSizeInner __setActive:NO]; + [sbvsc.widthSizeInner __equalTo:nil]; if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil && (sbvsc.heightSizeInner.priority == MyPriority_Low || !lsc.heightSizeInner.dimeWrapVal)) - [sbvsc.heightSizeInner __setActive:NO]; + [sbvsc.heightSizeInner __equalTo:nil]; if ([sbv isKindOfClass:[MyBaseLayout class]]) { diff --git a/MyLayout/Lib/MyFlexLayout.m b/MyLayout/Lib/MyFlexLayout.m index 095848f..83f63ec 100644 --- a/MyLayout/Lib/MyFlexLayout.m +++ b/MyLayout/Lib/MyFlexLayout.m @@ -611,6 +611,7 @@ -(instancetype)init self.orientation = MyOrientation_Vert; //默认row self.arrangedCount = NSIntegerMax; //默认单行 self.isFlex = YES; //满足flexbox的需求。 + self.lastlineGravityPolicy = MyGravityPolicy_Always; MyFlexBoxAttrs *attrs = [MyFlexBoxAttrs new]; attrs.view = self; @@ -686,9 +687,9 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( sbvsc.heightSize.shrink = flexItem.attrs.flex_shrink != MyFlex_Auto? flexItem.attrs.flex_shrink:0; //如果没有设置尺寸约束则默认是自适应。 - if (sbvsc.widthSizeInner == nil) + if (sbvsc.widthSizeInner.dimeVal == nil) [sbvsc.widthSize __equalTo:@(MyLayoutSize.wrap)]; - if (sbvsc.heightSizeInner == nil) + if (sbvsc.heightSizeInner.dimeVal == nil) [sbvsc.heightSize __equalTo:@(MyLayoutSize.wrap)]; //基准值设置。 diff --git a/MyLayout/Lib/MyFloatLayout.h b/MyLayout/Lib/MyFloatLayout.h index 5a97104..c5d5984 100644 --- a/MyLayout/Lib/MyFloatLayout.h +++ b/MyLayout/Lib/MyFloatLayout.h @@ -120,6 +120,16 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace; -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace inSizeClass:(MySizeClass)sizeClass; +/** + 上面函数的加强版本。 + + @param subviewSize 指定子视图的尺寸 + @param minSpace 指定子视图之间的最小间距 + @param maxSpace 指定子视图之间的最大间距 + @param centered 指定是否所有子视图居中 + */ +-(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace centered:(BOOL)centered; +-(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace centered:(BOOL)centered inSizeClass:(MySizeClass)sizeClass; @end diff --git a/MyLayout/Lib/MyFloatLayout.m b/MyLayout/Lib/MyFloatLayout.m index 1edc96d..d0ce5e2 100644 --- a/MyLayout/Lib/MyFloatLayout.m +++ b/MyLayout/Lib/MyFloatLayout.m @@ -93,13 +93,35 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace: -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace inSizeClass:(MySizeClass)sizeClass { - MyFloatLayoutViewSizeClass *lsc = (MyFloatLayoutViewSizeClass*)[self fetchLayoutSizeClass:sizeClass]; - lsc.subviewSize = subviewSize; - lsc.minSpace = minSpace; - lsc.maxSpace = maxSpace; + [self setSubviewsSize:subviewSize minSpace:minSpace maxSpace:maxSpace centered:NO inSizeClass:sizeClass]; +} + +-(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace centered:(BOOL)centered +{ + [self setSubviewsSize:subviewSize minSpace:minSpace maxSpace:maxSpace centered:centered inSizeClass:MySizeClass_hAny | MySizeClass_wAny]; +} + +-(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace centered:(BOOL)centered inSizeClass:(MySizeClass)sizeClass +{ + MySequentLayoutViewSizeClass *lsc = (MySequentLayoutViewSizeClass*)[self fetchLayoutSizeClass:sizeClass]; + if (subviewSize == 0) + { + lsc.flexSpace = nil; + } + else + { + if (lsc.flexSpace == nil) + lsc.flexSpace = [MySequentLayoutFlexSpace new]; + + lsc.flexSpace.subviewSize = subviewSize; + lsc.flexSpace.minSpace = minSpace; + lsc.flexSpace.maxSpace = maxSpace; + lsc.flexSpace.centered = centered; + } [self setNeedsLayout]; } + #pragma mark -- Override Methods -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:(BOOL*)pHasSubLayout sizeClass:(MySizeClass)sizeClass sbs:(NSMutableArray*)sbs @@ -118,13 +140,13 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( orientation == MyOrientation_Vert && sbvsc.weight != 0 && [sbvsc.view isKindOfClass:[MyBaseLayout class]]) - [sbvsc.widthSizeInner __setActive:NO]; + [sbvsc.widthSizeInner __equalTo:nil]; if (sbvsc.heightSizeInner.dimeWrapVal && orientation == MyOrientation_Horz && sbvsc.weight != 0 && [sbvsc.view isKindOfClass:[MyBaseLayout class]]) - [sbvsc.heightSizeInner __setActive:NO]; + [sbvsc.heightSizeInner __equalTo:nil]; }]; if (orientation == MyOrientation_Vert) @@ -309,35 +331,6 @@ -(CGPoint)myFindTopCandidatePoint:(CGRect)bottomCandidateRect height:(CGFloat)h return retPoint; } --(CGFloat)myLayout:(MyFloatLayoutViewSizeClass*)lsc calcMaxMinSubviewSizeWithSelfSize:(CGFloat)selfSize space:(CGFloat*)pSpace -{ - CGFloat subviewSize = lsc.subviewSize; - if (subviewSize != 0) - { - CGFloat minSpace = lsc.minSpace; - CGFloat maxSpace = lsc.maxSpace; - - NSInteger rowCount = floor((selfSize + minSpace) / (subviewSize + minSpace)); - if (rowCount > 1) - { - *pSpace = (selfSize - subviewSize * rowCount)/(rowCount - 1); - - //如果超过最大间距或者小于最小间距则调整子视图的宽度。 - if (_myCGFloatGreat(*pSpace, maxSpace) || _myCGFloatLess(*pSpace, minSpace)) - { - if (_myCGFloatGreat(*pSpace, maxSpace)) - *pSpace = maxSpace; - if (_myCGFloatLess(*pSpace, minSpace)) - *pSpace = minSpace; - - subviewSize = (selfSize - (*pSpace) * (rowCount - 1)) / rowCount; - } - } - } - - return subviewSize; -} - -(void)myLayout:(MyFloatLayoutViewSizeClass*)lsc calcSizeOfSubviews:(NSArray*)sbs selfSize:(CGSize)selfSize @@ -393,8 +386,6 @@ -(CGSize)myVertOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - CGFloat paddingHorz = paddingLeading + paddingTrailing; - // CGFloat paddingVert = paddingTop + paddingBottom; //如果没有边界限制我们将宽度设置为最大。。 BOOL isBeyondFlag = NO; //子视图是否超出剩余空间需要换行。 @@ -407,8 +398,9 @@ -(CGSize)myVertOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv //支持浮动水平间距。 CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = [self myLayout:lsc calcMaxMinSubviewSizeWithSelfSize:selfSize.width - paddingHorz space:&horzSpace]; - + CGFloat subviewSize = [lsc.flexSpace calcMaxMinSubviewSizeForContent:selfSize.width startPadding:&paddingLeading endPadding:&paddingTrailing space:&horzSpace]; + CGFloat paddingHorz = paddingLeading + paddingTrailing; + //设置子视图的宽度和高度。 [self myLayout:lsc calcSizeOfSubviews:sbs selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing subviewSize:subviewSize isWidth:YES]; @@ -871,8 +863,6 @@ -(CGSize)myHorzOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - // CGFloat paddingHorz = paddingLeading + paddingTrailing; - CGFloat paddingVert = paddingTop + paddingBottom; //如果没有边界限制我们将高度设置为最大。。 BOOL isBeyondFlag = NO; //子视图是否超出剩余空间需要换行。 @@ -885,8 +875,9 @@ -(CGSize)myHorzOrientationLayout:(MyFloatLayoutViewSizeClass*)lsc calcRectOfSubv //支持浮动垂直间距。 CGFloat horzSpace = lsc.subviewHSpace; CGFloat vertSpace = lsc.subviewVSpace; - CGFloat subviewSize = [self myLayout:lsc calcMaxMinSubviewSizeWithSelfSize:selfSize.height - paddingVert space:&vertSpace]; - + CGFloat subviewSize = [lsc.flexSpace calcMaxMinSubviewSizeForContent:selfSize.height startPadding:&paddingTop endPadding:&paddingBottom space:&vertSpace]; + CGFloat paddingVert = paddingTop + paddingBottom; + //设置子视图的宽度和高度。 [self myLayout:lsc calcSizeOfSubviews:sbs selfSize:selfSize paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing subviewSize:subviewSize isWidth:NO]; diff --git a/MyLayout/Lib/MyFlowLayout.h b/MyLayout/Lib/MyFlowLayout.h index eebf3c6..d0631df 100644 --- a/MyLayout/Lib/MyFlowLayout.h +++ b/MyLayout/Lib/MyFlowLayout.h @@ -214,7 +214,7 @@ MyGravity_Horz_Right 右边对齐 MyGravity_Horz_Fill 两端对齐 MyGravity_Horz_Stretch 如果子视图未设置约束或者非布局子视图宽度自适应则子视图宽度被拉伸 - MyGravity_Horz_Between 数量约束垂直流式布局有效,子视图会紧凑进行排列,当设置为这个属性值时,子视图的x轴的位置总是从对应行的上一列的结尾开始,而不是上一列的最宽位置开始。 + MyGravity_Horz_Between 数量约束水平流式布局有效,子视图会紧凑进行排列,当设置为这个属性值时,子视图的x轴的位置总是从对应行的上一列的结尾开始,而不是上一列的最宽位置开始。 MyGravity_Horz_Around 如果列内子视图没有设置宽度约束,则子视图的宽度填充整行,否则按子视图的宽度是宽度约束决定。 @endcode @note 如果您想单独设置某个子视图在行内的对齐方式则请使用子视图的扩展属性alignment。 @@ -222,6 +222,18 @@ */ @property(nonatomic,assign) MyGravity arrangedGravity; +/** +指定流式布局最后一行的尺寸或间距的拉伸策略。默认值是MyGravityPolicy_No,表示最后一行的尺寸或间接拉伸策略不生效。如果布局只有一行则不会受到这个策略的影响。 +在流式布局中我们可以通过gravity属性来对每一行的尺寸或间距进行拉伸处理。但是在实际情况中最后一行的子视图数量可能会小于等于前面行的数量。 +在这种情况下如果对最后一行进行相同的尺寸或间距的拉伸处理则有可能会影响整体的布局效果。因此我们可通过这个属性来指定最后一行的尺寸或间距的生效策略。 +这个策略在不同的流式布局中效果不一样: + +1.在数量约束布局中如果最后一行的子视图数量小于arrangedCount的值时,那么当我们使用gravity来对行内视图进间距拉伸时(between,around,among) +可以指定三种策略:no表示最后一行不进行任何间距拉伸处理,always表示最后一行总是进行间距拉伸处理,auto表示最后一行的每个子视图都和上一行对应位置视图左对齐。 + +2.在内容约束布局中因为每行的子视图数量不固定,所以只有no和always两种策略有效,并且这两种策略不仅影响子视图的尺寸的拉伸(fill,stretch)还影响间距的拉伸效果(between,around,among)。 + */ +@property(nonatomic, assign) MyGravityPolicy lastlineGravityPolicy; /** @@ -265,5 +277,17 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace inSizeClass:(MySizeClass)sizeClass; +/** + 上面函数的加强版本。 + + @param subviewSize 指定子视图的尺寸 + @param minSpace 指定子视图之间的最小间距 + @param maxSpace 指定子视图之间的最大间距 + @param isCenter 指定是否所有子视图居中 + */ +-(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace centered:(BOOL)centered; +-(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace centered:(BOOL)centered inSizeClass:(MySizeClass)sizeClass; + + @end diff --git a/MyLayout/Lib/MyFlowLayout.m b/MyLayout/Lib/MyFlowLayout.m index f9aae10..455fd2c 100644 --- a/MyLayout/Lib/MyFlowLayout.m +++ b/MyLayout/Lib/MyFlowLayout.m @@ -113,6 +113,21 @@ -(MyGravity)arrangedGravity return self.myCurrentSizeClass.arrangedGravity; } +-(MyGravityPolicy)lastlineGravityPolicy +{ + return self.myCurrentSizeClass.lastlineGravityPolicy; +} + +-(void)setLastlineGravityPolicy:(MyGravityPolicy)lastlineGravityPolicy +{ + MyFlowLayout *lsc = self.myCurrentSizeClass; + if (lsc.lastlineGravityPolicy != lastlineGravityPolicy) + { + lsc.lastlineGravityPolicy = lastlineGravityPolicy; + [self setNeedsLayout]; + } +} + -(BOOL)isFlex { return self.myCurrentSizeClass.isFlex; @@ -124,6 +139,10 @@ -(void)setIsFlex:(BOOL)isFlex if (lsc.isFlex != isFlex) { lsc.isFlex = isFlex; + if (isFlex) + lsc.lastlineGravityPolicy = MyGravityPolicy_Always; + else + lsc.lastlineGravityPolicy = MyGravityPolicy_No; [self setNeedsLayout]; } } @@ -135,10 +154,31 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace: -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace inSizeClass:(MySizeClass)sizeClass { - MyFlowLayoutViewSizeClass *lsc = (MyFlowLayoutViewSizeClass*)[self fetchLayoutSizeClass:sizeClass]; - lsc.subviewSize = subviewSize; - lsc.maxSpace = maxSpace; - lsc.minSpace = minSpace; + [self setSubviewsSize:subviewSize minSpace:minSpace maxSpace:maxSpace centered:NO inSizeClass:sizeClass]; +} + +-(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace centered:(BOOL)centered +{ + [self setSubviewsSize:subviewSize minSpace:minSpace maxSpace:maxSpace centered:centered inSizeClass:MySizeClass_hAny | MySizeClass_wAny]; +} + +-(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace centered:(BOOL)centered inSizeClass:(MySizeClass)sizeClass +{ + MySequentLayoutViewSizeClass *lsc = (MySequentLayoutViewSizeClass*)[self fetchLayoutSizeClass:sizeClass]; + if (subviewSize == 0) + { + lsc.flexSpace = nil; + } + else + { + if (lsc.flexSpace == nil) + lsc.flexSpace = [MySequentLayoutFlexSpace new]; + + lsc.flexSpace.subviewSize = subviewSize; + lsc.flexSpace.minSpace = minSpace; + lsc.flexSpace.maxSpace = maxSpace; + lsc.flexSpace.centered = centered; + } [self setNeedsLayout]; } @@ -168,7 +208,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( (gravity & MyGravity_Vert_Mask) == MyGravity_Horz_Fill ) { if ([sbvsc.view isKindOfClass:[MyBaseLayout class]]) - [sbvsc.widthSizeInner __setActive:NO]; + [sbvsc.widthSizeInner __equalTo:nil]; } } @@ -181,7 +221,7 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( (gravity & MyGravity_Horz_Mask) == MyGravity_Vert_Fill) { if ([sbvsc.view isKindOfClass:[MyBaseLayout class]]) - [sbvsc.heightSizeInner __setActive:NO]; + [sbvsc.heightSizeInner __equalTo:nil]; } } }]; @@ -294,11 +334,17 @@ - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc adjustSingleline:(NSInteger lineHorzGravity = horzGravity; } - CGFloat addXFill = 0; + //只有最后一行,并且数量小于arrangedCount,并且不是第一行才应用策略。 + BOOL applyLastlineGravityPolicy = ((startItemIndex + count) == sbs.count && + count != lsc.arrangedCount && + startItemIndex != 0 && + lineHorzGravity == MyGravity_Horz_Fill); + + + CGFloat addXFill = 0.0; if (lineHorzGravity == MyGravity_Horz_Fill && lineTotalWeight == 0.0) { - //流式布局中最后一行不会进行拉伸处理。 - if (lsc.isFlex || (startItemIndex + count) != sbs.count) + if (!applyLastlineGravityPolicy || lsc.lastlineGravityPolicy == MyGravityPolicy_Always) addXFill = lineSpareWidth / count; } else @@ -347,11 +393,17 @@ - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc adjustSingleline:(NSInteger lineVertGravity = vertGravity; } + //只有最后一行,并且数量小于arrangedCount,并且不是第一行才应用策略。 + BOOL applyLastlineGravityPolicy = ((startItemIndex + count) == sbs.count && + count != lsc.arrangedCount && + startItemIndex != 0 && + lineVertGravity == MyGravity_Vert_Fill); + + CGFloat addYFill = 0; if (lineVertGravity == MyGravity_Vert_Fill && lineTotalWeight == 0.0) { - //流式布局中最后一行不会进行拉伸处理。 - if (lsc.isFlex || (startItemIndex + count) != sbs.count) + if (!applyLastlineGravityPolicy || lsc.lastlineGravityPolicy == MyGravityPolicy_Always) addYFill = lineSpareHeight / count; } else @@ -445,15 +497,11 @@ - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSinglelineShrink:(CGFlo } -- (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)lineIndex vertAlignment:(MyGravity)vertAlignment horzGravity:(MyGravity)horzGravity lineMaxHeight:(CGFloat)lineMaxHeight lineMaxWidth:(CGFloat)lineMaxWidth lineTotalShrink:(CGFloat)lineTotalShrink sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate inSelfSize:(CGSize)selfSize +- (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)lineIndex vertAlignment:(MyGravity)vertAlignment horzGravity:(MyGravity)horzGravity lineMaxHeight:(CGFloat)lineMaxHeight lineMaxWidth:(CGFloat)lineMaxWidth lineTotalShrink:(CGFloat)lineTotalShrink sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate inSelfSize:(CGSize)selfSize paddingHorz:(CGFloat)paddingHorz { if (count == 0) return; - CGFloat paddingLeading = lsc.myLayoutLeadingPadding; - CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - CGFloat paddingHorz = paddingLeading + paddingTrailing; - CGFloat lineSpareWidth = selfSize.width - lineMaxWidth - paddingHorz; if (_myCGFloatGreatOrEqual(lineSpareWidth, 0.0)) lineTotalShrink = 0.0; @@ -462,8 +510,8 @@ - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l lineMaxWidth = selfSize.width - paddingHorz; //计算每行的gravity情况。 - CGFloat addXPos = 0; //多出来的空隙区域,用于停靠处理。 - CGFloat addXFill = 0; //多出来的平均区域,用于拉伸间距或者尺寸 + CGFloat addXPos = 0.0; //多出来的空隙区域,用于停靠处理。 + CGFloat addXPosInc = 0.0; MyGravity lineHorzGravity = horzGravity; MyGravity lineVertAlignment = vertAlignment; @@ -481,6 +529,12 @@ - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l lineVertAlignment = vertAlignment; } + //只有最后一行,并且数量小于arrangedCount,并且不是第一行才应用策略。 + BOOL applyLastlineGravityPolicy = ((startItemIndex + count) == sbs.count && + count != lsc.arrangedCount && + startItemIndex != 0 && + (lineHorzGravity == MyGravity_Horz_Between || lineHorzGravity == MyGravity_Horz_Around || lineHorzGravity == MyGravity_Horz_Among)); + switch (lineHorzGravity) { case MyGravity_Horz_Center: @@ -495,24 +549,32 @@ - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l break; case MyGravity_Horz_Between: { - //总宽度减去最大的宽度。再除以数量表示每个应该扩展的空间。最后一行无效(如果最后一行的数量和其他行的数量一样以及总共就只有一行除外)。 - if ((lsc.isFlex || (startItemIndex + count) != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) - { - addXFill = (selfSize.width - paddingHorz - lineMaxWidth) / (count - 1); + if (count > 1 && (!applyLastlineGravityPolicy || lsc.lastlineGravityPolicy == MyGravityPolicy_Always)) { + addXPosInc = (selfSize.width - paddingHorz - lineMaxWidth)/(count - 1); } } break; case MyGravity_Horz_Around: { - //多于一个拉伸间距,只有一个则居中处理。 - if (count > 1) - { - addXFill = (selfSize.width - paddingHorz - lineMaxWidth) / count; - addXPos = addXFill / 2.0; + if (!applyLastlineGravityPolicy || lsc.lastlineGravityPolicy == MyGravityPolicy_Always) { + if (count > 1) { + addXPosInc = (selfSize.width - paddingHorz - lineMaxWidth) / count; + addXPos = addXPosInc / 2.0; + } else { + addXPos = (selfSize.width - paddingHorz - lineMaxWidth) / 2.0; + } } - else - { - addXPos = (selfSize.width - paddingHorz - lineMaxWidth) / 2; + } + break; + case MyGravity_Horz_Among: + { + if (!applyLastlineGravityPolicy || lsc.lastlineGravityPolicy == MyGravityPolicy_Always) { + if (count > 1) { + addXPosInc = (selfSize.width - paddingHorz - lineMaxWidth) / (count + 1); + addXPos = addXPosInc; + } else { + addXPos = (selfSize.width - paddingHorz - lineMaxWidth) / 2.0; + } } } break; @@ -581,7 +643,7 @@ - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l sbvVertAlignment = MyGravity_Vert_Top; } - if ((sbvVertAlignment != MyGravity_None && sbvVertAlignment != MyGravity_Vert_Top) || _myCGFloatNotEqual(addXPos, 0.0) || _myCGFloatNotEqual(addXFill, 0.0) || lineTotalShrink != 0.0) + if ((sbvVertAlignment != MyGravity_None && sbvVertAlignment != MyGravity_Vert_Top) || _myCGFloatNotEqual(addXPos, 0.0) || _myCGFloatNotEqual(addXPosInc, 0.0) || applyLastlineGravityPolicy || lineTotalShrink != 0.0) { sbvmyFrame.leading += addXPos; @@ -598,14 +660,10 @@ - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l totalShrinkSize += (sbvsc.trailingPosInner.shrink / lineTotalShrink) * lineSpareWidth; } - //内容约束布局并且是填充尺寸或者拉升尺寸。 - if (addXFill != 0.0) - { - if ( lineHorzGravity != MyGravity_Horz_Fill) - { - //其他的只拉伸间距 - sbvmyFrame.leading += addXFill * (itemIndex - startItemIndex); - } + sbvmyFrame.leading += addXPosInc * (itemIndex - startItemIndex); + if (applyLastlineGravityPolicy && lsc.lastlineGravityPolicy == MyGravityPolicy_Auto) { + //对齐前一行对应位置的 + sbvmyFrame.leading = sbs[itemIndex - lsc.arrangedCount].myFrame.leading; } switch (sbvVertAlignment) { @@ -647,15 +705,11 @@ - (void)myVertLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l } } -- (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)lineIndex horzAlignment:(MyGravity)horzAlignment vertGravity:(MyGravity)vertGravity lineMaxWidth:(CGFloat)lineMaxWidth lineMaxHeight:(CGFloat)lineMaxHeight lineTotalShrink:(CGFloat)lineTotalShrink sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate inSelfSize:(CGSize)selfSize +- (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)lineIndex horzAlignment:(MyGravity)horzAlignment vertGravity:(MyGravity)vertGravity lineMaxWidth:(CGFloat)lineMaxWidth lineMaxHeight:(CGFloat)lineMaxHeight lineTotalShrink:(CGFloat)lineTotalShrink sbs:(NSArray *)sbs startItemIndex:(NSInteger)startItemIndex count:(NSInteger)count vertSpace:(CGFloat)vertSpace horzSpace:(CGFloat)horzSpace isEstimate:(BOOL)isEstimate inSelfSize:(CGSize)selfSize paddingVert:(CGFloat)paddingVert { if (count == 0) return; - CGFloat paddingTop = lsc.myLayoutTopPadding; - CGFloat paddingBottom = lsc.myLayoutBottomPadding; - CGFloat paddingVert = paddingTop + paddingBottom; - CGFloat lineSpareHeight = selfSize.height - lineMaxHeight - paddingVert; if (_myCGFloatGreatOrEqual(lineSpareHeight, 0.0)) lineTotalShrink = 0.0; @@ -665,7 +719,7 @@ - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l //计算每行的gravity情况。 CGFloat addYPos = 0; - CGFloat addYFill = 0; + CGFloat addYPosInc = 0; MyGravity lineHorzAlignment = horzAlignment; MyGravity lineVertGravity = vertGravity; if (self.lineGravity != nil) @@ -682,6 +736,13 @@ - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l lineVertGravity = vertGravity; } + //只有最后一行,并且数量小于arrangedCount,并且不是第一行才应用策略。 + BOOL applyLastlineGravityPolicy = ((startItemIndex + count) == sbs.count && + count != lsc.arrangedCount && + startItemIndex != 0 && + (lineVertGravity == MyGravity_Vert_Between || lineVertGravity == MyGravity_Vert_Around || lineVertGravity == MyGravity_Vert_Among)); + + switch (lineVertGravity) { case MyGravity_Vert_Center: @@ -696,23 +757,32 @@ - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l break; case MyGravity_Vert_Between: { - //总高度减去最大的高度。再除以数量表示每个应该扩展的空间。最后一列无效(如果最后一列的数量和其他列的数量一样以及总共就只有一列除外)。 - if ((lsc.isFlex || (startItemIndex + count) != sbs.count || count == lsc.arrangedCount || sbs.count == count) && count > 1) - { - addYFill = (selfSize.height - paddingVert - lineMaxHeight) / (count - 1); + if (count > 1 && (!applyLastlineGravityPolicy || lsc.lastlineGravityPolicy == MyGravityPolicy_Always)) { + addYPosInc = (selfSize.height - paddingVert - lineMaxHeight) / (count - 1); } } break; case MyGravity_Vert_Around: { - if (count > 1) - { - addYFill = (selfSize.height - paddingVert - lineMaxHeight) / count; - addYPos = addYFill / 2.0; + if (!applyLastlineGravityPolicy || lsc.lastlineGravityPolicy == MyGravityPolicy_Always) { + if (count > 1) { + addYPosInc = (selfSize.height - paddingVert - lineMaxHeight) / count; + addYPos = addYPosInc / 2.0; + } else { + addYPos = (selfSize.height - paddingVert - lineMaxHeight) / 2.0; + } } - else - { - addYPos = (selfSize.height - paddingVert - lineMaxHeight) / 2; + } + break; + case MyGravity_Vert_Among: + { + if (!applyLastlineGravityPolicy || lsc.lastlineGravityPolicy == MyGravityPolicy_Always) { + if (count > 1) { + addYPosInc = (selfSize.height - paddingVert - lineMaxHeight) / (count + 1); + addYPos = addYPosInc; + } else { + addYPos = (selfSize.height - paddingVert - lineMaxHeight) / 2.0; + } } } break; @@ -773,7 +843,7 @@ - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l if (horzAlignment == MyGravity_Horz_Between) sbvHorzAlignment = MyGravity_None; - if ((sbvHorzAlignment != MyGravity_None && sbvHorzAlignment != MyGravity_Horz_Leading) || _myCGFloatNotEqual(addYPos, 0.0) || _myCGFloatNotEqual(addYFill, 0.0) || lineTotalShrink != 0.0) + if ((sbvHorzAlignment != MyGravity_None && sbvHorzAlignment != MyGravity_Horz_Leading) || _myCGFloatNotEqual(addYPos, 0.0) || _myCGFloatNotEqual(addYPosInc, 0.0) || applyLastlineGravityPolicy || lineTotalShrink != 0.0) { sbvmyFrame.top += addYPos; @@ -789,14 +859,10 @@ - (void)myHorzLayout:(MyFlowLayoutViewSizeClass*)lsc calcSingleline:(NSInteger)l totalShrinkSize += (sbvsc.bottomPosInner.shrink / lineTotalShrink) * lineSpareHeight; } - //内容约束布局并且是填充尺寸或者拉升尺寸。 - if (addYFill != 0.0) - { - if (lineVertGravity != MyGravity_Vert_Fill) - { - //只拉伸间距 - sbvmyFrame.top += addYFill * (itemIndex - startItemIndex); - } + sbvmyFrame.top += addYPosInc * (itemIndex - startItemIndex); + if (applyLastlineGravityPolicy && lsc.lastlineGravityPolicy == MyGravityPolicy_Auto) { + //对齐前一行对应位置的 + sbvmyFrame.top = sbs[itemIndex - lsc.arrangedCount].myFrame.top; } switch (sbvHorzAlignment) { @@ -917,59 +983,6 @@ -(void)myCalcAutoArrangeSinglelineSubviews:(NSMutableArray*)sbs } } --(CGFloat)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcMaxMinSubviewSizeForContent:(CGFloat)selfSize space:(CGFloat*)pSpace -{ - CGFloat subviewSize = lsc.subviewSize; - if (subviewSize != 0) - { - CGFloat minSpace = lsc.minSpace; - CGFloat maxSpace = lsc.maxSpace; - - NSInteger rowCount = floor((selfSize + minSpace) / (subviewSize + minSpace)); - if (rowCount > 1) - { - *pSpace = (selfSize - subviewSize * rowCount)/(rowCount - 1); - if (_myCGFloatGreat(*pSpace, maxSpace) || _myCGFloatLess(*pSpace, minSpace)) - { - if (_myCGFloatGreat(*pSpace, maxSpace)) - *pSpace = maxSpace; - if (_myCGFloatLess(*pSpace, minSpace)) - *pSpace = minSpace; - - subviewSize = (selfSize - (*pSpace) * (rowCount - 1)) / rowCount; - } - } - } - - return subviewSize; -} - - --(CGFloat)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcMaxMinSubviewSize:(CGFloat)selfSize arrangedCount:(NSInteger)arrangedCount space:(CGFloat*)pSpace -{ - CGFloat subviewSize = lsc.subviewSize; - if (subviewSize != 0) - { - CGFloat maxSpace = lsc.maxSpace; - CGFloat minSpace = lsc.minSpace; - if (arrangedCount > 1) - { - *pSpace = (selfSize - subviewSize * arrangedCount)/(arrangedCount - 1); - if (_myCGFloatGreat(*pSpace, maxSpace) || _myCGFloatLess(*pSpace, minSpace)) - { - if (_myCGFloatGreat(*pSpace, maxSpace)) - *pSpace = maxSpace; - if (_myCGFloatLess(*pSpace, minSpace)) - *pSpace = minSpace; - - subviewSize = (selfSize - (*pSpace) * (arrangedCount - 1)) / arrangedCount; - } - } - } - - return subviewSize; -} - -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationContent:(CGSize)selfSize sbs:(NSMutableArray*)sbs isEstimate:(BOOL)isEstimate { @@ -977,9 +990,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - CGFloat paddingHorz = paddingLeading + paddingTrailing; - CGFloat paddingVert = paddingTop + paddingBottom; - + MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; MyGravity vertAlignment = lsc.arrangedGravity & MyGravity_Horz_Mask; @@ -987,8 +998,10 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont //支持浮动水平间距。 CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = [self myLayout:lsc calcMaxMinSubviewSizeForContent:selfSize.width - paddingHorz space:&horzSpace]; + CGFloat subviewSize = [lsc.flexSpace calcMaxMinSubviewSizeForContent:selfSize.width startPadding:&paddingLeading endPadding:&paddingTrailing space:&horzSpace]; + CGFloat paddingHorz = paddingLeading + paddingTrailing; + CGFloat paddingVert = paddingTop + paddingBottom; CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; CGFloat lineMaxHeight = 0.0; //某一行的最高值。 @@ -1214,7 +1227,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont yPos += vertSpace; yPos += lineMaxHeight; - [self myVertLayout:lsc calcSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; + [self myVertLayout:lsc calcSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize paddingHorz:paddingHorz]; lineMaxHeight = 0.0; lineMaxWidth = 0.0; @@ -1257,7 +1270,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont lineMaxHeight = selfSize.height - paddingVert; //最后一行 - [self myVertLayout:lsc calcSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; + [self myVertLayout:lsc calcSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize paddingHorz:paddingHorz]; //整体的停靠 if (vertGravity != MyGravity_None && selfSize.height != yPos) @@ -1269,6 +1282,9 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont CGFloat between = 0.0; CGFloat fill = 0.0; + if (arranges <= 1 && vertGravity == MyGravity_Vert_Around) + vertGravity = MyGravity_Vert_Center; + if (vertGravity == MyGravity_Vert_Center) { addYPos = (selfSize.height - yPos) / 2; @@ -1279,7 +1295,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont } else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) { - if (lineFirstSubviewIndexSet.count > 0) + if (arranges > 0) fill = (selfSize.height - yPos) / arranges; //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' @@ -1288,13 +1304,16 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont } else if (vertGravity == MyGravity_Vert_Between) { - if (lineFirstSubviewIndexSet.count > 1) + if (arranges > 1) between = (selfSize.height - yPos) / (arranges - 1); } else if (vertGravity == MyGravity_Vert_Around) { - if (lineFirstSubviewIndexSet.count > 1) - between = (selfSize.height - yPos) / arranges; + between = (selfSize.height - yPos) / arranges; + } + else if (vertGravity == MyGravity_Vert_Among) + { + between = (selfSize.height - yPos) / (arranges + 1); } if (addYPos != 0.0 || between != 0.0 || fill != 0.0) @@ -1349,6 +1368,9 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientationCont if (vertGravity == MyGravity_Vert_Around) sbvmyFrame.top += (between / 2.0); + + if (vertGravity == MyGravity_Vert_Among) + sbvmyFrame.top += between; } } } @@ -1364,8 +1386,6 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - CGFloat paddingHorz = paddingLeading + paddingTrailing; - CGFloat paddingVert = paddingTop + paddingBottom; BOOL autoArrange = lsc.autoArrange; NSInteger arrangedCount = lsc.arrangedCount; @@ -1376,7 +1396,10 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = [self myLayout:lsc calcMaxMinSubviewSize:selfSize.width - paddingHorz arrangedCount:arrangedCount space:&horzSpace]; + CGFloat subviewSize = [lsc.flexSpace calcMaxMinSubviewSize:selfSize.width arrangedCount:arrangedCount startPadding:&paddingLeading endPadding:&paddingTrailing space:&horzSpace]; + + CGFloat paddingHorz = paddingLeading + paddingTrailing; + CGFloat paddingVert = paddingTop + paddingBottom; CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; @@ -1625,7 +1648,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG yPos += vertSpace; yPos += lineMaxHeight; - [self myVertLayout:lsc calcSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; + [self myVertLayout:lsc calcSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize paddingHorz:paddingHorz]; //分别处理水平分页和垂直分页。 if (isHorzPaging) @@ -1816,7 +1839,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG lineMaxHeight = selfSize.height - paddingVert; //最后一行,有可能因为行宽的压缩导致那些高度依赖宽度以及高度自适应的视图会增加高度,从而使得行高被调整。 - [self myVertLayout:lsc calcSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; + [self myVertLayout:lsc calcSingleline:lineIndex vertAlignment:vertAlignment horzGravity:horzGravity lineMaxHeight:lineMaxHeight lineMaxWidth:lineMaxWidth lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize paddingHorz:paddingHorz]; //整体的停靠 @@ -1829,6 +1852,9 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG CGFloat between = 0.0; CGFloat fill = 0.0; + if (arranges <= 1 && vertGravity == MyGravity_Vert_Around) + vertGravity = MyGravity_Vert_Center; + if (vertGravity == MyGravity_Vert_Center) { addYPos = (selfSize.height - maxHeight) / 2; @@ -1853,8 +1879,11 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG } else if (vertGravity == MyGravity_Vert_Around) { - if (arranges > 1) - between = (selfSize.height - maxHeight) / arranges; + between = (selfSize.height - maxHeight) / arranges; + } + else if (vertGravity == MyGravity_Vert_Among) + { + between = (selfSize.height - maxHeight) / (arranges + 1); } if (addYPos != 0.0 || between != 0.0 || fill != 0.0) @@ -1900,6 +1929,9 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForVertOrientation:(CG //如果是vert_around那么所有行都应该添加一半的between值。 if (vertGravity == MyGravity_Vert_Around) sbvmyFrame.top += (between / 2.0); + + if (vertGravity == MyGravity_Vert_Among) + sbvmyFrame.top += between; } } } @@ -1929,8 +1961,6 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - CGFloat paddingVert = paddingTop + paddingBottom; - CGFloat paddingHorz = paddingLeading + paddingTrailing; MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; @@ -1940,8 +1970,11 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont //支持浮动垂直间距。 CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = [self myLayout:lsc calcMaxMinSubviewSizeForContent:selfSize.height - paddingVert space:&vertSpace]; + CGFloat subviewSize = [lsc.flexSpace calcMaxMinSubviewSizeForContent:selfSize.height startPadding:&paddingTop endPadding:&paddingBottom space:&vertSpace]; + CGFloat paddingVert = paddingTop + paddingBottom; + CGFloat paddingHorz = paddingLeading + paddingTrailing; + CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; CGFloat lineMaxWidth = 0.0; //某一列的最宽值。 @@ -2178,7 +2211,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont xPos += horzSpace; xPos += lineMaxWidth; - [self myHorzLayout:lsc calcSingleline:lineIndex horzAlignment:horzAlign vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; + [self myHorzLayout:lsc calcSingleline:lineIndex horzAlignment:horzAlign vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize paddingVert:paddingVert]; lineMaxWidth = 0.0; @@ -2220,7 +2253,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont lineMaxWidth = selfSize.width - paddingHorz; //最后一行 - [self myHorzLayout:lsc calcSingleline:lineIndex horzAlignment:horzAlign vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; + [self myHorzLayout:lsc calcSingleline:lineIndex horzAlignment:horzAlign vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:0 sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize paddingVert:paddingVert]; //整体的停靠 if (horzGravity != MyGravity_None && selfSize.width != xPos) @@ -2231,6 +2264,10 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont CGFloat addXPos = 0.0; CGFloat fill = 0.0; CGFloat between = 0.0; + + if (arranges <= 1 && horzGravity == MyGravity_Horz_Around) + horzGravity = MyGravity_Horz_Center; + if (horzGravity == MyGravity_Horz_Center) { addXPos = (selfSize.width - xPos) / 2; @@ -2241,8 +2278,8 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont } else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) { - if (lineFirstSubviewIndexSet.count > 0) - fill = (selfSize.width - xPos) / lineFirstSubviewIndexSet.count; + if (arranges > 0) + fill = (selfSize.width - xPos) / arranges; //满足flex规则:如果剩余的空间是负数,该值等效于'flex-start' if (fill < 0.0 && horzGravity == MyGravity_Horz_Stretch) @@ -2250,13 +2287,16 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont } else if (horzGravity == MyGravity_Horz_Between) { - if (lineFirstSubviewIndexSet.count > 1) - between = (selfSize.width - xPos) / (lineFirstSubviewIndexSet.count - 1); + if (arranges > 1) + between = (selfSize.width - xPos) / (arranges - 1); } else if (horzGravity == MyGravity_Horz_Around) { - if (lineFirstSubviewIndexSet.count > 1) - between = (selfSize.width - xPos) / lineFirstSubviewIndexSet.count; + between = (selfSize.width - xPos) / arranges; + } + else if (horzGravity == MyGravity_Horz_Among) + { + between = (selfSize.width - xPos) / (arranges + 1); } if (addXPos != 0.0 || between != 0.0 || fill != 0.0) @@ -2309,6 +2349,9 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientationCont if (horzGravity == MyGravity_Horz_Around) sbvmyFrame.leading += (between / 2.0); + + if (horzGravity == MyGravity_Horz_Among) + sbvmyFrame.leading += between; } } } @@ -2325,8 +2368,6 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - CGFloat paddingHorz = paddingLeading + paddingTrailing; - CGFloat paddingVert = paddingTop + paddingBottom; BOOL autoArrange = lsc.autoArrange; NSInteger arrangedCount = lsc.arrangedCount; @@ -2337,8 +2378,11 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG CGFloat vertSpace = lsc.subviewVSpace; CGFloat horzSpace = lsc.subviewHSpace; - CGFloat subviewSize = [self myLayout:lsc calcMaxMinSubviewSize:selfSize.height - paddingVert arrangedCount:arrangedCount space:&vertSpace]; + CGFloat subviewSize = [lsc.flexSpace calcMaxMinSubviewSize:selfSize.height arrangedCount:arrangedCount startPadding:&paddingTop endPadding:&paddingBottom space:&vertSpace]; + CGFloat paddingHorz = paddingLeading + paddingTrailing; + CGFloat paddingVert = paddingTop + paddingBottom; + CGFloat xPos = paddingLeading; CGFloat yPos = paddingTop; CGFloat lineMaxWidth = 0.0; //每一列的最大宽度 @@ -2608,7 +2652,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG xPos += horzSpace; xPos += lineMaxWidth; - [self myHorzLayout:lsc calcSingleline:lineIndex horzAlignment:horzAlignment vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; + [self myHorzLayout:lsc calcSingleline:lineIndex horzAlignment:horzAlignment vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - arrangedCount count:arrangedCount vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize paddingVert:paddingVert]; //分别处理水平分页和垂直分页。 @@ -2760,7 +2804,7 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG lineMaxWidth = selfSize.width - paddingHorz; //最后一行 - [self myHorzLayout:lsc calcSingleline:lineIndex horzAlignment:horzAlignment vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize]; + [self myHorzLayout:lsc calcSingleline:lineIndex horzAlignment:horzAlignment vertGravity:vertGravity lineMaxWidth:lineMaxWidth lineMaxHeight:lineMaxHeight lineTotalShrink:lineTotalShrink sbs:sbs startItemIndex:i - itemIndex count:itemIndex vertSpace:vertSpace horzSpace:horzSpace isEstimate:isEstimate inSelfSize:selfSize paddingVert:paddingVert]; //整体的停靠。 if (horzGravity != MyGravity_None && selfSize.width != maxWidth && !(isHorzPaging && isPagingScroll)) @@ -2773,6 +2817,9 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG CGFloat between = 0.0; CGFloat fill = 0.0; + if (arranges <= 1 && horzGravity == MyGravity_Horz_Around) + horzGravity = MyGravity_Horz_Center; + if (horzGravity == MyGravity_Horz_Center) { addXPos = (selfSize.width - maxWidth) / 2; @@ -2797,8 +2844,11 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG } else if (horzGravity == MyGravity_Horz_Around) { - if (arranges > 1) - between = (selfSize.width - maxWidth) / arranges; + between = (selfSize.width - maxWidth) / arranges; + } + else if (horzGravity == MyGravity_Horz_Among) + { + between = (selfSize.width - maxWidth) / (arranges + 1); } if (addXPos != 0.0 || between != 0.0 || fill != 0.0) @@ -2843,6 +2893,9 @@ -(CGSize)myLayout:(MyFlowLayoutViewSizeClass*)lsc calcSizeForHorzOrientation:(CG if (horzGravity == MyGravity_Horz_Around) sbvmyFrame.leading += (between / 2.0); + + if (horzGravity == MyGravity_Horz_Among) + sbvmyFrame.leading += between; } } } diff --git a/MyLayout/Lib/MyLayout.h b/MyLayout/Lib/MyLayout.h index 166d13d..7603efb 100644 --- a/MyLayout/Lib/MyLayout.h +++ b/MyLayout/Lib/MyLayout.h @@ -37,7 +37,7 @@ */ -//Current version is 1.9.0, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.9.1, please open: https://github.com/youngsoft/MyLinearLayout/blob/master/CHANGELOG.md to show the changes. #ifndef MyLayout_MyLayout_h diff --git a/MyLayout/Lib/MyLayoutDef.h b/MyLayout/Lib/MyLayoutDef.h index 8bef1cd..bf590a6 100644 --- a/MyLayout/Lib/MyLayoutDef.h +++ b/MyLayout/Lib/MyLayoutDef.h @@ -78,14 +78,16 @@ typedef enum : unsigned short { MyGravity_Horz_Right = 4, /**窗口水平中心停靠,表示在屏幕窗口的水平中心停靠*/ MyGravity_Horz_Window_Center = 8, - /**水平间距拉伸*/ + /**水平间距拉伸,并且头尾部分的间距是0, 如果只有一个子视图则变为左边停靠*/ MyGravity_Horz_Between = 16, /**头部对齐,对于阿拉伯国家来说是和Right等价的,对于非阿拉伯国家则是和Left等价的*/ MyGravity_Horz_Leading = 32, /**尾部对齐,对于阿拉伯国家来说是和Left等价的,对于非阿拉伯国家则是和Right等价的*/ MyGravity_Horz_Trailing = 64, - /**水平间距拉伸,并且头尾部分为其他部分间距的一半,如果只有一个子视图则变为水平居中停靠*/ + /**水平间距环绕拉伸,并且头尾部分为其他部分间距的一半,如果只有一个子视图则变为水平居中停靠*/ MyGravity_Horz_Around = 128, + /**水平间距等分拉伸,并且头尾部分和其他部分间距的一样, 如果只有一个子视图则变为水平居中停靠*/ + MyGravity_Horz_Among = MyGravity_Horz_Between | MyGravity_Horz_Around, /**水平宽度填充*/ MyGravity_Horz_Fill = MyGravity_Horz_Left | MyGravity_Horz_Center | MyGravity_Horz_Right, /**水平宽度拉伸,它跟宽度填充的区别是如果子视图指定了宽度(非布局子视图宽度自适应除外)则不会被拉伸*/ @@ -102,12 +104,14 @@ typedef enum : unsigned short { MyGravity_Vert_Bottom = 4 << 8, /**窗口垂直中心停靠,表示在屏幕窗口的垂直中心停靠*/ MyGravity_Vert_Window_Center = 8 << 8, - /**垂直间距拉伸*/ + /**垂直间距拉伸,并且头尾部分的间距是0, 如果只有一个子视图则变为上边停靠*/ MyGravity_Vert_Between = 16 << 8, /**基线对齐,只支持水平线性布局,指定基线对齐必须要指定出一个基线标准的子视图*/ MyGravity_Vert_Baseline = 32 << 8, - /**垂直间距拉伸,并且头尾部分为其他部分间距的一半, 如果只有一个子视图则变为垂直居中停靠*/ + /**垂直间距环绕拉伸,并且头尾部分为其他部分间距的一半, 如果只有一个子视图则变为垂直居中停靠*/ MyGravity_Vert_Around = 64 << 8, + /**垂直间距等分拉伸,并且头尾部分和其他部分间距的一样, 如果只有一个子视图则变为垂直居中停靠*/ + MyGravity_Vert_Among = MyGravity_Vert_Between | MyGravity_Vert_Around, /**垂直高度填充*/ MyGravity_Vert_Fill = MyGravity_Vert_Top | MyGravity_Vert_Center | MyGravity_Vert_Bottom, /**垂直高度拉伸,它跟高度填充的区别是如果子视图指定了高度(非布局子视图高度自适应除外)则不会被拉伸*/ @@ -126,6 +130,18 @@ typedef enum : unsigned short { } MyGravity; +/** + 停靠对齐的生效策略,主要用于流式布局中的最后一行。 + */ +typedef enum : unsigned char { + /**不做任何停靠对齐*/ + MyGravityPolicy_No, + /**总是停靠对齐*/ + MyGravityPolicy_Always, + /**自动使用前面的停靠对齐策略*/ + MyGravityPolicy_Auto, +} MyGravityPolicy; + /** *设置当将布局视图嵌入到UIScrollView以及其派生类时对UIScrollView的contentSize的调整设置模式的枚举类型定义。 diff --git a/MyLayout/Lib/MyLayoutSizeClass.h b/MyLayout/Lib/MyLayoutSizeClass.h index 8e0528a..50e6475 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.h +++ b/MyLayout/Lib/MyLayoutSizeClass.h @@ -122,9 +122,23 @@ @end + +@interface MySequentLayoutFlexSpace:NSObject +@property(nonatomic,assign) CGFloat subviewSize; +@property(nonatomic,assign) CGFloat minSpace; +@property(nonatomic,assign) CGFloat maxSpace; +@property(nonatomic,assign) BOOL centered; + +-(CGFloat)calcMaxMinSubviewSizeForContent:(CGFloat)selfSize startPadding:(CGFloat*)pStarPadding endPadding:(CGFloat*)pEndPadding space:(CGFloat*)pSpace; +-(CGFloat)calcMaxMinSubviewSize:(CGFloat)selfSize arrangedCount:(NSInteger)arrangedCount startPadding:(CGFloat*)pStarPadding endPadding:(CGFloat*)pEndPadding space:(CGFloat*)pSpace; + +@end + + @interface MySequentLayoutViewSizeClass : MyLayoutViewSizeClass @property(nonatomic,assign) MyOrientation orientation; +@property(nonatomic,strong) MySequentLayoutFlexSpace *flexSpace; @end @@ -143,22 +157,15 @@ @property(nonatomic,assign) MyGravity arrangedGravity; @property(nonatomic,assign) BOOL autoArrange; @property(nonatomic,assign) BOOL isFlex; +@property(nonatomic,assign) MyGravityPolicy lastlineGravityPolicy; @property(nonatomic,assign) NSInteger arrangedCount; @property(nonatomic, assign) NSInteger pagedCount; -@property(nonatomic, assign) CGFloat subviewSize; -@property(nonatomic, assign) CGFloat minSpace; -@property(nonatomic, assign) CGFloat maxSpace; - @end @interface MyFloatLayoutViewSizeClass : MySequentLayoutViewSizeClass -@property(nonatomic, assign) CGFloat subviewSize; -@property(nonatomic, assign) CGFloat minSpace; -@property(nonatomic, assign) CGFloat maxSpace; - @end @interface MyRelativeLayoutViewSizeClass : MyLayoutViewSizeClass diff --git a/MyLayout/Lib/MyLayoutSizeClass.m b/MyLayout/Lib/MyLayoutSizeClass.m index 99597c7..ef26541 100644 --- a/MyLayout/Lib/MyLayoutSizeClass.m +++ b/MyLayout/Lib/MyLayoutSizeClass.m @@ -746,13 +746,90 @@ -(NSString*)debugDescription @end +@implementation MySequentLayoutFlexSpace + +-(CGFloat)calcMaxMinSubviewSizeForContent:(CGFloat)selfSize startPadding:(CGFloat*)pStarPadding endPadding:(CGFloat*)pEndPadding space:(CGFloat*)pSpace +{ + CGFloat subviewSize = self.subviewSize; + + CGFloat extralSpace = self.minSpace; + if (self.centered) + extralSpace *= -1; + + NSInteger rowCount = MAX(floor((selfSize - (*pStarPadding) - (*pEndPadding) + extralSpace) / (subviewSize + self.minSpace)) , 1); + NSInteger spaceCount = rowCount - 1; + if (self.centered) + spaceCount += 2; + + if (spaceCount > 0) { + *pSpace = (selfSize - (*pStarPadding) - (*pEndPadding) - subviewSize * rowCount) / spaceCount; + + if (_myCGFloatGreat(*pSpace , self.maxSpace)) { + *pSpace = self.maxSpace; + subviewSize = (selfSize - (*pStarPadding) - (*pEndPadding) - (*pSpace) * spaceCount) / rowCount; + } + + if (self.centered) { + *pStarPadding = (*pStarPadding + *pSpace); + *pEndPadding = (*pEndPadding + *pSpace); + } + } + + return subviewSize; +} + + +-(CGFloat)calcMaxMinSubviewSize:(CGFloat)selfSize arrangedCount:(NSInteger)arrangedCount startPadding:(CGFloat*)pStarPadding endPadding:(CGFloat*)pEndPadding space:(CGFloat*)pSpace +{ + CGFloat subviewSize = self.subviewSize; + + NSInteger spaceCount = arrangedCount - 1; + if (self.centered) { + spaceCount += 2; + } + + if (spaceCount > 0) { + *pSpace = (selfSize - *pStarPadding - *pEndPadding - subviewSize * arrangedCount) / spaceCount; + + if (_myCGFloatGreat(*pSpace , self.maxSpace) || _myCGFloatLess(*pSpace, self.minSpace)) + { + if (_myCGFloatGreat(*pSpace , self.maxSpace)) + *pSpace = self.maxSpace; + + if (_myCGFloatLess(*pSpace, self.minSpace)) + *pSpace = self.minSpace; + + subviewSize = (selfSize - *pStarPadding - *pEndPadding - (*pSpace) * spaceCount) / arrangedCount; + } + + if (self.centered) { + *pStarPadding = (*pStarPadding + *pSpace); + *pEndPadding = (*pEndPadding + *pSpace); + } + } + + return subviewSize; +} + +@end + + @implementation MySequentLayoutViewSizeClass - (id)copyWithZone:(NSZone *)zone { MySequentLayoutViewSizeClass *lsc = [super copyWithZone:zone]; lsc.orientation = self.orientation; - return lsc; + if (self.flexSpace != nil) + { + lsc.flexSpace = [MySequentLayoutFlexSpace new]; + lsc.flexSpace.subviewSize = self.flexSpace.subviewSize; + lsc.flexSpace.minSpace = self.flexSpace.minSpace; + lsc.flexSpace.maxSpace = self.flexSpace.maxSpace; + lsc.flexSpace.centered = self.flexSpace.centered; + } + + return lsc; } -(NSString*)debugDescription @@ -805,9 +882,6 @@ - (id)copyWithZone:(NSZone *)zone { MyFloatLayoutViewSizeClass *lsc = [super copyWithZone:zone]; - lsc.subviewSize = self.subviewSize; - lsc.minSpace = self.minSpace; - lsc.maxSpace = self.maxSpace; return lsc; } @@ -823,10 +897,8 @@ - (id)copyWithZone:(NSZone *)zone lsc.arrangedCount = self.arrangedCount; lsc.autoArrange = self.autoArrange; lsc.isFlex = self.isFlex; + lsc.lastlineGravityPolicy = self.lastlineGravityPolicy; lsc.arrangedGravity = self.arrangedGravity; - lsc.subviewSize = self.subviewSize; - lsc.minSpace = self.minSpace; - lsc.maxSpace = self.maxSpace; lsc.pagedCount = self.pagedCount; return lsc; diff --git a/MyLayout/Lib/MyLinearLayout.h b/MyLayout/Lib/MyLinearLayout.h index 61c25b9..ea47426 100644 --- a/MyLayout/Lib/MyLinearLayout.h +++ b/MyLayout/Lib/MyLinearLayout.h @@ -196,6 +196,23 @@ -(void)equalizeSubviewsSpace:(BOOL)centered inSizeClass:(MySizeClass)sizeClass; +/** + 在一些应用场景中我们希望子视图的宽度是固定的但间距是浮动的,这样就尽可能在一排中容纳更多的子视图。比如设置每个子视图的宽度固定为80,那么在小屏幕下每排只能放3个,而大屏幕则每排能放4个或者5个子视图。 因此您可以通过如下方法来设置子视图的固定尺寸和最小最大浮动间距。这个方法会根据您当前布局的方向不同而具有不同的意义: + + 1.如果您的布局方向是垂直的则设置的是每行内子视图的水平浮动间距,其中的subviewSize指定的是子视图的固定宽度;minSpace指定的是最小的水平间距;maxSpace指定的是最大的水平间距,如果指定的subviewSize计算出的间距大于最大间距maxSpace则会缩小subviewSize的宽度值。 + + 2.如果您的布局方向是水平的则设置的是每列内子视图的垂直浮动间距,其中的subviewSize指定的是子视图的固定高度;minSpace指定的是最小的垂直间距;maxSpace指定的是最大的垂直间距,如果指定的subviewSize计算出的间距大于最大间距maxSpace则会调整subviewSize的高度值。 + + @note 如果您不想使用浮动间距则请将subviewSize设置为0就可以了。 + + @param subviewSize 指定子视图的尺寸。 + @param minSpace 指定子视图之间的最小间距 + @param maxSpace 指定子视图之间的最大间距 + @param centered 指定是否所有子视图居中 + */ +-(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace centered:(BOOL)centered; +-(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace centered:(BOOL)centered inSizeClass:(MySizeClass)sizeClass; + @end diff --git a/MyLayout/Lib/MyLinearLayout.m b/MyLayout/Lib/MyLinearLayout.m index 3ecc884..69d67c0 100644 --- a/MyLayout/Lib/MyLinearLayout.m +++ b/MyLayout/Lib/MyLinearLayout.m @@ -131,6 +131,31 @@ -(void)equalizeSubviewsSpace:(BOOL)centered inSizeClass:(MySizeClass)sizeClass sbv.myFrame.sizeClass = sbv.myDefaultSizeClass; } +-(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace centered:(BOOL)centered +{ + [self setSubviewsSize:subviewSize minSpace:minSpace maxSpace:maxSpace centered:centered inSizeClass:MySizeClass_hAny | MySizeClass_wAny]; +} + +-(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace centered:(BOOL)centered inSizeClass:(MySizeClass)sizeClass +{ + MySequentLayoutViewSizeClass *lsc = (MySequentLayoutViewSizeClass*)[self fetchLayoutSizeClass:sizeClass]; + if (subviewSize == 0) + { + lsc.flexSpace = nil; + } + else + { + if (lsc.flexSpace == nil) + lsc.flexSpace = [MySequentLayoutFlexSpace new]; + + lsc.flexSpace.subviewSize = subviewSize; + lsc.flexSpace.minSpace = minSpace; + lsc.flexSpace.maxSpace = maxSpace; + lsc.flexSpace.centered = centered; + } + [self setNeedsLayout]; +} + #pragma mark -- Override Methods @@ -183,29 +208,29 @@ - (void)myLayout:(MyLinearLayoutViewSizeClass*)lsc orientation:(MyOrientation)or { //如果是拉伸处理则需要把包裹宽度取消。 if (sbvsc.widthSizeInner.dimeWrapVal && gravity == MyGravity_Horz_Fill) - [sbvsc.widthSizeInner __setActive:NO]; + [sbvsc.widthSizeInner __equalTo:nil]; //如果同时设置了左右依赖。并且优先级低时或者布局视图不是宽度自适应则取消自视图宽度自适应,这里是为了兼容老版本。 if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil && (sbvsc.widthSizeInner.priority == MyPriority_Low || !lsc.widthSizeInner.dimeWrapVal)) - [sbvsc.widthSizeInner __setActive:NO]; + [sbvsc.widthSizeInner __equalTo:nil]; //只要同时设置了高度或者比重属性则应该把尺寸设置为空 if (sbvsc.heightSizeInner.dimeWrapVal && sbvsc.weight != 0) - [sbvsc.heightSizeInner __setActive:NO]; + [sbvsc.heightSizeInner __equalTo:nil]; } else { //如果是拉伸处理则需要把包裹高度 if (sbvsc.heightSizeInner.dimeWrapVal && gravity == MyGravity_Vert_Fill) - [sbvsc.heightSizeInner __setActive:NO]; + [sbvsc.heightSizeInner __equalTo:nil]; //如果同时设置了左右依赖。并且优先级低时则取消宽度自适应,这里是为了兼容老版本。 if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil && (sbvsc.heightSizeInner.priority == MyPriority_Low || !lsc.heightSizeInner.dimeWrapVal)) - [sbvsc.heightSizeInner __setActive:NO]; + [sbvsc.heightSizeInner __equalTo:nil]; //只要同时设置了宽度或者比重属性则应该把宽度置空 if (sbvsc.widthSizeInner.dimeWrapVal && sbvsc.weight != 0) - [sbvsc.widthSizeInner __setActive:NO]; + [sbvsc.widthSizeInner __equalTo:nil]; } } @@ -278,20 +303,22 @@ -(void)myLayout:(MyLinearLayoutViewSizeClass*)lsc setIntelligentBorderlineOnSubv -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSubviews:(NSArray*)sbs withSelfSize:(CGSize)selfSize { - CGFloat subviewSpace = lsc.subviewVSpace; CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - CGFloat paddingVert = paddingTop + paddingBottom; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; + CGFloat subviewSpace = lsc.subviewVSpace; + CGFloat subviewSize = [lsc.flexSpace calcMaxMinSubviewSize:selfSize.height arrangedCount:sbs.count startPadding:&paddingTop endPadding:&paddingBottom space:&subviewSpace]; + CGFloat paddingVert = paddingTop + paddingBottom; CGFloat fixedHeight = 0.0; //计算固定部分的高度 CGFloat totalWeight = 0.0; //剩余部分的总比重 CGFloat totalShrink = 0.0; //总的压缩比重 CGFloat addSpace = 0.0; //用于压缩时的间距压缩增量。 CGFloat maxSelfWidth = 0.0; + //高度可以被伸缩的子视图集合 NSMutableSet *flexSbsSet = [NSMutableSet new]; @@ -342,7 +369,10 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub } //计算子视图的高度 - rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; + if (subviewSize != 0.0) + rect.size.height = subviewSize; + else + rect.size.height = [self myLayout:lsc heightSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; //特殊处理宽度等于高度的情况 @@ -367,18 +397,21 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub maxSelfWidth = tempSelfWidth; } - if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) - {//特殊处理高度等于宽度的情况 - - rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; - } - - //再次特殊处理高度包裹的场景 - if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) + if (subviewSize == 0.0) { - rect.size.height = [self mySubview:sbvsc wrapHeightSizeFits:rect.size.width]; - rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) + {//特殊处理高度等于宽度的情况 + + rect.size.height = [sbvsc.heightSizeInner measureWith:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } + + //再次特殊处理高度包裹的场景 + if (sbvsc.heightSizeInner.dimeWrapVal && ![sbv isKindOfClass:[MyBaseLayout class]]) + { + rect.size.height = [self mySubview:sbvsc wrapHeightSizeFits:rect.size.width]; + rect.size.height = [self myValidMeasure:sbvsc.heightSizeInner sbv:sbv calcSize:rect.size.height sbvSize:rect.size selfLayoutSize:selfSize]; + } } //计算固定高度尺寸和浮动高度尺寸部分 @@ -597,6 +630,11 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub pos = (selfSize.height - fixedHeight - paddingVert)/2.0 + paddingTop; } } + else if (vertGravity == MyGravity_Vert_Among) + { + between = (selfSize.height - fixedHeight - paddingVert) / (sbs.count + 1); + pos = paddingTop + between; + } else if (vertGravity == MyGravity_Vert_Fill || vertGravity == MyGravity_Vert_Stretch) { pos = paddingTop; @@ -747,20 +785,21 @@ -(CGSize)myVertOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSubviews:(NSArray*)sbs withSelfSize:(CGSize)selfSize { - CGFloat subviewSpace = lsc.subviewHSpace; CGFloat paddingTop = lsc.myLayoutTopPadding; CGFloat paddingBottom = lsc.myLayoutBottomPadding; CGFloat paddingLeading = lsc.myLayoutLeadingPadding; CGFloat paddingTrailing = lsc.myLayoutTrailingPadding; - CGFloat paddingHorz = paddingLeading + paddingTrailing; MyGravity vertGravity = lsc.gravity & MyGravity_Horz_Mask; MyGravity horzGravity = [self myConvertLeftRightGravityToLeadingTrailing:lsc.gravity & MyGravity_Vert_Mask]; + CGFloat subviewSpace = lsc.subviewHSpace; + CGFloat subviewSize = [lsc.flexSpace calcMaxMinSubviewSize:selfSize.width arrangedCount:sbs.count startPadding:&paddingLeading endPadding:&paddingTrailing space:&subviewSpace]; CGFloat fixedWidth = 0.0; //计算固定部分的宽度 CGFloat totalWeight = 0.0; //剩余部分的总比重 CGFloat totalShrink = 0.0; //总的压缩比重 CGFloat addSpace = 0.0; //用于压缩时的间距压缩增量。 - + CGFloat paddingHorz = paddingLeading + paddingTrailing; + //宽度是可伸缩的子视图集合 NSMutableSet *flexSbsSet = [NSMutableSet new]; //宽度是固定尺寸的子视图集合 @@ -816,7 +855,10 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub } //计算子视图的宽度,这里不管是否设置约束以及是否宽度是weight的都是进行计算。 - rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; + if (subviewSize != 0.0) + rect.size.width = subviewSize; + else + rect.size.width = [self myLayout:lsc widthSizeValueOfSubview:sbvsc selfSize:selfSize sbvSize:rect.size paddingTop:paddingTop paddingLeading:paddingLeading paddingBottom:paddingBottom paddingTrailing:paddingTrailing]; rect.size.width = [self myValidMeasure:sbvsc.widthSizeInner sbv:sbv calcSize:rect.size.width sbvSize:rect.size selfLayoutSize:selfSize]; if (sbvsc.heightSizeInner.dimeRelaVal != nil && sbvsc.heightSizeInner.dimeRelaVal == sbvsc.widthSizeInner) @@ -851,7 +893,7 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub baselinePos = rect.origin.y + (rect.size.height - sbvFont.lineHeight) / 2.0 + sbvFont.ascender; } - if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner) + if (sbvsc.widthSizeInner.dimeRelaVal != nil && sbvsc.widthSizeInner.dimeRelaVal == sbvsc.heightSizeInner && subviewSize == 0.0) {//特殊处理宽度等于高度的情况 rect.size.width = [sbvsc.widthSizeInner measureWith:rect.size.height]; @@ -1122,6 +1164,11 @@ -(CGSize)myHorzOrientationLayout:(MyLinearLayoutViewSizeClass*)lsc calcRectOfSub pos = (selfSize.width - fixedWidth - paddingHorz)/2.0 + paddingLeading; } } + else if (horzGravity == MyGravity_Horz_Among) + { + between = (selfSize.width - fixedWidth - paddingHorz) / (sbs.count + 1); + pos = paddingLeading + between; + } else if (horzGravity == MyGravity_Horz_Fill || horzGravity == MyGravity_Horz_Stretch) { pos = paddingLeading; diff --git a/MyLayout/Lib/MyRelativeLayout.m b/MyLayout/Lib/MyRelativeLayout.m index 295cf25..7607f42 100644 --- a/MyLayout/Lib/MyRelativeLayout.m +++ b/MyLayout/Lib/MyRelativeLayout.m @@ -41,13 +41,13 @@ -(CGSize)calcLayoutSize:(CGSize)size isEstimate:(BOOL)isEstimate pHasSubLayout:( if (sbvsc.leadingPosInner.posVal != nil && sbvsc.trailingPosInner.posVal != nil && (sbvsc.widthSizeInner.priority == MyPriority_Low || !lsc.widthSizeInner.dimeWrapVal)) - [sbvsc.widthSizeInner __setActive:NO]; + [sbvsc.widthSizeInner __equalTo:nil]; //只要同时设置了上下边距且高度优先级很低则把高度值置空 if (sbvsc.topPosInner.posVal != nil && sbvsc.bottomPosInner.posVal != nil && (sbvsc.heightSizeInner.priority == MyPriority_Low || !lsc.heightSizeInner.dimeWrapVal)) - [sbvsc.heightSizeInner __setActive:NO]; + [sbvsc.heightSizeInner __equalTo:nil]; if ([sbv isKindOfClass:[MyBaseLayout class]]) diff --git a/MyLayoutDemo/FLLTest1ViewController.m b/MyLayoutDemo/FLLTest1ViewController.m index f0364b6..22207ba 100644 --- a/MyLayoutDemo/FLLTest1ViewController.m +++ b/MyLayoutDemo/FLLTest1ViewController.m @@ -53,14 +53,16 @@ -(void)loadView [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"adjust align", @"") action:@selector(handleAdjustArrangeGravity:)]]; [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"adjust spacing", @"") - action:@selector(handleAdjustMargin:)]]; + action:@selector(handleAdjustSpace:)]]; + [actionLayout addSubview:[self createActionButton:NSLocalizedString(@"adjust gravity policy", @"") + action:@selector(handleAdjustGravityPolicy:)]]; UILabel *flowLayoutSetLabel = [UILabel new]; flowLayoutSetLabel.font = [CFTool font:13]; flowLayoutSetLabel.textColor = [UIColor redColor]; flowLayoutSetLabel.adjustsFontSizeToFitWidth = YES; flowLayoutSetLabel.myHeight = MyLayoutSize.wrap; - flowLayoutSetLabel.numberOfLines = 5; + flowLayoutSetLabel.numberOfLines = 6; [rootLayout addSubview:flowLayoutSetLabel]; self.flowLayoutSetLabel = flowLayoutSetLabel; @@ -175,6 +177,9 @@ -(void)handleAdjustVertGravity:(id)sender vertGravity = MyGravity_Vert_Around; break; case MyGravity_Vert_Around: + vertGravity = MyGravity_Vert_Among; + break; + case MyGravity_Vert_Among: vertGravity = MyGravity_Vert_Fill; break; case MyGravity_Vert_Fill: @@ -218,6 +223,9 @@ -(void)handleAdjustHorzGravity:(id)sender horzGravity = MyGravity_Horz_Around; break; case MyGravity_Horz_Around: + horzGravity = MyGravity_Horz_Among; + break; + case MyGravity_Horz_Among: horzGravity = MyGravity_Horz_Fill; break; case MyGravity_Horz_Fill: @@ -305,7 +313,7 @@ -(void)handleAdjustArrangeGravity:(id)sender } --(void)handleAdjustMargin:(id)sender +-(void)handleAdjustSpace:(id)sender { //调整所有子视图的水平和垂直间距。 if (self.flowLayout.subviewHSpace == 0) @@ -322,6 +330,26 @@ -(void)handleAdjustMargin:(id)sender [self flowlayoutInfo]; } +-(void)handleAdjustGravityPolicy:(id)sender +{ + switch (self.flowLayout.lastlineGravityPolicy) { + case MyGravityPolicy_No: + self.flowLayout.lastlineGravityPolicy = MyGravityPolicy_Always; + break; + case MyGravityPolicy_Always: + self.flowLayout.lastlineGravityPolicy = MyGravityPolicy_Auto; + break; + case MyGravityPolicy_Auto: + self.flowLayout.lastlineGravityPolicy = MyGravityPolicy_No; + default: + break; + } + + [self.flowLayout.subviews makeObjectsPerformSelector:@selector(sizeToFit)]; + [self.flowLayout layoutAnimationWithDuration:0.4]; + [self flowlayoutInfo]; +} + #pragma mark -- Private Method -(void)flowlayoutInfo @@ -340,8 +368,9 @@ -(void)flowlayoutInfo NSString *subviewSpaceStr = [NSString stringWithFormat:@"vert:%.0f,horz:%.0f",self.flowLayout.subviewVSpace, self.flowLayout.subviewHSpace]; + NSString *gravityPolicyStr = [self gravityPolicyInfo:self.flowLayout.lastlineGravityPolicy]; - self.flowLayoutSetLabel.text = [NSString stringWithFormat:@"flowLayout:\norientation=%@, arrangedCount=%@\ngravity=%@\narrangedGravity=%@\nsubviewSpace=(%@)",orientationStr,arrangeCountStr,gravityStr,arrangedGravityStr,subviewSpaceStr]; + self.flowLayoutSetLabel.text = [NSString stringWithFormat:@"flowLayout:\norientation=%@, arrangedCount=%@\ngravity=%@\narrangedGravity=%@\nsubviewSpace=(%@)\n%@",orientationStr,arrangeCountStr,gravityStr,arrangedGravityStr,subviewSpaceStr,gravityPolicyStr]; } -(NSString*)gravityInfo:(MyGravity)gravity @@ -370,6 +399,9 @@ -(NSString*)gravityInfo:(MyGravity)gravity case MyGravity_Vert_Around: vertGravityStr = @"MyGravity_Vert_Around"; break; + case MyGravity_Vert_Among: + vertGravityStr = @"MyGravity_Vert_Among"; + break; case MyGravity_Vert_Stretch: vertGravityStr = @"MyGravity_Vert_Stretch"; break; @@ -401,6 +433,9 @@ -(NSString*)gravityInfo:(MyGravity)gravity case MyGravity_Horz_Around: horzGravityStr = @"MyGravity_Horz_Around"; break; + case MyGravity_Horz_Among: + horzGravityStr = @"MyGravity_Horz_Among"; + break; case MyGravity_Horz_Stretch: horzGravityStr = @"MyGravity_Horz_Stretch"; break; @@ -417,6 +452,22 @@ -(NSString*)gravityInfo:(MyGravity)gravity } +-(NSString*)gravityPolicyInfo:(MyGravityPolicy)gravityPolicy +{ + switch (gravityPolicy) { + case MyGravityPolicy_No: + return @"policy:No"; + break; + case MyGravityPolicy_Always: + return @"policy:Always"; + case MyGravityPolicy_Auto: + return @"policy:Auto"; + default: + break; + } + + return @""; +} /* #pragma mark - Navigation diff --git a/MyLayoutDemo/FLLTest2ViewController.m b/MyLayoutDemo/FLLTest2ViewController.m index 130ac84..adcbe14 100644 --- a/MyLayoutDemo/FLLTest2ViewController.m +++ b/MyLayoutDemo/FLLTest2ViewController.m @@ -130,7 +130,10 @@ - (IBAction)handleAutoArrangeChange:(UISwitch *)sender { -(IBAction)handleGravityAlwaysChange:(id)sender { - self.flowLayout.isFlex = !self.flowLayout.isFlex; + if (self.flowLayout.lastlineGravityPolicy == MyGravityPolicy_No) + self.flowLayout.lastlineGravityPolicy = MyGravityPolicy_Always; + else + self.flowLayout.lastlineGravityPolicy = MyGravityPolicy_No; } diff --git a/MyLayoutDemo/FLLTest8ViewController.m b/MyLayoutDemo/FLLTest8ViewController.m index f31c6b4..e56bc01 100644 --- a/MyLayoutDemo/FLLTest8ViewController.m +++ b/MyLayoutDemo/FLLTest8ViewController.m @@ -12,6 +12,12 @@ @interface FLLTest8ViewController () +@property(nonatomic, strong) MyFlowLayout *vertLayout; +@property(nonatomic, strong) MyFlowLayout *horzLayout; +@property(nonatomic, strong) MyFlowLayout *vertLayout2; +@property(nonatomic, strong) MyFlowLayout *horzLayout2; + + @end @implementation FLLTest8ViewController @@ -21,7 +27,7 @@ -(void)loadView /* 这个例子主要用于展示流式布局的间距的可伸缩性。当我们布局视图中的子视图的宽度或者高度为固定值,但是其中的间距又希望是可以伸缩的,那么就可以借助流式布局提供的方法 - -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace; + -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace:(CGFloat)maxSpace centered:(BOOL)centered 来设置子视图的尺寸,以及最小和最大的间距值。并且当布局视图中子视图的间距小于最小值时会自动调整子视图的尺寸来满足这个最小的间距。 @@ -44,14 +50,12 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace: MyFlowLayout *vertLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:4]; - //这个垂直流式布局中,每个子视图之间的水平间距是浮动的,并且子视图的宽度是固定为60。间距最小为10,最大不限制。 - [vertLayout setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX]; - - vertLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); + vertLayout.padding = UIEdgeInsetsMake(5, 0, 5, 0); vertLayout.backgroundColor = [CFTool color:5]; vertLayout.subviewVSpace = 20; vertLayout.gravity = MyGravity_Vert_Fill; //因为上面setSubviewsSize设置了固定宽度,这个属性设置子视图的高度是填充满子布局视图,因此系统内部会自动设置每个子视图的高度,如果你不设置这个属性,那么你就需要在下面分别为每个子视图设置高度。 [rootLayout addSubview:vertLayout]; + self.vertLayout = vertLayout; for (int i = 0; i < 14; i++) { @@ -66,14 +70,13 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace: MyFlowLayout *horzLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:4]; - //这个水平流式布局中,每个子视图之间的垂直间距是浮动的,并且子视图的高度是固定为60。间距最小为10,最大不限制。 - [horzLayout setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX]; - horzLayout.padding = UIEdgeInsetsMake(5, 5, 5, 5); + horzLayout.padding = UIEdgeInsetsMake(0, 5, 0, 5); horzLayout.backgroundColor = [CFTool color:6]; horzLayout.subviewHSpace = 20; horzLayout.gravity = MyGravity_Horz_Fill; //因为上面setSubviewsSize设置了固定高度,这个属性设置子视图的宽度是填充满子布局视图,因此系统内部会自动设置每个子视图的宽度,如果你不设置这个属性,那么你就需要在下面分别为每个子视图设置宽度。 [rootLayout addSubview:horzLayout]; + self.horzLayout = horzLayout; for (int i = 0; i < 14; i++) { @@ -85,11 +88,67 @@ -(void)setSubviewsSize:(CGFloat)subviewSize minSpace:(CGFloat)minSpace maxSpace: [horzLayout addSubview:label]; } + + MyFlowLayout *vertLayout2 = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:0]; + vertLayout2.padding = UIEdgeInsetsMake(5, 0, 5, 0); + vertLayout2.backgroundColor = [CFTool color:5]; + vertLayout2.subviewVSpace = 20; + vertLayout2.gravity = MyGravity_Vert_Fill; //因为上面setSubviewsSize设置了固定宽度,这个属性设置子视图的高度是填充满子布局视图,因此系统内部会自动设置每个子视图的高度,如果你不设置这个属性,那么你就需要在下面分别为每个子视图设置高度。 + [rootLayout addSubview:vertLayout2]; + self.vertLayout2 = vertLayout2; + + for (int i = 0; i < 14; i++) + { + UILabel *label = [UILabel new]; + //label.myHeight = 60; 因为子视图的宽度在布局视图的setSubviewsSize:minSpace:maxSpace:中设置了,你也可以在这里单独为每个子视图设置高度,当然如果你的父布局视图使用了gravity来设置填充属性的话,那么子视图是不需要单独设置高度尺寸的。 + label.text = [NSString stringWithFormat:@"%d", i]; + label.textAlignment = NSTextAlignmentCenter; + label.backgroundColor = [CFTool color:2]; + [vertLayout2 addSubview:label]; + } + + + + MyFlowLayout *horzLayout2 = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:0]; + + horzLayout2.padding = UIEdgeInsetsMake(0, 5, 0, 5); + horzLayout2.backgroundColor = [CFTool color:6]; + horzLayout2.subviewHSpace = 20; + horzLayout2.gravity = MyGravity_Horz_Fill; //因为上面setSubviewsSize设置了固定高度,这个属性设置子视图的宽度是填充满子布局视图,因此系统内部会自动设置每个子视图的宽度,如果你不设置这个属性,那么你就需要在下面分别为每个子视图设置宽度。 + [rootLayout addSubview:horzLayout2]; + self.horzLayout2 = horzLayout2; + + for (int i = 0; i < 14; i++) + { + UILabel *label = [UILabel new]; + //label.myWidth = 60; 因为子视图的高度在布局视图的setSubviewsSize:minSpace:maxSpace:中设置了,你也可以在这里单独为每个子视图设置宽度,当然如果你的父布局视图使用了gravity来设置填充属性的话,那么子视图是不需要单独设置宽度尺寸的。 + label.text = [NSString stringWithFormat:@"%d", i]; + label.textAlignment = NSTextAlignmentCenter; + label.backgroundColor = [CFTool color:3];; + [horzLayout2 addSubview:label]; + } + + + //这个垂直流式布局中,每个子视图之间的水平间距是浮动的,并且子视图的宽度是固定为60。间距最小为10,最大不限制。 + [vertLayout setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX centered:NO]; + + //这个水平流式布局中,每个子视图之间的垂直间距是浮动的,并且子视图的高度是固定为60。间距最小为10,最大不限制。 + [horzLayout setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX centered:NO]; + + //这个垂直流式布局中,每个子视图之间的水平间距是浮动的,并且子视图的宽度是固定为60。间距最小为10,最大不限制。 + [vertLayout2 setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX centered:NO]; + + //这个水平流式布局中,每个子视图之间的垂直间距是浮动的,并且子视图的高度是固定为60。间距最小为10,最大不限制。 + [horzLayout2 setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX centered:NO]; + } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. + + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"center off" style:UIBarButtonItemStylePlain target:self action:@selector(handleCenterOnOff:)]; + } - (void)didReceiveMemoryWarning { @@ -97,6 +156,29 @@ - (void)didReceiveMemoryWarning { // Dispose of any resources that can be recreated. } +-(IBAction)handleCenterOnOff:(UIBarButtonItem*)sender { + + if ([sender.title isEqualToString:@"center off"]) { + sender.title = @"center on"; + [self.vertLayout setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX centered:YES]; + [self.horzLayout setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX centered:YES]; + [self.vertLayout2 setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX centered:YES]; + [self.horzLayout2 setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX centered:YES]; + + } else { + sender.title = @"center off"; + [self.vertLayout setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX centered:NO]; + [self.horzLayout setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX centered:NO]; + [self.vertLayout2 setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX centered:NO]; + [self.horzLayout2 setSubviewsSize:60 minSpace:10 maxSpace:CGFLOAT_MAX centered:NO]; + } + + [self.vertLayout layoutAnimationWithDuration:0.3]; + [self.horzLayout layoutAnimationWithDuration:0.3]; + [self.vertLayout2 layoutAnimationWithDuration:0.3]; + [self.horzLayout2 layoutAnimationWithDuration:0.3]; +} + /* #pragma mark - Navigation diff --git a/MyLayoutDemo/LLTest3ViewController.m b/MyLayoutDemo/LLTest3ViewController.m index 2a7ba6d..83eb942 100644 --- a/MyLayoutDemo/LLTest3ViewController.m +++ b/MyLayoutDemo/LLTest3ViewController.m @@ -133,6 +133,7 @@ -(void)createVertLayoutGravityActionLayout:(MyLinearLayout*)contentLayout NSLocalizedString(@"screen horz center",@""), NSLocalizedString(@"between",@""), NSLocalizedString(@"around",@""), + NSLocalizedString(@"among",@""), NSLocalizedString(@"horz fill",@""), NSLocalizedString(@"vert fill", @""), NSLocalizedString(@"horz stretch", @""), @@ -223,6 +224,7 @@ -(void)createHorzLayoutGravityActionLayout:(MyLinearLayout*)contentLayout NSLocalizedString(@"screen horz center",@""), NSLocalizedString(@"between",@""), NSLocalizedString(@"around",@""), + NSLocalizedString(@"among",@""), NSLocalizedString(@"horz fill",@""), NSLocalizedString(@"vert fill", @""), NSLocalizedString(@"horz stretch",@""), @@ -339,16 +341,19 @@ -(void)handleVertLayoutGravity:(UIButton*)button case 10: //垂直间距环绕 vertGravity = MyGravity_Vert_Around; break; - case 11: //水平填充 + case 11: //垂直间距等分 + vertGravity = MyGravity_Vert_Among; + break; + case 12: //水平填充 horzGravity = MyGravity_Horz_Fill; break; - case 12: //垂直填充 + case 13: //垂直填充 vertGravity = MyGravity_Vert_Fill; //这里模拟器顶部出现黑线,真机是不会出现的。。 break; - case 13: //水平拉伸 + case 14: //水平拉伸 horzGravity = MyGravity_Horz_Stretch; break; - case 14: //垂直拉伸 + case 15: //垂直拉伸 vertGravity = MyGravity_Vert_Stretch; //这里模拟器顶部出现黑线,真机是不会出现的。。 break; default: @@ -401,16 +406,19 @@ -(void)handleHorzLayoutGravity:(UIButton*)button case 10: //水平间距环绕 horzGravity = MyGravity_Horz_Around; break; - case 11: //水平填充 + case 11: //水平间距等分 + horzGravity = MyGravity_Horz_Among; + break; + case 12: //水平填充 horzGravity = MyGravity_Horz_Fill; break; - case 12: + case 13: vertGravity = MyGravity_Vert_Fill; break; - case 13: //水平拉伸 + case 14: //水平拉伸 horzGravity = MyGravity_Horz_Stretch; break; - case 14: //垂直拉伸 + case 15: //垂直拉伸 vertGravity = MyGravity_Vert_Stretch; break; default: @@ -500,6 +508,9 @@ -(NSString*)gravityText:(MyGravity)gravity prefixText:(NSString*)prefixText case MyGravity_Vert_Around: vertGravityStr = @"MyGravity_Vert_Around"; break; + case MyGravity_Vert_Among: + vertGravityStr = @"MyGravity_Vert_Among"; + break; case MyGravity_Vert_Window_Center: vertGravityStr = @"MyGravity_Vert_Window_Center"; break; @@ -531,6 +542,9 @@ -(NSString*)gravityText:(MyGravity)gravity prefixText:(NSString*)prefixText case MyGravity_Horz_Around: horzGravityStr = @"MyGravity_Horz_Around"; break; + case MyGravity_Horz_Among: + horzGravityStr = @"MyGravity_Horz_Among"; + break; case MyGravity_Horz_Window_Center: horzGravityStr = @"MyGravity_Horz_Window_Center"; break; diff --git a/MyLayoutDemo/zh-Hans.lproj/FLLTest2ViewController.xib b/MyLayoutDemo/zh-Hans.lproj/FLLTest2ViewController.xib index 21f83b9..1918733 100644 --- a/MyLayoutDemo/zh-Hans.lproj/FLLTest2ViewController.xib +++ b/MyLayoutDemo/zh-Hans.lproj/FLLTest2ViewController.xib @@ -121,7 +121,7 @@ -