版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2018.01.19 |
前言
2017年iOS版本更新到了11.0的系統(tǒng),新機(jī)器比如iPhone X都是預(yù)裝11.0的系統(tǒng),而我們的UIKit框架中的UIView類都做了哪些更改?接下來(lái)我們就看一下iOS11.0中UIView類的改變暮芭,都是在分類
UIViewHierarchy
中有五處更改,下面我們就詳細(xì)的看一下欲低。
@property (nonatomic) NSDirectionalEdgeInsets directionalLayoutMargins API_AVAILABLE(ios(11.0),tvos(11.0));
先看一下谴麦,API給的注釋
/* directionalLayoutMargins.leading is used on the left when the user interface direction is LTR and on the right for RTL.
Vice versa for directionalLayoutMargins.trailing.
*/
翻譯過(guò)來(lái)就是
當(dāng)用戶界面方向?yàn)長(zhǎng)TR時(shí),
directionalLayoutMargins.leading
用于左側(cè)伸头,當(dāng)用戶界面方向?yàn)镽TL時(shí),directionalLayoutMargins
用于右側(cè)舷蟀;DirectionLayoutMargins.trailing
則反之恤磷。
這里NSDirectionalEdgeInsets
是什么呢?我們繼續(xù)看一下野宜。
/* Specifically for use in methods and functions supporting user interface layout direction
*/
typedef struct NSDirectionalEdgeInsets {
CGFloat top, leading, bottom, trailing; // specify amount to inset (positive) for each of the edges. values can be negative to 'outset'
} NSDirectionalEdgeInsets API_AVAILABLE(ios(11.0),tvos(11.0),watchos(4.0));
其實(shí)就是一個(gè)結(jié)構(gòu)體扫步,大家應(yīng)該對(duì)這個(gè)結(jié)構(gòu)很熟悉,雖然也是iOS11.0才出來(lái)匈子,但是順序還是上左下右這個(gè)順序河胎,正數(shù)表示縮進(jìn),負(fù)數(shù)表示外擴(kuò)虎敦。
說(shuō)了這么多游岳,這個(gè)屬性有啥用呢?
這個(gè)屬性一般是在中東的某些國(guó)家有用其徙,與LTR 和 RTL語(yǔ)言有關(guān)胚迫,例子:當(dāng)你設(shè)置了trailing = 30;當(dāng)在一個(gè)right to left 語(yǔ)言下trailing的值會(huì)被設(shè)置在view的左邊唾那,可以通過(guò)layout margins
的left屬性讀出該值访锻。如下圖所示:
還有其他一些更新。自從引入layout margins,當(dāng)將一個(gè)view添加到viewController時(shí)期犬, viewController會(huì)修復(fù)view的layoutMargins
為UIKit定義的一個(gè)值河哑,這些調(diào)整對(duì)外是封閉的。從iOS11開(kāi)始龟虎,這些不再是一個(gè)固定的值璃谨,它們實(shí)際是最小值,你可以改變你的view的 layoutMargins為任意一個(gè)更大的值遣总。而且睬罗,viewController新增了一個(gè)屬性: viewRespectsSystemMinimumLayoutMargins
,如果你設(shè)置該屬性為false
旭斥,你就可以改變你的layout margins
為任意你想設(shè)置的值容达,包括0,如下圖所示:
@property (nonatomic,readonly) UIEdgeInsets safeAreaInsets API_AVAILABLE(ios(11.0),tvos(11.0));
這是一個(gè)只讀屬性垂券,使用safeAreaLayoutGuide
和safeAreaInsets
用于獲取安全區(qū)域和邊距花盐。
下面我們繼續(xù)看一段代碼
@implementation ViewController
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *edgeStr = NSStringFromUIEdgeInsets(self.view.safeAreaInsets);
NSString *layoutFrmStr = NSStringFromCGRect(self.view.safeAreaLayoutGuide.layoutFrame);
NSLog(@"viewDidLoad safeAreaInsets = %@, layoutFrame = %@", edgeStr, layoutFrmStr);
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSString *edgeStr = NSStringFromUIEdgeInsets(self.view.safeAreaInsets);
NSString *layoutFrmStr = NSStringFromCGRect(self.view.safeAreaLayoutGuide.layoutFrame);
NSLog(@"viewDidAppear safeAreaInsets = %@, layoutFrame = %@", edgeStr, layoutFrmStr);
}
@end
下面看一下輸出結(jié)果
2018-01-19 12:21:50.615003+0800 JJLayer_demo1[43966:28819180] viewDidLoad safeAreaInsets = {0, 0, 0, 0}, layoutFrame = {{0, 0}, {414, 736}}
2018-01-19 12:21:50.644033+0800 JJLayer_demo1[43966:28819180] viewDidAppear safeAreaInsets = {20, 0, 0, 0}, layoutFrame = {{0, 20}, {414, 716}}
從輸出可以看出來(lái),viewDidAppear里面菇爪,頂部變成了20算芯,也就是向下縮進(jìn)20,也就是頂部狀態(tài)欄凳宙。同樣原理熙揍,如果你的是一個(gè)UINavigationController
那在顯示的時(shí)候view.safeAreaInsets
就會(huì)變成{64, 0, 0, 0}
。注意:在該VC下所有的UIView及其子類獲取到safeAreaInsets
的值是相同的氏涩。
- (void)safeAreaInsetsDidChange API_AVAILABLE(ios(11.0),tvos(11.0));
由上面可以看見(jiàn)届囚,邊距的改變是在viewDidAppear
方法里面更改的,但是具體是什么時(shí)候更改的呢是尖,其實(shí)就可以在UIView類里面重寫(xiě)safeAreaInsetsDidChange
意系,可以獲取邊距發(fā)生改變的時(shí)機(jī)。
@property(nonatomic,readonly,strong) UILayoutGuide *safeAreaLayoutGuide API_AVAILABLE(ios(11.0),tvos(11.0));
這個(gè)也是一個(gè)只讀屬性饺汹,首先看一下英文注釋
/* The top of the safeAreaLayoutGuide indicates the unobscured top edge of the view (e.g, not behind
the status bar or navigation bar, if present). Similarly for the other edges.
*/
safeAreaLayoutGuide
的頂部指示視圖的不被遮擋的頂部邊緣(例如蛔添,不在狀態(tài)欄或?qū)Ш綑诤竺妫绻嬖诘脑挘?同樣的其他邊緣兜辞。
下面我們看一下這個(gè)UILayoutGuide
類
#import <CoreGraphics/CoreGraphics.h>
#import <Foundation/Foundation.h>
@class NSLayoutXAxisAnchor, NSLayoutYAxisAnchor, NSLayoutDimension;
NS_ASSUME_NONNULL_BEGIN
@class UIView;
/* UILayoutGuides will not show up in the view hierarchy, but may be used as items in
an NSLayoutConstraint and represent a rectangle in the layout engine.
Create a UILayoutGuide with -init, and add to a view with -[UIView addLayoutGuide:]
before using it in a constraint.
*/
NS_CLASS_AVAILABLE_IOS(9_0)
@interface UILayoutGuide : NSObject <NSCoding>
/* The frame of the UILayoutGuide in its owningView's coordinate system.
Valid by the time the owningView receives -layoutSubviews.
*/
@property(nonatomic,readonly) CGRect layoutFrame;
/* The guide must be added to a view with -[UIView addLayoutGuide:] before being used in a constraint.
Do not use this property directly to change the owningView of a layout guide. Instead, use
-[UIView addLayoutGuide:] and -[UIView removeLayoutGuide:], which will use this property to
change the owningView.
*/
@property(nonatomic,weak,nullable) UIView *owningView;
/* For ease of debugging.
'UI' prefix is reserved for UIKit-created layout guides.
*/
@property(nonatomic,copy) NSString *identifier;
/* Constraint creation conveniences. See NSLayoutAnchor.h for details.
*/
@property(nonatomic,readonly,strong) NSLayoutXAxisAnchor *leadingAnchor;
@property(nonatomic,readonly,strong) NSLayoutXAxisAnchor *trailingAnchor;
@property(nonatomic,readonly,strong) NSLayoutXAxisAnchor *leftAnchor;
@property(nonatomic,readonly,strong) NSLayoutXAxisAnchor *rightAnchor;
@property(nonatomic,readonly,strong) NSLayoutYAxisAnchor *topAnchor;
@property(nonatomic,readonly,strong) NSLayoutYAxisAnchor *bottomAnchor;
@property(nonatomic,readonly,strong) NSLayoutDimension *widthAnchor;
@property(nonatomic,readonly,strong) NSLayoutDimension *heightAnchor;
@property(nonatomic,readonly,strong) NSLayoutXAxisAnchor *centerXAnchor;
@property(nonatomic,readonly,strong) NSLayoutYAxisAnchor *centerYAnchor;
@end
NS_ASSUME_NONNULL_END
下面我們看代碼
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *layoutFrmStr = NSStringFromCGRect(self.view.safeAreaLayoutGuide.layoutFrame);
NSLog(@"viewDidLoad layoutFrame = %@", layoutFrmStr);
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSString *layoutFrmStr = NSStringFromCGRect(self.view.safeAreaLayoutGuide.layoutFrame);
NSLog(@"viewDidLoad layoutFrame = %@", layoutFrmStr);
}
@end
用iphoneX運(yùn)行看結(jié)果迎瞧,下面我們看輸出結(jié)果
2018-01-19 14:34:34.519614+0800 JJLayer_demo1[44903:29054064] viewDidLoad layoutFrame = {{0, 0}, {375, 812}}
2018-01-19 14:34:34.658567+0800 JJLayer_demo1[44903:29054064] viewDidLoad layoutFrame = {{0, 44}, {375, 734}}
iphoneX的狀態(tài)欄是44.0,安全區(qū)域高度是812 - 44 - 34.0 = 734.0(頂部預(yù)留觸控區(qū)域)逸吵,這個(gè)代碼沒(méi)有導(dǎo)航和底部tabBar夹攒。
@property (nonatomic) BOOL insetsLayoutMarginsFromSafeArea API_AVAILABLE(ios(11.0),tvos(11.0)); // Default: YES
這是個(gè)BOOL屬性,默認(rèn)為YES胁塞。
如果你不想讓safeAreaInsets
影響你的視圖布局咏尝,則可以將insetsLayoutMarginsFromSafeArea
設(shè)置為NO压语,所有的視圖布局將會(huì)忽略safeAreaInsets這個(gè)屬性了。要注意的是编检,insetsLayoutMarginsFromSafeArea
僅用于使用代碼實(shí)現(xiàn)AutoLayout(如果你是使用Xib或者SB布局你的視圖胎食,那么對(duì)該屬性的設(shè)置是無(wú)效的,至少我沒(méi)有發(fā)現(xiàn)怎么可以讓布局產(chǎn)生變化)允懂,即使該屬性為NO厕怜,視圖的safeAreaInsets還是一樣有值,而且安全區(qū)域變更方法safeAreaInsetsDidChange
一樣被調(diào)用蕾总。
看下面這段代碼
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UITableView *tableView;
@end
@implementation ViewController
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
[super viewDidLoad];
self.view.backgroundColor = [UIColor blueColor];
//insetsLayoutMarginsFromSafeArea默認(rèn)為YES粥航,所有的視圖布局將會(huì)受到safeAreaInsets這個(gè)屬性影響
self.view.insetsLayoutMarginsFromSafeArea = YES;
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
self.tableView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.tableView];
NSArray<__kindof NSLayoutConstraint *> *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[tableView]-|" options:0 metrics:nil views:@{@"tableView" : self.tableView}];
[self.view addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[tableView]|" options:0 metrics:nil views:@{@"tableView" : self.tableView}];
[self.view addConstraints:constraints];
}
@end
這里面self.view.insetsLayoutMarginsFromSafeArea = YES;
取默認(rèn)值,所有的視圖布局將會(huì)受到safeAreaInsets
這個(gè)屬性影響生百,如下圖所示递雀。
下面self.view.insetsLayoutMarginsFromSafeArea = NO;
,這么設(shè)置后看一下效果蚀浆,這個(gè)時(shí)候布局就不會(huì)受到safeAreaInsets
這個(gè)屬性影響缀程。
可以看見(jiàn)不受上下邊距的影響了。
后記
這篇就結(jié)束了市俊,后面還會(huì)持續(xù)介紹別的方面的知識(shí)杨凑。