Xcode升級后,發(fā)現(xiàn)跑舊項目調(diào)試遇到自定義View部分會卡死,找到原因是在layoutSubviews給self.frame賦值,導致循環(huán)調(diào)用。
發(fā)展壯大離不開廣大客戶長期以來的信賴與支持,我們將始終秉承“誠信為本、服務至上”的服務理念,堅持“二合一”的優(yōu)良服務模式,真誠服務每家企業(yè),認真做好每個細節(jié),不斷完善自我,成就企業(yè),實現(xiàn)共贏。行業(yè)涉及成都VR全景等,在成都網(wǎng)站建設、成都全網(wǎng)營銷推廣、WAP手機網(wǎng)站、VI設計、軟件開發(fā)等項目上具有豐富的設計經(jīng)驗。
其實在我們的項目中,難免會用到自動布局,簡單的使用frame就可以搞定,但是復雜的控件,如果外面用的自動布局,自定義控件使用frame就很復雜。
一般我們都會在View內(nèi)部算好大小,通知外部去更新布局,這種方案是可以實現(xiàn),但是復雜了點。我們希望自定義的View像UILabel那樣,autolayout時方便快捷。
在了解如何讓自定義View支持自動布局,我們需要了解intrinsicContentSize這個屬性,也就是控件的內(nèi)置大小。比如UILabel,UIButton等控件,他們都有自己的內(nèi)置大小。控件的內(nèi)置大小往往是由控件本身的內(nèi)容所決定的,比如一個UILabel的文字很長,那么該UILabel的內(nèi)置大小自然會很長??丶膬?nèi)置大小可以通過UIView的intrinsicContentSize屬性來獲取內(nèi)置大小,也可以通過invalidateIntrinsicContentSize方法來在下次UI規(guī)劃事件中重新計算intrinsicContentSize。如果直接創(chuàng)建一個原始的UIView對象,顯然它的內(nèi)置大小為0。
那么我們就可以使用這個屬性來讓我們的View支持自動布局,只需要簡單的幾步
1、重寫intrinsicContentSize返回內(nèi)部大小
2、在大小變化的時候調(diào)用 invalidateIntrinsicContentSize 通知內(nèi)部大小變化。
于是就有了下面這個自定義的tagView
1、支持自動布局,不需要計算高度,也不需要指定frame,自適應高度
2、支持單行,多行顯示
3、支持分頁顯示
4、支持單選,多選,禁用選擇
5、支持添加和刪除Tag
6、支持字典數(shù)據(jù)類型
使用也比較簡單
具體Demo見
一、autoresizingMask
這是IOS舊的約束實現(xià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:想對父布局的高度等比縮放
注意:所有的屬性都是位移運算,因此可以疊加
如:設置約束,距離左邊彈性,距離上部彈性以及寬度彈性
self.view1.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin| UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
二、AutoLayout
AutoLayout是從autoresizingMask演化而來的,因此需要禁用autoresizingMask的方式。
translatesAutoresizingMaskIntoConstraints = NO;
AutoLayout的功能強大,可以設置任意View的約束關系。但添加約束有對應的規(guī)則,規(guī)則如下:
1、針對View的獨立屬性,不需要依賴其他View,則將約束添加到自己上面
//設置View的寬度
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self.view1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeWidth multiplier:1.0 constant:200];
//設置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ī)則:
(1)兩個同層級view之間的約束關系,添加到他們共同的父view上
(2)兩個不同層級上的view之間的約束關系,添加到他們最近的共同的父view上
(3)兩個有層次關系的view之間的約束關系,添加到層次較高的view上
請謹記此規(guī)則,如果添加錯了則會崩潰:( 我將約束添加到了自己上面,沒有添加到父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直接設置,也可以使用自動布局設置。
根據(jù)排列組合,共有 2*2 = 4 中情況,下面分別分析:
這種情況沒什么好說的,直接設置即可。
這種情況相當于是第四種情況的簡化版,故請先看[第四種方式]。
我們知道,只要設置 scrollView 的 contentSize,就限定了 scrollView 的可滾動范圍。所以這種情況,并不能很好的根據(jù)子控件的變化而動態(tài)顯示完整的內(nèi)容。
所以子控件bounds變化的情況,需要使用[第四種方式]設置。
首先來做個分析:
第1條,兩種設置方式,自己根據(jù)實際情況選擇一種即可;
第2條,將所有子視圖塞進一個容器視圖中。即先給scrollView添加一個 唯一直接子視圖 。
通俗點說就是創(chuàng)建一個 sizeView 設置其大?。ㄖ苯釉O置frame或者使用autolayout設置皆可),然后將其添加到scrollView的子視圖,其他七七八八的所有小子視圖都添加在這個直接子視圖 sizeView 中,這個直接子視圖就相當于 contentView。
這樣只要設置這個直接子視圖 sizeView 的大小和約束就好了。
如果設置好了這個直接子視圖 sizeView 的約束,那么這個直接子視圖 sizeView 的范圍就是 scrollView 的滾動范圍嘍!
第3條,其實設置子視圖布局就2個要點:
如圖1、圖2
圖2為豎直、水平方向皆可滾動,注意觀察滾動條位置。
圖2為豎直、水平方向皆可滾動,注意觀察滾動條位置。
如此設置布局是不是很方便呢?
os系統(tǒng)和ios系統(tǒng)相比之下,ios系統(tǒng)較為復雜。
Mac OS 和iOS都是基于Darwin(蘋果的一個開源的系統(tǒng)內(nèi)核,基于Unix),但這只是操作系統(tǒng)部分,前者只能運行在X86\X86-64構(gòu)架的硬件上(過去的版本還支持PowerPC構(gòu)架),而iOS只能運行在ARM構(gòu)架的設備上,比如iPhone、iPod Touch、iPad和Apple TV 2/3代上。
因為構(gòu)架不同,二者之間完全不能通用,所以iPad上自然無法運行OSX,也不能運行基于OSX開發(fā)的。
當然很多/應用都有對應的iOS版本,比如常見的iWork辦公套件、iLife娛樂套件、Photoshop和CAD等,也有很多的編程,只是這些都是全新版本,并不是直接移植拿來用。
而且平板更多的是日常應用和娛樂,傳統(tǒng)意義上的工作,比如處理文檔、 變成和平面/3D設計并不是iPad的本職工作。
iOS開發(fā)之自定義表情鍵盤(組件封裝與自動布局)
iOS開發(fā)之自定義表情鍵盤(組件封裝與自動布局)
原理:IOS6.0 之后,蘋果優(yōu)化了UI界面的布局方式,提出了自動布局的概念,和之前的autoresizing相比功能更強大。子視圖基于父視圖的自動布局顯示。都是父視圖去添加對子視圖的約束。
在這里主要說的是通過代碼對自動布局視圖的實現(xiàn)。
代碼中一般用到的有兩個添加約束的方式:
1.- (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);
2.- (void)addConstraints:(NSArray *)constraints NS_AVAILABLE_IOS(6_0);
/span
在使用自動布局之前要對子視圖的布局方式進行調(diào)整,用到這個UIView的屬性。
- (BOOL)translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0); // Default YES
需要將其設置為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];//添加兩個允許自動布局的子視圖
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:v1
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:0]];//設置子視圖的寬度和父視圖的寬度相同
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:v1
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeHeight
multiplier:0.5
constant:0]];//設置子視圖的高度是父視圖高度的一半
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[v1][v2(==v1)]-0-|" options:0 metrics:nil views:views]];//通過addConstraints 添加對水平方向上v1的控制--距離父視圖左側(cè)距離為0(距離為0的話也可省略)同時將v2的水平方向的寬度和v1設置成相同
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[v1][v2(==v1)]|" options:0 metrics:nil views:views]];/通過addConstraints 添加對垂直方向上v1的控制--距離父視圖上側(cè)距離為0(距離為0的話也可省略)同時將v2的垂直方向的高度和v1設置成相同
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[v1]-0-[v2]-0-|" options:0 metrics:nil views:views]];//最后是垂直布局兩個子view
這樣就可以實現(xiàn)上下兩個view,各占一半。旋轉(zhuǎn)屏幕的情況下也會自動處理布局。這樣看起來代碼多,但是可以適應多種分辨率的屏幕。不排除以后蘋果出更大更多分辨率的手機。
關于constraintsWithVisualFormat:函數(shù)介紹:
constraintsWithVisualFormat:參數(shù)為NSString型,指定Contsraint的屬性,是垂直方向的限定還是水平方向的限定,參數(shù)定義一般如下:
V:|-(=XXX) :表示垂直方向上相對于SuperView大于、等于、小于某個距離
若是要定義水平方向,則將V:改成H:即可
在接著后面-[]中括號里面對當前的View/控件 的高度/寬度進行設定;
options:字典類型的值;這里的值一般在系統(tǒng)定義的一個enum里面選取
metrics:nil;一般為nil ,參數(shù)類型為NSDictionary,從外部傳入 //衡量標準
views:就是上面所加入到NSDictionary中的綁定的View
在這里要注意的是 AddConstraints 和 AddConstraint 之間的區(qū)別,一個添加的參數(shù)是NSArray,一個是NSLayoutConstraint
使用規(guī)則
|: 表示父視圖
-:表示距離
V: :表示垂直
H: :表示水平
= :表示視圖間距、寬度和高度必須大于或等于某個值
= :表示視圖間距、寬度和高度必須小宇或等于某個值
== :表示視圖間距、寬度或者高度必須等于某個值
@ :=、=、== 限制 最大為 1000
1.|-[view]-|: 視圖處在父視圖的左右邊緣內(nèi)
2.|-[view] : 視圖處在父視圖的左邊緣
3.|[view] : 視圖和父視圖左邊對齊
4.-[view]- : 設置視圖的寬度高度
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,這兩個視圖間距必須大于或等于0并且距離底部父視圖為 padding。
10: [wideView(=60@700)] :視圖的寬度為至少為60 不能超過 700
11: 如果沒有聲明方向默認為 水平 V:
本文標題:ios開發(fā)自動布局,ios 布局 最佳實踐
本文URL:http://jinyejixie.com/article34/dssepse.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、網(wǎng)站建設、用戶體驗、關鍵詞優(yōu)化、服務器托管、外貿(mào)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)