YOGA簡介
Facebook引領(lǐng)著移動(dòng)開源風(fēng)向,這次它對(duì)布局出手了东囚,推出了Yoga開源項(xiàng)目,意在打造一個(gè)跨iOS战授、Android页藻、Windows平臺(tái)在內(nèi)的布局引擎桨嫁,兼容Flexbox布局方式,讓界面布局更加簡單份帐。
Yoga官網(wǎng):https://facebook.github.io/yoga/
官網(wǎng)上描述的特性包括:
完全兼容Flexbox布局璃吧,遵守W3C的規(guī)范
支持Java、C#废境、Objective-C肚逸、C四種語言
底層代碼使用C語言編寫,性能不是問題
支持流行框架如React Native
背景
目前彬坏,各個(gè)平臺(tái)都有自己的一套解決方案朦促。iOS平臺(tái)有AutoLayout,Android有容器布局系統(tǒng)栓始,而Web端有基于CSS的布局系統(tǒng)务冕。多種布局系統(tǒng)共存所帶來的弊端是很明顯的,平臺(tái)間的共享變得很困難幻赚,而每個(gè)平臺(tái)都需要專人來開發(fā)維護(hù)禀忆,增加了開發(fā)成本。
像微信小程序落恼、ReactNative這種箩退,都是采用js/html/css開發(fā),客戶端native展現(xiàn)的方式佳谦,那如何把前端的布局對(duì)應(yīng)到Android/iOS的不同平臺(tái)上戴涝?
微信小程序、ReactNative都是怎么來實(shí)現(xiàn)的钻蔑?
YOGA就是為了解決這樣的問題產(chǎn)生的啥刻。
在React Native里Facebook里引入了一種跨平臺(tái)的基于CSS的布局系統(tǒng),它實(shí)現(xiàn)了Flexbox規(guī)范咪笑】擅保基于這個(gè)布局系統(tǒng),不同團(tuán)隊(duì)終于可以走到一起窗怒,一起解決缺陷映跟,改進(jìn)性能,讓這個(gè)系統(tǒng)更加地貼合Flexbox規(guī)范扬虚。隨著這個(gè)系統(tǒng)的不斷完善努隙,F(xiàn)acebook決定對(duì)它進(jìn)行重啟發(fā)布,并取名Yoga孔轴。
Yoga是基于C實(shí)現(xiàn)的剃法。之所以選擇C,首先當(dāng)然是從性能方面考慮的〈蓿基于C實(shí)現(xiàn)的Yoga比之前Java實(shí)現(xiàn)在性能上提升了33%收厨。其次,使用C實(shí)現(xiàn)可以更容易地跟其它平臺(tái)集成优构。到目前為止诵叁,Yoga已經(jīng)有以下幾個(gè)平臺(tái)的綁定:Java(Android)、Objective-C(UIKit)钦椭、C#(.NET)拧额。而且已經(jīng)有很多項(xiàng)目在使用Yoga,比如React Native彪腔、Components for Android侥锦、Oculus,等等德挣。
不同于其它的一些布局框架恭垦,比如bootstrap的柵格系統(tǒng)或Masonry,它們要么不夠強(qiáng)大格嗅,要么不支持跨平臺(tái)番挺。Yoga遵循了Flexbox規(guī)范,同時(shí)又將布局元素抽象成Node屯掖,為各個(gè)不同平臺(tái)暴露出一組標(biāo)準(zhǔn)的接口玄柏,這樣不同的平臺(tái)只需實(shí)現(xiàn)這些接口就可以了。
當(dāng)然贴铜,F(xiàn)acebook不會(huì)就此止步粪摘。作為一款跨平臺(tái)的布局引擎,自然需要各個(gè)平臺(tái)的開發(fā)人員一起努力來促進(jìn)它的發(fā)展阀湿,所以Facebook把Yoga開源了赶熟。目前微軟已經(jīng)成為Yoga的貢獻(xiàn)者之一,他們不僅修復(fù)缺陷陷嘴,還為Yoga帶來新的特性。
除了完全遵循Flexbox規(guī)范间坐,F(xiàn)acebook還計(jì)劃在未來為Yoga加入更多特性灾挨,這些特性將超出Flexbox的范疇。
應(yīng)用展望
從目前為止竹宋,困擾客戶端的一大問題就是Android/iOS完全不同的布局系統(tǒng)劳澄,對(duì)于Android來說復(fù)雜的布局必須使用xml來描述,而xml不能動(dòng)態(tài)發(fā)布的特性蜈七,也完全限制了客戶端view的展現(xiàn)秒拔,試想一下,如果能把Android/iOS的布局統(tǒng)一飒硅,并且可以根據(jù)下發(fā)的布局配置實(shí)時(shí)生成動(dòng)態(tài)的布局砂缩,豈不是很爽作谚!
利用YOGA我們可以
- 只寫一次布局,就可以得到在不同端上的布局展示庵芭。
- 動(dòng)態(tài)更改view的布局
- 還有各種意義妹懒。。双吆。
總的來說眨唬,大前端的趨勢(shì)越發(fā)明顯
YOGA初探
當(dāng)?shù)弥猋OGA開源的消息時(shí),樓主第一時(shí)間去github上看了源代碼好乐,F(xiàn)acebook提供了iOS和Windows的sample工程匾竿,唯獨(dú)沒有提供Android的example,只有一個(gè)Java庫的代碼蔚万,于是樓主在想既然源碼都有岭妖,那寫一個(gè)Android的example,于是就動(dòng)起手來笛坦,最后終于把YOGA集成在了Android的工程上区转,并順利跑通。具體過程如下版扩。
生成so
YOGA是基于C實(shí)現(xiàn)的废离,因此我們的思路很明確,就是把YOGA的C代碼交叉編譯成可在
Android上運(yùn)行的so礁芦。這里我們需要用到BUCK,因?yàn)閅OGA是基于BUCK構(gòu)建的蜻韭,BUCK可以理解成是和Gradle一樣的構(gòu)建工具,這里有一個(gè)關(guān)于Gradle和Buck的構(gòu)建速度對(duì)圖:
要得到android-armv7的so柿扣,需要交叉編譯肖方,我們需要確保本地已經(jīng)安裝了Android NDK的環(huán)境,可以參考Android 官網(wǎng)未状。
通過分析YOGA工程的BUCK配置俯画,發(fā)現(xiàn)YOGA由3個(gè)模塊組成,分布在三個(gè)地方司草,分別是:
- libyogacore.so 在/yoga目錄下
- libyouga.so 在/java/jni目錄下
- liblib_fb_fbjni.so 在/lib/fb 目錄下
我們只要執(zhí)行BUCK的構(gòu)建代碼艰垂,就可以生成上面提到的三個(gè)so,構(gòu)建代碼如下:
$ buck build //java:jni#android-armv7,shared
這里有坑埋虹,編譯時(shí)我們需要兩個(gè)flavor猜憎,分別是android-armv7
和shared
- android-armv7 就是支持armeabi架構(gòu)的.so文件,這里需要有NDK環(huán)境的支持
- shared 就是生成動(dòng)態(tài)鏈接庫
因?yàn)樯危绻覀冎苯邮褂媚J(rèn)的構(gòu)建配置
$ buck build
會(huì)發(fā)現(xiàn)胰柑,生成的不是動(dòng)態(tài)鏈接庫so,而是靜態(tài)鏈接庫,而且也不是基于android-armv7生成的so柬讨,所以需要指定編譯的platform和明確要編譯的是動(dòng)態(tài)鏈接庫崩瓤,才能生成可用的so.
當(dāng)完成上面的步驟之后,我們還會(huì)發(fā)現(xiàn)一個(gè)問題姐浮,就是當(dāng)你的工程在加載so的時(shí)候谷遂,會(huì)報(bào)錯(cuò):
can't find libgnustl_shared.so
這時(shí)我們需要把ndk目錄下的 libgnustl_shared.so 也拷貝到工程目錄下,路徑如下:
android-ndk-r13b/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a
為什么會(huì)有這樣的
創(chuàng)建Android工程
在生成so之后卖鲤,后面的步驟大家應(yīng)該很清楚了肾扰,把生成的so放在Android目錄下的jniLibs下,并把YOGA中的java庫引入工程蛋逾,一個(gè)完整的可以運(yùn)行YOGA的Android工程就創(chuàng)建好了集晚。
sample
目前寫了一個(gè)很簡單的用YOGA實(shí)現(xiàn)的布局,首先我們用基于Flexbox的規(guī)范來布局view区匣,然后調(diào)用root.calculateLayout()
就可以得到在Android下的view的坐標(biāo)偷拔、長、寬等基本布局信息,代碼如下:
YogaNode root = new YogaNode();
root.setWidth(500);
root.setHeight(300);
root.setAlignItems(YogaAlign.CENTER);
root.setJustifyContent(YogaJustify.CENTER);
root.setPadding(YogaEdge.ALL, 20);
YogaNode text = new YogaNode();
text.setWidth(200);
text.setHeight(25);
YogaNode image = new YogaNode();
image.setWidth(50);
image.setHeight(50);
image.setPositionType(YogaPositionType.ABSOLUTE);
image.setPosition(YogaEdge.END, 20);
image.setPosition(YogaEdge.TOP, 20);
root.addChildAt(text, 0);
root.addChildAt(image, 1);
root.calculateLayout();
Log.d(TAG,"text,layout X:"+text.getLayoutX()+" layout Y:"+text.getLayoutY());
Log.d(TAG,"image,layout X:"+image.getLayoutX()+" layout Y:"+image.getLayoutY());
工程
目前我把基于YOGA的Android工程已傳到github亏钩,歡迎各位多多交流莲绰,多給star。Thanks!
地址:https://github.com/koudle/AndYogaSample
文章參考:
https://facebook.github.io/yoga/
https://buckbuild.com/
http://mp.weixin.qq.com/s/VT6uytG8di-KNfJDCZE5Og