From f4f548cfe0379c0521b6b12306392cef5772804a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E6=9F=8F=E6=B3=89?= Date: Tue, 7 Nov 2017 23:37:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AF=B9iOS11=E7=9A=84?= =?UTF-8?q?=E6=94=AF=E6=8C=81=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=9F=BA=E7=BA=BF?= =?UTF-8?q?=E5=AF=B9=E9=BD=90=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E8=AF=B8=E5=A4=9ABUG=EF=BC=8C=E4=BC=98=E5=8C=96DEMO=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 27 ++ README.md | 2 +- README.zh.md | 2 +- TangramKit.podspec | 2 +- TangramKit.xcodeproj/project.pbxproj | 9 +- TangramKit/Info.plist | 2 +- TangramKit/TGBaseLayout.swift | 333 +++++++++++++++--- TangramKit/TGFloatLayout.swift | 8 +- TangramKit/TGFlowLayout.swift | 33 +- TangramKit/TGFrameLayout.swift | 49 ++- TangramKit/TGLayoutPos.swift | 123 ++++++- TangramKit/TGLayoutSizeClass.swift | 130 ++++--- TangramKit/TGLinearLayout.swift | 185 ++++++---- TangramKit/TGPathLayout.swift | 19 +- TangramKit/TGRelativeLayout.swift | 191 +++++++--- TangramKit/TGTableLayout.swift | 36 +- TangramKit/TangramKit.swift | 6 +- TangramKitDemo/AppDelegate.swift | 8 + TangramKitDemo/DetailViewController.swift | 144 ++++++++ .../FOLTest3ViewController.swift | 3 +- .../FLTest1ViewController.swift | 4 +- .../FLTest2ViewController.swift | 1 + .../AppIcon.appiconset/Contents.json | 5 + TangramKitDemo/Info.plist | 2 +- .../AllTest8ViewController.swift | 9 +- .../AllTest1TableViewCell.swift | 11 +- .../PLTest1ViewController.swift | 6 +- .../RLTest1ViewController.swift | 10 +- .../RLTest4ViewController.swift | 6 + .../TLTest1ViewController.swift | 3 +- .../TLTest3ViewController.swift | 25 +- TangramKitDemo/ViewController.swift | 227 +++++++----- .../LLTest2ViewController.swift | 52 ++- .../LLTest6ViewController.swift | 17 +- 34 files changed, 1308 insertions(+), 382 deletions(-) create mode 100644 TangramKitDemo/DetailViewController.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index eb391b5..1f9f065 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,33 @@ --- +## [V1.1.3](https://github.com/youngsoft/TangramKit/releases/tag/1.1.3)(2017/11/08) + +#### Added +1. 添加了对**基线对齐baseline**的支持[issue:#43](https://github.com/youngsoft/MyLinearLayout/issues/43),目前只有**水平线性布局(TGLinearLayout)**和**相对布局(TGRelativeLayout)**支持基线对齐。 + 1. 在**TGGravity**中添加了`TGGravity.vert.baseline`的枚举定义来支持线性布局的基线对齐,并且在线性布局中添加了一个属性:`tg_baselineBaseView`来指定某个基线基准视图。同时在布局视图的tg_gravity属性中支持对`TGGravity.vert.baseline`的设置。具体例子参考:[LLTest1ViewController](https://github.com/youngsoft/TangramKit/blob/master/TangramKitDemo/linerLayoutDemo/LLTest1ViewController.swift) + + 2. 在UIView的扩展属性中增加了一个扩展属性:`tg_baseline`。你可以在相对布局中的子视图使用这个属性来进行基线对齐的设置。具体例子请参考:[RLTest1ViewController](https://github.com/youngsoft/TangramKit/blob/master/TangramKitDemo/linerLayoutDemo/RLTest1ViewController.swift) + +2. **TGLayoutPos**中增加了一个特殊的值`tg_safeAreaMargin`用来支持对iOS11应用的适配。 +3. 添加对所有设备完美适配的例子,具体看各个DEMO。 + +#### Change +1. 优化DEMO的目录结构。以便展示更加合理和查找方便。 +2. 支持在XCODE8下编译MyLayout的能力。[issue:#54](https://github.com/youngsoft/MyLinearLayout/issues/54) +3. 优化在iPhoneX的横屏下UITableViewCell的动态高度的计算的问题,请参考[AllTest1TableViewCell.swift](https://github.com/youngsoft/TangramKit/blob/master/TangramKitDemo/IntegratedDemo/AllTestModel&View/AllTest1TableViewCell.swift) + +#### Fixed +1. 修复各种布局下均分尺寸时可能会中间留出一个像素空间的问题。 +2. 修复相对布局下某个子视图固定,其他子视图均分剩余尺寸的问题[BUG#53](https://github.com/youngsoft/MyLinearLayout/issues/53) +3. 优化V1.4.3版本中insetsPaddingFromSafeArea的默认属性设置导致UITableView的中的cell往下偏移,以及iOS11下的多余偏移的问题。 +4. 修复表格布局TGTableLayout中的添加行方法`tg_addRow`的列参数设置为整数时无法显示列宽或者列高的问题。 +5. 修复了一个当子视图不设置任何约束时,在进行布局时可能出现错误的问题。 +6. 修复了路径布局中的子视图在执行动画时可能会产生崩溃的问题。 + + + + ## [V1.1.2](https://github.com/youngsoft/TangramKit/releases/tag/1.1.2)(2017/9/23) #### Added diff --git a/README.md b/README.md index 2be8405..9da2d80 100644 --- a/README.md +++ b/README.md @@ -587,7 +587,7 @@ To integrate TangramKit into your Xcode project using CocoaPods, specify it in y source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' -pod 'TangramKit', '~> 1.1.2' +pod 'TangramKit', '~> 1.1.3' ``` Then, run the following command: diff --git a/README.zh.md b/README.zh.md index e935289..3e03cdc 100644 --- a/README.zh.md +++ b/README.zh.md @@ -590,7 +590,7 @@ $ gem install cocoapods source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' -pod 'TangramKit', '~> 1.1.2' +pod 'TangramKit', '~> 1.1.3' ``` 然后运行如下命令: diff --git a/TangramKit.podspec b/TangramKit.podspec index cff266e..6546c39 100644 --- a/TangramKit.podspec +++ b/TangramKit.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "TangramKit" - s.version = "1.1.2" + s.version = “1.1.3” s.summary = "TangramKit is A powerful iOS UI framework. It integrated the Android layout,AutoLayout,SizeClass, HTML/CSS float and flexbox functions." s.description = <<-DESC diff --git a/TangramKit.xcodeproj/project.pbxproj b/TangramKit.xcodeproj/project.pbxproj index 915d09b..bff1bd3 100644 --- a/TangramKit.xcodeproj/project.pbxproj +++ b/TangramKit.xcodeproj/project.pbxproj @@ -23,6 +23,7 @@ 1890A2251EDF96C800D61C1A /* TGRelativeLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 681BD90C1E0B92E100403A1F /* TGRelativeLayout.swift */; }; 1890A2261EDF96C800D61C1A /* TGTableLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 681BD90D1E0B92E100403A1F /* TGTableLayout.swift */; }; 18BCBD461E1336D900AC7766 /* AllTest8ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18BCBD451E1336D900AC7766 /* AllTest8ViewController.swift */; }; + 20B6C6E71FA40AEC001D51C7 /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20B6C6E61FA40AEC001D51C7 /* DetailViewController.swift */; }; 681BD8DF1E0B91A500403A1F /* TangramKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 681BD8DD1E0B91A500403A1F /* TangramKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 681BD90F1E0B92E100403A1F /* TangramKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 681BD9011E0B92E100403A1F /* TangramKit.swift */; }; 681BD9111E0B92E100403A1F /* TGBaseLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 681BD9021E0B92E100403A1F /* TGBaseLayout.swift */; }; @@ -100,6 +101,7 @@ 18270C241C954B3C00CBCC92 /* TangramKitDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TangramKitDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 184243071E327F0800E2CCE1 /* FLLTest5ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FLLTest5ViewController.swift; sourceTree = ""; }; 18BCBD451E1336D900AC7766 /* AllTest8ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllTest8ViewController.swift; sourceTree = ""; }; + 20B6C6E61FA40AEC001D51C7 /* DetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = ""; }; 681BD8DB1E0B91A500403A1F /* TangramKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TangramKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 681BD8DD1E0B91A500403A1F /* TangramKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TangramKit.h; sourceTree = ""; }; 681BD8DE1E0B91A500403A1F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -250,6 +252,7 @@ 68F035E71E0B7D2700CEBAEF /* AppDelegate.swift */, 68F035E81E0B7D2700CEBAEF /* CFTool.swift */, 68F0363B1E0B7D2700CEBAEF /* ViewController.swift */, + 20B6C6E61FA40AEC001D51C7 /* DetailViewController.swift */, 68F035FC1E0B7D2700CEBAEF /* Images.xcassets */, 68F035E91E0B7D2700CEBAEF /* LaunchScreen.storyboard */, 68F036AE1E0B800000CEBAEF /* TangramKitPrefix.pch */, @@ -444,6 +447,7 @@ TargetAttributes = { 18270C231C954B3C00CBCC92 = { CreatedOnToolsVersion = 7.2; + DevelopmentTeam = Q5MFLFRY64; LastSwiftMigration = 0900; SystemCapabilities = { com.apple.BackgroundModes = { @@ -530,6 +534,7 @@ 68F036731E0B7D2700CEBAEF /* RLTest2ViewController.swift in Sources */, 18058AAF1E63B4EA00EAECDC /* FLLTest6ViewController.swift in Sources */, 68F036501E0B7D2700CEBAEF /* AllTest2ViewController.swift in Sources */, + 20B6C6E71FA40AEC001D51C7 /* DetailViewController.swift in Sources */, 184243081E327F0800E2CCE1 /* FLLTest5ViewController.swift in Sources */, 68F0363D1E0B7D2700CEBAEF /* CFTool.swift in Sources */, 68F036581E0B7D2700CEBAEF /* AllTest2TableViewCell.swift in Sources */, @@ -729,7 +734,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = Q5MFLFRY64; FRAMEWORK_SEARCH_PATHS = ""; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = TangramKit/TangramKitDemo/TangramKitPrefix.pch; @@ -750,7 +755,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = Q5MFLFRY64; FRAMEWORK_SEARCH_PATHS = ""; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = TangramKit/TangramKitDemo/TangramKitPrefix.pch; diff --git a/TangramKit/Info.plist b/TangramKit/Info.plist index c5ddeda..58241b6 100644 --- a/TangramKit/Info.plist +++ b/TangramKit/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.1.2 + 1.1.3 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/TangramKit/TGBaseLayout.swift b/TangramKit/TGBaseLayout.swift index 9519f84..164cdf1 100644 --- a/TangramKit/TGBaseLayout.swift +++ b/TangramKit/TGBaseLayout.swift @@ -156,6 +156,12 @@ extension UIView:TGViewSizeClass { return self.tgCurrentSizeClass.tg_right } + + /// 视图的基线位置对象。目前只支持相对布局里面的视图的设置并且调用视图或者被调用视图都只能是UILabel和UITextField和UITextView三个只支持单行文本的视图。 + public var tg_baseline:TGLayoutPos + { + return self.tgCurrentSizeClass.tg_baseline + } /* @@ -388,14 +394,13 @@ extension UIView:TGViewSizeClass } } - /** - 指定子在布局视图上的对齐方式,默认是.none表示未指定,这个属性目前只支持框架布局,线性布局,流式布局下的属性设置 - - 在框架布局中支持上、中、下、垂直拉伸和左、中、右、水平拉伸8个设置 - - 在垂直线性布局中只支持左、中、右、水平拉伸对齐。(如果父布局视图设置了gravity,子视图设置了这个属性则这个属性优先级最高) - - 在水平线性布局中只支持上、中、下、垂直拉伸对齐。(如果父布局视图设置了gravity,子视图设置了这个属性则这个属性优先级最高) - - 在垂直流式布局中用来设置一行内的上、中、下、垂直拉伸对齐。(如果父布局视图设置了arrangedGravity,子视图设置了这个属性则这个属性优先级最高) - - 在水平流式布局中用来设置一列内的左、中、右、水平拉伸对齐。(如果父布局视图设置了arrangedGravity,子视图时设置了这个属性则这个属性优先级最高) - */ + + ///指定子在布局视图上的对齐方式,默认是.none表示未指定,这个属性目前只支持框架布局,线性布局,流式布局下的属性设置. + /// - 在框架布局中支持上、中、下、垂直拉伸和左、中、右、水平拉伸8个设置 + /// - 在垂直线性布局中只支持左、中、右、水平拉伸对齐。(如果父布局视图设置了gravity,子视图设置了这个属性则这个属性优先级最高) + /// - 在水平线性布局中只支持上、中、下、垂直拉伸对齐。(如果父布局视图设置了gravity,子视图设置了这个属性则这个属性优先级最高) + /// - 在垂直流式布局中用来设置一行内的上、中、下、垂直拉伸对齐。(如果父布局视图设置了arrangedGravity,子视图设置了这个属性则这个属性优先级最高) + /// - 在水平流式布局中用来设置一列内的左、中、右、水平拉伸对齐。(如果父布局视图设置了arrangedGravity,子视图时设置了这个属性则这个属性优先级最高) public var tg_alignment:TGGravity { get @@ -526,6 +531,36 @@ extension UIView } + /// 四周边距或者间距设置的简化方法 + /// + /// - Parameter val: 距离父视图四周的边距或者兄弟视图四周间距的值 + public func tg_margin(_ val:CGFloat) + { + self.tg_leading.equal(val) + self.tg_trailing.equal(val) + self.tg_top.equal(val) + self.tg_bottom.equal(val) + } + + + /// 水平边距或者间距设置的简化方法 + /// + /// - Parameter val: 距离父视图左右水平边距或者兄弟视图左右间距的值 + public func tg_horzMargin(_ val:CGFloat) + { + self.tg_leading.equal(val) + self.tg_trailing.equal(val) + } + + + /// 垂直边距或者间距设置的简化方法 + /// + /// - Parameter val: 距离父视图上下垂直边距或者兄弟视图上下间距的值 + public func tg_vertMargin(_ val:CGFloat) + { + self.tg_top.equal(val) + self.tg_bottom.equal(val) + } /** @@ -646,7 +681,7 @@ public typealias TGLayoutBorderline = TGBorderline 布局视图基类,基类不支持实例化对象。在编程时我们经常会用到一些视图,这种视图只是负责将里面的子视图按照某种规则进行排列和布局,而别无其他的作用。因此我们称这种视图为容器视图或者称为布局视图。 布局视图通过重载layoutSubviews方法来完成子视图的布局和排列的工作。对于每个加入到布局视图中的子视图,都会在加入时通过KVO机制监控子视图的center和bounds以及frame值的变化,每当子视图的这些属性一变化时就又会重新引发布局视图的布局动作。同时对每个视图的布局扩展属性的设置以及对布局视图的布局属性的设置都会引发布局视图的布局动作。布局视图在添加到非布局父视图时也会通过KVO机制来监控非布局父视图的frame值和bounds值,这样每当非布局父视图的尺寸变更时也会引发布局视图的布局动作。前面说的引起变动的方法就是会在KVO处理逻辑以及布局扩展属性和布局属性设置完毕后通过调用setNeedLayout来实现的,当布局视图收到setNeedLayout的请求后,会在下一个runloop中对布局视图进行重新布局而这就是通过调用layoutSubviews方法来实现的。布局视图基类只提供了更新所有子视图的位置和尺寸以及一些基础的设置,而至于如何排列和布局这些子视图则要根据应用的场景和需求来确定,因此布局基类视图提供了一个: - internal func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool, type:TGSizeClassType) ->(selfSize:CGSize, hasSubLayout:Bool) + internal func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool, hasSubLayout:inout Bool!, sbs:[UIView]!, type:TGSizeClassType) ->CGSize 的方法,要求派生类去重载这个方法,这样不同的派生类就可以实现不同的应用场景,这就是布局视图的核心实现机制。 TangramKit布局库根据实际中常见的场景实现了7种不同的布局视图派生类他们分别是:线性布局、表格布局、相对布局、框架布局、流式布局、浮动布局、路径布局。 @@ -853,7 +888,7 @@ open class TGBaseLayout: UIView,TGLayoutViewSizeClass { } /** - 指定padding内边距的缩进是在SafeArea基础之上进行的。默认是.all表示四周都会缩进SafeArea所指定的区域。你也可以设置只缩进某一个或则几个方向,或者不缩进任何一个方向。这个属性是为了支持iPoneX而设置的。为了支持iPhoneX的全屏幕适配。我们只需要对根布局视图设置这个扩展属性,默认情况下是不需要进行特殊设置的,TangramKit自动会对iPhoneX进行适配。我们知道iOS11中引入了安全区域的概念,TangramKit中的根布局视图会自动将安全区域叠加到设置的padding中去。默认情况下四周的安全区域都会叠加到padding中去,因此您可以根据特殊情况来设置只需要叠加哪一个方向的安全区域。 + 指定padding内边距的缩进是在SafeArea基础之上进行的。默认是.all表示四周都会缩进SafeArea所指定的区域。你也可以设置只缩进某一个或则几个方向,或者不缩进任何一个方向。这个属性是为了支持iPoneX而设置的。为了支持iPhoneX的全屏幕适配。我们只需要对根布局视图设置这个扩展属性,默认情况下是不需要进行特殊设置的,TangramKit自动会对iPhoneX进行适配。我们知道iOS11中引入了安全区域的概念,TangramKit中的根布局视图会自动将安全区域叠加到设置的padding中去。默认情况下左右的安全区域都会叠加到padding中去,因此您可以根据特殊情况来设置只需要叠加哪一个方向的安全区域。 */ public var tg_insetsPaddingFromSafeArea:UIRectEdge { @@ -1386,6 +1421,30 @@ open class TGBaseLayout: UIView,TGLayoutViewSizeClass { _tgTouchEventDelegate = nil } + open override func safeAreaInsetsDidChange() { + + if #available(iOS 11.0, *) { + super.safeAreaInsetsDidChange() + } else { + // Fallback on earlier versions + } + + if self.superview != nil && !self.superview!.isKind(of: TGBaseLayout.self) + { + let lsc = self.tgCurrentSizeClass as! TGLayoutViewSizeClassImpl + if lsc.leading.isSafeAreaPos || lsc.trailing.isSafeAreaPos || lsc.top.isSafeAreaPos || lsc.bottom.isSafeAreaPos + { + if !self.tg_isLayouting + { + self.tg_isLayouting = true + _ = self.tgUpdateLayoutRectInNoLayoutSuperview(self.superview!) + self.tg_isLayouting = false + } + } + } + + } + override open func layoutSubviews() { if !self.autoresizesSubviews @@ -1456,7 +1515,8 @@ open class TGBaseLayout: UIView,TGLayoutViewSizeClass { } else { - (newSelfSize,_) = self.tgCalcLayoutRect(self.tgCalcSizeInNoLayout(newSuperview: self.superview, currentSize: oldSelfSize),isEstimate: false, sbs:nil, type:sizeClassType) + var hasSubLayout:Bool! = nil + newSelfSize = self.tgCalcLayoutRect(self.tgCalcSizeInNoLayout(newSuperview: self.superview, currentSize: oldSelfSize),isEstimate: false, hasSubLayout:&hasSubLayout, sbs:nil, type:sizeClassType) } newSelfSize = _tgRoundSize(newSelfSize) _tgUseCacheRects = false @@ -1636,14 +1696,33 @@ open class TGBaseLayout: UIView,TGLayoutViewSizeClass { let supv:UIView! = self.superview //如果自己的父视图是非UIScrollView以及非布局视图。以及自己的宽度是.wrap或者高度是.wrap时,并且如果设置了在父视图居中或者居下或者居右时要在父视图中更新自己的位置。 - if supv != nil && !supv.isKind(of: TGBaseLayout.self) && !supv.isKind(of: UIScrollView.self) + if supv != nil && !supv.isKind(of: TGBaseLayout.self) { - if lsc.isSomeSizeWrap + let rectSuper = supv.bounds + let rectSelf = self.bounds + var centerPonintSelf = self.center + + //特殊处理低版本下的top和bottom的两种安全区域的场景。 + if #available(iOS 11.0, *){} + else { + if lsc.top.isSafeAreaPos || lsc.bottom.isSafeAreaPos + { + if (lsc.top.isSafeAreaPos) + { + centerPonintSelf.y = lsc.top.weightPosIn(rectSuper.height) + self.layer.anchorPoint.y * rectSelf.height + } + else + { + centerPonintSelf.y = rectSuper.height - rectSelf.height - lsc.bottom.weightPosIn(rectSuper.height) + self.layer.anchorPoint.y * rectSelf.height + } + } + } + + + if !supv.isKind(of: UIScrollView.self) && lsc.isSomeSizeWrap { - let rectSuper = supv.bounds - let rectSelf = self.bounds - var centerPonintSelf = self.center + if TGBaseLayout.tg_isRTL { @@ -1681,12 +1760,12 @@ open class TGBaseLayout: UIView,TGLayoutViewSizeClass { centerPonintSelf.x = rectSuper.size.width - centerPonintSelf.x } - - //如果有变化则只调整自己的center。而不变化 - if !_tgCGPointEqual(self.center, centerPonintSelf) - { - self.center = centerPonintSelf - } + } + + //如果有变化则只调整自己的center。而不变化 + if !_tgCGPointEqual(self.center, centerPonintSelf) + { + self.center = centerPonintSelf } } @@ -1829,6 +1908,7 @@ open class TGBaseLayout: UIView,TGLayoutViewSizeClass { if (newSuperview != nil) { + let defRectEdge:UIRectEdge = [.left, .right] if self.value(forKey: "viewDelegate") != nil { if lsc.width.isWrap @@ -1841,9 +1921,22 @@ open class TGBaseLayout: UIView,TGLayoutViewSizeClass { lsc.tg_height.equal(nil) } + if lsc.tg_insetsPaddingFromSafeArea.rawValue == defRectEdge.rawValue + { + lsc.tg_insetsPaddingFromSafeArea = [.left, .right, .bottom] + } + self.tg_adjustScrollViewContentSizeMode = .no } + if ((newSuperview as? UIScrollView) != nil && (newSuperview as? UITableView) == nil && (newSuperview as? UICollectionView) == nil) + { + if lsc.tg_insetsPaddingFromSafeArea.rawValue == defRectEdge.rawValue + { + lsc.tg_insetsPaddingFromSafeArea = [.left, .right, .bottom] + } + } + } @@ -1948,6 +2041,17 @@ open class TGBaseLayout: UIView,TGLayoutViewSizeClass { { if self.tg_adjustScrollViewContentSizeMode == .auto { + //这里预先设置一下contentSize主要是为了解决contentOffset在后续计算contentSize的偏移错误的问题。 + UIView.performWithoutAnimation { + + // UIScrollView *scrollSuperView = (UIScrollView*)newSuperview; + if let scrollSuperView = newSuperview as? UIScrollView, scrollSuperView.contentSize.equalTo(.zero) + { + let screenSize = UIScreen.main.bounds.size + scrollSuperView.contentSize = CGSize(width:0, height:screenSize.height + 0.1) + } + } + self.tg_adjustScrollViewContentSizeMode = .yes } } @@ -2041,7 +2145,7 @@ open class TGBaseLayout: UIView,TGLayoutViewSizeClass { super.touchesCancelled(touches,with:event) } - internal func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool, sbs:[UIView]!, type:TGSizeClassType) ->(selfSize:CGSize, hasSubLayout:Bool) + internal func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool, hasSubLayout:inout Bool!, sbs:[UIView]!, type:TGSizeClassType) ->CGSize { var selfSize:CGSize @@ -2063,7 +2167,12 @@ open class TGBaseLayout: UIView,TGLayoutViewSizeClass { } } - return (selfSize, false) + if hasSubLayout != nil + { + hasSubLayout = false + } + + return selfSize } @@ -2368,7 +2477,15 @@ extension TGBaseLayout if (lsc.width.sizeVal != nil && lsc.width.sizeVal.view === newSuperview) || lsc.width.isFill { - size.width = lsc.width.measure(rectSuper.width) + + if lsc.width.isFill || lsc.width.sizeVal.type == TGGravity.horz.fill + { + size.width = lsc.width.measure(rectSuper.width) + } + else + { + size.width = lsc.width.measure(rectSuper.height) + } size.width = self.tgValidMeasure(lsc.width, sbv: self, calcSize: size.width, sbvSize: size, selfLayoutSize: rectSuper.size) } @@ -2391,7 +2508,15 @@ extension TGBaseLayout if (lsc.height.sizeVal != nil && lsc.height.sizeVal.view === newSuperview) || lsc.height.isFill { - size.height = lsc.height.measure(rectSuper.height) + if lsc.height.isFill || lsc.height.sizeVal.type == TGGravity.vert.fill + { + size.height = lsc.height.measure(rectSuper.height) + } + else + { + size.height = lsc.height.measure(rectSuper.width) + } + size.height = self.tgValidMeasure(lsc.height, sbv: self, calcSize: size.height, sbvSize: size, selfLayoutSize: rectSuper.size) } @@ -2423,9 +2548,9 @@ extension TGBaseLayout let lsc = self.tgCurrentSizeClass as! TGLayoutViewSizeClassImpl let rectSuper = newSuperview.bounds - let leadingMargin = lsc.leading.weightPosIn(rectSuper.width) + var leadingMargin = lsc.leading.weightPosIn(rectSuper.width) let trailingMargin = lsc.trailing.weightPosIn(rectSuper.width) - let topMargin = lsc.top.weightPosIn(rectSuper.height) + var topMargin = lsc.top.weightPosIn(rectSuper.height) let bottomMargin = lsc.bottom.weightPosIn(rectSuper.height) var rectSelf = self.bounds @@ -2491,6 +2616,14 @@ extension TGBaseLayout rectSelf.size.width = rectSuper.width - leadingMargin - trailingMargin rectSelf.size.width = self.tgValidMeasure(lsc.width,sbv:self,calcSize:rectSelf.width,sbvSize:rectSelf.size,selfLayoutSize:rectSuper.size); + if let scrollSuperView = newSuperview as? UIScrollView, #available(iOS 11.0, *) { + + if lsc.leading.isSafeAreaPos + { + leadingMargin = lsc.leading.offset + (TGBaseLayout.tg_isRTL ? scrollSuperView.safeAreaInsets.right : scrollSuperView.safeAreaInsets.left) - (TGBaseLayout.tg_isRTL ? scrollSuperView.adjustedContentInset.right : scrollSuperView.adjustedContentInset.left) + } + } + rectSelf.origin.x = leadingMargin } else if lsc.centerX.hasValue @@ -2500,6 +2633,14 @@ extension TGBaseLayout } else if lsc.leading.hasValue { + if let scrollSuperView = newSuperview as? UIScrollView, #available(iOS 11.0, *) { + + if lsc.leading.isSafeAreaPos + { + leadingMargin = lsc.leading.offset + (TGBaseLayout.tg_isRTL ? scrollSuperView.safeAreaInsets.right : scrollSuperView.safeAreaInsets.left) - (TGBaseLayout.tg_isRTL ? scrollSuperView.adjustedContentInset.right : scrollSuperView.adjustedContentInset.left) + } + } + rectSelf.origin.x = leadingMargin } else if lsc.trailing.hasValue @@ -2561,6 +2702,14 @@ extension TGBaseLayout rectSelf.size.height = rectSuper.height - topMargin - topMargin rectSelf.size.height = self.tgValidMeasure(lsc.height,sbv:self,calcSize:rectSelf.height,sbvSize:rectSelf.size,selfLayoutSize:rectSuper.size) + if let scrollSuperView = newSuperview as? UIScrollView, #available(iOS 11.0, *) { + + if lsc.top.isSafeAreaPos + { + topMargin = lsc.top.offset + scrollSuperView.safeAreaInsets.top - scrollSuperView.adjustedContentInset.top + } + } + rectSelf.origin.y = topMargin } else if lsc.centerY.hasValue @@ -2570,6 +2719,14 @@ extension TGBaseLayout } else if lsc.top.hasValue { + if let scrollSuperView = newSuperview as? UIScrollView, #available(iOS 11.0, *) { + + if lsc.top.isSafeAreaPos + { + topMargin = lsc.top.offset + scrollSuperView.safeAreaInsets.top - scrollSuperView.adjustedContentInset.top + } + } + rectSelf.origin.y = topMargin } else if lsc.bottom.hasValue @@ -2649,10 +2806,34 @@ extension TGBaseLayout let rectSuper = scrolv.bounds //这里把自己在父视图中的上下左右边距也算在contentSize的包容范围内。 - let leadingMargin = lsc.leading.weightPosIn(rectSuper.width) - let trailingMargin = lsc.trailing.weightPosIn(rectSuper.width) - let topMargin = lsc.top.weightPosIn(rectSuper.height) - let bottomMargin = lsc.bottom.weightPosIn(rectSuper.height) + var leadingMargin = lsc.leading.weightPosIn(rectSuper.width) + var trailingMargin = lsc.trailing.weightPosIn(rectSuper.width) + var topMargin = lsc.top.weightPosIn(rectSuper.height) + var bottomMargin = lsc.bottom.weightPosIn(rectSuper.height) + + + if #available(iOS 11.0, *){ + + if lsc.leading.isSafeAreaPos + { + leadingMargin = lsc.leading.offset + } + + if lsc.trailing.isSafeAreaPos + { + trailingMargin = lsc.trailing.offset + } + + if lsc.top.isSafeAreaPos + { + topMargin = lsc.top.offset + } + + if lsc.bottom.isSafeAreaPos + { + bottomMargin = lsc.bottom.offset + } + } if contSize.height != newSize.height + topMargin + bottomMargin { @@ -2663,8 +2844,22 @@ extension TGBaseLayout contSize.width = newSize.width + leadingMargin + trailingMargin } - scrolv.contentSize = contSize + //因为调整contentsize可能会调整contentOffset,所以为了保持一致性这里要还原掉原来的contentOffset + let oldOffset = scrolv.contentOffset + if !scrolv.contentSize.equalTo(contSize) + { + scrolv.contentSize = contSize + } + + if (oldOffset.x <= 0.0 || oldOffset.x <= contSize.width - rectSuper.size.width) && + (oldOffset.y <= 0.0 || oldOffset.y <= contSize.height - rectSuper.size.height) + { + if !scrolv.contentOffset.equalTo(oldOffset) + { + scrolv.contentOffset = oldOffset; + } + } } } @@ -2687,12 +2882,13 @@ extension TGBaseLayout } } - var (selfSize, hasSubLayout) = self.tgCalcLayoutRect(size, isEstimate: false, sbs:sbs, type: type) + var hasSubLayout:Bool! = false + var selfSize = self.tgCalcLayoutRect(size, isEstimate: false, hasSubLayout:&hasSubLayout, sbs:sbs, type: type) if hasSubLayout { tgFrame.width = selfSize.width tgFrame.height = selfSize.height - (selfSize,_) = self.tgCalcLayoutRect(.zero, isEstimate: true, sbs:sbs, type: type) + selfSize = self.tgCalcLayoutRect(.zero, isEstimate: true, hasSubLayout:&hasSubLayout, sbs:sbs, type: type) } tgFrame.width = selfSize.width tgFrame.height = selfSize.height @@ -2720,6 +2916,22 @@ extension TGBaseLayout } + + internal func tgGetSubviewFont(_ sbv:UIView) ->UIFont! + { + var sbvFont:UIFont! = nil; + + if sbv.isKind(of: UILabel.self) || + sbv.isKind(of: UITextField.self) || + sbv.isKind(of: UITextView.self) || + sbv.isKind(of: UIButton.self) + { + sbvFont = sbv.value(forKey: "font") as! UIFont + } + + return sbvFont; + } + internal func tgGetSubviewVertGravity(_ sbv:UIView, sbvsc:TGViewSizeClassImpl, vertGravity:TGGravity)->TGGravity { let sbvVertAlignment = sbvsc.tg_alignment & TGGravity.horz.mask @@ -2764,21 +2976,40 @@ extension TGBaseLayout - internal func tgCalcVertGravity(_ vert:TGGravity, selfSize:CGSize, sbv:UIView, sbvsc:TGViewSizeClassImpl, lsc:TGLayoutViewSizeClassImpl, rect:inout CGRect) + internal func tgCalcVertGravity(_ vert:TGGravity, selfSize:CGSize, topPadding:CGFloat, bottomPadding:CGFloat, baselinePos:CGFloat!, sbv:UIView, sbvsc:TGViewSizeClassImpl, lsc:TGLayoutViewSizeClassImpl, rect:inout CGRect) { - let fixedHeight = lsc.tgTopPadding + lsc.tgBottomPadding + let fixedHeight = topPadding + bottomPadding let topMargin = sbvsc.top.weightPosIn(selfSize.height - fixedHeight) let centerMargin = sbvsc.centerY.weightPosIn(selfSize.height - fixedHeight) let bottomMargin = sbvsc.bottom.weightPosIn(selfSize.height - fixedHeight) + var vert = vert + + //确保设置基线对齐的视图都是UILabel,UITextField,UITextView + if baselinePos == nil && vert == TGGravity.vert.baseline + { + vert = TGGravity.vert.top + } + + var sbvFont:UIFont! = nil + if vert == TGGravity.vert.baseline + { + sbvFont = self.tgGetSubviewFont(sbv) + } + + if sbvFont == nil && vert == TGGravity.vert.baseline + { + vert = TGGravity.vert.top + } + if vert == TGGravity.vert.fill { - rect.origin.y = lsc.tgTopPadding + topMargin; + rect.origin.y = topPadding + topMargin; rect.size.height = self.tgValidMeasure(sbvsc.height, sbv: sbv, calcSize:selfSize.height - fixedHeight - topMargin - bottomMargin , sbvSize: rect.size, selfLayoutSize: selfSize) } else if vert == TGGravity.vert.center { - rect.origin.y = (selfSize.height - fixedHeight - topMargin - bottomMargin - rect.size.height)/2 + lsc.tgTopPadding + topMargin + centerMargin; + rect.origin.y = (selfSize.height - fixedHeight - topMargin - bottomMargin - rect.size.height)/2 + topPadding + topMargin + centerMargin; } else if vert == TGGravity.vert.windowCenter { @@ -2792,11 +3023,16 @@ extension TGBaseLayout else if vert == TGGravity.vert.bottom { - rect.origin.y = selfSize.height - lsc.tgBottomPadding - bottomMargin - rect.size.height; + rect.origin.y = selfSize.height - bottomPadding - bottomMargin - rect.size.height; + } + else if vert == TGGravity.vert.baseline + { + //得到基线位置。 + rect.origin.y = baselinePos - sbvFont.ascender - (rect.height - sbvFont.lineHeight) / 2.0 } else { - rect.origin.y = lsc.tgTopPadding + topMargin; + rect.origin.y = topPadding + topMargin; } } @@ -2843,9 +3079,9 @@ extension TGBaseLayout } - internal func tgCalcHorzGravity(_ horz:TGGravity, selfSize:CGSize, sbv:UIView, sbvsc:TGViewSizeClassImpl, lsc:TGLayoutViewSizeClassImpl, rect:inout CGRect) + internal func tgCalcHorzGravity(_ horz:TGGravity, selfSize:CGSize, leadingPadding:CGFloat, trailingPadding:CGFloat, sbv:UIView, sbvsc:TGViewSizeClassImpl, lsc:TGLayoutViewSizeClassImpl, rect:inout CGRect) { - let fixedWidth = lsc.tgLeadingPadding + lsc.tgTrailingPadding + let fixedWidth = leadingPadding + trailingPadding let leadingMargin = sbvsc.leading.weightPosIn(selfSize.width - fixedWidth) let centerMargin = sbvsc.centerX.weightPosIn(selfSize.width - fixedWidth) let trailingMargin = sbvsc.trailing.weightPosIn(selfSize.width - fixedWidth) @@ -2853,12 +3089,12 @@ extension TGBaseLayout if horz == TGGravity.horz.fill { - rect.origin.x = lsc.tgLeadingPadding + leadingMargin; + rect.origin.x = leadingPadding + leadingMargin; rect.size.width = self.tgValidMeasure(sbvsc.width, sbv: sbv, calcSize:selfSize.width - fixedWidth - leadingMargin - trailingMargin , sbvSize: rect.size, selfLayoutSize: selfSize) } else if horz == TGGravity.horz.center { - rect.origin.x = (selfSize.width - fixedWidth - leadingMargin - trailingMargin - rect.size.width)/2 + lsc.tgLeadingPadding + leadingMargin + centerMargin; + rect.origin.x = (selfSize.width - fixedWidth - leadingMargin - trailingMargin - rect.size.width)/2 + leadingPadding + leadingMargin + centerMargin; } else if horz == TGGravity.horz.windowCenter { @@ -2876,12 +3112,11 @@ extension TGBaseLayout } else if horz == TGGravity.horz.trailing { - - rect.origin.x = selfSize.width - lsc.tgTrailingPadding - trailingMargin - rect.size.width; + rect.origin.x = selfSize.width - trailingPadding - trailingMargin - rect.size.width; } else { - rect.origin.x = lsc.tgLeadingPadding + leadingMargin; + rect.origin.x = leadingPadding + leadingMargin; } } @@ -3077,7 +3312,7 @@ extension TGBaseLayout let sbvtgFrame = subview.tgFrame if sbvtgFrame.sizeClass == nil { - sbvtgFrame.sizeClass = self.tgDefaultSizeClass + sbvtgFrame.sizeClass = subview.tgDefaultSizeClass } return (sbvtgFrame, sbvtgFrame.sizeClass as! TGViewSizeClassImpl) diff --git a/TangramKit/TGFloatLayout.swift b/TangramKit/TGFloatLayout.swift index cb16e79..5fc6044 100644 --- a/TangramKit/TGFloatLayout.swift +++ b/TangramKit/TGFloatLayout.swift @@ -199,9 +199,9 @@ open class TGFloatLayout: TGBaseLayout,TGFloatLayoutViewSizeClass { //MARK: override method - override internal func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool, sbs:[UIView]!, type :TGSizeClassType) ->(selfSize:CGSize, hasSubLayout:Bool) + override internal func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool, hasSubLayout:inout Bool!, sbs:[UIView]!, type :TGSizeClassType) -> CGSize { - var (selfSize, hasSubLayout) = super.tgCalcLayoutRect(size, isEstimate:isEstimate, sbs:sbs, type:type) + var selfSize = super.tgCalcLayoutRect(size, isEstimate:isEstimate, hasSubLayout:&hasSubLayout, sbs:sbs, type:type) var sbs:[UIView]! = sbs if sbs == nil @@ -224,7 +224,7 @@ open class TGFloatLayout: TGBaseLayout,TGFloatLayoutViewSizeClass { if let sbvl:TGBaseLayout = sbv as? TGBaseLayout { - if sbvsc.isSomeSizeWrap + if hasSubLayout != nil && sbvsc.isSomeSizeWrap { hasSubLayout = true } @@ -258,7 +258,7 @@ open class TGFloatLayout: TGBaseLayout,TGFloatLayoutViewSizeClass { tgAdjustSubviewsRTLPos(sbs: sbs, selfWidth: selfSize.width) - return (self.tgAdjustSizeWhenNoSubviews(size: selfSize, sbs: sbs, lsc:lsc),hasSubLayout) + return self.tgAdjustSizeWhenNoSubviews(size: selfSize, sbs: sbs, lsc:lsc) } diff --git a/TangramKit/TGFlowLayout.swift b/TangramKit/TGFlowLayout.swift index 1399c47..1d95302 100644 --- a/TangramKit/TGFlowLayout.swift +++ b/TangramKit/TGFlowLayout.swift @@ -260,8 +260,9 @@ open class TGFlowLayout:TGBaseLayout,TGFlowLayoutViewSizeClass { - override internal func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool, sbs:[UIView]!, type:TGSizeClassType) ->(selfSize:CGSize, hasSubLayout:Bool) { - var (selfSize, hasSubLayout) = super.tgCalcLayoutRect(size, isEstimate: isEstimate, sbs:sbs, type: type) + override internal func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool, hasSubLayout:inout Bool!, sbs:[UIView]!, type :TGSizeClassType) -> CGSize + { + var selfSize = super.tgCalcLayoutRect(size, isEstimate:isEstimate, hasSubLayout:&hasSubLayout, sbs:sbs, type:type) var sbs:[UIView]! = sbs if sbs == nil @@ -285,8 +286,6 @@ open class TGFlowLayout:TGBaseLayout,TGFlowLayoutViewSizeClass { if let sbvl:TGBaseLayout = sbv as? TGBaseLayout { - hasSubLayout = true - if sbvsc.width.isWrap { if (lsc.tg_pagedCount > 0 || (lsc.tg_orientation == .horz && (lsc.tg_arrangedGravity & TGGravity.vert.mask) == TGGravity.horz.fill) || @@ -305,7 +304,10 @@ open class TGFlowLayout:TGBaseLayout,TGFlowLayoutViewSizeClass { } } - + if hasSubLayout != nil && sbvsc.isSomeSizeWrap + { + hasSubLayout = true + } if isEstimate && sbvsc.isSomeSizeWrap { @@ -425,7 +427,7 @@ open class TGFlowLayout:TGBaseLayout,TGFlowLayoutViewSizeClass { tgAdjustSubviewsRTLPos(sbs: sbs, selfWidth: selfSize.width) - return (self.tgAdjustSizeWhenNoSubviews(size: selfSize, sbs: sbs, lsc:lsc),hasSubLayout) + return self.tgAdjustSizeWhenNoSubviews(size: selfSize, sbs: sbs, lsc:lsc) } @@ -805,6 +807,8 @@ extension TGFlowLayout fileprivate func tgCalcVertLayoutSinglelineWeight(selfSize:CGSize, totalFloatWidth:CGFloat, totalWeight:CGFloat,sbs:[UIView],startIndex:NSInteger, count:NSInteger) { + var totalFloatWidth = totalFloatWidth + var totalWeight = totalWeight for j in startIndex - count ..< startIndex { let sbv:UIView = sbs[j] @@ -817,7 +821,12 @@ extension TGFlowLayout widthWeight = t.rawValue/100 } - sbvtgFrame.width = self.tgValidMeasure(sbvsc.width, sbv:sbv,calcSize:sbvsc.width.measure(totalFloatWidth * widthWeight / totalWeight),sbvSize:sbvtgFrame.frame.size,selfLayoutSize:selfSize) + let tempWidth = sbvsc.width.measure(_tgRoundNumber(totalFloatWidth * ( widthWeight / totalWeight))) + + totalFloatWidth -= tempWidth + totalWeight -= widthWeight + + sbvtgFrame.width = self.tgValidMeasure(sbvsc.width, sbv:sbv,calcSize:tempWidth,sbvSize:sbvtgFrame.frame.size,selfLayoutSize:selfSize) sbvtgFrame.trailing = sbvtgFrame.leading + sbvtgFrame.width; } } @@ -825,6 +834,9 @@ extension TGFlowLayout fileprivate func tgCalcHorzLayoutSinglelineWeight(selfSize:CGSize, totalFloatHeight:CGFloat, totalWeight:CGFloat,sbs:[UIView],startIndex:NSInteger, count:NSInteger) { + var totalFloatHeight = totalFloatHeight + var totalWeight = totalWeight + for j in startIndex - count ..< startIndex { let sbv:UIView = sbs[j] let (sbvtgFrame, sbvsc) = self.tgGetSubviewFrameAndSizeClass(sbv) @@ -837,7 +849,12 @@ extension TGFlowLayout heightWeight = t.rawValue / 100 } - sbvtgFrame.height = self.tgValidMeasure(sbvsc.height,sbv:sbv,calcSize:sbvsc.height.measure(totalFloatHeight * heightWeight / totalWeight),sbvSize:sbvtgFrame.frame.size,selfLayoutSize:selfSize) + let tempHeight = sbvsc.height.measure(_tgRoundNumber(totalFloatHeight * ( heightWeight / totalWeight))) + + totalFloatHeight -= tempHeight + totalWeight -= heightWeight + + sbvtgFrame.height = self.tgValidMeasure(sbvsc.height,sbv:sbv,calcSize:tempHeight,sbvSize:sbvtgFrame.frame.size,selfLayoutSize:selfSize) sbvtgFrame.bottom = sbvtgFrame.top + sbvtgFrame.height; if sbvsc.width.isRelaSizeEqualTo(sbvsc.height) diff --git a/TangramKit/TGFrameLayout.swift b/TangramKit/TGFrameLayout.swift index 991b99c..0c20e92 100644 --- a/TangramKit/TGFrameLayout.swift +++ b/TangramKit/TGFrameLayout.swift @@ -23,9 +23,9 @@ open class TGFrameLayout: TGBaseLayout,TGFrameLayoutViewSizeClass { } - internal override func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool , sbs:[UIView]!, type:TGSizeClassType) -> (selfSize:CGSize, hasSubLayout:Bool) + override internal func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool, hasSubLayout:inout Bool!, sbs:[UIView]!, type :TGSizeClassType) -> CGSize { - var (selfSize,hasSubLayout) = super.tgCalcLayoutRect(size, isEstimate: isEstimate, sbs:sbs, type: type) + var selfSize = super.tgCalcLayoutRect(size, isEstimate:isEstimate, hasSubLayout:&hasSubLayout, sbs:sbs, type:type) var sbs:[UIView]! = sbs if sbs == nil @@ -37,13 +37,16 @@ open class TGFrameLayout: TGBaseLayout,TGFrameLayoutViewSizeClass { let horzGravity = self.tgConvertLeftRightGravityToLeadingTrailing(lsc.tg_gravity & TGGravity.vert.mask) let vertGravity = lsc.tg_gravity & TGGravity.horz.mask - - + let topPadding = lsc.tgTopPadding + let bottomPadding = lsc.tgBottomPadding + let leadingPadding = lsc.tgLeadingPadding + let trailingPadding = lsc.tgTrailingPadding + var maxWrapSize:CGSize! = nil if lsc.isSomeSizeWrap { - maxWrapSize = CGSize(width: lsc.tgLeadingPadding + lsc.tgTrailingPadding, height: lsc.tgTopPadding + lsc.tgBottomPadding) + maxWrapSize = CGSize(width: leadingPadding + trailingPadding, height: topPadding + bottomPadding) } for sbv in sbs @@ -70,7 +73,7 @@ open class TGFrameLayout: TGBaseLayout,TGFrameLayoutViewSizeClass { if let sbvl = sbv as? TGBaseLayout { - if sbvsc.isSomeSizeWrap + if hasSubLayout != nil && sbvsc.isSomeSizeWrap { hasSubLayout = true } @@ -94,6 +97,10 @@ open class TGFrameLayout: TGBaseLayout,TGFrameLayoutViewSizeClass { vertGravity:vertGravity, horzGravity:horzGravity, selfSize:selfSize, + leadingPadding:leadingPadding, + trailingPadding:trailingPadding, + topPadding:topPadding, + bottomPadding:bottomPadding, maxWrapSize:&maxWrapSize) } @@ -133,6 +140,10 @@ open class TGFrameLayout: TGBaseLayout,TGFrameLayoutViewSizeClass { vertGravity:vertGravity, horzGravity:horzGravity, selfSize:selfSize, + leadingPadding:leadingPadding, + trailingPadding:trailingPadding, + topPadding:topPadding, + bottomPadding:bottomPadding, maxWrapSize:&maxWrapSize) } @@ -141,7 +152,7 @@ open class TGFrameLayout: TGBaseLayout,TGFrameLayoutViewSizeClass { tgAdjustSubviewsRTLPos(sbs: sbs, selfWidth: selfSize.width) - return (self.tgAdjustSizeWhenNoSubviews(size: selfSize, sbs: sbs, lsc:lsc),hasSubLayout) + return self.tgAdjustSizeWhenNoSubviews(size: selfSize, sbs: sbs, lsc:lsc) } @@ -157,11 +168,15 @@ extension TGFrameLayout vertGravity:TGGravity, horzGravity:TGGravity, selfSize:CGSize, + leadingPadding:CGFloat, + trailingPadding:CGFloat, + topPadding:CGFloat, + bottomPadding:CGFloat, maxWrapSize:inout CGSize!) { - let selfFloatWidth = selfSize.width - lsc.tgLeadingPadding - lsc.tgTrailingPadding - let selfFloatHeight = selfSize.height - lsc.tgTopPadding - lsc.tgBottomPadding + let selfFloatWidth = selfSize.width - leadingPadding - trailingPadding + let selfFloatHeight = selfSize.height - topPadding - bottomPadding let leadingMargin = sbvsc.leading.weightPosIn(selfFloatWidth) let trailingMargin = sbvsc.trailing.weightPosIn(selfFloatWidth) let topMargin = sbvsc.top.weightPosIn(selfFloatHeight) @@ -215,7 +230,7 @@ extension TGFrameLayout //宽度有效性调整。 rect.size.width = self.tgValidMeasure(sbvsc.width, sbv:sbv, calcSize:rect.size.width, sbvSize:rect.size, selfLayoutSize:selfSize) - self.tgCalcHorzGravity(self.tgGetSubviewHorzGravity(sbv, sbvsc: sbvsc, horzGravity: horzGravity), selfSize:selfSize, sbv: sbv, sbvsc:sbvsc, lsc:lsc, rect: &rect) + self.tgCalcHorzGravity(self.tgGetSubviewHorzGravity(sbv, sbvsc: sbvsc, horzGravity: horzGravity), selfSize:selfSize,leadingPadding:leadingPadding,trailingPadding:trailingPadding, sbv: sbv, sbvsc:sbvsc, lsc:lsc, rect: &rect) if sbvsc.height.isFlexHeight @@ -226,7 +241,7 @@ extension TGFrameLayout rect.size.height = self.tgValidMeasure(sbvsc.height,sbv:sbv,calcSize:rect.size.height,sbvSize:rect.size, selfLayoutSize:selfSize) - self.tgCalcVertGravity(self.tgGetSubviewVertGravity(sbv, sbvsc: sbvsc, vertGravity: vertGravity), selfSize:selfSize, sbv: sbv, sbvsc:sbvsc, lsc:lsc,rect: &rect) + self.tgCalcVertGravity(self.tgGetSubviewVertGravity(sbv, sbvsc: sbvsc, vertGravity: vertGravity), selfSize:selfSize,topPadding:topPadding,bottomPadding: bottomPadding,baselinePos:nil, sbv: sbv, sbvsc:sbvsc, lsc:lsc,rect: &rect) //特殊处理宽度等于自身高度的情况。 @@ -234,7 +249,7 @@ extension TGFrameLayout { rect.size.width = self.tgValidMeasure(sbvsc.width, sbv: sbv, calcSize: sbvsc.width.measure(rect.size.height), sbvSize: rect.size, selfLayoutSize: selfSize) - self.tgCalcHorzGravity(self.tgGetSubviewHorzGravity(sbv, sbvsc: sbvsc, horzGravity: horzGravity), selfSize:selfSize, sbv: sbv, sbvsc:sbvsc, lsc:lsc, rect: &rect) + self.tgCalcHorzGravity(self.tgGetSubviewHorzGravity(sbv, sbvsc: sbvsc, horzGravity: horzGravity), selfSize:selfSize, leadingPadding:leadingPadding,trailingPadding:trailingPadding, sbv: sbv, sbvsc:sbvsc, lsc:lsc, rect: &rect) } @@ -251,7 +266,7 @@ extension TGFrameLayout rect.size.height = self.tgValidMeasure(sbvsc.height, sbv: sbv, calcSize: rect.size.height, sbvSize: rect.size, selfLayoutSize: selfSize) - self.tgCalcVertGravity(self.tgGetSubviewVertGravity(sbv, sbvsc: sbvsc, vertGravity: vertGravity), selfSize:selfSize, sbv: sbv,sbvsc:sbvsc, lsc:lsc, rect: &rect) + self.tgCalcVertGravity(self.tgGetSubviewVertGravity(sbv, sbvsc: sbvsc, vertGravity: vertGravity), selfSize:selfSize, topPadding:topPadding,bottomPadding: bottomPadding,baselinePos:nil,sbv: sbv,sbvsc:sbvsc, lsc:lsc, rect: &rect) } @@ -266,8 +281,8 @@ extension TGFrameLayout sbvSize:sbvsc.width, sbvMeasure:sbvtgFrame.width, sbvMaxPos:sbvtgFrame.trailing, - headPadding:lsc.tgLeadingPadding, - tailPadding:lsc.tgTrailingPadding, + headPadding:leadingPadding, + tailPadding:trailingPadding, lscSize:lsc.width, maxSize:maxWrapSize.width) @@ -277,8 +292,8 @@ extension TGFrameLayout sbvSize:sbvsc.height, sbvMeasure:sbvtgFrame.height, sbvMaxPos:sbvtgFrame.bottom, - headPadding:lsc.tgTopPadding, - tailPadding:lsc.tgBottomPadding, + headPadding:topPadding, + tailPadding:bottomPadding, lscSize:lsc.height, maxSize:maxWrapSize.height) } diff --git a/TangramKit/TGLayoutPos.swift b/TangramKit/TGLayoutPos.swift index 06bb71b..4f9b50f 100644 --- a/TangramKit/TGLayoutPos.swift +++ b/TangramKit/TGLayoutPos.swift @@ -29,6 +29,8 @@ protocol TGLayoutPosValue var absPos:CGFloat {get} + var isSafeAreaPos:Bool{get} + func weightPosIn(_ contentSize:CGFloat) -> CGFloat @@ -103,6 +105,46 @@ extension UIView:TGLayoutPosType{} final public class TGLayoutPos:TGLayoutPosValue { + /** + 特殊的位置。只用在布局视图和非布局父视图之间的位置约束和没有导航条时的布局视图内子视图的padding设置上。 + iOS11以后提出了安全区域的概念,因此对于iOS11以下的版本就需要兼容处理,尤其是在那些没有导航条的情况下。通过将布局视图的边距设置为这个特殊值就可以实现在任何版本中都能完美的实现位置的偏移而且各版本保持统一。比如下面的例子: + + @code + + //这里设置布局视图的左边和右边以及顶部的边距都是在父视图的安全区域外再缩进10个点的位置。你会注意到这里面定义了一个特殊的位置TGLayoutPos.tg_safeAreaMargin。 + //TGLayoutPos.tg_safeAreaMargin表示视图的边距不是一个固定的值而是所在的父视图的安全区域。这样布局视图就不会延伸到安全区域以外去了。 + //TGLayoutPos.tg_safeAreaMargin是同时支持iOS11和以下的版本的,对于iOS11以下的版本则顶部安全区域是状态栏以下的位置。 + //因此只要你设置边距为TGLayoutPos.tg_safeAreaMargin则可以同时兼容所有iOS的版本。。 + layoutView.tg_leading.equal(TGLayoutPos.tg_safeAreaMargin, offset:10) + layoutView.tg_trailing.equal(TGLayoutPos.tg_safeAreaMargin,offset:10) + layoutView.tg_top.equal(TGLayoutPos.tg_safeAreaMargin,offset:10) + + //如果你的左右边距都是安全区域,那么可以用下面的方法来简化设置。您可以注释掉这下面两句看看效果。 + //layoutView.tg_leading.equal(TGLayoutPos.tg_safeAreaMargin) + //layoutView.tg_trailing.equal(TGLayoutPos.tg_safeAreaMargin) + @endcode + + @code + + //在一个没有导航条的界面中,因为iPhoneX和其他设备的状态栏的高度不一致。所以你可以让布局视图的topPadding设置如下: + layoutView.tg_topPadding = TGLayoutPos.tg_safeAreaMargin + 10 //顶部内边距是安全区域外加10。那么这个和设置如下的: + layoutView.tg_topPadding = CGRectGetHeight([UIApplication sharedApplication].statusBarFrame) + 10; + + //这两者之间的区别后者是一个设置好的常数,一旦你的设备要支持横竖屏则不管横屏下是否有状态栏都会缩进固定的内边距,而前者则会根据当前是否状态栏而进行动态调整。 + //当然如果你的顶部就是要固定缩进状态栏的高度的话那么你可以直接直接用后者。 + + + @endcode + + @note + 需要注意的是这个值并不是一个真值,只是一个特殊值,不能用于读取。而且只能用于在MyLayoutPos的equalTo方法和布局视图上的padding属性上使用,其他地方使用后果未可知。 + + */ + public static var tg_safeAreaMargin:CGFloat + { + //在2017年10月3号定义的一个数字,没有其他特殊意义。 + return -20171003.0; + } //设置位置的值为数值类型,offset是在设置值的基础上的偏移量。 @discardableResult @@ -314,6 +356,42 @@ final public class TGLayoutPos:TGLayoutPosValue } } return v.length + case .safePosV(_): + if #available(iOS 11.0, *) + { + if let superView = _view.superview + { + switch (_type) { + case TGGravity.horz.leading: + return TGBaseLayout.tg_isRTL ? superView.safeAreaInsets.right : superView.safeAreaInsets.left + case TGGravity.horz.trailing: + return TGBaseLayout.tg_isRTL ? superView.safeAreaInsets.left : superView.safeAreaInsets.right + case TGGravity.vert.top: + return superView.safeAreaInsets.top + case TGGravity.vert.bottom: + return superView.safeAreaInsets.bottom + default: + return 0.0 + } + } + } + else + { + if let vc = self.findContainerVC() + { + if _type == TGGravity.vert.top + { + return vc.topLayoutGuide.length + } + else if _type == TGGravity.vert.bottom + { + return vc.bottomLayoutGuide.length + } + } + } + + return 0 + default: return nil } @@ -414,6 +492,7 @@ final public class TGLayoutPos:TGLayoutPosValue case posV(TGLayoutPos) case arrayV([TGLayoutPos]) case weightV(TGWeight) + case safePosV(CGFloat) case layoutSupport(UILayoutSupport) } @@ -442,7 +521,14 @@ extension TGLayoutPos if let v = val as? CGFloat { - _val = .floatV(v) + if v == TGLayoutPos.tg_safeAreaMargin + { + _val = .safePosV(v) + } + else + { + _val = .floatV(v) + } } else if let v = val as? Double { @@ -589,6 +675,24 @@ extension TGLayoutPos } } + internal var isSafeAreaPos:Bool + { + + guard _active && _val != nil else { + + return false + } + + switch _val! { + case .safePosV(_): + return true + case .layoutSupport(_): + return true + default: + return false + } + } + internal func weightPosIn(_ contentSize:CGFloat) -> CGFloat { @@ -638,6 +742,23 @@ extension TGLayoutPos baseLayout.setNeedsLayout() } } + + internal func findContainerVC() -> UIViewController! + { + var vc:UIViewController! = nil; + var v:UIView! = self.view; + while v != nil + { + vc = v.value(forKey: "viewDelegate") as? UIViewController + if (vc != nil) + { + break + } + + v = v.superview + } + return vc + } } diff --git a/TangramKit/TGLayoutSizeClass.swift b/TangramKit/TGLayoutSizeClass.swift index 611591a..581691a 100644 --- a/TangramKit/TGLayoutSizeClass.swift +++ b/TangramKit/TGLayoutSizeClass.swift @@ -116,6 +116,7 @@ public protocol TGViewSizeClass:class var tg_left:TGLayoutPos{get} var tg_right:TGLayoutPos{get} + var tg_baseline:TGLayoutPos{get} var tg_width:TGLayoutSize{get} var tg_height:TGLayoutSize{get} @@ -324,6 +325,16 @@ internal class TGViewSizeClassImpl:NSCopying,TGViewSizeClass { } } + + var tg_baseline: TGLayoutPos + { + if baseline.realPos == nil + { + baseline.realPos = TGLayoutPos(TGGravity.vert.baseline, view:self.view) + } + + return baseline.realPos + } var tg_width:TGLayoutSize @@ -369,6 +380,7 @@ internal class TGViewSizeClassImpl:NSCopying,TGViewSizeClass { internal lazy var trailing:TGLayoutPosValue2 = TGLayoutPosWrapper() internal lazy var centerX:TGLayoutPosValue2 = TGLayoutPosWrapper() internal lazy var centerY:TGLayoutPosValue2 = TGLayoutPosWrapper() + internal lazy var baseline:TGLayoutPosValue2 = TGLayoutPosWrapper() internal lazy var width:TGLayoutSizeValue2 = TGLayoutSizeWrapper() internal lazy var height:TGLayoutSizeValue2 = TGLayoutSizeWrapper() @@ -477,6 +489,10 @@ internal class TGViewSizeClassImpl:NSCopying,TGViewSizeClass { { tsc.centerY.realPos = self.centerY.realPos.copy() as? TGLayoutPos } + if self.baseline.realPos != nil + { + tsc.baseline.realPos = self.baseline.realPos.copy() as? TGLayoutPos + } if self.width.realSize != nil { tsc.width.realSize = self.width.realSize.copy() as? TGLayoutSize @@ -573,7 +589,7 @@ internal class TGLayoutViewSizeClassImpl:TGViewSizeClassImpl,TGLayoutViewSizeCla var tg_zeroPadding: Bool = true - var tg_insetsPaddingFromSafeArea: UIRectEdge = .all + var tg_insetsPaddingFromSafeArea: UIRectEdge = [.left, .right] var tg_insetLandscapeFringePadding: Bool = false var tg_vspace:CGFloat = 0 @@ -598,6 +614,11 @@ internal class TGLayoutViewSizeClassImpl:TGViewSizeClassImpl,TGLayoutViewSizeCla internal var tgTopPadding:CGFloat { + if self.tg_topPadding >= TGLayoutPos.tg_safeAreaMargin - 2000 && self.tg_topPadding <= TGLayoutPos.tg_safeAreaMargin + 2000 + { + return self.tg_topPadding - TGLayoutPos.tg_safeAreaMargin + UIApplication.shared.statusBarFrame.height + } + if ((self.tg_insetsPaddingFromSafeArea.rawValue & UIRectEdge.top.rawValue) == UIRectEdge.top.rawValue) { if #available(iOS 11.0, *) { @@ -610,6 +631,24 @@ internal class TGLayoutViewSizeClassImpl:TGViewSizeClassImpl,TGLayoutViewSizeCla internal var tgLeadingPadding:CGFloat { + if self.tg_leadingPadding >= TGLayoutPos.tg_safeAreaMargin - 2000 && self.tg_leadingPadding <= TGLayoutPos.tg_safeAreaMargin + 2000 + { + var leadingPaddingAdd:CGFloat = 0.0 + if UIScreen.main.bounds.height == 812 || UIScreen.main.bounds.width == 812 + { + if UIDevice.current.orientation.isLandscape + { + leadingPaddingAdd = 44 + } + else + { + leadingPaddingAdd = 0 + } + } + + return self.tg_leadingPadding - TGLayoutPos.tg_safeAreaMargin + leadingPaddingAdd + } + var inset:CGFloat = 0 if #available(iOS 11.0, *) { @@ -662,6 +701,25 @@ internal class TGLayoutViewSizeClassImpl:TGViewSizeClassImpl,TGLayoutViewSizeCla internal var tgBottomPadding:CGFloat { + + if self.tg_bottomPadding >= TGLayoutPos.tg_safeAreaMargin - 2000 && self.tg_bottomPadding <= TGLayoutPos.tg_safeAreaMargin + 2000 + { + var bottomPaddingAdd:CGFloat = 0.0 + //如果设备是iPhoneX就特殊处理。竖屏是34,横屏是21 + if UIScreen.main.bounds.height == 812 || UIScreen.main.bounds.width == 812 + { + if UIDevice.current.orientation.isLandscape + { + bottomPaddingAdd = 21 + } + else + { + bottomPaddingAdd = 34 + } + } + return self.tg_bottomPadding - TGLayoutPos.tg_safeAreaMargin + bottomPaddingAdd + } + if ((self.tg_insetsPaddingFromSafeArea.rawValue & UIRectEdge.bottom.rawValue) == UIRectEdge.bottom.rawValue) { if #available(iOS 11.0, *) { @@ -674,6 +732,25 @@ internal class TGLayoutViewSizeClassImpl:TGViewSizeClassImpl,TGLayoutViewSizeCla internal var tgTrailingPadding:CGFloat { + + if self.tg_trailingPadding >= TGLayoutPos.tg_safeAreaMargin - 2000 && self.tg_trailingPadding <= TGLayoutPos.tg_safeAreaMargin + 2000 + { + var trailingPaddingAdd:CGFloat = 0.0 + if UIScreen.main.bounds.height == 812 || UIScreen.main.bounds.width == 812 + { + if UIDevice.current.orientation.isLandscape + { + trailingPaddingAdd = 44 + } + else + { + trailingPaddingAdd = 0 + } + } + + return self.tg_trailingPadding - TGLayoutPos.tg_safeAreaMargin + trailingPaddingAdd + } + var inset:CGFloat = 0 if #available(iOS 11.0, *) { @@ -726,50 +803,12 @@ internal class TGLayoutViewSizeClassImpl:TGViewSizeClassImpl,TGLayoutViewSizeCla internal var tgLeftPadding:CGFloat { - var inset:CGFloat = 0 - - if #available(iOS 11.0, *) { - if (self.tg_insetsPaddingFromSafeArea.rawValue & UIRectEdge.left.rawValue) == UIRectEdge.left.rawValue - { - //如果只缩进刘海那一边。并且同时设置了左右缩进,并且当前刘海方向是右边那么就不缩进了。 - if (self.tg_insetLandscapeFringePadding && - (self.tg_insetsPaddingFromSafeArea.rawValue & (UIRectEdge.left.rawValue | UIRectEdge.right.rawValue)) == (UIRectEdge.left.rawValue | UIRectEdge.right.rawValue) && - UIDevice.current.orientation == .landscapeRight) - { - inset = 0 - } - else - { - inset = self.view.safeAreaInsets.left - } - } - } - - return self.tg_leftPadding + inset + return TGLayoutViewSizeClassImpl.IsRTL ? self.tgTrailingPadding : self.tgLeadingPadding } internal var tgRightPadding:CGFloat { - var inset:CGFloat = 0 - - if #available(iOS 11.0, *) { - if (self.tg_insetsPaddingFromSafeArea.rawValue & UIRectEdge.right.rawValue) == UIRectEdge.right.rawValue - { - //如果只缩进刘海那一边。并且同时设置了左右缩进,并且当前刘海方向是右边那么就不缩进了。 - if (self.tg_insetLandscapeFringePadding && - (self.tg_insetsPaddingFromSafeArea.rawValue & (UIRectEdge.left.rawValue | UIRectEdge.right.rawValue)) == (UIRectEdge.left.rawValue | UIRectEdge.right.rawValue) && - UIDevice.current.orientation == .landscapeLeft) - { - inset = 0 - } - else - { - inset = self.view.safeAreaInsets.right - } - } - } - - return self.tg_rightPadding + inset + return TGLayoutViewSizeClassImpl.IsRTL ? self.tgLeadingPadding : self.tgTrailingPadding } @@ -1021,6 +1060,15 @@ internal class TGLayoutPosWrapper:TGLayoutPosValue2 return p.absPos } + var isSafeAreaPos: Bool + { + guard let p = self.realPos else { + return false + } + + return p.isSafeAreaPos + } + func weightPosIn(_ contentSize:CGFloat) -> CGFloat { guard let p = self.realPos else { diff --git a/TangramKit/TGLinearLayout.swift b/TangramKit/TGLinearLayout.swift index ea3df57..e5aa316 100644 --- a/TangramKit/TGLinearLayout.swift +++ b/TangramKit/TGLinearLayout.swift @@ -85,7 +85,7 @@ open class TGLinearLayout: TGBaseLayout,TGLinearLayoutViewSizeClass { /** - *@param 用来设置当线性布局中的子视图的尺寸大于线性布局的尺寸时的子视图压缩策略。默认值是.none。 + *用来设置当线性布局中的子视图的尺寸大于线性布局的尺寸时的子视图压缩策略。默认值是.none。 * 这个枚举定义在线性布局里面当某个子视图的尺寸或者位置值为TGWeight类型时,而当剩余的有固定尺寸和间距的子视图的尺寸总和要大于 * 视图本身的尺寸时,对那些具有固定尺寸或者固定间距的子视图的处理方式。需要注意的是只有当子视图的尺寸和间距总和大于布局视图的尺寸时才有意义,否则无意义。 * 比如某个垂直线性布局的高度是100。 里面分别有A,B,C,D四个子视图。其中: @@ -157,6 +157,14 @@ open class TGLinearLayout: TGBaseLayout,TGLinearLayoutViewSizeClass { } } + /** + 设置水平线性布局里面的基线对齐基准视图,所有其他子视图的基线都以这个为准。 + 这个属性要和tg_gravity属性设置为TGGravity.vert.baseline配合使用。并且要求这个属性所指定的视图,必须具有font属性。 + 目前支持具有font属性的有UILabel,UITextField,UITextView, UIButton几个系统控件。 + */ + public var tg_baselineBaseView:UIView! + + /** *均分子视图和间距,布局会根据里面的子视图的数量来平均分配子视图的高度或者宽度以及间距。 *这个函数只对已经加入布局的视图有效,函数调用后新加入的子视图无效。 @@ -247,9 +255,9 @@ open class TGLinearLayout: TGBaseLayout,TGLinearLayoutViewSizeClass { //MARK: override method - override internal func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool, sbs:[UIView]!, type:TGSizeClassType) ->(selfSize:CGSize, hasSubLayout:Bool) + override internal func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool, hasSubLayout:inout Bool!, sbs:[UIView]!, type :TGSizeClassType) -> CGSize { - var (selfSize, hasSubLayout) = super.tgCalcLayoutRect(size, isEstimate:isEstimate, sbs:sbs, type:type) + var selfSize = super.tgCalcLayoutRect(size, isEstimate:isEstimate, hasSubLayout:&hasSubLayout, sbs:sbs, type:type) var sbs:[UIView]! = sbs if sbs == nil @@ -278,9 +286,9 @@ open class TGLinearLayout: TGBaseLayout,TGLinearLayoutViewSizeClass { if let sbvl:TGBaseLayout = sbv as? TGBaseLayout { - if sbvsc.isSomeSizeWrap + if hasSubLayout != nil && sbvsc.isSomeSizeWrap { - hasSubLayout = true + hasSubLayout = true } if isEstimate && (sbvsc.isSomeSizeWrap) @@ -330,7 +338,7 @@ open class TGLinearLayout: TGBaseLayout,TGLinearLayoutViewSizeClass { tgAdjustSubviewsRTLPos(sbs: sbs, selfWidth: selfSize.width) - return (self.tgAdjustSizeWhenNoSubviews(size: selfSize, sbs: sbs, lsc:lsc),hasSubLayout) + return self.tgAdjustSizeWhenNoSubviews(size: selfSize, sbs: sbs, lsc:lsc) } @@ -340,6 +348,15 @@ open class TGLinearLayout: TGBaseLayout,TGLinearLayoutViewSizeClass { return TGLinearLayoutViewSizeClassImpl(view:self) } + override open func willRemoveSubview(_ subview: UIView) { + super.willRemoveSubview(subview) + + if subview === self.tg_baselineBaseView + { + self.tg_baselineBaseView = nil + } + } + } //internal and private method @@ -507,7 +524,7 @@ extension TGLinearLayout { } - private func tgAdjustSelfWidth(_ sbs:[UIView], selfSize:CGSize, lsc:TGLinearLayoutViewSizeClassImpl) ->CGFloat + private func tgCalcMaxWrapWidth(_ sbs:[UIView], selfSize:CGSize, horzPadding:CGFloat, lsc:TGLinearLayoutViewSizeClassImpl) ->CGFloat { var maxSubviewWidth:CGFloat = 0 @@ -539,7 +556,7 @@ extension TGLinearLayout { } } - retWidth = maxSubviewWidth + lsc.tgLeadingPadding + lsc.tgTrailingPadding; + retWidth = maxSubviewWidth + horzPadding } return retWidth @@ -635,15 +652,19 @@ extension TGLinearLayout { var totalWeight:TGWeight = .zeroWeight //剩余部分的总比重 var selfSize = selfSize let horzGravity = self.tgConvertLeftRightGravityToLeadingTrailing(lsc.tg_gravity & TGGravity.vert.mask) + let topPadding = lsc.tgTopPadding + let bottomPadding = lsc.tgBottomPadding + let leadingPadding = lsc.tgLeadingPadding + let trailingPadding = lsc.tgTrailingPadding - selfSize.width = self.tgAdjustSelfWidth(sbs, selfSize:selfSize, lsc:lsc) //调整自身的宽度 + selfSize.width = self.tgCalcMaxWrapWidth(sbs, selfSize:selfSize, horzPadding: leadingPadding + trailingPadding, lsc:lsc) //调整自身的宽度 var addSpace:CGFloat = 0 var fixedSizeSbs = [UIView]() var fixedSizeHeight:CGFloat = 0 var fixedSpaceCount:Int = 0 var fixedSpaceHeight:CGFloat = 0 - var pos:CGFloat = lsc.tgTopPadding + var pos:CGFloat = topPadding for sbv in sbs { let (sbvtgFrame, sbvsc) = self.tgGetSubviewFrameAndSizeClass(sbv) @@ -653,12 +674,12 @@ extension TGLinearLayout { var rect = sbvtgFrame.frame; - self.tgCalcLeadingTrailingRect(horzGravity: horzGravity, selfSize: selfSize, sbv: sbv, sbvsc: sbvsc, lsc: lsc, rect:&rect) + self.tgCalcLeadingTrailingRect(horzGravity: horzGravity, selfSize: selfSize, leadingPadding:leadingPadding, trailingPadding:trailingPadding, sbv: sbv, sbvsc: sbvsc, lsc: lsc, rect:&rect) rect.size.height = sbvsc.height.numberSize(rect.size.height) if (sbvsc.height.isRelaSizeEqualTo(lsc.height) && !lsc.height.isWrap) { - rect.size.height = sbvsc.height.measure(selfSize.height - lsc.tgTopPadding - lsc.tgBottomPadding) + rect.size.height = sbvsc.height.measure(selfSize.height - topPadding - bottomPadding) } if sbvsc.height.isRelaSizeEqualTo(sbvsc.width) @@ -756,7 +777,7 @@ extension TGLinearLayout { //在包裹宽度且总体比重不为0时则,则需要还原最小的宽度,这样就不会使得宽度在横竖屏或者多次计算后越来越宽。 if lsc.height.isWrap && totalWeight != .zeroWeight { - var tempSelfHeight = lsc.tgTopPadding + lsc.tgBottomPadding + var tempSelfHeight = topPadding + bottomPadding if sbs.count > 1 { tempSelfHeight += CGFloat(sbs.count - 1) * lsc.tg_vspace @@ -770,7 +791,7 @@ extension TGLinearLayout { //剩余的可浮动的高度,那些weight不为0的从这个高度来进行分发 var isWeightShrinkSpace = false var weightShrinkSpaceTotalHeight:CGFloat = 0.0 - floatingHeight = selfSize.height - fixedHeight - lsc.tgTopPadding - lsc.tgBottomPadding + floatingHeight = selfSize.height - fixedHeight - topPadding - bottomPadding let sstMode:TGSubviewsShrinkType = TGSubviewsShrinkType(rawValue: lsc.tg_shrinkType.rawValue & 0x0F) //压缩策略 let sstContent:TGSubviewsShrinkType = TGSubviewsShrinkType(rawValue: lsc.tg_shrinkType.rawValue & 0xF0) //压缩内容 if _tgCGFloatLessOrEqual(floatingHeight, 0) @@ -830,7 +851,7 @@ extension TGLinearLayout { if totalWeight != .zeroWeight || (sstMode != .none && _tgCGFloatLessOrEqual(floatingHeight, 0)) { - pos = lsc.tgTopPadding + pos = topPadding for sbv in sbs { let (sbvtgFrame, sbvsc) = self.tgGetSubviewFrameAndSizeClass(sbv) @@ -949,7 +970,7 @@ extension TGLinearLayout { } } - pos += lsc.tgBottomPadding; + pos += bottomPadding; if lsc.height.isWrap @@ -969,6 +990,11 @@ extension TGLinearLayout { var fixedWidth:CGFloat = 0; //计算固定部分的高度 var floatingWidth:CGFloat = 0; //浮动的高度。 var totalWeight:TGWeight = .zeroWeight + let topPadding = lsc.tgTopPadding + let bottomPadding = lsc.tgBottomPadding + let leadingPadding = lsc.tgLeadingPadding + let trailingPadding = lsc.tgTrailingPadding + var maxSubviewHeight:CGFloat = 0; var selfSize = selfSize @@ -1035,7 +1061,7 @@ extension TGLinearLayout { var vWidth = sbvsc.width.numberSize(sbvtgFrame.width) if (sbvsc.width.isRelaSizeEqualTo(lsc.width) && !lsc.width.isWrap) { - vWidth = sbvsc.width.measure(selfSize.width - lsc.tgLeadingPadding - lsc.tgTrailingPadding) + vWidth = sbvsc.width.measure(selfSize.width - leadingPadding - trailingPadding) } vWidth = self.tgValidMeasure(sbvsc.width,sbv:sbv,calcSize:vWidth,sbvSize:sbvtgFrame.frame.size,selfLayoutSize:selfSize) @@ -1071,7 +1097,7 @@ extension TGLinearLayout { //在包裹宽度且总体比重不为0时则,则需要还原最小的宽度,这样就不会使得宽度在横竖屏或者多次计算后越来越宽。 if (lsc.width.isWrap && totalWeight != .zeroWeight) { - var tempSelfWidth = lsc.tgLeadingPadding + lsc.tgTrailingPadding + var tempSelfWidth = leadingPadding + trailingPadding if sbs.count > 1 { tempSelfWidth += CGFloat(sbs.count - 1) * lsc.tg_hspace @@ -1083,7 +1109,7 @@ extension TGLinearLayout { //剩余的可浮动的宽度,那些weight不为0的从这个高度来进行分发 var isWeightShrinkSpace = false //是否按比重缩小间距。。。 var weightShrinkSpaceTotalWidth:CGFloat = 0.0 - floatingWidth = selfSize.width - fixedWidth - lsc.tgLeadingPadding - lsc.tgTrailingPadding; + floatingWidth = selfSize.width - fixedWidth - leadingPadding - trailingPadding; if _tgCGFloatLessOrEqual(floatingWidth, 0) { var sstMode:TGSubviewsShrinkType = TGSubviewsShrinkType(rawValue: lsc.tg_shrinkType.rawValue & 0x0F) //压缩策略 @@ -1186,8 +1212,9 @@ extension TGLinearLayout { floatingWidth = 0; } + var baselinePos:CGFloat! = nil //保存基线的值 //调整所有子视图的宽度 - var pos:CGFloat = lsc.tgLeadingPadding; + var pos:CGFloat = leadingPadding; for sbv in sbs { let (sbvtgFrame, sbvsc) = self.tgGetSubviewFrameAndSizeClass(sbv) @@ -1206,7 +1233,7 @@ extension TGLinearLayout { if sbvsc.height.isRelaSizeEqualTo(lsc.height) { - rect.size.height = sbvsc.height.measure(selfSize.height - lsc.tgTopPadding - lsc.tgBottomPadding) + rect.size.height = sbvsc.height.measure(selfSize.height - topPadding - bottomPadding) } @@ -1340,13 +1367,23 @@ extension TGLinearLayout { } else { - self.tgCalcTopBottomRect(vertGravity:vertGravity, selfSize: selfSize, sbv: sbv, sbvsc: sbvsc, lsc: lsc, rect: &rect) + self.tgCalcTopBottomRect(vertGravity:vertGravity, selfSize: selfSize, topPadding:topPadding, bottomPadding:bottomPadding,baselinePos:baselinePos, sbv: sbv, sbvsc: sbvsc, lsc: lsc, rect: &rect) + + //如果垂直方向的对齐方式是基线对齐,那么就以第一个具有基线的视图作为标准位置。 + if vertGravity == TGGravity.vert.baseline && baselinePos == nil && self.tg_baselineBaseView === sbv + { + let sbvFont = sbv.value(forKey: "font") as! UIFont + //这里要求baselineBaseView必须要具有font属性。 + //得到基线位置。 + baselinePos = rect.origin.y + (rect.height - sbvFont.lineHeight) / 2.0 + sbvFont.ascender + } + } sbvtgFrame.frame = rect; } - pos += lsc.tgTrailingPadding; + pos += trailingPadding; if lsc.width.isWrap { @@ -1355,7 +1392,7 @@ extension TGLinearLayout { if lsc.height.isWrap { - selfSize.height = maxSubviewHeight + lsc.tgTopPadding + lsc.tgBottomPadding + selfSize.height = maxSubviewHeight + topPadding + bottomPadding //调整所有子视图的高度 for sbv in sbs @@ -1363,9 +1400,19 @@ extension TGLinearLayout { let (sbvtgFrame, sbvsc) = self.tgGetSubviewFrameAndSizeClass(sbv) var rect:CGRect = sbvtgFrame.frame; - self.tgCalcTopBottomRect(vertGravity:vertGravity, selfSize: selfSize, sbv: sbv, sbvsc: sbvsc, lsc: lsc, rect: &rect) + self.tgCalcTopBottomRect(vertGravity:vertGravity, selfSize: selfSize, topPadding:topPadding, bottomPadding:bottomPadding,baselinePos:baselinePos, sbv: sbv, sbvsc: sbvsc, lsc: lsc, rect: &rect) sbvtgFrame.frame = rect + + //如果垂直方向的对齐方式是基线对齐,那么就以第一个具有基线的视图作为标准位置。 + if vertGravity == TGGravity.vert.baseline && baselinePos == nil && self.tg_baselineBaseView == sbv + { + let sbvFont = sbv.value(forKey: "font") as! UIFont + //这里要求baselineBaseView必须要具有font属性。 + //得到基线位置。 + baselinePos = rect.origin.y + (rect.height - sbvFont.lineHeight) / 2.0 + sbvFont.ascender + } + } } @@ -1379,6 +1426,11 @@ extension TGLinearLayout { let vertGravity = lsc.tg_gravity & TGGravity.horz.mask let horzGravity = self.tgConvertLeftRightGravityToLeadingTrailing(lsc.tg_gravity & TGGravity.vert.mask) + let topPadding = lsc.tgTopPadding + let bottomPadding = lsc.tgBottomPadding + let leadingPadding = lsc.tgLeadingPadding + let trailingPadding = lsc.tgTrailingPadding + var totalHeight:CGFloat = 0 @@ -1388,9 +1440,9 @@ extension TGLinearLayout { } var selfSize = selfSize - selfSize.width = self.tgAdjustSelfWidth(sbs, selfSize:selfSize, lsc:lsc) + selfSize.width = self.tgCalcMaxWrapWidth(sbs, selfSize:selfSize, horzPadding: leadingPadding + trailingPadding, lsc:lsc) - var floatingHeight:CGFloat = selfSize.height - lsc.tgTopPadding - lsc.tgBottomPadding - totalHeight + var floatingHeight:CGFloat = selfSize.height - topPadding - bottomPadding - totalHeight if _tgCGFloatLessOrEqual(floatingHeight, 0) { floatingHeight = 0 @@ -1409,7 +1461,7 @@ extension TGLinearLayout { var rect:CGRect = sbvtgFrame.frame; - self.tgCalcLeadingTrailingRect(horzGravity: horzGravity , selfSize: selfSize, sbv: sbv, sbvsc: sbvsc, lsc: lsc, rect: &rect) + self.tgCalcLeadingTrailingRect(horzGravity: horzGravity , selfSize: selfSize, leadingPadding:leadingPadding,trailingPadding:trailingPadding, sbv: sbv, sbvsc: sbvsc, lsc: lsc, rect: &rect) rect.size.height = sbvsc.height.numberSize(rect.size.height) @@ -1417,7 +1469,7 @@ extension TGLinearLayout { if (sbvsc.height.isRelaSizeEqualTo(lsc.height) && !lsc.height.isWrap) { - rect.size.height = sbvsc.height.measure(selfSize.height - lsc.tgTopPadding - lsc.tgBottomPadding) + rect.size.height = sbvsc.height.measure(selfSize.height - topPadding - bottomPadding) canAddToNoWrapSbs = false } @@ -1468,12 +1520,12 @@ extension TGLinearLayout { if vertGravity == TGGravity.vert.top { - pos = lsc.tgTopPadding; + pos = topPadding; } else if vertGravity == TGGravity.vert.center { - pos = (selfSize.height - totalHeight - lsc.tgBottomPadding - lsc.tgTopPadding)/2.0; - pos += lsc.tgTopPadding; + pos = (selfSize.height - totalHeight - bottomPadding - topPadding)/2.0; + pos += topPadding; } else if vertGravity == TGGravity.vert.windowCenter { @@ -1489,28 +1541,28 @@ extension TGLinearLayout { } else if vertGravity == TGGravity.vert.bottom { - pos = selfSize.height - totalHeight - lsc.tgBottomPadding + pos = selfSize.height - totalHeight - bottomPadding } else if vertGravity == TGGravity.vert.between { - pos = lsc.tgTopPadding; + pos = topPadding; if sbs.count > 1 { - between = (selfSize.height - totalHeight - lsc.tgTopPadding - lsc.tgBottomPadding) / CGFloat(sbs.count - 1) + between = (selfSize.height - totalHeight - topPadding - bottomPadding) / CGFloat(sbs.count - 1) } } else if vertGravity == TGGravity.vert.fill { - pos = lsc.tgTopPadding + pos = topPadding if noWrapsbsSet.count > 0 { - fill = (selfSize.height - totalHeight - lsc.tgTopPadding - lsc.tgBottomPadding) / CGFloat(noWrapsbsSet.count) + fill = (selfSize.height - totalHeight - topPadding - bottomPadding) / CGFloat(noWrapsbsSet.count) } } else { - pos = lsc.tgTopPadding + pos = topPadding } @@ -1550,6 +1602,10 @@ extension TGLinearLayout { { let vertGravity = lsc.tg_gravity & TGGravity.horz.mask let horzGravity = self.tgConvertLeftRightGravityToLeadingTrailing(lsc.tg_gravity & TGGravity.vert.mask) + let topPadding = lsc.tgTopPadding + let bottomPadding = lsc.tgBottomPadding + let leadingPadding = lsc.tgLeadingPadding + let trailingPadding = lsc.tgTrailingPadding var totalWidth:CGFloat = 0; if sbs.count > 1 { @@ -1562,7 +1618,7 @@ extension TGLinearLayout { var maxSubviewHeight:CGFloat = 0; var selfSize = selfSize - floatingWidth = selfSize.width - lsc.tgLeadingPadding - lsc.tgTrailingPadding - totalWidth; + floatingWidth = selfSize.width - leadingPadding - trailingPadding - totalWidth if _tgCGFloatLessOrEqual(floatingWidth, 0) { floatingWidth = 0 @@ -1590,13 +1646,13 @@ extension TGLinearLayout { if (sbvsc.width.isRelaSizeEqualTo(lsc.width) && !lsc.width.isWrap) { - rect.size.width = sbvsc.width.measure(selfSize.width - lsc.tgLeadingPadding - lsc.tgTrailingPadding) + rect.size.width = sbvsc.width.measure(selfSize.width - leadingPadding - trailingPadding) canAddToNoWrapSbs = false } if sbvsc.height.isRelaSizeEqualTo(lsc.height) { - rect.size.height = sbvsc.height.measure(selfSize.height - lsc.tgTopPadding - lsc.tgBottomPadding) + rect.size.height = sbvsc.height.measure(selfSize.height - topPadding - bottomPadding) } if sbvsc.width.isRelaSizeEqualTo(sbvsc.height) @@ -1661,7 +1717,7 @@ extension TGLinearLayout { //调整自己的高度。 if lsc.height.isWrap { - selfSize.height = maxSubviewHeight + lsc.tgTopPadding + lsc.tgBottomPadding; + selfSize.height = maxSubviewHeight + topPadding + bottomPadding; } //根据对齐的方位来定位子视图的布局对齐 @@ -1671,12 +1727,12 @@ extension TGLinearLayout { if horzGravity == TGGravity.horz.leading { - pos = lsc.tgLeadingPadding + pos = leadingPadding } else if horzGravity == TGGravity.horz.center { - pos = (selfSize.width - totalWidth - lsc.tgLeadingPadding - lsc.tgTrailingPadding)/2.0; - pos += lsc.tgLeadingPadding; + pos = (selfSize.width - totalWidth - leadingPadding - trailingPadding)/2.0; + pos += leadingPadding; } else if horzGravity == TGGravity.horz.windowCenter { @@ -1695,32 +1751,32 @@ extension TGLinearLayout { } else if horzGravity == TGGravity.horz.trailing { - pos = selfSize.width - totalWidth - lsc.tgTrailingPadding; + pos = selfSize.width - totalWidth - trailingPadding; } else if horzGravity == TGGravity.horz.between { - pos = lsc.tgLeadingPadding + pos = leadingPadding if sbs.count > 1 { - between = (selfSize.width - totalWidth - lsc.tgLeadingPadding - lsc.tgTrailingPadding) / CGFloat(sbs.count - 1) + between = (selfSize.width - totalWidth - leadingPadding - trailingPadding) / CGFloat(sbs.count - 1) } } else if horzGravity == TGGravity.horz.fill { - pos = lsc.tgLeadingPadding + pos = leadingPadding if noWrapsbsSet.count > 0 { - fill = (selfSize.width - totalWidth - lsc.tgLeadingPadding - lsc.tgTrailingPadding) / CGFloat(noWrapsbsSet.count) + fill = (selfSize.width - totalWidth - leadingPadding - trailingPadding) / CGFloat(noWrapsbsSet.count) } } else { - pos = lsc.tgLeadingPadding + pos = leadingPadding } - + var baselinePos:CGFloat! = nil; //保存基线的值。 for sbv in sbs { let (sbvtgFrame, sbvsc) = self.tgGetSubviewFrameAndSizeClass(sbv) @@ -1735,7 +1791,7 @@ extension TGLinearLayout { var rect = sbvtgFrame.frame; rect.origin.x = pos; - self.tgCalcTopBottomRect(vertGravity: vertGravity, selfSize: selfSize, sbv: sbv, sbvsc: sbvsc, lsc: lsc, rect: &rect) + self.tgCalcTopBottomRect(vertGravity: vertGravity, selfSize: selfSize, topPadding:topPadding, bottomPadding:bottomPadding, baselinePos:baselinePos, sbv: sbv, sbvsc: sbvsc, lsc: lsc, rect: &rect) if fill != 0 && noWrapsbsSet.contains(sbv) { @@ -1753,7 +1809,16 @@ extension TGLinearLayout { pos += lsc.tg_hspace; } - pos += between; //只有mghorz为between才加这个间距拉伸。 + pos += between //只有mghorz为between才加这个间距拉伸。 + + //如果垂直方向的对齐方式是基线对齐,那么就以第一个具有基线的视图作为标准位置。 + if vertGravity == TGGravity.vert.baseline && baselinePos == nil && self.tg_baselineBaseView == sbv + { + let sbvFont = sbv.value(forKey: "font") as! UIFont + //这里要求baselineBaseView必须要具有font属性。 + //得到基线位置。 + baselinePos = rect.origin.y + (rect.height - sbvFont.lineHeight) / 2.0 + sbvFont.ascender + } } return selfSize; @@ -1782,10 +1847,10 @@ extension TGLinearLayout { } } - fileprivate func tgCalcLeadingTrailingRect(horzGravity:TGGravity, selfSize:CGSize, sbv:UIView, sbvsc:TGViewSizeClassImpl, lsc:TGLinearLayoutViewSizeClassImpl, rect:inout CGRect) + fileprivate func tgCalcLeadingTrailingRect(horzGravity:TGGravity, selfSize:CGSize,leadingPadding:CGFloat,trailingPadding:CGFloat, sbv:UIView, sbvsc:TGViewSizeClassImpl, lsc:TGLinearLayoutViewSizeClassImpl, rect:inout CGRect) { - let floatingWidth = selfSize.width - lsc.tgLeadingPadding - lsc.tgTrailingPadding + let floatingWidth = selfSize.width - leadingPadding - trailingPadding let realLeadingMargin = sbvsc.leading.weightPosIn(floatingWidth) let realTrailingMargin = sbvsc.trailing.weightPosIn(floatingWidth) @@ -1808,13 +1873,13 @@ extension TGLinearLayout { } rect.size.width = self.tgValidMeasure(sbvsc.width,sbv:sbv,calcSize:rect.size.width,sbvSize:rect.size,selfLayoutSize:selfSize) - self.tgCalcHorzGravity(self.tgGetSubviewHorzGravity(sbv, sbvsc:sbvsc, horzGravity: horzGravity), selfSize:selfSize, sbv:sbv,sbvsc:sbvsc, lsc:lsc, rect:&rect) + self.tgCalcHorzGravity(self.tgGetSubviewHorzGravity(sbv, sbvsc:sbvsc, horzGravity: horzGravity), selfSize:selfSize,leadingPadding:leadingPadding, trailingPadding:trailingPadding, sbv:sbv,sbvsc:sbvsc, lsc:lsc, rect:&rect) } - fileprivate func tgCalcTopBottomRect(vertGravity:TGGravity, selfSize:CGSize, sbv:UIView, sbvsc:TGViewSizeClassImpl, lsc:TGLinearLayoutViewSizeClassImpl, rect:inout CGRect) + fileprivate func tgCalcTopBottomRect(vertGravity:TGGravity, selfSize:CGSize, topPadding:CGFloat, bottomPadding:CGFloat, baselinePos:CGFloat!, sbv:UIView, sbvsc:TGViewSizeClassImpl, lsc:TGLinearLayoutViewSizeClassImpl, rect:inout CGRect) { - let floatingHeight = selfSize.height - lsc.tgTopPadding - lsc.tgBottomPadding + let floatingHeight = selfSize.height - topPadding - bottomPadding let realTopMargin = sbvsc.top.weightPosIn(floatingHeight) let realBottomMargin = sbvsc.bottom.weightPosIn(floatingHeight) @@ -1839,7 +1904,7 @@ extension TGLinearLayout { //优先以容器中的指定为标准 rect.size.height = self.tgValidMeasure(sbvsc.height, sbv: sbv, calcSize: rect.size.height, sbvSize: rect.size, selfLayoutSize: selfSize) - self.tgCalcVertGravity(self.tgGetSubviewVertGravity(sbv, sbvsc:sbvsc, vertGravity: vertGravity), selfSize:selfSize, sbv:sbv, sbvsc:sbvsc, lsc:lsc, rect:&rect) + self.tgCalcVertGravity(self.tgGetSubviewVertGravity(sbv, sbvsc:sbvsc, vertGravity: vertGravity), selfSize:selfSize, topPadding:topPadding, bottomPadding:bottomPadding,baselinePos:baselinePos, sbv:sbv, sbvsc:sbvsc, lsc:lsc, rect:&rect) } diff --git a/TangramKit/TGPathLayout.swift b/TangramKit/TGPathLayout.swift index 5ca7c65..faf4239 100644 --- a/TangramKit/TGPathLayout.swift +++ b/TangramKit/TGPathLayout.swift @@ -315,6 +315,10 @@ open class TGPathLayout : TGBaseLayout,TGPathLayoutViewSizeClass { start = realFromIndex end = realToIndex }else{ + if tgPointIndexs!.count <= realFromIndex || tgPointIndexs!.count <= realToIndex + { + return nil + } start = tgPointIndexs![realFromIndex] end = tgPointIndexs![realToIndex] } @@ -323,6 +327,10 @@ open class TGPathLayout : TGBaseLayout,TGPathLayoutViewSizeClass { retPoints.append(tgPathPoints![i]) } }else{ + if tgPointIndexs!.count <= realFromIndex || tgPointIndexs!.count <= realToIndex + { + return nil + } var end = tgPointIndexs![realFromIndex] let start = tgPointIndexs![realToIndex] while end >= start { @@ -391,8 +399,9 @@ open class TGPathLayout : TGBaseLayout,TGPathLayoutViewSizeClass { } - override func tgCalcLayoutRect(_ size: CGSize, isEstimate: Bool, sbs:[UIView]!, type: TGSizeClassType) -> (selfSize: CGSize, hasSubLayout: Bool) { - var (selfSize,hasSubLayout) = super.tgCalcLayoutRect(size, isEstimate: isEstimate, sbs:sbs,type: type) + override internal func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool, hasSubLayout:inout Bool!, sbs:[UIView]!, type :TGSizeClassType) -> CGSize + { + var selfSize = super.tgCalcLayoutRect(size, isEstimate:isEstimate, hasSubLayout:&hasSubLayout, sbs:sbs, type:type) var sbs:[UIView]! = sbs if sbs == nil @@ -416,7 +425,9 @@ open class TGPathLayout : TGBaseLayout,TGPathLayoutViewSizeClass { let sbvl = sbv as! TGBaseLayout - if hasSubLayout && (sbvsc.isSomeSizeWrap){ + + if hasSubLayout != nil && sbvsc.isSomeSizeWrap + { hasSubLayout = true } @@ -629,7 +640,7 @@ open class TGPathLayout : TGBaseLayout,TGPathLayoutViewSizeClass { tgAdjustLayoutSelfSize(selfSize: &selfSize, lsc: lsc) - return (self.tgAdjustSizeWhenNoSubviews(size: selfSize, sbs: sbs2, lsc:lsc),hasSubLayout) + return self.tgAdjustSizeWhenNoSubviews(size: selfSize, sbs: sbs2, lsc:lsc) } override func tgCreateInstance() -> AnyObject { diff --git a/TangramKit/TGRelativeLayout.swift b/TangramKit/TGRelativeLayout.swift index 13801ec..7155eba 100644 --- a/TangramKit/TGRelativeLayout.swift +++ b/TangramKit/TGRelativeLayout.swift @@ -48,9 +48,9 @@ open class TGRelativeLayout: TGBaseLayout,TGRelativeLayoutViewSizeClass { //MARK: override method - override func tgCalcLayoutRect(_ size: CGSize, isEstimate: Bool, sbs:[UIView]!, type: TGSizeClassType) -> (selfSize: CGSize, hasSubLayout: Bool) { - - var (selfSize, hasSubLayout) = super.tgCalcLayoutRect(size, isEstimate: isEstimate, sbs:sbs, type: type) + override internal func tgCalcLayoutRect(_ size:CGSize, isEstimate:Bool, hasSubLayout:inout Bool!, sbs:[UIView]!, type :TGSizeClassType) -> CGSize + { + var selfSize = super.tgCalcLayoutRect(size, isEstimate:isEstimate, hasSubLayout:&hasSubLayout, sbs:sbs, type:type) let lsc = self.tgCurrentSizeClass as! TGRelativeLayoutViewSizeClassImpl @@ -64,7 +64,7 @@ open class TGRelativeLayout: TGBaseLayout,TGRelativeLayoutViewSizeClass { continue } - if !isEstimate { + if !isEstimate || (hasSubLayout != nil && hasSubLayout) { sbvtgFrame.reset() } @@ -83,7 +83,7 @@ open class TGRelativeLayout: TGBaseLayout,TGRelativeLayoutViewSizeClass { if let sbvl: TGBaseLayout = sbv as? TGBaseLayout { - if sbvsc.isSomeSizeWrap + if hasSubLayout != nil && sbvsc.isSomeSizeWrap { hasSubLayout = true } @@ -152,7 +152,7 @@ open class TGRelativeLayout: TGBaseLayout,TGRelativeLayoutViewSizeClass { tgAdjustSubviewsRTLPos(sbs: sbs2, selfWidth: selfSize.width) - return (self.tgAdjustSizeWhenNoSubviews(size: selfSize, sbs: sbs2, lsc:lsc), hasSubLayout) + return self.tgAdjustSizeWhenNoSubviews(size: selfSize, sbs: sbs2, lsc:lsc) } internal override func tgCreateInstance() -> AnyObject @@ -392,7 +392,48 @@ extension TGRelativeLayout sbvtgFrame.height = sbvsc.height.measure(selfSize.height - lsc.tgTopPadding - lsc.tgBottomPadding) } } - if let t = sbvsc.centerY.posVal + if let t = sbvsc.baseline.posVal + { + //得到基线的位置。基线的位置等于top + (子视图的高度 - 字体的高度) / 2 + 字体基线以上的高度。 + let sbvFont:UIFont! = self.tgGetSubviewFont(sbv) + + if sbvFont != nil + { + //得到基线的位置。 + let relaView = t.view + sbvtgFrame.top = self.tgCalcRelationalSubview(relaView, lsc:lsc, gravity:t.type,selfSize:selfSize) - sbvFont.ascender - (sbvtgFrame.height - sbvFont.lineHeight) / 2.0 + sbvsc.baseline.absPos + + if relaView != self && self.tgIsNoLayoutSubview(relaView) + { + sbvtgFrame.top -= sbvsc.baseline.absPos + } + } + else + { + sbvtgFrame.top = lsc.tgTopPadding + sbvsc.baseline.absPos + } + + sbvtgFrame.bottom = sbvtgFrame.top + sbvtgFrame.height + + } + else if let t = sbvsc.baseline.numberVal + { + //得到基线的位置。基线的位置等于top + (子视图的高度 - 字体的高度) / 2 + 字体基线以上的高度。 + let sbvFont:UIFont! = self.tgGetSubviewFont(sbv) + + if sbvFont != nil + { + //得到基线的位置。 + sbvtgFrame.top = lsc.tgTopPadding - sbvFont.ascender - (sbvtgFrame.height - sbvFont.lineHeight) / 2.0 + t + } + else + { + sbvtgFrame.top = lsc.tgTopPadding + t + } + + sbvtgFrame.bottom = sbvtgFrame.top + sbvtgFrame.height + } + else if let t = sbvsc.centerY.posVal { let relaView = t.view @@ -771,55 +812,66 @@ extension TGRelativeLayout { isViewHidden = self.tgIsNoLayoutSubview(dime.view) if !isViewHidden { - if dime.numberVal != nil { - totalAdd += (-1 * dime.numberVal) - } - else if (dime.view as? TGBaseLayout) == nil && dime.isWrap + + + if dime.hasValue { - totalAdd += -1 * dime.view.tgFrame.width + _ = self.tgCalcSubviewWidth(dime.view, sbvsc:dime.view.tgCurrentSizeClass as! TGViewSizeClassImpl, sbvtgFrame:dime.view.tgFrame, lsc:lsc, selfSize:selfSize) + + totalAdd += -1.0 * dime.view.tgFrame.width } - else { + else + { totalMulti += dime.multiple } totalAdd += dime.increment + } } } - var floatWidth: CGFloat = selfSize.width - lsc.tgLeadingPadding - lsc.tgTrailingPadding + totalAdd - if _tgCGFloatLessOrEqual(floatWidth, 0) + var floatingWidth: CGFloat = selfSize.width - lsc.tgLeadingPadding - lsc.tgTrailingPadding + totalAdd + if _tgCGFloatLessOrEqual(floatingWidth, 0) { - floatWidth = 0 + floatingWidth = 0 } if totalMulti != 0 { - sbvtgFrame.width = self.tgValidMeasure(sbvsc.width, sbv: sbv, calcSize: floatWidth * (sbvsc.width.multiple / totalMulti), sbvSize: sbvtgFrame.frame.size, selfLayoutSize: selfSize) + + var tempWidth = _tgRoundNumber(floatingWidth * (sbvsc.width.multiple / totalMulti)) + sbvtgFrame.width = self.tgValidMeasure(sbvsc.width, sbv: sbv, calcSize: tempWidth, sbvSize: sbvtgFrame.frame.size, selfLayoutSize: selfSize) if self.tgIsNoLayoutSubview(sbv) { sbvtgFrame.width = 0 } + else + { + floatingWidth -= tempWidth + totalMulti -= sbvsc.width.multiple + } for dime:TGLayoutSize in dimeArray { - if dime.isActive + if dime.isActive && !self.tgIsNoLayoutSubview(dime.view) { let (dimetgFrame, dimesbvsc) = self.tgGetSubviewFrameAndSizeClass(dime.view) - - if dime.numberVal == nil { - dimetgFrame.width = floatWidth * (dime.multiple / totalMulti) - } - else { - dimetgFrame.width = dime.numberVal + + if !dime.hasValue + { + tempWidth = _tgRoundNumber(floatingWidth * (dime.multiple / totalMulti)) + floatingWidth -= tempWidth + totalMulti -= dime.multiple + dimetgFrame.width = tempWidth } - + dimetgFrame.width = self.tgValidMeasure(dimesbvsc.width, sbv: dime.view, calcSize: dimetgFrame.width, sbvSize: dimetgFrame.frame.size, selfLayoutSize: selfSize) - if self.tgIsNoLayoutSubview(dime.view) - { - dimetgFrame.width = 0 - } + } + else + { + dime.view.tgFrame.width = 0 } } @@ -840,14 +892,15 @@ extension TGRelativeLayout { isViewHidden = self.tgIsNoLayoutSubview(dime.view) if !isViewHidden { - if dime.numberVal != nil { - totalAdd += (-1 * dime.numberVal!) - } - else if (dime.view as? TGBaseLayout) == nil && dime.isWrap + + if dime.hasValue { - totalAdd += -1 * dime.view.tgFrame.height; + _ = self.tgCalcSubviewHeight(dime.view, sbvsc:dime.view.tgCurrentSizeClass as! TGViewSizeClassImpl, sbvtgFrame:dime.view.tgFrame, lsc:lsc, selfSize:selfSize) + + totalAdd += -1.0 * dime.view.tgFrame.height } - else { + else + { totalMulti += dime.multiple } @@ -856,38 +909,47 @@ extension TGRelativeLayout } } - var floatHeight = selfSize.height - lsc.tgTopPadding - lsc.tgBottomPadding + totalAdd - if _tgCGFloatLessOrEqual(floatHeight, 0) + var floatingHeight = selfSize.height - lsc.tgTopPadding - lsc.tgBottomPadding + totalAdd + if _tgCGFloatLessOrEqual(floatingHeight, 0) { - floatHeight = 0 + floatingHeight = 0 } if totalMulti != 0 { - sbvtgFrame.height = self.tgValidMeasure(sbvsc.height, sbv: sbv, calcSize: floatHeight * (sbvsc.height.multiple / totalMulti), sbvSize: sbvtgFrame.frame.size, selfLayoutSize: selfSize) + + var tempHeight = _tgRoundNumber(floatingHeight * (sbvsc.height.multiple / totalMulti)) + + sbvtgFrame.height = self.tgValidMeasure(sbvsc.height, sbv: sbv, calcSize: floatingHeight * (sbvsc.height.multiple / totalMulti), sbvSize: sbvtgFrame.frame.size, selfLayoutSize: selfSize) if self.tgIsNoLayoutSubview(sbv) { sbvtgFrame.height = 0 } + else + { + floatingHeight -= tempHeight + totalMulti -= sbvsc.height.multiple + } for dime: TGLayoutSize in dimeArray { - if dime.isActive + if dime.isActive && !self.tgIsNoLayoutSubview(dime.view) { let (dimetgFrame, dimesbvsc) = self.tgGetSubviewFrameAndSizeClass(dime.view) - - if dime.numberVal == nil { - dimetgFrame.height = floatHeight * (dime.multiple / totalMulti) - } - else { - dimetgFrame.height = dime.numberVal + + if !dime.hasValue + { + tempHeight = _tgRoundNumber(floatingHeight * (dime.multiple / totalMulti)) + floatingHeight -= tempHeight + totalMulti -= dime.multiple + dimetgFrame.height = tempHeight } dimetgFrame.height = self.tgValidMeasure(dimesbvsc.height, sbv: dime.view, calcSize: dimetgFrame.height, sbvSize: dimetgFrame.frame.size, selfLayoutSize: selfSize) - if self.tgIsNoLayoutSubview(dime.view) - { - dimetgFrame.height = 0 - } + } + else + { + dime.view.tgFrame.height = 0 } } @@ -1219,6 +1281,35 @@ extension TGRelativeLayout return sbvtgFrame.bottom + case TGGravity.vert.baseline: + if sbv == self || sbv == nil + { + return lsc.tgTopPadding + } + + let sbvFont:UIFont! = self.tgGetSubviewFont(sbv) + if sbvFont != nil + { + if sbvtgFrame.top == CGFloat.greatestFiniteMagnitude || sbvtgFrame.height == CGFloat.greatestFiniteMagnitude + { + self.tgCalcSubviewTopBottom(sbv,sbvsc:sbvsc,sbvtgFrame:sbvtgFrame,lsc:lsc,selfSize:selfSize) + } + + //得到基线的位置。 + return sbvtgFrame.top + (sbvtgFrame.height - sbvFont.lineHeight)/2.0 + sbvFont.ascender + + } + else + { + if sbvtgFrame.top != CGFloat.greatestFiniteMagnitude + { + return sbvtgFrame.top + } + + self.tgCalcSubviewTopBottom(sbv,sbvsc:sbvsc,sbvtgFrame:sbvtgFrame,lsc:lsc,selfSize:selfSize) + + return sbvtgFrame.top + } case TGGravity.horz.fill: if sbv == self || sbv == nil { diff --git a/TangramKit/TGTableLayout.swift b/TangramKit/TGTableLayout.swift index cff5a8e..43d0ede 100644 --- a/TangramKit/TGTableLayout.swift +++ b/TangramKit/TGTableLayout.swift @@ -163,30 +163,28 @@ open class TGTableLayout: TGLinearLayout { } else { - if let v = rowView.colSize as? CGFloat + if let v = rowView.colSize as? CGFloat, v < TGTableLayout._stgColCountTag { - if v < TGTableLayout._stgColCountTag + + let colCount = TGTableLayout._stgColCountTag - v + if rowsc.tg_orientation == .horz { - let colCount = TGTableLayout._stgColCountTag - v - if rowsc.tg_orientation == .horz - { - colsc.tg_width.equalHelper(val:rowView.tg_width, increment:-1 * rowView.tg_hspace * (colCount - 1.0) / colCount, multiple:1.0 / colCount) - } - else - { - colsc.tg_height.equalHelper(val:rowView.tg_height,increment:-1 * rowView.tg_vspace * (colCount - 1.0) / colCount, multiple:1.0 / colCount) - } + colsc.tg_width.equalHelper(val:rowView.tg_width, increment:-1 * rowView.tg_hspace * (colCount - 1.0) / colCount, multiple:1.0 / colCount) } else { - if (rowsc.tg_orientation == .horz) - { - colsc.tg_width.equalHelper(val:rowView.colSize) - } - else - { - colsc.tg_height.equalHelper(val:rowView.colSize) - } + colsc.tg_height.equalHelper(val:rowView.tg_height,increment:-1 * rowView.tg_vspace * (colCount - 1.0) / colCount, multiple:1.0 / colCount) + } + } + else + { + if (rowsc.tg_orientation == .horz) + { + colsc.tg_width.equalHelper(val:rowView.colSize) + } + else + { + colsc.tg_height.equalHelper(val:rowView.colSize) } } } diff --git a/TangramKit/TangramKit.swift b/TangramKit/TangramKit.swift index dd7d975..2cd76f2 100644 --- a/TangramKit/TangramKit.swift +++ b/TangramKit/TangramKit.swift @@ -53,7 +53,7 @@ */ -//Current version is 1.1.2, please open: https://github.com/youngsoft/TangramKit/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.1.3, please open: https://github.com/youngsoft/TangramKit/blob/master/CHANGELOG.md to show the changes. @@ -137,6 +137,8 @@ public struct TGGravity : OptionSet{ public static let between = TGGravity(rawValue: 16 << 8) /// 垂直高度填充 public static let fill:TGGravity = [vert.top, vert.center, vert.bottom] + /// 基线对齐,只支持水平线性布局,指定基线对齐必须要指定出一个基线标准的子视图 + public static let baseline = TGGravity(rawValue: 32 << 8) /// 垂直掩码,用来获取垂直方向的枚举值 public static let mask = TGGravity(rawValue:0x00FF) @@ -148,8 +150,6 @@ public struct TGGravity : OptionSet{ public static let fill:TGGravity = [horz.fill, vert.fill] /// 全部拉伸 public static let between:TGGravity = [horz.between, vert.between] - /// 基线对齐,暂时不支持 - public static let baseline = TGGravity(rawValue: 32 << 8) } diff --git a/TangramKitDemo/AppDelegate.swift b/TangramKitDemo/AppDelegate.swift index eae95ea..e3cc44f 100644 --- a/TangramKitDemo/AppDelegate.swift +++ b/TangramKitDemo/AppDelegate.swift @@ -57,6 +57,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } + override func touchesEnded(_ touches: Set, with event: UIEvent?) { + super.touchesEnded(touches, with: event) + + if let pt = touches.first?.location(in: self.window), pt.y < 20.0 && pt.x > 0.0 && pt.x < 100.0 + { + self.window?.rootViewController?.dismiss(animated: true, completion: nil) + } + } } diff --git a/TangramKitDemo/DetailViewController.swift b/TangramKitDemo/DetailViewController.swift new file mode 100644 index 0000000..b1f2a95 --- /dev/null +++ b/TangramKitDemo/DetailViewController.swift @@ -0,0 +1,144 @@ +// +// DetailViewController.swift +// TangramKit +// +// Created by apple on 16/7/14. +// Copyright © 2016年 youngsoft. All rights reserved. +// + +import UIKit + + + +class DetailViewController: UITableViewController { + + var demoVCList:[[String:Any]]! + var isPresentVC:Bool = false + + convenience init(demoVCList:[[String:Any]]) { + self.init(style: .plain) + self.demoVCList = demoVCList + } + + override func viewDidLoad() { + super.viewDidLoad() + + + self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "test") + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Present", style: .plain, target: self, action: #selector(handlePushOrPresent)) + + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + + // MARK: - Handle Method + + @objc func handlePushOrPresent(_ sender:UIBarButtonItem) + { + self.isPresentVC = !self.isPresentVC + sender.title = self.isPresentVC ? "Push" : "Present" + + if (self.isPresentVC) + { + UIAlertView(title: "", message: NSLocalizedString("If you select \"Present\", than you can touch topleft corner of Status bar to dissmis the view controller",comment:""), delegate: nil, cancelButtonTitle: "OK").show() + } + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + + return self.demoVCList.count + } + + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "test", for:indexPath) + + cell.textLabel?.adjustsFontSizeToFitWidth = true + cell.textLabel?.font = CFTool.font(15) + cell.textLabel?.textColor = CFTool.color(4) + cell.textLabel?.text = self.demoVCList[indexPath.row]["title"] as? String + cell.textLabel?.textAlignment = TGBaseLayout.tg_isRTL ? .right : .left + + return cell + } + + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) + { + tableView.deselectRow(at: indexPath, animated: true) + + + let demoVC:UIViewController = (self.demoVCList[indexPath.row]["class"] as! UIViewController.Type).init() + demoVC.title = self.demoVCList[indexPath.row]["title"] as? String + + if self.isPresentVC{ + self.navigationController?.present(demoVC, animated: true, completion: nil) + } + else{ + self.navigationController?.pushViewController(demoVC, animated: true) + } + + } + + + /* + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + // Delete the row from the data source + tableView.deleteRows(at: [indexPath], with: .fade) + } else if editingStyle == .insert { + // Create a new instance of the appropriate, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) { + // Get the new view controller using segue.destinationViewController. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/TangramKitDemo/FloatLayoutDemo/FOLTest3ViewController.swift b/TangramKitDemo/FloatLayoutDemo/FOLTest3ViewController.swift index 36159da..4fe4f59 100644 --- a/TangramKitDemo/FloatLayoutDemo/FOLTest3ViewController.swift +++ b/TangramKitDemo/FloatLayoutDemo/FOLTest3ViewController.swift @@ -63,8 +63,7 @@ class FOLTest3ViewController: UIViewController { let floatLayout = TGFloatLayout(.vert) floatLayout.backgroundColor = .white - floatLayout.tg_width.equal(.fill) - floatLayout.tg_height.equal(.fill) + floatLayout.tg_margin(TGLayoutPos.tg_safeAreaMargin) ////浮动布局和父视图四周的边界是安全区,也就是说浮动布局的宽度和高度和父视图的安全区相等。 您可以将tg_margin设置为0并在iPhoneX上看看效果和区别。 //通过智能分界线的使用,浮动布局里面的所有子布局视图的分割线都会进行智能的设置,从而解决了我们需求中需要提供边界线的问题。 floatLayout.tg_intelligentBorderline = TGBorderline(color: UIColor.lightGray.withAlphaComponent(0.2)) self.view.addSubview(floatLayout) diff --git a/TangramKitDemo/FrameLayoutDemo/FLTest1ViewController.swift b/TangramKitDemo/FrameLayoutDemo/FLTest1ViewController.swift index 89dbfd1..1cf88e3 100644 --- a/TangramKitDemo/FrameLayoutDemo/FLTest1ViewController.swift +++ b/TangramKitDemo/FrameLayoutDemo/FLTest1ViewController.swift @@ -62,11 +62,13 @@ class FLTest1ViewController: UIViewController { self.edgesForExtendedLayout = UIRectEdge(rawValue:0) //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + super.loadView() let frameLayout = TGFrameLayout() frameLayout.backgroundColor = .white + frameLayout.tg_margin(TGLayoutPos.tg_safeAreaMargin) frameLayout.tg_padding = UIEdgeInsetsMake(20, 20, 20, 20) - self.view = frameLayout + self.view.addSubview(frameLayout) //全部填充。 all fill subview let fill = self.createLabel("", backgroundColor: CFTool.color(0)) diff --git a/TangramKitDemo/FrameLayoutDemo/FLTest2ViewController.swift b/TangramKitDemo/FrameLayoutDemo/FLTest2ViewController.swift index edf519e..c524322 100644 --- a/TangramKitDemo/FrameLayoutDemo/FLTest2ViewController.swift +++ b/TangramKitDemo/FrameLayoutDemo/FLTest2ViewController.swift @@ -37,6 +37,7 @@ class FLTest2ViewController: UIViewController { let rootLayout = TGFrameLayout() rootLayout.backgroundColor = CFTool.color(15) + rootLayout.tg_insetsPaddingFromSafeArea = [.left, .right, .top] //默认情况下底部的安全区会和布局视图的底部padding进行叠加,当这样设置后底部安全区将不会叠加到底部的padding上去。您可以注释这句代码看看效果。 self.view = rootLayout /* diff --git a/TangramKitDemo/Images.xcassets/AppIcon.appiconset/Contents.json b/TangramKitDemo/Images.xcassets/AppIcon.appiconset/Contents.json index cba7067..d9e47dd 100644 --- a/TangramKitDemo/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/TangramKitDemo/Images.xcassets/AppIcon.appiconset/Contents.json @@ -98,6 +98,11 @@ "idiom" : "ipad", "filename" : "appiconiPadPro@2x.png", "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" } ], "info" : { diff --git a/TangramKitDemo/Info.plist b/TangramKitDemo/Info.plist index 0d5ca27..f4b9183 100644 --- a/TangramKitDemo/Info.plist +++ b/TangramKitDemo/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.1.2 + 1.1.3 CFBundleSignature ???? CFBundleVersion diff --git a/TangramKitDemo/IntegratedDemo/AllTest8ViewController.swift b/TangramKitDemo/IntegratedDemo/AllTest8ViewController.swift index c002461..69e251f 100644 --- a/TangramKitDemo/IntegratedDemo/AllTest8ViewController.swift +++ b/TangramKitDemo/IntegratedDemo/AllTest8ViewController.swift @@ -32,8 +32,13 @@ class AllTest8ViewController: UIViewController { override func viewDidLoad() { - self.edgesForExtendedLayout = UIRectEdge(rawValue:0) //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 - + if #available(iOS 11.0, *) + { + } + else + { + self.edgesForExtendedLayout = UIRectEdge(rawValue:0) //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + } super.viewDidLoad() diff --git a/TangramKitDemo/IntegratedDemo/AllTestModel&View/AllTest1TableViewCell.swift b/TangramKitDemo/IntegratedDemo/AllTestModel&View/AllTest1TableViewCell.swift index 4bf188f..06a8f9c 100644 --- a/TangramKitDemo/IntegratedDemo/AllTestModel&View/AllTest1TableViewCell.swift +++ b/TangramKitDemo/IntegratedDemo/AllTestModel&View/AllTest1TableViewCell.swift @@ -57,7 +57,16 @@ class AllTest1TableViewCell: UITableViewCell { 通过布局视图的sizeThatFits方法能够评估出UITableViewCell的动态高度。sizeThatFits并不会进行布局而只是评估布局的尺寸。 因为cell的高度是自适应的,因此这里通过调用高度为wrap的布局视图的sizeThatFits来获取真实的高度。 */ - return self.rootLayout.sizeThatFits(targetSize) //如果使用系统自带的分割线,请记得将返回的高度height+1 + + if #available(iOS 11.0, *) { + //如果你的界面要支持横屏的话,因为iPhoneX的横屏左右有44的安全区域,所以这里要减去左右的安全区域的值,来作为布局宽度尺寸的评估值。 + //如果您的界面不需要支持横屏,或者延伸到安全区域外则不需要做这个特殊处理,而直接使用else部分的代码即可。 + return self.rootLayout.sizeThatFits(CGSize(width:targetSize.width - self.safeAreaInsets.left - self.safeAreaInsets.right, height:targetSize.height)) + } else { + // Fallback on earlier versions + return self.rootLayout.sizeThatFits(targetSize) //如果使用系统自带的分割线,请记得将返回的高度height+1 + } + } func setModel(model: AllTest1DataModel, isImageMessageHidden: Bool) diff --git a/TangramKitDemo/PathLayoutDemo/PLTest1ViewController.swift b/TangramKitDemo/PathLayoutDemo/PLTest1ViewController.swift index d7c4f22..0f01241 100644 --- a/TangramKitDemo/PathLayoutDemo/PLTest1ViewController.swift +++ b/TangramKitDemo/PathLayoutDemo/PLTest1ViewController.swift @@ -21,13 +21,11 @@ class PLTest1ViewController: UIViewController { * 本例子是介绍TGPathLayout布局视图的。用来建立曲线布局。 */ - self.edgesForExtendedLayout = UIRectEdge(rawValue:0) //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 - - //为了支持iPhoneX而设置附加的安全区缩进。否则根视图将延伸到工具栏下面去了。 if #available(iOS 11.0, *) { - self.additionalSafeAreaInsets = UIEdgeInsetsMake(0, 0, 44, 0) } else { // Fallback on earlier versions + self.edgesForExtendedLayout = UIRectEdge(rawValue:0) //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + } myPathLayout = TGPathLayout() diff --git a/TangramKitDemo/RelativeLayoutDemo/RLTest1ViewController.swift b/TangramKitDemo/RelativeLayoutDemo/RLTest1ViewController.swift index bbd9c56..20e8b49 100644 --- a/TangramKitDemo/RelativeLayoutDemo/RLTest1ViewController.swift +++ b/TangramKitDemo/RelativeLayoutDemo/RLTest1ViewController.swift @@ -43,6 +43,8 @@ class RLTest1ViewController: UIViewController { let rootLayout: TGRelativeLayout = TGRelativeLayout() rootLayout.tg_padding = UIEdgeInsetsMake(10, 10, 10, 10) rootLayout.backgroundColor = .white + + rootLayout.tg_insetsPaddingFromSafeArea = [.top, .left, .right] //默认情况下底部的安全区会和布局视图的底部padding进行叠加,当这样设置后底部安全区将不会叠加到底部的padding上去。您可以注释这句代码看看效果。 self.view = rootLayout /* @@ -184,7 +186,7 @@ class RLTest1ViewController: UIViewController { rootLayout.addSubview(lineView3) let walkLabel2 = UILabel() - walkLabel2.text = "walk" + walkLabel2.text = "Weight" walkLabel2.font = CFTool.font(15) walkLabel2.textColor = CFTool.color(11) walkLabel2.sizeToFit() @@ -193,12 +195,12 @@ class RLTest1ViewController: UIViewController { rootLayout.addSubview(walkLabel2) let walkLabel3 = UILabel() - walkLabel3.text = "18 Min" - walkLabel3.font = CFTool.font(15) + walkLabel3.text = "70 kg" + walkLabel3.font = CFTool.font(20) walkLabel3.textColor = CFTool.color(12) walkLabel3.sizeToFit() walkLabel3.tg_leading.equal(walkLabel2.tg_trailing,offset:5) - walkLabel3.tg_centerY.equal(walkLabel2.tg_centerY) + walkLabel3.tg_baseline.equal(walkLabel2.tg_baseline) rootLayout.addSubview(walkLabel3) let timeLabel1 = UILabel() diff --git a/TangramKitDemo/RelativeLayoutDemo/RLTest4ViewController.swift b/TangramKitDemo/RelativeLayoutDemo/RLTest4ViewController.swift index 075aba4..6bbf012 100644 --- a/TangramKitDemo/RelativeLayoutDemo/RLTest4ViewController.swift +++ b/TangramKitDemo/RelativeLayoutDemo/RLTest4ViewController.swift @@ -42,6 +42,12 @@ class RLTest4ViewController: UIViewController { self.view = scrollView; scrollView.delegate = self; + if #available(iOS 11.0, *) { + scrollView.contentInsetAdjustmentBehavior = .never + } else { + // Fallback on earlier versions + } + let rootLayout = TGRelativeLayout() rootLayout.tg_padding = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) rootLayout.tg_height.equal(.wrap) diff --git a/TangramKitDemo/TableLayoutDemo/TLTest1ViewController.swift b/TangramKitDemo/TableLayoutDemo/TLTest1ViewController.swift index dd1853e..9b3a267 100644 --- a/TangramKitDemo/TableLayoutDemo/TLTest1ViewController.swift +++ b/TangramKitDemo/TableLayoutDemo/TLTest1ViewController.swift @@ -41,8 +41,7 @@ class TLTest1ViewController: UIViewController { tableLayout.backgroundColor = CFTool.color(0) tableLayout.tg_hspace = 2 tableLayout.tg_vspace = 2 - tableLayout.tg_width.equal(.fill) - tableLayout.tg_height.equal(.fill) + tableLayout.tg_margin(TGLayoutPos.tg_safeAreaMargin) //和父视图的安全区域保持一致的尺寸,因为这里和父视图四周的边距都是安全区边距。你可以设置为0看看效果。 self.view.addSubview(tableLayout) diff --git a/TangramKitDemo/TableLayoutDemo/TLTest3ViewController.swift b/TangramKitDemo/TableLayoutDemo/TLTest3ViewController.swift index 42344ff..0e01a25 100644 --- a/TangramKitDemo/TableLayoutDemo/TLTest3ViewController.swift +++ b/TangramKitDemo/TableLayoutDemo/TLTest3ViewController.swift @@ -33,17 +33,32 @@ class TLTest3ViewController: UIViewController { 这个例子是将表格布局和智能边界线的应用结合,实现一个表格界面。 */ - super.loadView() - let scrollView = UIScrollView(frame:self.view.bounds.insetBy(dx: 10, dy: 10)) - scrollView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + let scrollView = UIScrollView() scrollView.backgroundColor = .white - self.view.addSubview(scrollView) + self.view = scrollView + + + if #available(iOS 11.0, *) { + } else { + // Fallback on earlier versions + + self.edgesForExtendedLayout = UIRectEdge(rawValue:0) + + } let tableLayout = TGTableLayout(.vert) - tableLayout.tg_width.equal(.fill) tableLayout.tg_height.equal(.wrap) + //这里设置表格的左边和右边以及顶部的边距都是在父视图的安全区域外再缩进10个点的位置。你会注意到这里面定义了一个特殊的位置TGLayoutPos.tg_safeAreaMargin。 + //TGLayoutPos.tg_safeAreaMargin表示视图的边距不是一个固定的值而是所在的父视图的安全区域。这样布局视图就不会延伸到安全区域以外去了。 + //TGLayoutPos.tg_safeAreaMargin是同时支持iOS11和以下的版本的,对于iOS11以下的版本则顶部安全区域是状态栏以下的位置。 + //因此只要你设置边距为MyLayoutPos.safeAreaMargin则可以同时兼容所有iOS的版本。。 + tableLayout.tg_leading.equal(TGLayoutPos.tg_safeAreaMargin, offset: 10) + tableLayout.tg_trailing.equal(TGLayoutPos.tg_safeAreaMargin, offset: 10) + tableLayout.tg_top.equal(TGLayoutPos.tg_safeAreaMargin, offset: 10) + + scrollView.addSubview(tableLayout) self.rootLayout = tableLayout diff --git a/TangramKitDemo/ViewController.swift b/TangramKitDemo/ViewController.swift index 659e047..4709abc 100644 --- a/TangramKitDemo/ViewController.swift +++ b/TangramKitDemo/ViewController.swift @@ -12,7 +12,7 @@ import UIKit class ViewController: UITableViewController { - var demoVCList:[[String:Any]] = [[String:Any]]() + var demoTypeList:[[String:Any]] = [[String:Any]]() override func viewDidLoad() { super.viewDidLoad() @@ -35,133 +35,172 @@ class ViewController: UITableViewController { // Uncomment the following line to display an Edit button in the navigation bar for this view controller. self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "RTL", style: .plain, target: self, action: #selector(handleRTL)) - - - - demoVCList.append(["title":NSLocalizedString("1.LinearLayout - Vert&Horz",comment:""), - "class":LLTest1ViewController.self] + + //linear layout list + var demoVCList1:[[String:Any]] = [[String:Any]]() + demoVCList1.append(["title":NSLocalizedString("1.LinearLayout - Vert&Horz",comment:""), + "class":LLTest1ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("2.LinearLayout - Combine with UIScrollView",comment:""), - "class":LLTest2ViewController.self] + demoVCList1.append(["title":NSLocalizedString("2.LinearLayout - Combine with UIScrollView",comment:""), + "class":LLTest2ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("3.LinearLayout - Gravity&Fill",comment:""), - "class":LLTest3ViewController.self] + demoVCList1.append(["title":NSLocalizedString("3.LinearLayout - Gravity&Fill",comment:""), + "class":LLTest3ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("4.LinearLayout - Wrap content",comment:""), - "class":LLTest4ViewController.self] + demoVCList1.append(["title":NSLocalizedString("4.LinearLayout - Wrap content",comment:""), + "class":LLTest4ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("5.LinearLayout - Weight & Relative margin",comment:""), - "class":LLTest5ViewController.self] + demoVCList1.append(["title":NSLocalizedString("5.LinearLayout - Weight & Relative margin",comment:""), + "class":LLTest5ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("6.LinearLayout - Size limit & Flexed margin",comment:""), - "class":LLTest6ViewController.self] + demoVCList1.append(["title":NSLocalizedString("6.LinearLayout - Size limit & Flexed margin",comment:""), + "class":LLTest6ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("7.LinearLayout - Average size&spacing",comment:""), - "class":LLTest7ViewController.self] + demoVCList1.append(["title":NSLocalizedString("7.LinearLayout - Average size&spacing",comment:""), + "class":LLTest7ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("1.FrameLayout - Gravity&Fill",comment:""), - "class":FLTest1ViewController.self] + + //frame layout list + var demoVCList2 = [[String:Any]]() + demoVCList2.append(["title":NSLocalizedString("1.FrameLayout - Gravity&Fill",comment:""), + "class":FLTest1ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("2.FrameLayout - Complex UI",comment:""), - "class":FLTest2ViewController.self] + demoVCList2.append(["title":NSLocalizedString("2.FrameLayout - Complex UI",comment:""), + "class":FLTest2ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("1.RelativeLayout - Constraint&Dependence",comment:""), - "class":RLTest1ViewController.self] + + + //relative layout list + var demoVCList3 = [[String:Any]]() + demoVCList3.append(["title":NSLocalizedString("1.RelativeLayout - Constraint&Dependence",comment:""), + "class":RLTest1ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("2.RelativeLayout - Prorate size",comment:""), - "class":RLTest2ViewController.self] + demoVCList3.append(["title":NSLocalizedString("2.RelativeLayout - Prorate size",comment:""), + "class":RLTest2ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("3.RelativeLayout - Centered",comment:""), - "class":RLTest3ViewController.self] + demoVCList3.append(["title":NSLocalizedString("3.RelativeLayout - Centered",comment:""), + "class":RLTest3ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("4.RelativeLayout - Scroll&Dock",comment:""), - "class":RLTest4ViewController.self] + demoVCList3.append(["title":NSLocalizedString("4.RelativeLayout - Scroll&Dock",comment:""), + "class":RLTest4ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("5.RelativeLayout - Boundary limit",comment:""), - "class":RLTest5ViewController.self] + demoVCList3.append(["title":NSLocalizedString("5.RelativeLayout - Boundary limit",comment:""), + "class":RLTest5ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("1.TableLayout - Vert",comment:""), - "class":TLTest1ViewController.self] + + + //table layout list + var demoVCList4 = [[String:Any]]() + demoVCList4.append(["title":NSLocalizedString("1.TableLayout - Vert",comment:""), + "class":TLTest1ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("2.TableLayout - Waterfall(Horz)",comment:""), - "class":TLTest2ViewController.self] + demoVCList4.append(["title":NSLocalizedString("2.TableLayout - Waterfall(Horz)",comment:""), + "class":TLTest2ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("3.TableLayout - Intelligent Borderline",comment:""), - "class":TLTest3ViewController.self] + demoVCList4.append(["title":NSLocalizedString("3.TableLayout - Intelligent Borderline",comment:""), + "class":TLTest3ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("1.FlowLayout - Regular arrangement",comment:""), - "class":FLLTest1ViewController.self] + + + //flow layout list + var demoVCList5 = [[String:Any]]() + demoVCList5.append(["title":NSLocalizedString("1.FlowLayout - Regular arrangement",comment:""), + "class":FLLTest1ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("2.FlowLayout - Tag cloud",comment:""), - "class":FLLTest2ViewController.self] + demoVCList5.append(["title":NSLocalizedString("2.FlowLayout - Tag cloud",comment:""), + "class":FLLTest2ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("3.FlowLayout - Drag",comment:""), - "class":FLLTest3ViewController.self] + demoVCList5.append(["title":NSLocalizedString("3.FlowLayout - Drag",comment:""), + "class":FLLTest3ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("4.FlowLayout - Weight",comment:""), - "class":FLLTest4ViewController.self] + demoVCList5.append(["title":NSLocalizedString("4.FlowLayout - Weight",comment:""), + "class":FLLTest4ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("5.FlowLayout - Paging",comment:""), - "class":FLLTest5ViewController.self] + demoVCList5.append(["title":NSLocalizedString("5.FlowLayout - Paging",comment:""), + "class":FLLTest5ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("6.FlowLayout - Scroll",comment:""), - "class":FLLTest6ViewController.self] + demoVCList5.append(["title":NSLocalizedString("6.FlowLayout - Scroll",comment:""), + "class":FLLTest6ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("1.FloatLayout - Float",comment:""), - "class":FOLTest1ViewController.self] + + + //float layout list + var demoVCList6 = [[String:Any]]() + demoVCList6.append(["title":NSLocalizedString("1.FloatLayout - Float",comment:""), + "class":FOLTest1ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("2.FloatLayout - Jagged",comment:""), - "class":FOLTest2ViewController.self] + demoVCList6.append(["title":NSLocalizedString("2.FloatLayout - Jagged",comment:""), + "class":FOLTest2ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("3.FloatLayout - Card news",comment:""), - "class":FOLTest3ViewController.self] + demoVCList6.append(["title":NSLocalizedString("3.FloatLayout - Card news",comment:""), + "class":FOLTest3ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("4.FloatLayout - Tag cloud",comment:""), - "class":FOLTest4ViewController.self] + demoVCList6.append(["title":NSLocalizedString("4.FloatLayout - Tag cloud",comment:""), + "class":FOLTest4ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("5.FloatLayout - Title & Description",comment:""), - "class":FOLTest5ViewController.self] + demoVCList6.append(["title":NSLocalizedString("5.FloatLayout - Title & Description",comment:""), + "class":FOLTest5ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("6.FloatLayout - User Profiles",comment:""), - "class":FOLTest6ViewController.self] + demoVCList6.append(["title":NSLocalizedString("6.FloatLayout - User Profiles",comment:""), + "class":FOLTest6ViewController.self] ) - // MARK: - PathLayout - demoVCList.append(["title":NSLocalizedString("1.PathLayout - Animations",comment:""), - "class":PLTest1ViewController.self] + + + //path layout list + var demoVCList7 = [[String:Any]]() + demoVCList7.append(["title":NSLocalizedString("1.PathLayout - Animations",comment:""), + "class":PLTest1ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("2.PathLayout - Curves",comment:""), - "class":PLTest2ViewController.self] + demoVCList7.append(["title":NSLocalizedString("2.PathLayout - Curves",comment:""), + "class":PLTest2ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("3.PathLayout - Menu in Circle",comment:""), - "class":PLTest3ViewController.self] + demoVCList7.append(["title":NSLocalizedString("3.PathLayout - Menu in Circle",comment:""), + "class":PLTest3ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("4.PathLayout - Fan",comment:""), - "class":PLTest4ViewController.self] + demoVCList7.append(["title":NSLocalizedString("4.PathLayout - Fan",comment:""), + "class":PLTest4ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("1.UITableView - Dynamic height",comment:""), - "class":AllTest1ViewController.self] + + + //all layout list + var demoVCList8 = [[String:Any]]() + demoVCList8.append(["title":NSLocalizedString("1.UITableView - Dynamic height",comment:""), + "class":AllTest1ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("2.UITableView - Static height",comment:""), - "class":AllTest2ViewController.self] + demoVCList8.append(["title":NSLocalizedString("2.UITableView - Static height",comment:""), + "class":AllTest2ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("3.Replacement of UITableView",comment:""), - "class":AllTest3ViewController.self] + demoVCList8.append(["title":NSLocalizedString("3.Replacement of UITableView",comment:""), + "class":AllTest3ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("4.Replacement of UICollectionView",comment:""), - "class":AllTest4ViewController.self] + demoVCList8.append(["title":NSLocalizedString("4.Replacement of UICollectionView",comment:""), + "class":AllTest4ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("1.SizeClass - Demo1",comment:""), - "class":AllTest5ViewController.self] + demoVCList8.append(["title":NSLocalizedString("1.SizeClass - Demo1",comment:""), + "class":AllTest5ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("2.SizeClass - Demo2",comment:""), - "class":AllTest6ViewController.self] + demoVCList8.append(["title":NSLocalizedString("2.SizeClass - Demo2",comment:""), + "class":AllTest6ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("❁1.Screen perfect fit - Demo1",comment:""), - "class":AllTest7ViewController.self] + demoVCList8.append(["title":NSLocalizedString("❁1.Screen perfect fit - Demo1",comment:""), + "class":AllTest7ViewController.self] ) - demoVCList.append(["title":NSLocalizedString("❁2.Screen perfect fit - Demo2",comment:""), - "class":AllTest8ViewController.self] + demoVCList8.append(["title":NSLocalizedString("❁2.Screen perfect fit - Demo2",comment:""), + "class":AllTest8ViewController.self] ) + + + //type list + demoTypeList.append(["type_title":"线性布局(LinearLayout)", "type_desc":"ll.png", "type_vclist":demoVCList1]) + demoTypeList.append(["type_title":"框架布局(FrameLayout)", "type_desc":"fl.png", "type_vclist":demoVCList2]) + demoTypeList.append(["type_title":"相对布局(RelativeLayout)", "type_desc":"rl.png", "type_vclist":demoVCList3]) + demoTypeList.append(["type_title":"表格布局(TableLayout)", "type_desc":"tl.png", "type_vclist":demoVCList4]) + demoTypeList.append(["type_title":"流式布局(FlowLayout)", "type_desc":"fll.png", "type_vclist":demoVCList5]) + demoTypeList.append(["type_title":"浮动布局(FloatLayout)", "type_desc":"flo.png", "type_vclist":demoVCList6]) + demoTypeList.append(["type_title":"路径布局(PathLayout)", "type_desc":"pl.png", "type_vclist":demoVCList7]) + demoTypeList.append(["type_title":"综合布局(All Layout)", "type_desc":"all.png", "type_vclist":demoVCList8]) + + } override func didReceiveMemoryWarning() { @@ -198,7 +237,7 @@ class ViewController: UITableViewController { override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return self.demoVCList.count + return self.demoTypeList.count } @@ -208,8 +247,9 @@ class ViewController: UITableViewController { cell.textLabel?.adjustsFontSizeToFitWidth = true cell.textLabel?.font = CFTool.font(15) cell.textLabel?.textColor = CFTool.color(4) - cell.textLabel?.text = self.demoVCList[indexPath.row]["title"] as? String + cell.textLabel?.text = self.demoTypeList[indexPath.row]["type_title"] as? String cell.textLabel?.textAlignment = TGBaseLayout.tg_isRTL ? .right : .left + cell.imageView?.image = UIImage(named: self.demoTypeList[indexPath.row]["type_desc"] as! String) return cell } @@ -220,10 +260,13 @@ class ViewController: UITableViewController { tableView.deselectRow(at: indexPath, animated: true) + let detailVC:DetailViewController = DetailViewController(demoVCList:self.demoTypeList[indexPath.row]["type_vclist"] as! [[String : Any]]) + detailVC.title = self.demoTypeList[indexPath.row]["type_title"] as? String + self.navigationController?.pushViewController(detailVC, animated: true) - let demoVC:UIViewController = (self.demoVCList[indexPath.row]["class"] as! UIViewController.Type).init() - demoVC.title = self.demoVCList[indexPath.row]["title"] as? String - self.navigationController?.pushViewController(demoVC, animated: true) + // let demoVC:UIViewController = (self.demoVCList[indexPath.row]["class"] as! UIViewController.Type).init() + // demoVC.title = self.demoVCList[indexPath.row]["title"] as? String + // self.navigationController?.pushViewController(demoVC, animated: true) } diff --git a/TangramKitDemo/linerLayoutDemo/LLTest2ViewController.swift b/TangramKitDemo/linerLayoutDemo/LLTest2ViewController.swift index 6a05227..feaca67 100644 --- a/TangramKitDemo/linerLayoutDemo/LLTest2ViewController.swift +++ b/TangramKitDemo/linerLayoutDemo/LLTest2ViewController.swift @@ -123,11 +123,14 @@ left | a | | P | /*垂直线性布局套水平线性布局,水平线性布局利用相对边距实现左右布局*/ createSection5(in: contentLayout) - /*对子视图的高度的缩放调整*/ + /*水平线性布局中的基线对齐*/ createSection6(in: contentLayout) - /*子视图的显示和隐藏*/ + /*对子视图的高度的缩放调整*/ createSection7(in: contentLayout) + + /*子视图的显示和隐藏*/ + createSection8(in: contentLayout) } @@ -387,8 +390,47 @@ extension LLTest2ViewController } - //线性布局片段6:实现子视图的缩放。 + //建立一个基线对齐的水平线性布局 func createSection6(in contentLayout:TGLinearLayout) + { + //这个例子主要介绍基线对齐的使用方法,目前只有水平线性布局和相对布局是支持基线对齐的。水平线性布局里面要实现基线对齐,必须要设置一个基线对齐的标准视图。 + //线性布局里面的tg_baselineBaseView属性用来指定基线的标准视图,设置为tg_baselineBaseView的子视图必须是一个UILabel或者UITextField或者UITextView,并且只能是一行。 + //除了指定基线对齐的标准视图外,还需要为线性布局的tg_gravity属性设置上TGGravity.vert.baseline才可以完成基线对齐的设置。所有其他的UILabel,UITextField,UITextView都将和标准视图的基线进行对齐,而其他类型的子视图则忽略。 + //基线对齐对于中文来说基本没有什么效果,主要是针对英文以及具有基线的字符集。 + + let baselineLayout = TGLinearLayout(.horz) + baselineLayout.layer.borderColor = UIColor.lightGray.cgColor + baselineLayout.layer.borderWidth = 0.5 + baselineLayout.layer.cornerRadius = 4 + baselineLayout.tg_padding = UIEdgeInsetsMake(5, 5, 5, 5) + baselineLayout.tg_top.equal(20) + baselineLayout.tg_horzMargin(0) + baselineLayout.tg_height.equal(50) + baselineLayout.tg_gravity = [TGGravity.horz.center, TGGravity.vert.baseline] + contentLayout.addSubview(baselineLayout) + + let baselineLabel = UILabel() + baselineLabel.text = "Baseline view" + baselineLabel.tg_size(width: .wrap, height: .wrap) + baselineLabel.font = CFTool.font(20) + baselineLabel.backgroundColor = CFTool.color(5) + baselineLabel.tg_alignment = TGGravity.vert.center //标准视图垂直居中。 + baselineLayout.addSubview(baselineLabel) + + let rightLabel = UILabel() + rightLabel.text = "Right view" + rightLabel.tg_size(width: .wrap, height: .wrap) + rightLabel.font = CFTool.font(32) + rightLabel.backgroundColor = CFTool.color(6) + baselineLayout.addSubview(rightLabel) + + baselineLayout.tg_baselineBaseView = baselineLabel //这里将左边的视图设置为基线对齐的标准视图。 + + } + + + //线性布局片段7:实现子视图的缩放。 + func createSection7(in contentLayout:TGLinearLayout) { let shrinkLabel = UILabel() shrinkLabel.text = NSLocalizedString("This is a can automatically wrap text.To realize this function, you need to set the clear width, and set the flexedHeight to YES and set the numberOfLines to 0.You can try to switch different simulator or different orientation screen to see the effect.", comment:"") @@ -414,8 +456,8 @@ extension LLTest2ViewController } - //线性布局片段7:子视图的隐藏设置能够激发布局视图的重新布局。 - func createSection7(in contentLayout:TGLinearLayout) + //线性布局片段8:子视图的隐藏设置能够激发布局视图的重新布局。 + func createSection8(in contentLayout:TGLinearLayout) { let button = UIButton(type:.system) diff --git a/TangramKitDemo/linerLayoutDemo/LLTest6ViewController.swift b/TangramKitDemo/linerLayoutDemo/LLTest6ViewController.swift index f5fb50b..edbcd82 100644 --- a/TangramKitDemo/linerLayoutDemo/LLTest6ViewController.swift +++ b/TangramKitDemo/linerLayoutDemo/LLTest6ViewController.swift @@ -43,13 +43,28 @@ class LLTest6ViewController: UIViewController , UITextViewDelegate { 2.如果想让一个布局视图的高度和非布局视图的高度相等则请将布局视图的tg_height.equal(.fill) */ - self.edgesForExtendedLayout = UIRectEdge(rawValue:0) //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 super.loadView() let scrollView = UIScrollView(frame: self.view.bounds) scrollView.autoresizingMask = [.flexibleWidth, .flexibleHeight] self.view.addSubview(scrollView) + self.edgesForExtendedLayout = UIRectEdge(rawValue:0) //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + + /* + 当上面设置了根视图的边不延伸到导航条下或者导航条的navigationBar.translucent = NO,也就是不透明时。在push时发现除了从右往左的动画外,还出现了从下往上的动画效果。这个从下往上的动画效果不是我们需要的,这是因为iOS11后的UIScrollView的contentInset默认是叠加安全区的,而这里又因为滚动视图不延伸到导航条下面,所以这里出现了contentInset不断缩小的效果而产生了动画效果。这个锅是iOS11的锅,也是一个BUG。为了解决这个问题可以有如下方案: + */ + + if #available(iOS 11.0, *) { + scrollView.contentInsetAdjustmentBehavior = .never + + //滚动视图不把安全区叠加到滚动的缩进里面去。这个属性不是必须要这么设置的,只有当你出现了上面的情况时才这么设置。 + //如果导航条是半透明的或者根视图可以延伸到导航条下面去,就不需要这么设置。 + + } else { + // Fallback on earlier versions + } + let rootLayout = TGLinearLayout(.vert) rootLayout.backgroundColor = .white rootLayout.tg_width.equal(.fill)