日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

史上比较用心的纯代码实现 AutoLayout

發布時間:2024/6/21 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 史上比较用心的纯代码实现 AutoLayout 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

入職有兩三個月了吧,都是使用 Objective-C 純代碼(雖然有時候偷偷參雜一些 Swift 開源庫)來編寫公司APP,寫布局的時候幾乎都是要么在初始化的時候用 initWithFrame,要么就初始化完畢之后用 view.frame。雖然這種方法很直觀,一眼就可以看出這個 view 的位置以及大小,但是壞處也是有的,比如說在計算的時候麻煩等等。

?

概述

?

使用 Objective-C 純代碼編寫 AutoLayout,看 AutoLayout 的字面理解就是自動布局,聽起來好像蠻屌的樣子。說白了就是適配:適應、兼容各種不同的情況,包括不同版本的操作系統的適配(系統適配)和不同屏幕尺寸的適配(屏幕適配)。

?

在 Storyboard 中,AutoLayout 有以下 3 個常用面板:

?

1.Align(對齊)

?

?

2.Pin(相對)

?

?

3.Resolve Auto Layout Issues(約束處理)

?

?

在 Storyboard 中實現 AutoLayout 我就不在本文講解,因為講了就是違背了不忘初心,方得始終的標題了。

?

?

Talk is cheap, show me the code

?

先說一下用代碼實現 AutoLayout 步驟,別眨眼:

?

  • 利用 NSLayoutConstraint 類創建具體的約束對象;

  • 添加約束對象到相應的 view 上,代碼有這兩種:

  • ?

    - (void)addConstraint:(NSLayoutConstraint *)constraint;

    - (void)addConstraints:(NSArray *)constraints;

    ?

    或許有人問了,原來才兩個步驟就可以了,我剛剛褲子都脫了,你就給我看這個?!

    ?

    話不多說,馬上 show you the code !

    ?

    先看看我們使用 frame 的方式是如何確定一個 view 的位置的:

    ?

    - (void)viewDidLoad {

    ????[super viewDidLoad];

    ????self.title = @"使用 frame 的方式";

    ????UIView *purpleView = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 150, 150)];

    ????purpleView.backgroundColor = [UIColor purpleColor];

    ????[self.view addSubview:purpleView];

    }

    ?

    代碼很簡單,運行效果如下:

    ?

    ?

    再來看看 AutoLayout 的實現:

    ?

    - (void)viewDidLoad {

    ????[super viewDidLoad];

    ????self.title = @"使用 AutoLayout 的方式";

    ????UIView *purpleView = [[UIView alloc] init];

    ????purpleView.backgroundColor = [UIColor purpleColor];

    ????// 禁止將 AutoresizingMask 轉換為 Constraints

    ????purpleView.translatesAutoresizingMaskIntoConstraints = NO;

    ????[self.view addSubview:purpleView];

    ?

    ????// 添加 width 約束

    ????NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:purpleView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:150];

    ????[purpleView addConstraint:widthConstraint];

    ?

    ????// 添加 height 約束

    ????NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:purpleView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:150];

    ????[purpleView addConstraint:heightConstraint];

    ?

    ????// 添加 left 約束

    ????NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:purpleView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:100];

    ????[self.view addConstraint:leftConstraint];

    ?

    ????// 添加 top 約束

    ????NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:purpleView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:200];

    ????[self.view addConstraint:topConstraint];

    }

    ?

    看完這段代碼,我收到了驚嚇!我被這一大段代碼嚇到了,很多童鞋看到那么簡單的布局需要寫那么多代碼,可能就被嚇跑了。我只能說一句:先不要走,待我慢慢解釋~

    ?

  • 創建約束對象(NSLayoutConstraint)的常用方法

    一個 NSLayoutConstraint 對象就代表一個約束。

  • ?

    + (id)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;

    ?

    總共有 7 個參數 ?,那就以 leftConstraint 為例吧介紹這 7 個參數吧

    ?

    • ? view1: 要約束的控件(purpleView)

    • ? attr1: 約束的類型(常量),就是要做怎么樣的約束,大家可以進去看看都有什么常量(這里是NSLayoutAttributeLeft)

    • ? relation: 與參照控件之間的關系(常量),包括等于、大于等于、小于等于(NSLayoutRelationEqual 是指等于)

    • ? view2: 參照的控件(self.view)

    • ? attr2: 約束的類型(常量),就是要做怎么樣的約束,大家可以進去看看都有什么常量(這里是NSLayoutAttributeLeft)(NSLayoutAttributeLeft)

    • ? multiplier: 乘數,就是多少倍(1.0)

    • ? c: 常量,做好了上述的約束之后會加上這個常量(100)

    ?

    所以 leftConstraint 就是代表:要約束的控件purpleView 的左間距是等于參照控件 self.view 的左間距的 1.0 倍加上 100。

    ?

    所以我們得出 AutoLayout 的核心計算公式:

    ?

    obj1.property1 =(obj2.property2 * multiplier)+ constant value

    ?

    1.添加約束(addConstraint)的規則

    在創建約束了之后,需要將其添加到作用的控件上才能生效,注意在添加約束的時候目標控件需要遵循以下規則(這里控件就用 view 簡單表示吧):

    (1)對于兩個同層級 view 之間的約束關系,添加到它們的父 view 上

    ?

    ?

    對于兩個同層級 view 之間的約束關系,添加到它們的父 view 上

    (2)對于兩個不同層級 view 之間的約束關系,添加到他們最近的共同父 view 上

    ?

    ?

    對于兩個不同層級 view 之間的約束關系,添加到他們最近的共同父 view 上

    (3)對于有層次關系的兩個 view 之間的約束關系,添加到層次較高的父 view 上

    ?

    對于有層次關系的兩個 view 之間的約束關系,添加到層次較高的父 view 上

    ?

    (4)對于比如長寬之類的,只作用在該 view 自己身上的話,添加到該 view 自己上,不用圖了吧?

    ?

    可以看出,widthConstraint 和 Constraint 屬于第(4)種,leftConstraint 和 rightConstraint 屬于第(3)種。

    ?

    1.代碼實現 AutoLayout 的注意事項

    如果只是創建和添加了約束,是不能正常運行的,要做好以下的工作:

    ?

    (1)要先禁止 autoresizing 功能,防止 AutoresizingMask 轉換成 Constraints,避免造成沖突,需要設置 view 的下面屬性為 NO:

    ?

    view.translatesAutoresizingMaskIntoConstraints = NO;

    ?

    (2)添加約束之前,一定要保證相關控件都已經在各自的父控件上。用上面的例子就是 [self.view addSubview:purpleView]; 一定要放在添加 left 約束之前,否則程序會 crash,因為要確保 purpleView 要已經在 self.view 上了。建議先寫 [self.view addSubview:purpleView]; 之后,再專心寫約束。

    ?

    (3)不用再給 view 設置 frame

    ?

    看到了吧,那么簡單的一個界面,用 AutoLayout 實現的話竟然要那么多代碼,感覺上并沒有那么方便是吧?

    ?

    其實 AutoLayout 要看應用內容決定,上面只是一個使用的 demo。如果你的內容是信息眾多,同時需要展示的類別也很多,尺寸動態不定,比如說微博列表、QQ 動態列表等等,寫這些復雜界面使用 AutoLayout 能給予(jǐ yǔ?)很大的幫助。

    ?

    Apple 為了簡化 AutoLayout 復雜的代碼,開發了一種 VFL 語言(Visual format language),事實上沒看見簡化多少,而且還有比較大的局限性,這里就不介紹了,想了解的童鞋自己 Google 去。

    ?

    算了,給個官方鏈接吧:

    https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/VisualFormatLanguage.html

    ?

    如何優雅的代碼編寫 AutoLayout

    ?

    看到了 Apple 自帶的 AutoLayout 實現方式,感覺實在是太惡心了,那么如何優雅的代碼編寫 AutoLayout 呢?

    ?

    —— 使用第三方框架 Masonry。GitHub: https://github.com/SnapKit/Masonry 看它的介紹,感覺挺牛掰的:

    ?

    Harness the power of AutoLayout NSLayoutConstraints with a simplified, chainable and expressive syntax. Supports iOS and OSX Auto Layout.

    ?

    看完 README.md 文件發現的確蠻優雅的。

    ?

    先一覽 Masonry 是如何實現 AutoLayout 的:

    ?

    #import "ViewController.h"

    #import "Masonry.h" // 第三方或自己寫的用引號,系統自帶用雙引號。

    ?

    @interface ViewController ()

    @end

    ?

    @implementation ViewController

    ?

    - (void)viewDidLoad {

    ????[super viewDidLoad];

    ?

    ????UIView *purpleView = [[UIView alloc] init];

    ????purpleView.backgroundColor = [UIColor purpleColor];

    ????[self.view addSubview:purpleView];

    ?

    ????[purpleView mas_makeConstraints:^(MASConstraintMaker *make) {

    ????????// 在這個 block 里面,利用 make 對象創建約束

    ????????make.size.mas_equalTo(CGSizeMake(100, 100));

    ????????make.center.mas_equalTo(self.view);

    ????}];

    }

    ?

    運行效果:

    ?

    ?

    創建一個長和寬均為 100、與父 view 居中的 view

    注意:purpleView.translatesAutoresizingMaskIntoConstraints = NO;不需要在這里寫了,因為 Masonry 已經寫好了。

    ?

    Masonry 開車,趕緊上車

    ?

    一步一步跟著來,哈哈嘻嘻

    ?

    ????// 長寬均為 100,粘著父 view 右下角

    ????[purpleView mas_makeConstraints:^(MASConstraintMaker *make) {

    ????????make.width.equalTo(@100);

    ????????make.height.equalTo(@100);

    ????????make.right.equalTo(self.view);

    ????????make.bottom.equalTo(self.view);

    ????}];

    ?

    ?

    ?

    長寬均為 100,粘著父 view 右下角

    ?

    ????// 長寬均為 100,粘著父 view 右下角,間距為 16

    ????[purpleView mas_makeConstraints:^(MASConstraintMaker *make) {

    ????????make.width.equalTo(@100);

    ????????make.height.equalTo(@100);

    ????????// 這里也可以寫 make.right.equalTo(self.view.mas_right).offset(-16);

    ????????// 為了增強可讀性,可以在 .offset 前加上 .with 或者 .and: make.right.equalTo(self.view).with.offset(-16); 看自己習慣吧

    ????????make.right.equalTo(self.view).offset(-16);

    ????????// 這里也可以寫 make.right.equalTo(self.view.mas_bottom).offset(-16);

    ????????make.bottom.equalTo(self.view).offset(-16);

    ????}];

    ?

    ?

    長寬均為 100,粘著父 view 右下角,間距為 16

    看到上面代碼的包裝好的 @100,其實也可以直接傳值 100,不過要把 equalTo 改成 mas_equalTo,這樣它就自動幫你包裝好了。

    ?

    make.width.mas_equalTo(100);

    make.height.mas_equalTo(100);

    ?

    其實 mas_equalTo 就是一個宏,大家可以進去看看定義。

    ?

    • mas_equalTo 這個方法會對參數進行包裝

    • equalTo 這個方法不會對參數進行包裝

    • mas_equalTo 的功能強于 equalTo

    ?

    大家可能會覺得有點兒暈,有時候用 mas_equalTo,有時候用 equalTo,其實大家可以在 pch 文件里定義兩個宏,就可以完美解決這個糾結問題。注意要寫在 #import "Masonry.h" 前面。

    ?

    //define this constant if you want to use Masonry without the 'mas_' prefix,這樣子 `mas_width` 等就可以寫成 `width`

    #define MAS_SHORTHAND

    ?

    //define this constant if you want to enable auto-boxing for default syntax,這樣子 `mas_equalTo` 和 `equalTo` 就沒有區別了

    #define MAS_SHORTHAND_GLOBALS

    ?

    好,現在來一個稍微比剛才的復雜一點點的界面:

    ?

    - (void)viewDidLoad {

    ????[super viewDidLoad];

    ?

    ????UIView *purpleView = [[UIView alloc] init];

    ????purpleView.backgroundColor = [UIColor purpleColor];

    ????[self.view addSubview:purpleView];

    ?

    ????UIView *orangeView = [[UIView alloc] init];

    ????orangeView.backgroundColor = [UIColor orangeColor];

    ????[self.view addSubview:orangeView];

    ?

    ????CGFloat margin = 16;

    ????CGFloat height = 32;

    ????[purpleView mas_makeConstraints:^(MASConstraintMaker *make) {

    ????????make.left.equalTo(self.view).offset(margin);

    ????????make.bottom.equalTo(self.view).offset(-margin);

    ????????make.right.equalTo(orangeView.left).offset(-margin);

    ????????make.height.equalTo(height);

    ????????make.width.equalTo(orangeView);

    ????}];

    ?

    ????[orangeView mas_makeConstraints:^(MASConstraintMaker *make) {

    ????????make.bottom.equalTo(self.view).offset(-margin);

    ????????make.right.equalTo(self.view).offset(-margin);

    ????????make.height.equalTo(height);

    ????}];

    }

    ?

    ?

    兩個等高等寬的 view 平分屏幕寬度,帶有間隙

    其實實現這個界面有很多中寫法,大家可以試試,比如說這樣寫:

    ?

    - (void)viewDidLoad {??

    ?

    ????...

    ?

    ????[purpleView mas_makeConstraints:^(MASConstraintMaker *make) {

    ????????make.left.equalTo(self.view).offset(margin);

    ????????make.bottom.equalTo(self.view).offset(-margin);

    ????????make.right.equalTo(orangeView.left).offset(-margin);

    ????????make.height.equalTo(height);

    ????????make.height.equalTo(orangeView);

    ????????make.width.equalTo(orangeView);

    ????????make.top.equalTo(orangeView);

    ????}];

    ?

    ????[orangeView mas_makeConstraints:^(MASConstraintMaker *make) {

    ????????make.right.equalTo(self.view).offset(-margin);

    ????}];

    }

    ?

    總結

    ?

    其實 Masonry 的文檔已經很詳細了,建議大家去看文檔,我寫這個主要是為了做這個界面的 Tableview 上下拉阻尼效果而準備的

    ?

    轉載于:https://www.cnblogs.com/fengmin/p/5599525.html

    總結

    以上是生活随笔為你收集整理的史上比较用心的纯代码实现 AutoLayout的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 国产精品美女在线观看 | 日韩成人一区二区 | 日韩中文在线视频 | 五月激情久久 | 国产成a人亚洲精v品在线观看 | 欧美日韩不卡一区二区三区 | 亚洲av综合一区 | 欧美熟妇另类久久久久久不卡 | 久久精品亚洲一区二区 | 性生活三级视频 | 999视频在线播放 | 国产伦理av| 伊人国产在线 | 欧美精品在线一区二区三区 | 欧美啪啪网站 | 中文字幕一区av | 四虎成人精品在永久免费 | 国产亚洲一区二区不卡 | 老师用丝袜脚帮我脚交 | 亚洲视频色图 | 超碰伊人网 | 一级黄色毛毛片 | 精品国产伦一区二区三区免费 | 日韩av色图| 日韩一区免费观看 | 肥臀熟女一区二区三区 | 欧美亚洲第一页 | 日韩欧美二区三区 | 少妇精品高潮欲妇又嫩中文字幕 | 日日摸日日碰夜夜爽无码 | 日韩一卡二卡三卡四卡 | 黑白配在线观看免费观看 | 欧美性猛交性大交 | 一区二区在线免费视频 | 网友自拍一区 | 致单身男女免费观看完整版 | 一区二区观看 | 三级男人添奶爽爽爽视频 | 精品国产av色一区二区深夜久久 | 亚洲图片中文字幕 | 久久国产精品偷 | 人妻av无码一区二区三区 | 蜜臀av无码精品人妻色欲 | 久久九九国产精品 | 国产女上位| 自拍视频一区 | 深夜福利免费观看 | 国产毛片网 | 久久久久久久网站 | 人人草人人射 | 欧美激情成人在线 | 人妻丰满熟妇岳av无码区hd | 色伊人av | 国产精品av在线免费观看 | 不卡一二区 | 天天想你在线观看完整版电影高清 | 国产欧美日韩二区 | av av在线| 91精品国产91久久久 | 亚洲精品久久久久久 | 麻豆免费网站 | 蜜桃成人av | 老汉av在线 | 欧美在线色图 | 嫩草嫩草嫩草嫩草嫩草嫩草 | 痴汉电车在线观看 | 亚洲伦理在线观看 | 五月婷婷激情综合 | av999| 污黄视频网站 | 欧美黑人性生活 | 另类综合在线 | 日韩欧美v| 成人午夜淫片免费观看 | 亚洲成人精品一区 | 久久e热 | 亚洲性图第一页 | 91爱国产 | 狠狠艹av| 99热只有这里有精品 | 密乳av| 超碰97国产 | 无码国产69精品久久久久同性 | 亚洲视频网站在线观看 | 99这里只有| 精品无码m3u8在线观看 | jizz在线看| 男人天堂av电影 | 天天天天色 | 黄色网页在线 | 欧美精品成人一区二区在线观看 | 曰韩精品 | 日本熟妇毛茸茸丰满 | www.奇米| 超碰997| 91视色| 性生交大片免费看视频 | 国产精品一区二区毛片 | 国产精品第108页 |