原文地址:http://www.reibang.com/p/ac47c4826a19
NerdyUI
最好用的快速布局 UI 庫沉衣,適用于 iOS 8 及以上版本涮较。
github:https://github.com/nerdycat/NerdyUI
相關文章:
序言
眾所周知获洲,UI在一個App中所占的比重是很大的,如果能快速的布局UI程拭,就能大大的提高App的整體開發(fā)效率建蹄,NerdyUI正是基于這個理由創(chuàng)建的。
NerdyUI使用非常緊湊的鏈式語法动看,提供一些常用但系統(tǒng)控件又缺失的功能尊剔,更為簡便的約束創(chuàng)建方式和更好理解的布局系統(tǒng),勢必能大大減少您的代碼量和開發(fā)時間菱皆。
快速創(chuàng)建 NSString, UIFont, UIColor, UIImage 和常用的 structs
你可以用Str()來轉(zhuǎn)換大部分類型到NSString须误。同理,你可以用Log()來打印大部分的變量仇轻。
Str(100);//@"100"Str(3.14);//@"3.14"Str(@0.618);//@"0.618"Str(view.frame);//@"{{0, 0}, {100, 100}}"Str(view.center);//@"{50, 50}"Str(_cmd);//@"viewDidLoad"Str(NSString.class);//@"NSString"Str("C-String");//@"C-String"Str(@"1 + 1 = %d",1+1);//@"1 + 1 = 2Log(100);Log(3.14);Log(@0.618);Log(view.frame);...Log(@"1 + 1 = %d",1+1);//拼接字符串@"1".a(@"2").a(3).a(nil).a(4.0f).a(@5).a(@"%d",6);//@"123456"
你可以用AttStr()來創(chuàng)建NSAttributedString京痢。
AttStr(@"hello, 101").match(@"[0-9]+").underline;//給101加下劃線AttStr(@"A smile ", Img(@"smile"), @" !!");//帶圖片的NSAttributedString
你可以用Fnt()來創(chuàng)建UIFont。
Fnt(15);//[UIFont systemFontOfSize:15]Fnt(@15);//[UIFont boldSystemFontOfSize:15]Fnt(@"body");//UIFontTextStyleBodyFnt(@"Helvetica,15");//helvetica font with size 15
你可以用Color()來創(chuàng)建UIColor篷店。
Color(@"red");//[UIColor redColor]Color(@"0,0,255");//RGB colorColor(@"#0000FF");//Hex colorColor(@"random");//random color//以上這些還可以有一個可選的alpha參數(shù)Color(@"red,0.5");//red color with alpha 0.5Color(@"0,0,255,0.8");//blue color with alpha 0.8...Color(Img(@"pattern"));//pattern image color
你可以用Img()來創(chuàng)建UIImage祭椰。
Img(@"imageName");//[UIImage imageNamed:@"imageName"]Img(@"#imageName");//加上#號會返回一個可拉伸的圖片,拉伸位置在圖片中心Img(@"red");//返回一個 1x1 大小的紅色圖片疲陕,可用在某些需要純色圖片的地方
你可以用XY(),WH(),XYWH(),Range(),Insets()來創(chuàng)建CGPoint, CGSize, CGRect, NSRange, UIEdgeInsets方淤。XYWH()和Insets()支持多種創(chuàng)建方式。
CGPoint? ? ? ? p = XY(20,20);CGSize? ? ? ? s = WH(50,50);CGRect? ? ? ? f1 = XYWH(20,20,50,50);CGRect? ? ? ? f2 = XYWH(f1.origin, f1.size);CGRect? ? ? ? f3 = XYWH(f2.origin,50,50);CGRect? ? ? ? f4 = XYWH(20,20, f3.size);NSRange? ? ? ? r = Range(10,20);UIEdgeInsets i1 = Insets(10);//{10, 10, 10, 10}UIEdgeInsets i2 = Insets(10,20);//{10, 20, 10, 20}UIEdgeInsets i3 = Insets(10,20,30);//{10, 20, 30, 20}UIEdgeInsets i4 = Insets(10,20,30,40);//{10, 20, 30, 40}
使用這些宏可以簡化一些常見類型的創(chuàng)建過程蹄殃,更重要的是你可以用同樣的方式來設置視圖的屬性值携茂,稍后你就會明白這是什么意思。
快速訪問frame屬性和屏幕大小
someView.x =10;someView.y = someView.x;someView.xy = XY(10,10);someView.w =50;//widthsomeView.h = someView.w;//heightsomeView.wh = WH(50,50);someView.frame = XYWH(10,10,50,50);someView.cx =25;someView.cy = someView.cx;someView.center = XY(25,25);someView.maxX =60;someView.maxY = someView.maxX;someView.maxXY = XY(60,60);//Screen只是 [UIScreen mainScreen] 的宏定義someView.wh = WH(Screen.width, Screen.height);
我猜大部分人都有類似的擴展吧
快速的創(chuàng)建UI控件
NerdyUI 使用鏈式語法來快速的創(chuàng)建和設置 UI 控件诅岩。
UIView *view1 = View.xywh(20,30,50,50).bgColor(@"red").opacity(0.7).border(3, @"3d3d3d");UIView *view2 = View.xy(80,30).wh(view1.wh).bgColor(@"blue,0.7").borderRadius(25).shadow(0.8).onClick(^{? ? Log(@"view2");});
view
UIImageView *moose = ImageView.img(@"moose").x(20).y(100).shadow(0.6,2,-3,-1);UILabel *quiz = Label.str(@"%d+%d=?",1,1).fnt(@17).color(@"66,66,66").fitSize.x(moose.maxX +10).cy(moose.cy);
moose
//如果后續(xù)不需要再訪問 title 的屬性讳苦,定義為 id 可以減少一些代碼量id title = AttStr(@"TAP ME").fnt(15).underline.range(0,3).fnt(@18).color(@"random");UIButton *button1 = Button.str(title).insets(5,10).fitSize.border(1).xy(20,150).onClick(^(UIButton *btn) {//Exp() 可在任何位置執(zhí)行任意代碼quiz.text = Str(@"%d+%d=%d",1,1, Exp(btn.tag +=1));? ? [quiz sizeToFit];});UIButton *button2 = Button.str(@"HAT").highColor(@"brown").img(@"hat").gap(8);button2.xywh(button1.frame).x(button1.maxX +10).borderRadius(5).bgImg(@"blue,0.5").highBgImg(@"orange");//.highBgImg() 可以用來設置 UIButton 的 highlightedBackgroundColor,這是一個非常有用的功能
button
id pinField = TextField.x(button1.x).y(button1.maxY +15).wh(170,30).onChange(^(NSString *text) {//這里的 self 已經(jīng)自動做了 weakify 處理, 不用擔心會有引用循環(huán)[(id)[self.view viewWithTag:101]setText:text];}).numberKeyboard.maxLength(4).hint(@"pin code").fnt(15).roundStyle;id textView = TextView.xywh(20,240,170,100).border(1).insets(8).hint(@"placeholder").fnt([pinField font]).tg(101);
input
正如你所看到的按厘,大部分鏈式屬性還是比較簡單明了的医吊。有一些屬性非常的靈活,可以接受不同類型的參數(shù)逮京。順便說一下卿堂,View只是[UIView new]的宏定義,Label只是[UILabel new]的宏定義,其他幾個UI類也一樣(就是類名去掉 UI )草描。
你可以用.opacity()和.tg()來設置視圖的 alpha 和 tag 值.
你可以用.x(),.y(),.xy(),.w(),.h(),.wh(),.xywh(),.cx(),.cy(),.cxy(),.maxX(),.maxY(),.maxXY()等來設置視圖的大小和位置览绿。
你可以用.touchEnabled,.touchDisabled,.invisible來設置視圖是否可點和是否可見。
你可以用.flexibleLeft,.flexibleRight,.flexibleTop,.flexibleBottom,.flexibleLR,.flexibleTB,.flexibleLRTB,.flexibleWidth,.flexibleHeight,.flexibleWH等來設置autoresizingMask穗慕。
你可以用.centerAlignment,.rightAlignment等來設置對齊屬性饿敲。
你可以用.fnt()來設置字體,它能接受的參數(shù)跟Fnt()一樣逛绵。
你可以用.str()來設置 text 或者 attribtedText怀各, 它能接受的參數(shù)跟Str()一樣。
你可以用.img(),.highImg(),.bgImg()和.highBgImg()來設置 image, highlightedImage, backgroundImage 和 highlightedBackgroundImage术浪。 他們能接受的參數(shù)跟Img()一樣瓢对。
你可以用.tint(),.color(),.bgColor(),.highColor()來設置 tintColor, textColor, backgroundColor 和 highlightedTextColor, 它們能接受的參數(shù)跟Color()一樣。
你可以用.border(),.borderRadius()和.shadow()來設置邊框和陰影胰苏。
你可以用.fitWidth,.fitHeight和.fitSize來改變視圖的大小硕蛹,使它的大小剛好能包含視圖的內(nèi)容。
你可以用.onClick()來給任何視圖添加一個單擊事件硕并。
至于 UITextField? 和 UITextView, 你可以用.hint()來設置 placeholder,.maxLength()來限制輸入文本的長度,.onChange()來添加一個文本改變事件法焰。
如果是 UIButton, UITextField 和 UITextView, 你還可以使用.insets()來添加一些padding。
這里列出的只是一部分屬性倔毙,你可以到對應的擴展頭文件里看完整的屬性列表埃仪。
UILabel擴展
以前如果想給UILabel添加行間距,必須使用NSAttributedString∩略撸現(xiàn)在你只需要使用.lineGap()設置一下就行了贵试。
另一個很有的擴展功能是鏈接,你只需要使用AttStr()來創(chuàng)建一個NSAttributedString凯正, 并標記其中一部分為.linkForLabel,那么標記的那部分自動就會變成鏈接豌蟋。然后你只需要用.onLink()來給UILabel 添加一個鏈接點擊事件就行了廊散。
idstr= @"Lorem ipsum 20 dolor sit er elit lamet, consectetaur cillium #adipisicing pecu, sed do #eiusmod tempor incididunt ut labore et 3.14 dolore magna aliqua.";id attStr = AttStr(str).range(0,5).match(@"lamet").match(@"[0-9.]+").matchHashTag.linkForLabel;Label.str(attStr).multiline.lineGap(10).xywh(self.view.bounds).onLink(^(NSString *text) {? ? Log(text);}).addTo(self.view);
label
快速的創(chuàng)建約束
有的時候手動修改 frame 會顯得很麻煩。NerdyUI 提供一些鏈式屬性和一個跟 Masonry 類似的方式來創(chuàng)建約束梧疲。
你可以用.fixWidth(),.fixHeight(),.fixWH()來添加寬高約束允睹。
你可以用.embedIn()來把一個視圖嵌入到它的父視圖里, 這會添加上下左右的約束幌氮。
你可以用.horHugging(),.horResistance(),.verHugging(),.verResistance(),.lowHugging,.lowResistance,.highHugging和.highResistance來設置 contentHuggingPriority 和 contentCompressionResistancePriority缭受。當有多個視圖在 StackView 里時,可以用這些屬性來設置允許哪些視圖可以拉伸该互,哪些視圖不可以拉伸米者。
對于更復雜的約束, 你可以用.makeCons(),.remakeCons()和.updateCons()來設置約束, 就像Masonry一樣。
ImageView.img(@"macbook").embedIn(self.view).centerMode;id hello =Label.str(@"HELLO").fnt(@20).wh(80, 80).centerAlignment;idmac=Label.str(@"MAC").fnt(@20).wh(80, 80).centerAlignment;//使用 .makeCons() 之前必須把當前視圖加到父視圖里蔓搞,這里使用 .addTo() 來執(zhí)行此操作EffectView.darkBlur.fixWH(80, 80).addTo(self.view).makeCons(^{//在 .makeCons() 里你可以直接使用 make 變量胰丁,不需要顯示的定義它make.right.equal.superview.centerX.constants(0);? ? make.bottom.equal.superview.centerY.constants(0);}).addVibrancyChild(hello).tg(101);EffectView.extraLightBlur.fixWidth(80).fixHeight(80).addTo(self.view).makeCons(^{? ? make.left.bottom.equal.view(self.view).center.constants(0, 0);});EffectView.lightBlur.addTo(self.view).makeCons(^{? ? make.size.equal.constants(80, 80).And.center.equal.constants(40, 40);}).addVibrancyChild(mac);id subImg = Img(@"macbook").subImg(95, 110, 80, 80).blur(10);ImageView.img(subImg).addTo(self.view).makeCons(^{? ? make.centerX.top.equal.view([self.viewviewWithTag:101]).centerX.bottom.constants(0);});
constraints
快速布局
手動給每個視圖添加約束稍微想一下就知道會很麻煩。幸好大部分的 UI 可以用HorStack()和VerStack()來實現(xiàn)喂分。使用這兩個簡易版 StackView锦庸,加上上面介紹的那幾個屬性,很多時候你根本不需要手動顯示的創(chuàng)建任何約束蒲祈。
_indexLabel = Label.fnt(17).color(@"darkGray").fixWidth(44).centerAlignment;_iconView = ImageView.fixWH(64,64).borderRadius(10).border(Screen.onePixel, @"#CCCCCC");//用 .preferWidth() 來設置 preferredMaxLayoutWidth甘萧,有助于提高性能_titleLabel = Label.fnt(15).lines(2).preferWidth(Screen.width -205);_categoryLabel = Label.fnt(13).color(@"darkGray");_ratingLabel = Label.fnt(11).color(@"orange");_countLabel = Label.fnt(11).color(@"darkGray");_actionButton = Button.fnt(@15).color(@"#0065F7").border(1, @"#0065F7").borderRadius(3);_actionButton.highColor(@"white").highBgImg(@"#0065F7").insets(5,10);_iapLabel = Label.fnt(9).color(@"darkGray").lines(2).str(@"In-App\nPurchases").centerAlignment;//.gap() 會在每一個StackView Item 之間添加間隙id ratingStack = HorStack(_ratingLabel, _countLabel).gap(5);id midStack = VerStack(_titleLabel, _categoryLabel, ratingStack).gap(4);id actionStack = VerStack(_actionButton, _iapLabel).gap(4).centerAlignment;HorStack(? ? ? ? _indexLabel,? ? ? ? _iconView,? ? ? ? @10,//使用NSNumber可在兩個 Item 之間添加間隙midStack,? ? ? ? NERSpring,//NERSpring是一個特殊的變量,它相當于一個彈簧梆掸,保證actionStack始終停留在最右邊actionStack).embedIn(self.contentView,10,0,10,15);
appcell
這里我們模仿 AppStore 排行榜來創(chuàng)建一個類似的 Cell 扬卷。可以看出 HorStack (橫向) 和 VerStack (豎向)
的用法非常的簡單沥潭。你只需要找出最小的 Stack 邀泉,然后把它嵌到上一層的 Stack 里,重復這個過程直到最外層的 Stack 用
embedIn 來添加到它的父視圖里钝鸽。最后你還可以給這些視圖加上一些間隙(gap)汇恤。
使用 "Debug View Hierarchy" 可以看到這些視圖是怎么嵌套再一起的。
appcell2
一旦布局完拔恰,剩下的就是設置要顯示的內(nèi)容因谎,其他的都不需要再動了。
輕量級 Style
大部分鏈式屬性都可以設置為 style颜懊。
//全局StyleStyle(@"h1").color(@"#333333").fnt(17);Style(@"button").fixHeight(30).insets(0,10).borderRadius(5);//局部Styleid actionButtonStyle = Style().styles(@"button h1").bgImg(@"red").highBgImg(@"blue").highColor(@"white");
這里我們創(chuàng)建了兩個全局 Style 和一個局部 Style财岔。局部 Style 使用.styles()來繼承那兩個全局 Style。創(chuàng)建完之后河爹,全局 Style 可以使用 Style 名來全局引用匠璧,局部 Style 只能使用變量名來引用。所有的 UIView(及其子類) 和 NSAttributedString 都可以引用這些 Style咸这。
id foo= Label.styles(@"h1").str(@"hello world");id bar= Button.styles(actionButtonStyle).str(@"Send Email");
其他
你可以用PlainTV和GroupTV來創(chuàng)建靜態(tài)的 UITableView夷恍,比如說設置頁面。
PlainTV(Row.str(@"Row1"), Row.str(@"Row2"), Row.str(@"Row3")).embedIn(self.view);
你可以用Alert和ActionSheet來創(chuàng)建并顯示 UIAlert 和 UIActionSheet媳维。
Alert.title(@"Title").message(@"Message").action(@"OK",^{}),cancel(@"Cancel").show();ActionSheet.title(@"Title").message(@"Message").action(@"OK",^{}),cancel(@"Cancel").show();
對于NSArray, 我們提供了.forEach(),.map(),.filter()和.reduce()等這幾個鏈式屬性酿雪。
id result = @[@1, @2, @3, @4].map(^(NSInteger n) {returnn *2;}).filter(^(NSInteger n) {returnn <5;}).reduce(^(NSInteger ac, NSInteger n) {returnac + n;});
注意
在鏈式屬性里直接使用中文字符串常量會導致后續(xù)的自動補全提示失效,一個解決方案是把中文字符串單獨拿出來定義為一個變量侄刽,或者把.str(),.hint()等 放在最后面指黎。
當你使用.onClick(),.onLink(),.onChange()和.onFinish()時, 里面的self已經(jīng)做了 weakify 處理了州丹,所以你不需要擔心會有引用循環(huán)問題醋安。有時候你可能需要對它做個強引用來保證它不會被提前釋放。這幾個屬性除了可以傳一個 block 之外,還可以傳一個方法名來作為回調(diào)方法茬故。
NerdyUI 使用了非常多的宏定義和類別方法盖灸,而且為了方便使用沒添加任何前綴。雖然所有的名字都是經(jīng)過精心挑選的磺芭,不排除有跟您自己代碼或其他第三方庫沖突的可能赁炎,請注意。
用CocoaPods安裝
pod"NerdyUI"