Xcode升級后,發(fā)現(xiàn)跑舊項(xiàng)目調(diào)試遇到自定義View部分會卡死,找到原因是在layoutSubviews給self.frame賦值,導(dǎo)致循環(huán)調(diào)用。
發(fā)展壯大離不開廣大客戶長期以來的信賴與支持,我們將始終秉承“誠信為本、服務(wù)至上”的服務(wù)理念,堅(jiān)持“二合一”的優(yōu)良服務(wù)模式,真誠服務(wù)每家企業(yè),認(rèn)真做好每個(gè)細(xì)節(jié),不斷完善自我,成就企業(yè),實(shí)現(xiàn)共贏。行業(yè)涉及成都VR全景等,在成都網(wǎng)站建設(shè)、成都全網(wǎng)營銷推廣、WAP手機(jī)網(wǎng)站、VI設(shè)計(jì)、軟件開發(fā)等項(xiàng)目上具有豐富的設(shè)計(jì)經(jīng)驗(yàn)。
其實(shí)在我們的項(xiàng)目中,難免會用到自動(dòng)布局,簡單的使用frame就可以搞定,但是復(fù)雜的控件,如果外面用的自動(dòng)布局,自定義控件使用frame就很復(fù)雜。
一般我們都會在View內(nèi)部算好大小,通知外部去更新布局,這種方案是可以實(shí)現(xiàn),但是復(fù)雜了點(diǎn)。我們希望自定義的View像UILabel那樣,autolayout時(shí)方便快捷。
在了解如何讓自定義View支持自動(dòng)布局,我們需要了解intrinsicContentSize這個(gè)屬性,也就是控件的內(nèi)置大小。比如UILabel,UIButton等控件,他們都有自己的內(nèi)置大小。控件的內(nèi)置大小往往是由控件本身的內(nèi)容所決定的,比如一個(gè)UILabel的文字很長,那么該UILabel的內(nèi)置大小自然會很長。控件的內(nèi)置大小可以通過UIView的intrinsicContentSize屬性來獲取內(nèi)置大小,也可以通過invalidateIntrinsicContentSize方法來在下次UI規(guī)劃事件中重新計(jì)算intrinsicContentSize。如果直接創(chuàng)建一個(gè)原始的UIView對象,顯然它的內(nèi)置大小為0。
那么我們就可以使用這個(gè)屬性來讓我們的View支持自動(dòng)布局,只需要簡單的幾步
1、重寫intrinsicContentSize返回內(nèi)部大小
2、在大小變化的時(shí)候調(diào)用 invalidateIntrinsicContentSize 通知內(nèi)部大小變化。
于是就有了下面這個(gè)自定義的tagView
1、支持自動(dòng)布局,不需要計(jì)算高度,也不需要指定frame,自適應(yīng)高度
2、支持單行,多行顯示
3、支持分頁顯示
4、支持單選,多選,禁用選擇
5、支持添加和刪除Tag
6、支持字典數(shù)據(jù)類型
使用也比較簡單
具體Demo見
一、autoresizingMask
這是IOS舊的約束實(shí)現(xiàn)方式,而且只能用于約束父子關(guān)系的控件,約束子控件相對于父控件的位置關(guān)系。支持的約束種類有:
typedefNS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone? ? ? ? ? ? ? ? =0,
UIViewAutoresizingFlexibleLeftMargin? =10,
UIViewAutoresizingFlexibleWidth? ? ? ? =11,
UIViewAutoresizingFlexibleRightMargin? =12,
UIViewAutoresizingFlexibleTopMargin? ? =13,
UIViewAutoresizingFlexibleHeight? ? ? =14,
UIViewAutoresizingFlexibleBottomMargin =15
};
UIViewAutoresizingNone:不隨父View的變化而變化
UIViewAutoresizingFlexibleLeftMargin:相對父布局左邊距彈性變化,右邊距固定
UIViewAutoresizingFlexibleRightMargin:相對父布局右邊距彈性變化,左邊距固定
UIViewAutoresizingFlexibleTopMargin:相對父布局上邊距彈性變化,底部邊距固定
UIViewAutoresizingFlexibleBottomMargin:相對父布局底部邊距彈性變化,頂部邊距固定
UIViewAutoresizingFlexibleWidth:相對父布局的寬度等比縮放
UIViewAutoresizingFlexibleHeight:想對父布局的高度等比縮放
注意:所有的屬性都是位移運(yùn)算,因此可以疊加
如:設(shè)置約束,距離左邊彈性,距離上部彈性以及寬度彈性
self.view1.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin| UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
二、AutoLayout
AutoLayout是從autoresizingMask演化而來的,因此需要禁用autoresizingMask的方式。
translatesAutoresizingMaskIntoConstraints = NO;
AutoLayout的功能強(qiáng)大,可以設(shè)置任意View的約束關(guān)系。但添加約束有對應(yīng)的規(guī)則,規(guī)則如下:
1、針對View的獨(dú)立屬性,不需要依賴其他View,則將約束添加到自己上面
//設(shè)置View的寬度
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self.view1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeWidth multiplier:1.0 constant:200];
//設(shè)置View的高度
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:self.view1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeHeight multiplier:1.0 constant:200];
[self.view1addConstraint:widthConstraint];
[self.view1addConstraint:heightConstraint];
2、針對有依賴關(guān)系的情況,有以下規(guī)則:
(1)兩個(gè)同層級view之間的約束關(guān)系,添加到他們共同的父view上
(2)兩個(gè)不同層級上的view之間的約束關(guān)系,添加到他們最近的共同的父view上
(3)兩個(gè)有層次關(guān)系的view之間的約束關(guān)系,添加到層次較高的view上
請謹(jǐn)記此規(guī)則,如果添加錯(cuò)了則會崩潰:( 我將約束添加到了自己上面,沒有添加到父View上 )
2020-04-17 17:35:42.950274+0800 ConstraitLayoutTest[1216:429986] [LayoutConstraints] The view hierarchy is not prepared for the constraint:
When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView(UIConstraintBasedLayout) _viewHierarchyUnpreparedForConstraint:] to debug.
2020-04-17 17:35:42.951995+0800 ConstraitLayoutTest[1216:429986] [LayoutConstraints] View hierarchy unprepared for constraint.
Constraint:
Container hierarchy:?
UIView: 0x101407f90; frame = (0 0; 0 0); layer = CALayer: 0x28344f560
View not found in container hierarchy:
That view's superview: NO SUPERVIEW
2020-04-17 17:35:42.953478+0800 ConstraitLayoutTest[1216:429986] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view.? Does the constraint reference something from outside the subtree of the view?? That's illegal. constraint: view:'
*** First throw call stack:
(0x237f97ea0 0x237169a40 0x237e9e674 0x23897bd60 0x2651378c8 0x265137d94 0x265138494 0x100d9a3f0 0x100d99bac 0x26479620c 0x26479663c 0x2646c91f8 0x2646bd4cc 0x2647a7b24 0x2647aaa38 0x2647ab09c 0x2647aa990 0x2647aaccc 0x100d989e8 0x264d5e768 0x2647ec6d0 0x2647ec9f0 0x2647eb9f0 0x264d9818c 0x264d993f0 0x264d786ec 0x264e4457c 0x264e46f74 0x264e3fa64 0x237f281cc 0x237f2814c 0x237f27a30 0x237f228fc 0x237f221cc 0x23a199584 0x264d5d054 0x100d98be8 0x2379e2bb4)
libc++abi.dylib: terminating with uncaught exception of type NSException
Message from debugger: The LLDB RPC server has crashed. The crash log is located in ~/Library/Logs/DiagnosticReports and has a prefix 'lldb-rpc-server'. Please file a bug and attach the most recent crash log.
目錄:
注意:
- 不管以上那種情況,scrollView 本身的大小和位置一定要相對固定!
- 可以使用frame直接設(shè)置,也可以使用自動(dòng)布局設(shè)置。
根據(jù)排列組合,共有 2*2 = 4 中情況,下面分別分析:
這種情況沒什么好說的,直接設(shè)置即可。
這種情況相當(dā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è)置其大小(直接設(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è)置布局是不是很方便呢?
os系統(tǒng)和ios系統(tǒng)相比之下,ios系統(tǒng)較為復(fù)雜。
Mac OS 和iOS都是基于Darwin(蘋果的一個(gè)開源的系統(tǒng)內(nèi)核,基于Unix),但這只是操作系統(tǒng)部分,前者只能運(yùn)行在X86\X86-64構(gòu)架的硬件上(過去的版本還支持PowerPC構(gòu)架),而iOS只能運(yùn)行在ARM構(gòu)架的設(shè)備上,比如iPhone、iPod Touch、iPad和Apple TV 2/3代上。
因?yàn)闃?gòu)架不同,二者之間完全不能通用,所以iPad上自然無法運(yùn)行OSX,也不能運(yùn)行基于OSX開發(fā)的。
當(dāng)然很多/應(yīng)用都有對應(yīng)的iOS版本,比如常見的iWork辦公套件、iLife娛樂套件、Photoshop和CAD等,也有很多的編程,只是這些都是全新版本,并不是直接移植拿來用。
而且平板更多的是日常應(yīng)用和娛樂,傳統(tǒng)意義上的工作,比如處理文檔、 變成和平面/3D設(shè)計(jì)并不是iPad的本職工作。
iOS開發(fā)之自定義表情鍵盤(組件封裝與自動(dòng)布局)
iOS開發(fā)之自定義表情鍵盤(組件封裝與自動(dòng)布局)
原理:IOS6.0 之后,蘋果優(yōu)化了UI界面的布局方式,提出了自動(dòng)布局的概念,和之前的autoresizing相比功能更強(qiáng)大。子視圖基于父視圖的自動(dòng)布局顯示。都是父視圖去添加對子視圖的約束。
在這里主要說的是通過代碼對自動(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)布局之前要對子視圖的布局方式進(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 添加對水平方向上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 添加對垂直方向上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)屏幕的情況下也會自動(dòng)處理布局。這樣看起來代碼多,但是可以適應(yīng)多種分辨率的屏幕。不排除以后蘋果出更大更多分辨率的手機(jī)。
關(guān)于constraintsWithVisualFormat:函數(shù)介紹:
constraintsWithVisualFormat:參數(shù)為NSString型,指定Contsraint的屬性,是垂直方向的限定還是水平方向的限定,參數(shù)定義一般如下:
V:|-(=XXX) :表示垂直方向上相對于SuperView大于、等于、小于某個(gè)距離
若是要定義水平方向,則將V:改成H:即可
在接著后面-[]中括號里面對當(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] : 視圖和父視圖左邊對齊
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:
本文標(biāo)題:ios開發(fā)自動(dòng)布局,ios 布局 最佳實(shí)踐
本文URL:http://m.newbst.com/article34/dssepse.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、網(wǎng)站建設(shè)、用戶體驗(yàn)、關(guān)鍵詞優(yōu)化、服務(wù)器托管、外貿(mào)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)