TangramKit是一套在Swift3.0語言上開發(fā)的iOS界面視圖布局框架。它的名字來源于中國古代的玩具七巧板,寓意著可以用簡單的功能來構(gòu)造出各種千變?nèi)f化且非常復雜的UI界面。TangramKit的內(nèi)核是基于對UIView的layoutSubviews方法的重載以及對子視圖的bounds和center屬性的設(shè)置而實現(xiàn)的。TangramKit功能強大而且簡單易用,它集成了:iOS Autolayout和SizeClass、android的5大布局體系、HTML/CSS的浮動定位技術(shù)以及flex-box和bootstrap框架等市面上主流的平臺的界面布局功能,同時提供了一套非常簡單和完備的多屏幕尺寸適配的解決方案。TangramKit的objective-C版本的名字叫做:MyLayout
您可以加入到QQ群:178573773 或者添加個人QQ:156355113 來跟我討論或者郵件:obq0387_cn@sina.com 聯(lián)系我。
舉例下面一個應(yīng)用場景:
最終的效果圖如下:
let S = TGLinearLayout(.vert) S.tg_vspace = 10 S.tg_width.equal(100) S.tg_height.equal(.wrap) //you can use S.tg_size(width:100, height:.wrap) to instead let A = UIView() A.tg_left.equal(20%) A.tg_right.equal(30%) A.tg_height.equal(A.tg_width) S.addSubview(A) let B = UIView() B.tg_left.equal(40) B.tg_width.equal(.fill) B.tg_height.equal(40) S.addSubview(B) let C = UIView() C.tg_width.equal(.fill) C.tg_height.equal(40) S.addSubview(C) let D = UIView() D.tg_right.equal(20) D.tg_width.equal(50%) D.tg_height.equal(40) S.addSubview(D)因為TangramKit 重載了運算符:~=、>=、<=、+=、-=、*=、/= 來實現(xiàn)布局尺寸類
TGLayoutSize
和布局位置類
TGLayoutPos
的equal,max,min,add,offset,multiply方法。因此您也可以將代碼寫成如下方式:
let S = TGLinearLayout(.vert) S.tg_vspace = 10 S.tg_width ~=100 S.tg_height ~=.wrap let A = UIView() A.tg_left ~=20% A.tg_right ~=30% A.tg_height ~=A.tg_width S.addSubview(A) let B = UIView() B.tg_left ~=40 B.tg_width ~=.fill B.tg_height ~=40 S.addSubview(B) let C = UIView() C.tg_width ~=.fill C.tg_height ~=40 S.addSubview(C) let D = UIView() D.tg_right ~=20 D.tg_width ~=50% D.tg_height ~=40 S.addSubview(D)
TGLayoutPos類是用來描述一個視圖所在的位置的類。UIView中擴展出了tg_left,tg_top,tg_bottom,tg_right,tg_centerX,tg_centerY這六個變量來實現(xiàn)視圖的定位操作。您可以用這些變量的equal方法來設(shè)置視圖之間的邊距和間距。
TGLayoutSize類是用來描述一個視圖的尺寸的類。UIView中擴展出了tg_width,tg_height這兩個變量來實現(xiàn)視圖的寬度和高度尺寸的設(shè)置。您可以用其中的equal方法來設(shè)置視圖的寬度和高度。系統(tǒng)提供了三個常量的布局尺寸值:.wrap
, .fill
, .average
來分別表示尺寸包裹所有子視圖,尺寸填充父視圖的剩余空間,尺寸均分父視圖的剩余空間。
TGWeight類用來設(shè)置相對的位置和尺寸的值。相對值表明視圖的位置或者尺寸是占用父視圖的剩余空間或者父視圖空間的比例值。為了方便使用,您可以用重載的運算符%來構(gòu)建一個TGWeight對象,比如20%就等價于TGWeight(20).
等價于iOS的UIStackView和android的LinearLayout布局。
線性布局是一種里面的子視圖按添加的順序從上到下或者從左到右依次排列的單列(單行)布局視圖,因此里面的子視圖是通過添加的順序建立約束和依賴關(guān)系的。 子視圖從上到下依次排列的線性布局視圖稱為垂直線性布局視圖,而子視圖從左到右依次排列的線性布局視圖則稱為水平線性布局。
示例代碼:
override func loadView() { super.loadView() let S = TGLinearLayout(.vert) S.tg_width.equal(120) S.tg_height.equal(.wrap) S.tg_vspace = 10 let A = UIView() A.tg_left.equal(5) A.tg_right.equal(5) A.tg_width.equal(100) A.tg_height.equal(40) S.addSubview(A) let B = UIView() B.tg_left.equal(20) B.tg_width.equal(40) B.tg_height.equal(40) S.addSubview(B) let C = UIView() C.tg_right.equal(40) C.tg_width.equal(50) C.tg_height.equal(40) S.addSubview(C) let D = UIView() D.tg_left.equal(10) D.tg_right.equal(10) D.tg_width.equal(100) D.tg_height.equal(40) S.addSubview(D) self.view.addSubview(S) S.backgroundColor = .red A.backgroundColor = .green B.backgroundColor = .blue C.backgroundColor = .orange D.backgroundColor = .cyan }
等價于iOS的AutoLayout 和 Android的RelativeLayout布局。
相對布局是一種里面的子視圖通過相互之間的約束和依賴來進行布局和定位的布局視圖。相對布局里面的子視圖的布局位置和添加的順序無關(guān),而是通過設(shè)置子視圖的相對依賴關(guān)系來進行定位和布局的。
示例代碼:
override func loadView() { super.loadView() let S = TGRelativeLayout() S.tg_width.equal(170).and().tg_height.equal(280) let A = UIView() A.tg_left.equal(20).and().tg_top.equal(20) A.tg_width.equal(40).and().tg_height.equal(A.tg_width) S.addSubview(A) let B = UIView() B.tg_left.equal(A.tg_centerX).and().tg_top.equal(A.tg_bottom).offset(10) B.tg_width.equal(60).and().tg_height.equal(A.tg_height) S.addSubview(B) let C = UIView() C.tg_left.equal(B.tg_right).offset(10) C.tg_bottom.equal(B.tg_bottom) C.tg_width.equal(40) C.tg_height.equal(B.tg_height, multiple:0.5) S.addSubview(C) let D = UIView() D.tg_bottom.equal(C.tg_top).offset(10) D.tg_right.equal(15) D.tg_height.equal(A.tg_height) D.tg_width.equal(D.tg_height) S.addSubview(D) let E = UIView() E.tg_centerY.equal(0) E.tg_centerX.equal(0) E.tg_height.equal(40) E.tg_width.equal(S.tg_width).add(-20) S.addSubview(E) //...F,G self.view.addSubview(S) S.backgroundColor = .red A.backgroundColor = .green B.backgroundColor = .blue C.backgroundColor = .orange D.backgroundColor = .cyan E.backgroundColor = .magenta }
等價于Android的FrameLayout布局。
框架布局是一種里面的子視圖停靠在父視圖特定方位并且可以重疊的布局視圖。框架布局里面的子視圖的布局位置和添加的順序無關(guān),只跟父視圖建立布局約束依賴關(guān)系??蚣懿季謱⒋怪狈较蛏戏譃樯?、中、下三個方位,而水平方向上則分為左、中、右三個方位,任何一個子視圖都只能定位在垂直方向和水平方向上的一個方位上。
示例代碼:
override func loadView() { super.loadView() let S = TGFrameLayout() S.tg_width.equal(320) S.tg_height.equal(500) let A = UIView() A.tg_width.equal(40) A.tg_height.equal(40) S.addSubview(A) let B = UIView() B.tg_width.equal(40) B.tg_height.equal(40) B.tg_right.equal(0) S.addSubview(B) let C = UIView() C.tg_width.equal(40) C.tg_height.equal(40) C.tg_centerY.equal(0) S.addSubview(C) let D = UIView() D.tg_width.equal(40) D.tg_height.equal(40) D.tg_centerY.equal(0) D.tg_centerX.equal(0) S.addSubview(D) //..E,F(xiàn),G self.view.addSubview(S) S.backgroundColor = .red A.backgroundColor = .green B.backgroundColor = .blue C.backgroundColor = .orange D.backgroundColor = .cyan }
等價于Android的TableLayout布局和HTML的table元素。
表格布局是一種里面的子視圖可以像表格一樣多行多列排列的布局視圖。子視圖添加到表格布局視圖前必須先要建立并添加行視圖,然后再將子視圖添加到行視圖里面。如果行視圖在表格布局里面是從上到下排列的則表格布局為垂直表格布局,垂直表格布局里面的子視圖在行視圖里面是從左到右排列的;如果行視圖在表格布局里面是從左到右排列的則表格布局為水平表格布局,水平表格布局里面的子視圖在行視圖里面是從上到下排列的。
示例代碼:
override func loadView() { super.loadView() let S = TGTableLayout(.vert) S.tg_height.equal(.wrap) S.tg_width.equal(.wrap) S.tg_vspace = 10 S.tg_hspace = 10 S.tg_addRow(size:TGLayoutSize.wrap,colSize:TGLayoutSize.wrap) let A = UIView() A.tg_width.equal(50) A.tg_height.equal(40) S.addSubview(A) let B = UIView() B.tg_width.equal(100) B.tg_height.equal(40) S.addSubview(B) let C = UIView() C.tg_width.equal(30) C.tg_height.equal(40) S.addSubview(C) S.tg_addRow(size:TGLayoutSize.wrap,colSize:TGLayoutSize.wrap) let D = UIView() D.tg_width.equal(200) D.tg_height.equal(40) S.addSubview(D) //...E,F self.view.addSubview(S) S.backgroundColor = .red A.backgroundColor = .green B.backgroundColor = .blue C.backgroundColor = .orange D.backgroundColor = .cyan }
等價于CSS3的flex-box。
流式布局是一種里面的子視圖按照添加的順序依次排列,當遇到某種約束限制后會另起一行再重新排列的多行展示的布局視圖。這里的約束限制主要有數(shù)量約束限制和內(nèi)容尺寸約束限制兩種,而換行的方向又分為垂直和水平方向,因此流式布局一共有垂直數(shù)量約束流式布局、垂直內(nèi)容約束流式布局、水平數(shù)量約束流式布局、水平內(nèi)容約束流式布局。流式布局主要應(yīng)用于那些子視圖有規(guī)律排列的場景,在某種程度上可以作為UICollectionView的替代品。
示例代碼:
override func loadView() { super.loadView() let S = TGFlowLayout(.vert,arrangedCount:4) S.tg_height.equal(.wrap) S.tg_width.equal(300) S.tg_padding = UIEdgeInsetsMake(10,10,10,10) S.tg_gravity = TGGravity.horz.fill S.tg_space = 10 for _ in 0 ..< 10 { let A = UIView() A.tg_height.equal(A.tg_width) S.addSubview(A) A.backgroundColor = .green } self.view.addSubview(S) S.backgroundColor = .red }
等價于css中的float定位。
浮動布局是一種里面的子視圖按照約定的方向浮動停靠,當尺寸不足以被容納時會自動尋找最佳的位置進行浮動??康牟季忠晥D。浮動布局的理念源于HTML/CSS中的浮動定位技術(shù),因此浮動布局可以專門用來實現(xiàn)那些不規(guī)則布局或者圖文環(huán)繞的布局。根據(jù)浮動的方向不同,浮動布局可以分為左右浮動布局和上下浮動布局。
示例代碼:
override func loadView() { super.loadView() let S = TGFloatLayout(.vert) S.tg_height.equal(.wrap) S.tg_width.equal(300) S.tg_padding = UIEdgeInsetsMake(10,10,10,10) S.tg_space = 10 let A = UIView() A.tg_width.equal(80) A.tg_height.equal(70) S.addSubview(A) let B = UIView() B.tg_width.equal(150) B.tg_height.equal(40) S.addSubview(B) let C = UIView() C.tg_width.equal(70) C.tg_height.equal(40) S.addSubview(C) let D = UIView() D.tg_width.equal(100) D.tg_height.equal(140) S.addSubview(D) let E = UIView() E.tg_width.equal(150) E.tg_height.equal(40) E.tg_reverseFloat = true S.addSubview(E) let F = UIView() F.tg_width.equal(120) F.tg_height.equal(60) S.addSubview(F) self.view.addSubview(S) S.backgroundColor = .red A.backgroundColor = .green B.backgroundColor = .blue C.backgroundColor = .orange D.backgroundColor = .black E.backgroundColor = .magenta F.backgroundColor = .white }
等價于iOS的Size Classes
TangramKit布局體系為了實現(xiàn)對不同屏幕尺寸的設(shè)備進行適配,提供了對Size Classes的支持。您可以將Size Classes和上述的6種布局搭配使用,以便實現(xiàn)各種設(shè)備界面的完美適配。系統(tǒng)提供1個UIView的擴展方法:
public func tg_fetchSizeClass(with type:TGSizeClassType, from srcType:TGSizeClassType! = nil) ->TGViewSizeClass來實現(xiàn)對Size Classes的支持。比如下面的例子:
//all device let rootLayout = TGLinearLayout(.vert) rootLayout.tg_padding = UIEdgeInsetsMake(10, 10, 10, 10); rootLayout.tg_vspace = 10 rootLayout.tg_hspace = 10 //iPhone landscape orientation. let lsc = rootLayout.tg_fetchSizeClass(with: .comb(.any, .compact, nil), from:.default) as! TGLinearLayoutViewSizeClass lsc.tg_orientation = .horz
如果您還沒有安裝cocoapods則請先執(zhí)行如下命令:
$ gem install cocoapods為了用CocoaPods整合TangramKit到您的Xcode工程, 請建立如下的Podfile:
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' pod 'TangramKit', '~> 1.0.0'然后運行如下命令:
$ pod install
TangramKit is released under the MIT license. See LICENSE for details.