From 74ebd2a287e0edf4887711caacf8b31fda24498e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E6=9F=8F=E6=B3=89?= Date: Thu, 10 May 2018 20:04:57 +0800 Subject: [PATCH] Release V1.1.6 --- CHANGELOG.md | 12 + TangramKit.podspec | 2 +- TangramKit.xcodeproj/project.pbxproj | 4 + TangramKit/Info.plist | 2 +- TangramKit/TGBaseLayout.swift | 32 ++- TangramKit/TGFlowLayout.swift | 213 +++++++++++++++--- TangramKit/TangramKit.swift | 2 +- .../FLLTest7ViewController.swift | 135 +++++++++++ TangramKitDemo/Info.plist | 2 +- .../AllTest1TableViewCell.swift | 6 +- .../zh-Hans.lproj/Localizable.strings | 1 + TangramKitDemo/ViewController.swift | 4 +- 12 files changed, 374 insertions(+), 41 deletions(-) create mode 100644 TangramKitDemo/FlowLayoutDemo/FLLTest7ViewController.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a0fe43..28c6f67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ **TangramKit**中的所有历史版本变化将会在这个文件中列出。 --- + +## [V1.1.6](https://github.com/youngsoft/TangramKit/releases/tag/1.1.6)(2018/05/10) + +#### Added +1.添加了流式布局`TGFlowLayout`对瀑布流的支持,主要是数量约束流式布局来实现,通过设置`tg_autoArrange`为YES或者设置`tg_arrangedGravity`属性为`TGGravity.horz.between或者TGGravity.vert.between`来实现两种不同策略的瀑布流模式,瀑布流模式其实就是一种紧凑的流式布局排列方式。具体的DEMO在新增加的[FLLTest7ViewController](https://github.com/youngsoft/TangramKit/blob/master/TangramKitDemo/FlowLayoutDemo/FLLTest7ViewController.swift)中可以查看。 + +#### Fixed +1. 修复了流式布局`TGFlowLayout`中的tg_gravity属性设置后停靠有可能不正确的问题。 +2. 优化和修复了对UIScrollView+布局视图时,设置UIScrollView的高度或者宽度由布局视图的尺寸进行自适应的问题。新版本中UIScrollView的尺寸可以依赖于布局视图的尺寸,同时布局视图的最大最小尺寸可以设置为UIScrollView的尺寸。具体例子参考:[FLLTest7ViewController](https://github.com/youngsoft/TangramKit/blob/master/TangramKitDemo/FlowLayoutDemo/FLLTest7ViewController.swift) +3. 添加了对布局视图的`tg_cacheEstimatedRect`属性的使用限制说明,这个属性只能用于那些需要高度自适应的UITableViewCell的根布局视图中使用,其他地方如果使用则有可能会出现计算不正确的问题。 + + ## [V1.1.5](https://github.com/youngsoft/TangramKit/releases/tag/1.1.5)(2018/05/06) 1. 优化了编译时慢的一些代码。 diff --git a/TangramKit.podspec b/TangramKit.podspec index bdaf903..9e67791 100644 --- a/TangramKit.podspec +++ b/TangramKit.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "TangramKit" - s.version = "1.1.5" + s.version = "1.1.6" 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 9ec55d7..34fd18b 100644 --- a/TangramKit.xcodeproj/project.pbxproj +++ b/TangramKit.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 204DC323209E0BC000F6CB57 /* TLTest4ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 204DC322209E0BC000F6CB57 /* TLTest4ViewController.swift */; }; 20B6C6E71FA40AEC001D51C7 /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20B6C6E61FA40AEC001D51C7 /* DetailViewController.swift */; }; 20DCF335208CD022007A879B /* FOLTest7ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20DCF334208CD022007A879B /* FOLTest7ViewController.swift */; }; + 20FC8FE220A4241D0029DE31 /* FLLTest7ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20FC8FE120A4241D0029DE31 /* FLLTest7ViewController.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 */; }; @@ -106,6 +107,7 @@ 204DC322209E0BC000F6CB57 /* TLTest4ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLTest4ViewController.swift; sourceTree = ""; }; 20B6C6E61FA40AEC001D51C7 /* DetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = ""; }; 20DCF334208CD022007A879B /* FOLTest7ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FOLTest7ViewController.swift; sourceTree = ""; }; + 20FC8FE120A4241D0029DE31 /* FLLTest7ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FLLTest7ViewController.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 = ""; }; @@ -289,6 +291,7 @@ 68F035F81E0B7D2700CEBAEF /* FLLTest4ViewController.swift */, 184243071E327F0800E2CCE1 /* FLLTest5ViewController.swift */, 18058AAE1E63B4EA00EAECDC /* FLLTest6ViewController.swift */, + 20FC8FE120A4241D0029DE31 /* FLLTest7ViewController.swift */, ); path = FlowLayoutDemo; sourceTree = ""; @@ -553,6 +556,7 @@ 68F036441E0B7D2700CEBAEF /* FOLTest4ViewController.swift in Sources */, 68F0366C1E0B7D2700CEBAEF /* LLTest6ViewController.swift in Sources */, 18BCBD461E1336D900AC7766 /* AllTest8ViewController.swift in Sources */, + 20FC8FE220A4241D0029DE31 /* FLLTest7ViewController.swift in Sources */, 68F036541E0B7D2700CEBAEF /* AllTest6ViewController.swift in Sources */, 68F036801E0B7D2700CEBAEF /* TLTest3ViewController.swift in Sources */, 68F036811E0B7D2700CEBAEF /* ViewController.swift in Sources */, diff --git a/TangramKit/Info.plist b/TangramKit/Info.plist index 154313d..482d580 100644 --- a/TangramKit/Info.plist +++ b/TangramKit/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.1.5 + 1.1.6 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/TangramKit/TGBaseLayout.swift b/TangramKit/TGBaseLayout.swift index 6319cf9..07e1402 100644 --- a/TangramKit/TGBaseLayout.swift +++ b/TangramKit/TGBaseLayout.swift @@ -1132,7 +1132,8 @@ open class TGBaseLayout: UIView,TGLayoutViewSizeClass { return size.height; } - + + 这个属性有可能会造成动态高度计算不正确,请只在UITableviewCell的高度为自适应时使用,其他地方不建议设置这个属性!! */ public var tg_cacheEstimatedRect:Bool = false { @@ -2618,6 +2619,16 @@ extension TGBaseLayout } } + //这里要判断自己的宽度设置了最小和最大宽度依赖于父视图的情况。如果有这种情况,则父视图在变化时也需要调整自身。 + if let t = lsc.width.maxVal?.sizeVal, t.view === newSuperview + { + isAdjust = true + } + if let t = lsc.width.minVal?.sizeVal, t.view === newSuperview + { + isAdjust = true + } + rectSelf.size.width = self.tgValidMeasure(lsc.width,sbv:self,calcSize:rectSelf.width,sbvSize:rectSelf.size,selfLayoutSize:rectSuper.size); if TGBaseLayout.tg_isRTL @@ -2710,6 +2721,16 @@ extension TGBaseLayout } } + //这里要判断自己的高度设置了最小和最大高度依赖于父视图的情况。如果有这种情况,则父视图在变化时也需要调整自身。 + if let t = lsc.height.maxVal?.sizeVal, t.view === newSuperview + { + isAdjust = true + } + if let t = lsc.height.minVal?.sizeVal, t.view === newSuperview + { + isAdjust = true + } + rectSelf.size.height = self.tgValidMeasure(lsc.height,sbv:self,calcSize:rectSelf.height,sbvSize:rectSelf.size,selfLayoutSize:rectSuper.size); if lsc.isVertMarginHasValue @@ -3411,6 +3432,10 @@ extension TGBaseLayout { lv.removeObserver(self, forKeyPath: "center") } + else if let sv = subview as? UIScrollView + { + sv.removeObserver(self, forKeyPath: "center") + } else if let lb = subview as? UILabel { lb.removeObserver(self, forKeyPath: "text") @@ -3438,7 +3463,10 @@ extension TGBaseLayout if let lv = subview as? TGBaseLayout { lv.addObserver(self, forKeyPath:"center", options:.new, context: &TGBaseLayout._stgObserverCtxA) - lv.tg_cacheEstimatedRect = self.tg_cacheEstimatedRect + } + else if let sv = subview as? UIScrollView + { + sv.addObserver(self, forKeyPath:"center", options:.new, context: &TGBaseLayout._stgObserverCtxA) } else if let lb = subview as? UILabel { diff --git a/TangramKit/TGFlowLayout.swift b/TangramKit/TGFlowLayout.swift index c96fffa..e3fd099 100644 --- a/TangramKit/TGFlowLayout.swift +++ b/TangramKit/TGFlowLayout.swift @@ -630,14 +630,17 @@ extension TGFlowLayout } //为子视图设置单独的对齐方式 - let sbvVertAlignment = sbvsc.tg_alignment & TGGravity.horz.mask - var vertAlignment = vertAlignment - if sbvVertAlignment != TGGravity.none + var sbvVertAlignment = sbvsc.tg_alignment & TGGravity.horz.mask + if sbvVertAlignment == TGGravity.none { - vertAlignment = sbvVertAlignment + sbvVertAlignment = vertAlignment + } + if vertAlignment == TGGravity.vert.between + { + sbvVertAlignment = vertAlignment } - if (vertAlignment != TGGravity.none && vertAlignment != TGGravity.vert.top) || _tgCGFloatNotEqual(addXPos, 0) || _tgCGFloatNotEqual(addXFill, 0) + if (sbvVertAlignment != TGGravity.none && sbvVertAlignment != TGGravity.vert.top) || _tgCGFloatNotEqual(addXPos, 0) || _tgCGFloatNotEqual(addXFill, 0) { sbvtgFrame.leading += addXPos @@ -658,7 +661,7 @@ extension TGFlowLayout let topSpace = sbvsc.top.absPos let bottomSpace = sbvsc.bottom.absPos - switch vertAlignment { + switch sbvVertAlignment { case TGGravity.vert.center: sbvtgFrame.top += (rowMaxHeight - topSpace - bottomSpace - sbvtgFrame.height) / 2 break @@ -759,14 +762,17 @@ extension TGFlowLayout } //为子视图设置单独的对齐方式 - let sbvHorzAlignment = self.tgConvertLeftRightGravityToLeadingTrailing(sbvsc.tg_alignment & TGGravity.vert.mask) - var horzAlignment = horzAlignment - if sbvHorzAlignment != TGGravity.none + var sbvHorzAlignment = self.tgConvertLeftRightGravityToLeadingTrailing(sbvsc.tg_alignment & TGGravity.vert.mask) + if sbvHorzAlignment == TGGravity.none + { + sbvHorzAlignment = horzAlignment + } + if horzAlignment == TGGravity.vert.between { - horzAlignment = sbvHorzAlignment + sbvHorzAlignment = horzAlignment } - if (horzAlignment != TGGravity.none && horzAlignment != TGGravity.horz.leading) || _tgCGFloatNotEqual(addYPos, 0) || + if (sbvHorzAlignment != TGGravity.none && sbvHorzAlignment != TGGravity.horz.leading) || _tgCGFloatNotEqual(addYPos, 0) || _tgCGFloatNotEqual(addYFill, 0) { sbvtgFrame.top += addYPos @@ -786,7 +792,7 @@ extension TGFlowLayout let leadingSpace = sbvsc.leading.absPos let trailingSpace = sbvsc.trailing.absPos - switch horzAlignment { + switch sbvHorzAlignment { case TGGravity.horz.center: sbvtgFrame.leading += (colMaxWidth - leadingSpace - trailingSpace - sbvtgFrame.width)/2 break @@ -867,13 +873,16 @@ extension TGFlowLayout } fileprivate func tgLayoutSubviewsForVert(_ selfSize:CGSize, sbs:[UIView], isEstimate:Bool, lsc:TGFlowLayoutViewSizeClassImpl)->CGSize { + var selfSize = selfSize + let autoArrange:Bool = lsc.tg_autoArrange let arrangedCount:Int = lsc.tg_arrangedCount var xPos:CGFloat = lsc.tgLeadingPadding var yPos:CGFloat = lsc.tgTopPadding var rowMaxHeight:CGFloat = 0 var rowMaxWidth:CGFloat = 0 var maxWidth = lsc.tgLeadingPadding + var maxHeight = lsc.tgTopPadding let vertGravity:TGGravity = lsc.tg_gravity & TGGravity.horz.mask let horzGravity:TGGravity = self.tgConvertLeftRightGravityToLeadingTrailing(lsc.tg_gravity & TGGravity.vert.mask) @@ -1017,6 +1026,15 @@ extension TGFlowLayout self.tgCalcVertLayoutSinglelineWeight(selfSize:selfSize,totalFloatWidth:selfSize.width - lsc.tgLeadingPadding - lsc.tgTrailingPadding - rowTotalFixedWidth,totalWeight:rowTotalWeight,sbs:sbs,startIndex:sbs.count, count:arrangedIndex) } + var nextPointOfRows:[CGPoint]! = nil + if autoArrange + { + nextPointOfRows = [CGPoint]() + for _ in 0 ..< arrangedCount + { + nextPointOfRows.append(CGPoint(x:lsc.tgLeadingPadding, y: lsc.tgTopPadding)) + } + } var pageWidth:CGFloat = 0; //页宽 let averageWidth:CGFloat = (selfSize.width - lsc.tgLeadingPadding - lsc.tgTrailingPadding - (CGFloat(arrangedCount) - 1) * horzSpace) / CGFloat(arrangedCount) @@ -1118,17 +1136,77 @@ extension TGFlowLayout rect.size.height = self.tgValidMeasure(sbvsc.height, sbv: sbv, calcSize: rect.size.height, sbvSize: rect.size, selfLayoutSize: selfSize) + if _tgCGFloatLess(rowMaxHeight , topSpace + bottomSpace + rect.size.height) { + rowMaxHeight = topSpace + bottomSpace + rect.size.height + } + + if autoArrange + { + var minPt:CGPoint = CGPoint(x:CGFloat.greatestFiniteMagnitude, y:CGFloat.greatestFiniteMagnitude) + var minNextPointIndex:Int = 0 + for idx in 0 ..< arrangedCount + { + let pt = nextPointOfRows[idx] + if minPt.y > pt.y + { + minPt = pt + minNextPointIndex = idx + } + } + + xPos = minPt.x + yPos = minPt.y + + minPt.y = minPt.y + topSpace + rect.size.height + bottomSpace + vertSpace + nextPointOfRows[minNextPointIndex] = minPt + if minNextPointIndex + 1 <= arrangedCount - 1 + { + minPt = nextPointOfRows[minNextPointIndex + 1] + minPt.x = xPos + leadingSpace + rect.size.width + trailingSpace + horzSpace + nextPointOfRows[minNextPointIndex + 1] = minPt + } + + if _tgCGFloatLess(maxHeight, yPos + topSpace + rect.size.height + bottomSpace) + { + maxHeight = yPos + topSpace + rect.size.height + bottomSpace + } + + } + else if vertAlignment == TGGravity.vert.between + { + //当行是紧凑排行时需要特殊处理当前的垂直位置。 + //第0行特殊处理。 + if (i - arrangedCount < 0) + { + yPos = lsc.tgTopPadding + } + else + { + //取前一行的对应的列的子视图。 + let (prevSbvtgFrame, prevSbvsc) = self.tgGetSubviewFrameAndSizeClass(sbs[i - arrangedCount]) + //当前子视图的位置等于前一行对应列的最大y的值 + 前面对应列的尾部间距 + 子视图之间的行间距。 + yPos = prevSbvtgFrame.frame.maxY + prevSbvsc.bottom.absPos + vertSpace + } + + if _tgCGFloatLess(maxHeight, yPos + topSpace + rect.size.height + bottomSpace) + { + maxHeight = yPos + topSpace + rect.size.height + bottomSpace + } + } + else + { + maxHeight = yPos + rowMaxHeight + } + rect.origin.x = (xPos + leadingSpace) rect.origin.y = (yPos + topSpace) xPos += (leadingSpace + rect.size.width + trailingSpace) - if arrangedIndex != (arrangedCount - 1) { + if arrangedIndex != (arrangedCount - 1) && !autoArrange { xPos += horzSpace } - if _tgCGFloatLess(rowMaxHeight , topSpace + bottomSpace + rect.size.height) { - rowMaxHeight = topSpace + bottomSpace + rect.size.height - } + if _tgCGFloatLess(rowMaxWidth , xPos - lsc.tgLeadingPadding) { rowMaxWidth = xPos - lsc.tgLeadingPadding @@ -1145,9 +1223,11 @@ extension TGFlowLayout //最后一行 布局 self .tgCalcVertLayoutSinglelineAlignment(selfSize, rowMaxHeight: rowMaxHeight, rowMaxWidth: rowMaxWidth, horzGravity: horzGravity, vertAlignment: vertAlignment, sbs: sbs, startIndex: sbs.count, count: arrangedIndex,vertSpace: vertSpace, horzSpace: horzSpace, isEstimate: isEstimate, lsc:lsc) + maxHeight = maxHeight + lsc.tgBottomPadding + if lsc.height.isWrap { - selfSize.height = yPos + lsc.tgBottomPadding + rowMaxHeight + selfSize.height = maxHeight //只有在父视图为滚动视图,且开启了分页滚动时才会扩充具有包裹设置的布局视图的宽度。 if (isVertPaging && isPagingScroll) @@ -1169,16 +1249,16 @@ extension TGFlowLayout let arranges = floor(CGFloat(sbs.count + arrangedCount - 1) / CGFloat(arrangedCount)) if vertGravity == TGGravity.vert.center { - addYPos = (selfSize.height - lsc.tgBottomPadding - rowMaxHeight - yPos)/2 + addYPos = (selfSize.height - maxHeight)/2 } else if vertGravity == TGGravity.vert.bottom { - addYPos = selfSize.height - lsc.tgBottomPadding - rowMaxHeight - yPos + addYPos = selfSize.height - maxHeight } else if (vertGravity == TGGravity.vert.fill) { if (arranges > 0) { - fill = (selfSize.height - lsc.tgBottomPadding - rowMaxHeight - yPos) / arranges + fill = (selfSize.height - maxHeight) / arranges } } else if (vertGravity == TGGravity.vert.between) @@ -1186,7 +1266,7 @@ extension TGFlowLayout if (arranges > 1) { - between = (selfSize.height - lsc.tgBottomPadding - rowMaxHeight - yPos) / (arranges - 1) + between = (selfSize.height - maxHeight) / (arranges - 1) } } @@ -1459,12 +1539,14 @@ extension TGFlowLayout fileprivate func tgLayoutSubviewsForHorz(_ selfSize:CGSize, sbs:[UIView], isEstimate:Bool, lsc:TGFlowLayoutViewSizeClassImpl)->CGSize { + let autoArrange:Bool = lsc.tg_autoArrange let arrangedCount:Int = lsc.tg_arrangedCount var xPos:CGFloat = lsc.tgLeadingPadding var yPos:CGFloat = lsc.tgTopPadding var colMaxWidth:CGFloat = 0 var colMaxHeight:CGFloat = 0 var maxHeight:CGFloat = lsc.tgTopPadding + var maxWidth:CGFloat = lsc.tgLeadingPadding var selfSize = selfSize let vertGravity:TGGravity = lsc.tg_gravity & TGGravity.horz.mask @@ -1634,6 +1716,15 @@ extension TGFlowLayout self.tgCalcHorzLayoutSinglelineWeight(selfSize:selfSize,totalFloatHeight:selfSize.height - lsc.tgTopPadding - lsc.tgBottomPadding - rowTotalFixedHeight,totalWeight:rowTotalWeight,sbs:sbs,startIndex:sbs.count,count:arrangedIndex) } + var nextPointOfRows:[CGPoint]! = nil + if autoArrange + { + nextPointOfRows = [CGPoint]() + for _ in 0 ..< arrangedCount + { + nextPointOfRows.append(CGPoint(x:lsc.tgLeadingPadding, y: lsc.tgTopPadding)) + } + } var pageHeight:CGFloat = 0 let averageHeight:CGFloat = (selfSize.height - lsc.tgTopPadding - lsc.tgBottomPadding - (CGFloat(arrangedCount) - 1) * vertSpace) / CGFloat(arrangedCount) @@ -1723,19 +1814,77 @@ extension TGFlowLayout rect.size.width = self.tgValidMeasure(sbvsc.width, sbv: sbv, calcSize: rect.size.width, sbvSize: rect.size, selfLayoutSize: selfSize) } + if _tgCGFloatLess(colMaxWidth , leadingSpace + trailingSpace + rect.size.width) + { + colMaxWidth = leadingSpace + trailingSpace + rect.size.width + } + + if autoArrange + { + var minPt:CGPoint = CGPoint(x:CGFloat.greatestFiniteMagnitude, y:CGFloat.greatestFiniteMagnitude) + var minNextPointIndex:Int = 0 + for idx in 0 ..< arrangedCount + { + let pt = nextPointOfRows[idx] + if minPt.x > pt.x + { + minPt = pt + minNextPointIndex = idx + } + } + + xPos = minPt.x + yPos = minPt.y + + minPt.x = minPt.x + leadingSpace + rect.size.width + trailingSpace + horzSpace; + nextPointOfRows[minNextPointIndex] = minPt + if minNextPointIndex + 1 <= arrangedCount - 1 + { + minPt = nextPointOfRows[minNextPointIndex + 1] + minPt.y = yPos + topSpace + rect.size.height + bottomSpace + vertSpace + nextPointOfRows[minNextPointIndex + 1] = minPt + } + + if _tgCGFloatLess(maxWidth, xPos + leadingSpace + rect.size.width + trailingSpace) + { + maxWidth = xPos + leadingSpace + rect.size.width + trailingSpace + } + + } + else if horzAlignment == TGGravity.horz.between + { + //当列是紧凑排列时需要特殊处理当前的水平位置。 + //第0列特殊处理。 + if (i - arrangedCount < 0) + { + xPos = lsc.tgLeadingPadding + } + else + { + //取前一列的对应的行的子视图。 + let (prevSbvtgFrame, prevSbvsc) = self.tgGetSubviewFrameAndSizeClass(sbs[i - arrangedCount]) + //当前子视图的位置等于前一列对应行的最大x的值 + 前面对应行的尾部间距 + 子视图之间的列间距。 + xPos = prevSbvtgFrame.frame.maxX + prevSbvsc.trailing.absPos + horzSpace + } + + if _tgCGFloatLess(maxWidth, xPos + leadingSpace + rect.size.width + trailingSpace) + { + maxWidth = xPos + leadingSpace + rect.size.width + trailingSpace + } + } + else + { + maxWidth = xPos + colMaxWidth + } rect.origin.y = yPos + topSpace rect.origin.x = xPos + leadingSpace yPos += topSpace + rect.size.height + bottomSpace - if arrangedIndex != (arrangedCount - 1) { + if arrangedIndex != (arrangedCount - 1) && !autoArrange { yPos += vertSpace } - if _tgCGFloatLess(colMaxWidth , leadingSpace + trailingSpace + rect.size.width) - { - colMaxWidth = leadingSpace + trailingSpace + rect.size.width - } if _tgCGFloatLess(colMaxHeight , (yPos - lsc.tgTopPadding)) { colMaxHeight = yPos - lsc.tgTopPadding @@ -1770,9 +1919,11 @@ extension TGFlowLayout } + maxWidth = maxWidth + lsc.tgTrailingPadding + if lsc.width.isWrap { - selfSize.width = xPos + lsc.tgTrailingPadding + colMaxWidth + selfSize.width = maxWidth //只有在父视图为滚动视图,且开启了分页滚动时才会扩充具有包裹设置的布局视图的宽度。 if (isHorzPaging && isPagingScroll) @@ -1795,23 +1946,23 @@ extension TGFlowLayout if horzGravity == TGGravity.horz.center { - addXPos = (selfSize.width - lsc.tgTrailingPadding - colMaxWidth - xPos) / 2 + addXPos = (selfSize.width - maxWidth) / 2 } else if horzGravity == TGGravity.horz.trailing { - addXPos = selfSize.width - lsc.tgTrailingPadding - colMaxWidth - xPos + addXPos = selfSize.width - maxWidth } else if (horzGravity == TGGravity.horz.fill) { if (arranges > 0) { - fill = (selfSize.width - lsc.tgTrailingPadding - colMaxWidth - xPos) / arranges + fill = (selfSize.width - maxWidth) / arranges } } else if (horzGravity == TGGravity.horz.between) { if (arranges > 1) { - between = (selfSize.width - lsc.tgLeadingPadding - colMaxWidth - xPos) / (arranges - 1) + between = (selfSize.width - maxWidth) / (arranges - 1) } } diff --git a/TangramKit/TangramKit.swift b/TangramKit/TangramKit.swift index b0004b1..bfa1877 100644 --- a/TangramKit/TangramKit.swift +++ b/TangramKit/TangramKit.swift @@ -53,7 +53,7 @@ */ -//Current version is 1.1.5, please open: https://github.com/youngsoft/TangramKit/blob/master/CHANGELOG.md to show the changes. +//Current version is 1.1.6, please open: https://github.com/youngsoft/TangramKit/blob/master/CHANGELOG.md to show the changes. diff --git a/TangramKitDemo/FlowLayoutDemo/FLLTest7ViewController.swift b/TangramKitDemo/FlowLayoutDemo/FLLTest7ViewController.swift new file mode 100644 index 0000000..eb411d8 --- /dev/null +++ b/TangramKitDemo/FlowLayoutDemo/FLLTest7ViewController.swift @@ -0,0 +1,135 @@ +// +// FLLTest7ViewController.swift +// TangramKit +// +// Created by apple on 16/7/18. +// Copyright © 2016年 youngsoft. All rights reserved. +// + +import UIKit + + + +/** + *7.FlowLayout - Auto Arrange + */ +class FLLTest7ViewController: UIViewController { + + + func createItems(_ titles:[String], in flowLayout:TGFlowLayout) ->Void + { + for title in titles + { + let label = UILabel() + label.text = title + label.tg_size(width:.wrap, height:.wrap) + label.backgroundColor = CFTool.color(Int(arc4random()%14) + 1) + label.font = CFTool.font(16) + flowLayout.addSubview(label) + } + } + + + + override func loadView() { + + /* + 这个例子主要用来介绍数量约束流式布局的自动排列和紧凑排列的能力,目的是为了实现类似于瀑布流的功能,下面的代码您将能看到水平和垂直两种应用场景。 + 每种应用场景中,我们通过设置tg_autoArrange为true和tg_arrangedGravity属性为TGGravity.horz.between或者TGGravity.vert.between来分别实现两种不同的 + 排列策略: + tg_autoArrange: 的策略是让总体的空间达到最高效的利用,但是他会打乱视图添加的顺序。 + tg_arrangedGravity: 的策略则不会打乱视图的添加顺序,因此他的总体空间的利用率可能会不如tg_autoArrange那么高。 + */ + + /* + 需要注意的是,当您的数据量比较小时,我们可以考虑使用流式布局来实现瀑布流,而当你的数据量比较大,并且需要考虑复用,那么为了内存上的考虑建议您还是使用tableView或者collectionView来实现。 + */ + + let titles = ["11111111111111111", "222222222222222222222222222","3333333333333", "4444444444444444444444", "55555555", "6666666666666", "77777777", "8888888888888888888888", "99"] + + + + + self.edgesForExtendedLayout = UIRectEdge(rawValue:0) //设置视图控制器中的视图尺寸不延伸到导航条或者工具条下面。您可以注释这句代码看看效果。 + + let rootLayout = TGLinearLayout(.vert) + rootLayout.tg_gravity = TGGravity.horz.fill + rootLayout.tg_space = 20 + rootLayout.backgroundColor = UIColor.white + self.view = rootLayout + + //水平瀑布流1。 + let scrollView1 = UIScrollView() + scrollView1.tg_height.equal(.wrap) //这里可以设置滚动视图的高度为包裹属性,表示他的高度依赖于布局视图的高度。 + rootLayout.addSubview(scrollView1) + + let flowLayout1 = TGFlowLayout(.horz,arrangedCount:3) + flowLayout1.backgroundColor = CFTool.color(5) + flowLayout1.tg_height.equal(.wrap) //流式布局的尺寸由里面的子视图的整体尺寸决定。 + flowLayout1.tg_width.equal(.wrap).min(scrollView1.tg_width) //虽然尺寸是包裹的,但是最小宽度不能小于父视图的宽度 + flowLayout1.tg_autoArrange = true //通过将流式布局的autoArrange属性设置为YES可以实现里面的子视图进行紧凑的自动排列。 + flowLayout1.tg_space = 10; + flowLayout1.tg_padding = UIEdgeInsetsMake(10, 10, 10, 10); + scrollView1.addSubview(flowLayout1) + self.createItems(titles, in:flowLayout1) + + + //水平瀑布流2。 + let scrollView2 = UIScrollView() + scrollView2.tg_height.equal(.wrap) //这里可以设置滚动视图的高度为包裹属性,表示他的高度依赖于布局视图的高度。 + rootLayout.addSubview(scrollView2) + + let flowLayout2 = TGFlowLayout(.horz,arrangedCount:3) + flowLayout2.backgroundColor = CFTool.color(5) + flowLayout2.tg_height.equal(.wrap) //流式布局的尺寸由里面的子视图的整体尺寸决定。 + flowLayout2.tg_width.equal(.wrap).min(scrollView2.tg_width) //虽然尺寸是包裹的,但是最小宽度不能小于父视图的宽度 + flowLayout2.tg_arrangedGravity = TGGravity.horz.between //通过将水平流式布局的tg_arrangeGravity属性设置为TGGravity.vert.between,我们将得到里面的子视图在每行都会被紧凑的排列。大家可以看到和上面的将tg_autoArrange设置为true的不同的效果。 + flowLayout2.tg_space = 10; + flowLayout2.tg_padding = UIEdgeInsetsMake(10, 10, 10, 10); + scrollView2.addSubview(flowLayout2) + self.createItems(titles, in:flowLayout2) + + + //垂直瀑布流1 + let scrollView3 = UIScrollView() + scrollView3.tg_height.equal(50%) //这里可以设置滚动视图的高度为包裹属性,表示他的高度依赖于布局视图的高度。 + rootLayout.addSubview(scrollView3) + + let flowLayout3 = TGFlowLayout(.vert,arrangedCount:3) + flowLayout3.backgroundColor = CFTool.color(5) + flowLayout3.tg_height.equal(.wrap).min(scrollView3.tg_height) //虽然是包裹尺寸,但是最小不能小于父视图的高度。 + flowLayout3.tg_width.equal(.fill) + flowLayout3.tg_gravity = TGGravity.horz.fill //均分宽度。 + flowLayout3.tg_autoArrange = true //通过将流式布局的autoArrange属性设置为YES可以实现里面的子视图进行紧凑的自动排列。 + flowLayout3.tg_space = 10; + flowLayout3.tg_padding = UIEdgeInsetsMake(10, 10, 10, 10) + scrollView3.addSubview(flowLayout3) + self.createItems(titles, in:flowLayout3) + + + //垂直瀑布流2 + let scrollView4 = UIScrollView() + scrollView4.tg_height.equal(50%) //这里可以设置滚动视图的高度为包裹属性,表示他的高度依赖于布局视图的高度。 + rootLayout.addSubview(scrollView4) + + let flowLayout4 = TGFlowLayout(.vert,arrangedCount:3) + flowLayout4.backgroundColor = CFTool.color(5) + flowLayout4.tg_height.equal(.wrap).min(scrollView4.tg_height) //虽然是包裹尺寸,但是最小不能小于父视图的高度。 + flowLayout4.tg_width.equal(.fill) + flowLayout4.tg_gravity = TGGravity.horz.fill //均分宽度。 + flowLayout4.tg_arrangedGravity = TGGravity.vert.between + flowLayout4.tg_space = 10 + flowLayout4.tg_padding = UIEdgeInsetsMake(10, 10, 10, 10) + scrollView4.addSubview(flowLayout4) + self.createItems(titles, in:flowLayout4) + + + + } + + + override func viewDidLoad() { + super.viewDidLoad() + + } +} diff --git a/TangramKitDemo/Info.plist b/TangramKitDemo/Info.plist index a4faed8..f5d3bff 100644 --- a/TangramKitDemo/Info.plist +++ b/TangramKitDemo/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.1.5 + 1.1.6 CFBundleSignature ???? CFBundleVersion diff --git a/TangramKitDemo/IntegratedDemo/AllTestModel&View/AllTest1TableViewCell.swift b/TangramKitDemo/IntegratedDemo/AllTestModel&View/AllTest1TableViewCell.swift index 06a8f9c..ec5fb72 100644 --- a/TangramKitDemo/IntegratedDemo/AllTestModel&View/AllTest1TableViewCell.swift +++ b/TangramKitDemo/IntegratedDemo/AllTestModel&View/AllTest1TableViewCell.swift @@ -115,7 +115,7 @@ extension AllTest1TableViewCell self.rootLayout.tg_bottomPadding = 5 self.rootLayout.tg_width.equal(.fill) self.rootLayout.tg_height.equal(.wrap) - self.rootLayout.tg_cacheEstimatedRect = true + self.rootLayout.tg_cacheEstimatedRect = true //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! self.contentView.addSubview(self.rootLayout) //如果您将布局视图作为子视图添加到UITableViewCell本身,并且同时设置了布局视图的宽度等于父布局的情况下,那么有可能最终展示的宽度会不正确。经过试验是因为对UITableViewCell本身的KVO监控所得到的新老尺寸的问题导致的这应该是iOS的一个BUG。所以这里建议最好是把布局视图添加到UITableViewCell的子视图contentView里面去。 @@ -174,7 +174,7 @@ extension AllTest1TableViewCell self.rootLayout.tg_bottomPadding = 5 self.rootLayout.tg_width.equal(.fill) self.rootLayout.tg_height.equal(.wrap) - self.rootLayout.tg_cacheEstimatedRect = true + self.rootLayout.tg_cacheEstimatedRect = true //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! self.contentView.addSubview(self.rootLayout) /* @@ -223,7 +223,7 @@ extension AllTest1TableViewCell self.rootLayout.tg_bottomPadding = 5 self.rootLayout.tg_width.equal(.fill) self.rootLayout.tg_height.equal(.wrap) - self.rootLayout.tg_cacheEstimatedRect = true + self.rootLayout.tg_cacheEstimatedRect = true //这个属性只局限于在UITableViewCell中使用,用来优化tableviewcell的高度自适应的性能,其他地方请不要使用!!! self.contentView.addSubview(self.rootLayout) /* diff --git a/TangramKitDemo/Support Files/zh-Hans.lproj/Localizable.strings b/TangramKitDemo/Support Files/zh-Hans.lproj/Localizable.strings index 26ff406..4c4e416 100644 --- a/TangramKitDemo/Support Files/zh-Hans.lproj/Localizable.strings +++ b/TangramKitDemo/Support Files/zh-Hans.lproj/Localizable.strings @@ -32,6 +32,7 @@ "4.FlowLayout - Weight" = "4.流式布局-对线性布局的替代方案"; "5.FlowLayout - Paging" = "5.流式布局-对分页滚动的支持"; "6.FlowLayout - Scroll" = "6.流式布局-不同方向的滚动"; +"7.FlowLayout - Auto Arrange" = "7.流式布局-自动布局和对瀑布流的支持"; "1.FloatLayout - Float" = "1.浮动布局-浮动效果的演示"; "2.FloatLayout - Jagged" = "2.浮动布局-仿天猫淘宝首页实现" ; "3.FloatLayout - Card news" = "3.浮动布局-仿ZAKER今日头条实现"; diff --git a/TangramKitDemo/ViewController.swift b/TangramKitDemo/ViewController.swift index 6a786c3..ef56d87 100644 --- a/TangramKitDemo/ViewController.swift +++ b/TangramKitDemo/ViewController.swift @@ -125,7 +125,9 @@ class ViewController: UITableViewController { demoVCList5.append(["title":NSLocalizedString("6.FlowLayout - Scroll",comment:""), "class":FLLTest6ViewController.self] ) - + demoVCList5.append(["title":NSLocalizedString("7.FlowLayout - Auto Arrange",comment:""), + "class":FLLTest7ViewController.self] + ) //float layout list var demoVCList6 = [[String:Any]]()