Yoga是一個基于Flexbox布局思想的跨平台的布局庫。也就是說,Yoga布局庫是對Flexbox布局思想的一種實作。
Yoga最初是FaceBook在2014年推出的一個CSS布局的開源庫,2016年改版并更名為Yoga。
Yoga是一個跨平台庫,支援Java、C#、C、Swift等多個平台。
庫的開發者可以內建Yoga進布局系統,例如FB已經将Yoga內建進ReactNative、Litho、ComponentKit,阿裡的Weex也是使用Yoga來實作Flexbox布局的。
YogaKit是對Yoga在iOS開發平台上的封裝,我們可以直接使用YogaKit來進行頁面視圖的布局。
YogaKit的布局配置是交由YGLayout對象來完成,YGLayout包含的屬性有flex方向、對齊内容、對齊項目、t填充和邊距。YogaKit暴露YGLayout作為UIView上的一個Category,這個Categoryt添加configureLayoutWithBlock:方法到UIView,将YGLayout參數傳進block裡,并使用這些資訊來配置視圖的布局屬性。通過所需的Yoga屬性配置每個參與的視圖來建構你的布局。一旦完成,你在根視圖的YGLayout上調用applyLayoutPreservingOrigin:方法,這會計算并應用布局到根視圖和子視圖。
使用cocoapods進行安裝:
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, "8.0"
use_frameworks!
target 'AppDemo' do
pod 'YogaKit', '~> 1.5'
end
代碼中導入
#import <YogaKit/UIView+Yoga.h>
先布局一個試試手:
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.backgroundColor = [UIColor redColor];
[view configureLayoutWithBlock:^(YGLayout * layout) {
layout.isEnabled = YES;
layout.width = YGPointValue(320);
layout.height = YGPointValue(80);
layout.marginTop = YGPointValue(64);
layout.marginLeft = YGPointValue(0);
}];
[self.view addSubview:view];
[view.yoga applyLayoutPreservingOrigin:NO];

然後将top和left給删掉,看看是什麼效果:
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.backgroundColor = [UIColor redColor];
[view configureLayoutWithBlock:^(YGLayout * layout) {
layout.isEnabled = YES;
layout.width = YGPointValue(320);
layout.height = YGPointValue(80);
}];
[self.view addSubview:view];
[view.yoga applyLayoutPreservingOrigin:NO];
如果沒有設定位置,則其預設起始點是(0,0)。
再次将代碼簡化:
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.backgroundColor = [UIColor redColor];
[view configureLayoutWithBlock:^(YGLayout * layout) {
layout.isEnabled = YES;
layout.marginTop = YGPointValue(100);
layout.padding = YGPointValue(18);
}];
[self.view addSubview:view];
[view.yoga applyLayoutPreservingOrigin:NO];
padding中設定的值決定了視圖的尺寸(width和height是設定值的兩倍)。
下面示範如何往View上添加控件:
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.backgroundColor = [UIColor redColor];
[view configureLayoutWithBlock:^(YGLayout * layout) {
layout.isEnabled = YES;
layout.marginTop = YGPointValue(100);
layout.padding = YGPointValue(self.view.frame.size.width/2);
}];
[self.view addSubview:view];
UIView *bottomView = [[UIView alloc] initWithFrame:CGRectZero];
bottomView.backgroundColor = [UIColor yellowColor];
[bottomView configureLayoutWithBlock:^(YGLayout * layout) {
layout.isEnabled = YES;
layout.marginTop = YGPointValue(0);
layout.padding = YGPointValue(8);
}];
[view addSubview:bottomView];
[view.yoga applyLayoutPreservingOrigin:NO];
bottomView的marginTop設定的是0,按正常思維而言應該在view的最上方,但結果卻是在中間位置。
那麼,在view上再添加一個UIButton會是什麼結果呢?
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.backgroundColor = [UIColor redColor];
[view configureLayoutWithBlock:^(YGLayout * layout) {
layout.isEnabled = YES;
layout.marginTop = YGPointValue(100);
layout.padding = YGPointValue(self.view.frame.size.width/2);
}];
[self.view addSubview:view];
UIView *bottomView = [[UIView alloc] initWithFrame:CGRectZero];
bottomView.backgroundColor = [UIColor yellowColor];
[bottomView configureLayoutWithBlock:^(YGLayout * layout) {
layout.isEnabled = YES;
layout.marginTop = YGPointValue(0);
layout.padding = YGPointValue(8);
}];
[view addSubview:bottomView];
UIButton *but = [UIButton buttonWithType:UIButtonTypeCustom];
but.backgroundColor = [UIColor grayColor];
[but addTarget:self action:@selector(selectorBut) forControlEvents:UIControlEventTouchUpInside];
[but configureLayoutWithBlock:^(YGLayout * layout) {
layout.isEnabled = YES;
layout.marginTop = YGPointValue(0);
layout.padding = YGPointValue(50);
}];
[view addSubview:but];
[view.yoga applyLayoutPreservingOrigin:NO];
圖中顯示,Button的top和bottomView的bottom是在一起的。
以上