##代碼添加自動(dòng)布局 NSLayoutConstrain vfl火星語 使用vfl可以生成多個(gè)NSLayoutConstrain對(duì)象,存放在數(shù)組 |:是父視圖的邊界 [視圖的對(duì)象名==(另一個(gè)視圖)]: 例:"H:|-space-[view1(==space)]-|" [NSLayoutConstrain constrainsWithVisualFormat:火星語 options:添加的順序從左到右(默認(rèn)的就可以) metrics:所有數(shù)值的字典 views:對(duì)象字典或NSDictionaryOfVariableBindings(對(duì)象)這個(gè)是自動(dòng)生成字典] * 該對(duì)象一定要將translatesAutoresizingMaskIntoConstraints = NO不讓系統(tǒng)為我們添加額外的約束 * 約束應(yīng)該加到父視圖上
湘東ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書未來市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18982081108(備注:SSL證書合作)期待與您的合作!
目錄:
注意:
- 不管以上那種情況,scrollView 本身的大小和位置一定要相對(duì)固定!
- 可以使用frame直接設(shè)置,也可以使用自動(dòng)布局設(shè)置。
根據(jù)排列組合,共有 2*2 = 4 中情況,下面分別分析:
這種情況沒什么好說的,直接設(shè)置即可。
這種情況相當(dāng)于是第四種情況的簡化版,故請(qǐng)先看[第四種方式]。
我們知道,只要設(shè)置 scrollView 的 contentSize,就限定了 scrollView 的可滾動(dòng)范圍。所以這種情況,并不能很好的根據(jù)子控件的變化而動(dòng)態(tài)顯示完整的內(nèi)容。
所以子控件bounds變化的情況,需要使用[第四種方式]設(shè)置。
首先來做個(gè)分析:
第1條,兩種設(shè)置方式,自己根據(jù)實(shí)際情況選擇一種即可;
第2條,將所有子視圖塞進(jìn)一個(gè)容器視圖中。即先給scrollView添加一個(gè) 唯一直接子視圖 。
通俗點(diǎn)說就是創(chuàng)建一個(gè) sizeView 設(shè)置其大?。ㄖ苯釉O(shè)置frame或者使用autolayout設(shè)置皆可),然后將其添加到scrollView的子視圖,其他七七八八的所有小子視圖都添加在這個(gè)直接子視圖 sizeView 中,這個(gè)直接子視圖就相當(dāng)于 contentView。
這樣只要設(shè)置這個(gè)直接子視圖 sizeView 的大小和約束就好了。
如果設(shè)置好了這個(gè)直接子視圖 sizeView 的約束,那么這個(gè)直接子視圖 sizeView 的范圍就是 scrollView 的滾動(dòng)范圍嘍!
第3條,其實(shí)設(shè)置子視圖布局就2個(gè)要點(diǎn):
如圖1、圖2
圖2為豎直、水平方向皆可滾動(dòng),注意觀察滾動(dòng)條位置。
圖2為豎直、水平方向皆可滾動(dòng),注意觀察滾動(dòng)條位置。
如此設(shè)置布局是不是很方便呢?
個(gè)人還是比較建議用純代碼,至于原因,也很簡單,層的可控性更強(qiáng),項(xiàng)目構(gòu)架也會(huì)更緊湊,對(duì)于維護(hù)和其他開發(fā)者接手會(huì)更容易。缺點(diǎn)是代碼量大,對(duì)于開發(fā)語言程度不夠者會(huì)很吃力。至于很多人說SB和xib在適配方面的優(yōu)勢(shì)。。。。我只想說,iOS有自己的一套自動(dòng)布局的東西,稍微有點(diǎn)技術(shù)的開發(fā)者也會(huì)自己封裝些類別方法進(jìn)行封裝,或者也有自動(dòng)布局的開源庫等等,當(dāng)然,這個(gè)是仁者見人智者見智了。
關(guān)于SB和xib開發(fā)或者純代碼開發(fā)從蘋果開放SB,xib以后就有很大爭議,但是既然做開發(fā),那就是程序猿,不論個(gè)人技術(shù)水平如何,個(gè)人覺得開發(fā)者不應(yīng)該過多依賴于類似界面開發(fā)工具,只有從代碼出發(fā),才能更好的掌握一門語言和一種開發(fā)模式,只有這樣,對(duì)于自身的成長和技術(shù)的累計(jì)才是最有利的。
關(guān)于Xib與Storyboard和Code布局之間的爭論從iOS5開始就沒有停過 T_T
我原來也是一名忠實(shí)的Storyboard布局擁護(hù)者,并且認(rèn)為所見即所得的界面對(duì)于開發(fā)者和設(shè)計(jì)師都非常友好,再配合上初學(xué)時(shí)XCode5支持了拖自動(dòng)布局的約束,然后再加上Canvas庫在屬性檢查器里設(shè)置K-V屬性跑動(dòng)畫,我甚至一度以為這恐怕就是iOS在視圖層的全部了。
但是隨著經(jīng)驗(yàn)增長,特別是拋開個(gè)人開發(fā)的玩具應(yīng)用開始實(shí)習(xí)后,一個(gè)項(xiàng)目大部分視圖以及一些自定義的復(fù)雜控件(包括一些容器控件)以及一些與視圖相關(guān)的邏輯遠(yuǎn)遠(yuǎn)比我之前做的規(guī)模不大的應(yīng)用復(fù)雜得多,而且存在如下問題:
Storyboard和Xib存在老生常談的合并沖突難以解決,這個(gè)問題從我初學(xué)iOS開始和同學(xué)一起做一些小應(yīng)用時(shí)就遇到過,在屬性檢查器里更改一個(gè)值或者誤操作挪動(dòng)一個(gè)控件的位置或者按照XCode的提示自動(dòng)更新約束這樣的動(dòng)作,在不同機(jī)器上有時(shí)Git diff都是不一樣的,合并時(shí)多是不可名狀的XML讓人頭疼,雖然多個(gè)Storyboard或者分工Xib可能是種解決方案,但是還是或多或少存在協(xié)作的問題。
復(fù)雜的標(biāo)簽導(dǎo)航或者抽屜導(dǎo)航控制器反而在Xib和Storyboard中不直觀,早期在學(xué)習(xí)一個(gè)叫RESlideMenu的開源抽屜導(dǎo)航控件時(shí)發(fā)現(xiàn)了這個(gè)問題,作者的Demo拖出了4個(gè)控制器和若干個(gè)導(dǎo)航控制器,但是有內(nèi)容的只有兩個(gè),其他的被作為根視圖控制器或者容器控制器是一張白板,而強(qiáng)調(diào)通過聯(lián)線聯(lián)系各個(gè)控制器的Storyboard中就會(huì)出現(xiàn)一些拖出來的視圖控制器沒有聯(lián)線,且目前還無法像文件那樣分組,一堆堆白板控制器拖出來反而不直觀。
Xib和Storyboard的布局一般只決定視圖的初始狀態(tài)(靜態(tài)),拖出來的控件或者視圖或者約束是固定的,復(fù)雜應(yīng)用中一個(gè)視圖的控制器的狀態(tài)變化很多(跳轉(zhuǎn)、處理通知、刷新數(shù)據(jù)、事件驅(qū)動(dòng)的動(dòng)畫等等)都有可能影響視圖控制器乃至一些控件和視圖的狀態(tài),往往這個(gè)時(shí)候我發(fā)現(xiàn)還是需要用代碼來更新約束,跑動(dòng)畫[關(guān)閉菊花,隱藏對(duì)話框等],這個(gè)時(shí)候初始狀態(tài)的布局邏輯和后續(xù)狀態(tài)變化的邏輯反而造成了分離,一是有不太協(xié)調(diào),二是一定程度破壞了一整塊視圖控制器的邏輯的整體性。
一些視圖或者視圖控制器需要被繼承復(fù)用,往往需要拖出不少形態(tài)相似的控件出來,派生的類需要在Storyboard里重新拖出相應(yīng)的對(duì)象然后更改類型,如果是簡單狀態(tài)少變化少的視圖還好重新拖,如果稍微比較復(fù)雜就直接復(fù)制現(xiàn)有的視圖然后在慢慢鼠標(biāo)小幅度改動(dòng),體驗(yàn)上還是蠻揪心的。
但是但是這并不代表在開發(fā)過程中絕不使用Xib,同時(shí)這也不代表代碼布局就是Frame滿天飛。我反而不是特別喜歡Frame滿天飛這樣的做法,特別是一些魔數(shù)相互依賴,也沒有文檔或者注釋的時(shí)候那個(gè)維護(hù)簡直酸爽的不行,于是怎么解決呢?炒雞簡單:
在一些已知狀態(tài)極少改變甚至已知就是純粹的靜態(tài)視圖使用Xib,如:靜態(tài)表視圖表單,自定義的對(duì)話框等。
界面布局盡可能使用自動(dòng)布局的框架,如:Masonry(Obj-C),Snappy(Swift)等等,無論是make,update,remake約束都是一個(gè)非常友好的Block,十分方便,用了都說好(星星眼) 例子:(來自Masonry介紹與使用實(shí)踐(快速上手Autolayout))
[sv1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(sv).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
/* 等價(jià)于
make.top.equalTo(sv).with.offset(10);
make.left.equalTo(sv).with.offset(10);
make.bottom.equalTo(sv).with.offset(-10);
make.right.equalTo(sv).with.offset(-10);
*/
/* 也等價(jià)于
make.top.left.bottom.and.right.equalTo(sv).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
*/
}];
目前這樣的解決方案?jìng)€(gè)人感覺還是相當(dāng)不錯(cuò)的,就是一些特性可能不支持iOS5及一下的老版本。
1、iOS開發(fā) 純代碼創(chuàng)建UICollectionView_百度經(jīng)驗(yàn):
2、純代碼創(chuàng)建UICollectionView步驟以及簡單使用 - 簡書:
原理:IOS6.0 之后,蘋果優(yōu)化了UI界面的布局方式,提出了自動(dòng)布局的概念,和之前的autoresizing相比功能更強(qiáng)大。子視圖基于父視圖的自動(dòng)布局顯示。都是父視圖去添加對(duì)子視圖的約束。
在這里主要說的是通過代碼對(duì)自動(dòng)布局視圖的實(shí)現(xiàn)。
代碼中一般用到的有兩個(gè)添加約束的方式:
1.- (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);
2.- (void)addConstraints:(NSArray *)constraints NS_AVAILABLE_IOS(6_0);
/span
在使用自動(dòng)布局之前要對(duì)子視圖的布局方式進(jìn)行調(diào)整,用到這個(gè)UIView的屬性。
- (BOOL)translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0); // Default YES
需要將其設(shè)置為NO;
下面用簡單例子說明一下:
UIView *v1 = [[UIView alloc] initWithFrame:CGRectZero];
v1.translatesAutoresizingMaskIntoConstraints = NO;
v1.backgroundColor = [UIColor redColor];
[self.view addSubview:v1];
UIView *v2 = [[UIView alloc] initWithFrame:CGRectZero];
v2.backgroundColor = [UIColor grayColor];
v2.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:v2];//添加兩個(gè)允許自動(dòng)布局的子視圖
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:v1
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:0]];//設(shè)置子視圖的寬度和父視圖的寬度相同
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:v1
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeHeight
multiplier:0.5
constant:0]];//設(shè)置子視圖的高度是父視圖高度的一半
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[v1][v2(==v1)]-0-|" options:0 metrics:nil views:views]];//通過addConstraints 添加對(duì)水平方向上v1的控制--距離父視圖左側(cè)距離為0(距離為0的話也可省略)同時(shí)將v2的水平方向的寬度和v1設(shè)置成相同
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[v1][v2(==v1)]|" options:0 metrics:nil views:views]];/通過addConstraints 添加對(duì)垂直方向上v1的控制--距離父視圖上側(cè)距離為0(距離為0的話也可省略)同時(shí)將v2的垂直方向的高度和v1設(shè)置成相同
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[v1]-0-[v2]-0-|" options:0 metrics:nil views:views]];//最后是垂直布局兩個(gè)子view
這樣就可以實(shí)現(xiàn)上下兩個(gè)view,各占一半。旋轉(zhuǎn)屏幕的情況下也會(huì)自動(dòng)處理布局。這樣看起來代碼多,但是可以適應(yīng)多種分辨率的屏幕。不排除以后蘋果出更大更多分辨率的手機(jī)。
關(guān)于constraintsWithVisualFormat:函數(shù)介紹:
constraintsWithVisualFormat:參數(shù)為NSString型,指定Contsraint的屬性,是垂直方向的限定還是水平方向的限定,參數(shù)定義一般如下:
V:|-(=XXX) :表示垂直方向上相對(duì)于SuperView大于、等于、小于某個(gè)距離
若是要定義水平方向,則將V:改成H:即可
在接著后面-[]中括號(hào)里面對(duì)當(dāng)前的View/控件 的高度/寬度進(jìn)行設(shè)定;
options:字典類型的值;這里的值一般在系統(tǒng)定義的一個(gè)enum里面選取
metrics:nil;一般為nil ,參數(shù)類型為NSDictionary,從外部傳入 //衡量標(biāo)準(zhǔn)
views:就是上面所加入到NSDictionary中的綁定的View
在這里要注意的是 AddConstraints 和 AddConstraint 之間的區(qū)別,一個(gè)添加的參數(shù)是NSArray,一個(gè)是NSLayoutConstraint
使用規(guī)則
|: 表示父視圖
-:表示距離
V: :表示垂直
H: :表示水平
= :表示視圖間距、寬度和高度必須大于或等于某個(gè)值
= :表示視圖間距、寬度和高度必須小宇或等于某個(gè)值
== :表示視圖間距、寬度或者高度必須等于某個(gè)值
@ :=、=、== 限制 最大為 1000
1.|-[view]-|: 視圖處在父視圖的左右邊緣內(nèi)
2.|-[view] : 視圖處在父視圖的左邊緣
3.|[view] : 視圖和父視圖左邊對(duì)齊
4.-[view]- : 設(shè)置視圖的寬度高度
5.|-30.0-[view]-30.0-|: 表示離父視圖 左右間距 30
6.[view(200.0)] : 表示視圖寬度為 200.0
7.|-[view(view1)]-[view1]-| :表示視圖寬度一樣,并且在父視圖左右邊緣內(nèi)
8. V:|-[view(50.0)] : 視圖高度為 50
9: V:|-(==padding)-[imageView]-=0-[button]-(==padding)-| : 表示離父視圖的距離
為Padding,這兩個(gè)視圖間距必須大于或等于0并且距離底部父視圖為 padding。
10: [wideView(=60@700)] :視圖的寬度為至少為60 不能超過 700
11: 如果沒有聲明方向默認(rèn)為 水平 V: