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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

iOS AutoLayout

發布時間:2023/12/10 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS AutoLayout 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

iOS AutoLayout

  • Autolayout是一種全新的布局技術,專門用來布局UI界面的,用來取代Frame布局在遇見屏幕尺寸多重多樣的問題。Autolayout自iOS 6開始引入,但是由于Xcode 4的不給力,當時并沒有得到大規模推廣。在iOS 7(Xcode5)開始,Autolayout的開發效率得到很大的提升,蘋果官方也推薦開發者盡量使用Autolayout來布局UI界面,減少純代碼的方式。在iOS6之前是用Autoresize布局.
  • Autolayout的好處是能夠很方便的適配各種尺寸的屏幕,并且當很好的適配屏幕的橫向和豎向,不會造成使用在有些手機上顯示不全,或者橫豎屏后布局錯位的問題.
  • Autolayout父視圖去添加對子視圖的約束,Autoresize是子視圖添加都父視圖的相對位置和大小.

AutoLayout的使用

  • AutoLayout常見的使用方式有兩種:
    1.IB方式即StoryBoard,Xib;
    2.純代碼方式即VFL,NSLayoutConstraint,Masonry,SnapKit.

1.IB方式實現自動布局

  • 在xib或者stroyBoard中添加約束的核心思想是一定要確定視圖的frame,不管是設置(Leading,Top,Width,Height),還是設置距離上下左右的間距都是為了確定視圖的farme,根據需求做不同的設置.如果是設置上下左右的間距固定,則視圖的尺寸會不同尺寸的手機顯示的大小不同,如果設置的是Width,Height以及Leading(或者Trailing),Top(或者Bottom),則實體的長寬固定,而沒有添加約束的兩條邊的邊距根據手機的尺寸不同而不同.總至要至少要添加四條約束.

  • 但是有些控件添加兩條約束Leading(或者Trailing),Top(或者Bottom)也是可以的,如UILabel,UIimageView,UIButton,如果不設置寬高這些控件會根據內容自動調整大小.IB自動布局大家都比較熟悉,這里就不再詳述.

2.VFL/NSLayoutConstrais方式實現自動布局

  • VFL(Virsual Format Language)是一種虛擬的格式化語言,主要用來創建AutoLayout的約束字符串。
  • VFL官網介紹
  • VFL基本語法介紹:例如: "V:[view1]-0-[view2(==100@1000)]-<=0-|"
功能表達式
垂直方向V:
水平方向H:
Views[view1],[View2]
SuperView|
關系(不寫默認==)>=,==,<=
空間,間隙(不寫默認值8)-
優先級@value
  • 示例:添加上中下三個視圖,上中視圖等高,下視圖距中間視圖底部的間隙8,并且占滿屏幕剩余部分.
let topView = UIView()topView.backgroundColor = UIColor.redtopView.translatesAutoresizingMaskIntoConstraints = falselet middleView = UIView()middleView.backgroundColor = UIColor.greenmiddleView.translatesAutoresizingMaskIntoConstraints = falselet bottomView = UIView()bottomView.backgroundColor = UIColor.bluebottomView.translatesAutoresizingMaskIntoConstraints = falseview.addSubview(topView)view.addSubview(middleView)view.addSubview(bottomView)/*oc 中 NSDictionaryOfVariableBindings(v1,v2,v3)相當于[NSDictionary dictionaryWithObjectsAndKeys:v1,@“v1”,v2,@“v2”,v3,@“v3”,nil]*///水平約束,當為==時==可以省略let topViewHorizontalContriants = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[topView]-==0-|", options:[], metrics: nil, views: ["topView":topView])view.addConstraints(topViewHorizontalContriants)//垂直約束let topViewVContriants = NSLayoutConstraint.constraints(withVisualFormat: "V:|-64-[topView(==100@1000)]", options: [], metrics: nil, views: ["topView":topView])view.addConstraints(topViewVContriants)//middleView的頂部和topView的底部對齊let middleTopC = NSLayoutConstraint.init(item: middleView, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: topView, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1.0, constant: 0)//middleView的左邊和topView的左邊對齊對齊view.addConstraint(middleTopC)let middleleftC = NSLayoutConstraint.init(item: middleView, attribute: NSLayoutConstraint.Attribute.left, relatedBy: NSLayoutConstraint.Relation.equal, toItem: topView, attribute: NSLayoutConstraint.Attribute.left, multiplier: 1.0, constant: 0)view.addConstraint(middleleftC)//middleView的寬等于topView的寬度let middleWidthC = NSLayoutConstraint.init(item: middleView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: topView, attribute: NSLayoutConstraint.Attribute.width, multiplier: 1.0, constant: 0)view.addConstraint(middleWidthC)//middleView的高度等于topView的高度let middleHeigitC = NSLayoutConstraint.init(item: middleView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: topView, attribute: NSLayoutConstraint.Attribute.height, multiplier: 1.0, constant: 0)view.addConstraint(middleHeigitC)//bottomView的垂直方向上的約束,不寫間距默認是8let bottomVC = NSLayoutConstraint.constraints(withVisualFormat: "V:[middleView]-[bottomView]-0-|", options: [], metrics: nil, views: ["middleView":middleView,"bottomView":bottomView])view .addConstraints(bottomVC)//水平約束let bottomHC = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[bottomView]-0-|", options: [], metrics: nil, views: ["bottomView":bottomView])view.addConstraints(bottomHC)

  • 給下面藍色視圖添加一個UILabel,使其上左右邊距為10,高度自適應
let label = UILabel()label.translatesAutoresizingMaskIntoConstraints = falselabel.font = UIFont.systemFont(ofSize: 15)label.numberOfLines = 0;label.backgroundColor = UIColor.cyanbottomView.addSubview(label)//水平約束let labelHC = NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[label]-10-|", options: [], metrics: nil, views: ["label":label])bottomView.addConstraints(labelHC)//垂直約束,頂部對齊,高度自適應let labelVC = NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[label]", options: [], metrics: nil, views: ["label":label])bottomView.addConstraints(labelVC)label.text = "lalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世lalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世vlalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世lalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三lalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世lalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世vlalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世lalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三lalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世lalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世vlalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世lalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三lalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世lalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世vlalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世lalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三lalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世lalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世vlalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世lalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三lalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世lalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世vlalalalalaz汽車消費網lalalalalaz汽車消費網lalalalalaz三生三世"print(bottomView.constraints) // label.frame.size = CGSize(width: 10, height: 10)UIView.animate(withDuration: 3) { // self.label.setNeedsUpdateConstraints()self.label.layoutIfNeeded()}

  • 刪除約束,更新布局
extension ViewController {override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {let labelHC1 = NSLayoutConstraint.constraints(withVisualFormat: "H:|-60-[label]-60-|", options: [], metrics: nil, views: ["label":label])bottomView.removeConstraints(labelHC!)bottomView.addConstraints(labelHC1)UIView.animate(withDuration: 3) { // self.bottomView.setNeedsUpdateConstraints()self.bottomView.layoutIfNeeded() // self.bottomView.updateConstraints() // self.bottomView.updateConstraintsIfNeeded()}} }

小結

  • 上面可以看出:NSLayoutConstraint的constraints方法是通過VFL添加水平和垂直方向約束來進行自動布局,而NSLayoutConstraint的便利構造方法是通過添加上下左右間距或間距和大小來添加約束來自動布局,兩者單獨使用或結合使用都可以,各有優缺點,一般會結合使用.
/* withVisualFormat : VFL語句 options : 字典類型的值;這里的值一般在系統定義的一個enum里面選取,默認傳空的字典 metrics : 一般為nil ,參數類型為NSDictionary,從外部傳入 //衡量標準 views : 就是上面所加入到NSDictionary中的綁定的View,要求字典形式為 ["view":view,"label":label] */ open class func constraints(withVisualFormat format: String, options opts: NSLayoutConstraint.FormatOptions = [], metrics: [String : Any]?, views: [String : Any]) -> [NSLayoutConstraint] /* item : 指定需要添加約束的視圖 attr1 : 指定視圖一需要約束的屬性 relatedBy : 指定視圖一和視圖二添加約束的關系(lessThanOrEqual 小于等于,equal 等于,greaterThanOrEqual 大于等于) toItem : 指定視圖一依賴關系的視圖二;可為nil attr2 : 指定視圖一所依賴的視圖二的屬性,若view2=nil,該屬性設置 NSLayoutAttributeNotAnAttribute multiplier : 系數,情況一:設置A視圖的高度 = A視圖高度 * multiplier + constant;此時才會起作用;情況二:設置A視圖和其他視圖的關系或 toItem=nil,multiplier設置不等于0即可,若等于0會crash; constant :常量,間距的值 */public convenience init(item view1: Any, attribute attr1: NSLayoutConstraint.Attribute, relatedBy relation: NSLayoutConstraint.Relation, toItem view2: Any?, attribute attr2: NSLayoutConstraint.Attribute, multiplier: CGFloat, constant c: CGFloat)
  • oc 中 NSDictionaryOfVariableBindings(v1,v2,v3)宏相當于[NSDictionary dictionaryWithObjectsAndKeys:v1,@“v1”,v2,@“v2”,v3,@“v3”,nil]

  • 父控件是誰,這些約束就添加給誰.

  • UIView的open var translatesAutoresizingMaskIntoConstraints: Bool屬性,把 autoresizingMask 轉換為 Constraints,即:可以把 frame ,bouds,center 方式布局的視圖自動轉化為約束形式。(此時該視圖上約束已經足夠 不需要手動去添加別的約束).

  • 用代碼創建的所有view , translatesAutoresizingMaskIntoConstraints 默認是 true,用 IB 創建的所有 view ,translatesAutoresizingMaskIntoConstraints 默認是 false . 如果用代碼約束布局,則需要將該屬性設置為false.

  • translatesAutoresizingMaskIntoConstraints屬性autoresize布局:true,autolayout布局 :false`.

  • 在更新約束時,要先刪除一些約束removeConstraints,再添加對應的一些約束addConstraints,然后跟新約束才有有效.

  • 項目開發過程中,通常使用的是Masonry\SnapKit自動布局的三方庫,簡單高效。較之frame布局,自動布局更適合業務拓展。

基于約束的AutoLayer更新約束的方法

1、setNeedsUpdateConstraints
當一個自定義view的某個屬性發生改變,并且可能影響到constraint時,需要調用此方法去標記constraints需要在未來的某個點更新,系統然后調用updateConstraints.
2、needsUpdateConstraints
constraint-based layout system使用此返回值去決定是否需要調用updateConstraints作為正常布局過程的一部分。
3、updateConstraintsIfNeeded
立即觸發約束更新,自動更新布局。
4、updateConstraints
自定義view應該重寫此方法在其中建立constraints. 注意:要在實現在最后調用[super updateConstraints]
uto Layout Process 自動布局過程
與使用springs and struts(autoresizingMask)比較,Auto layout在view顯示之前,多引入了兩個步驟:updating constraints 和laying out views。每一個步驟都依賴于上一個。display依賴layout,而layout依賴updating constraints。 updating constraints->layout->display
第一步:updating constraints,被稱為測量階段,其從下向上(from subview to super view),為下一步layout準備信息。可以通過調用方法setNeedUpdateConstraints去觸發此步。constraints的改變也會自動的觸發此步。但是,當你自定義view的時候,如果一些改變可能會影響到布局的時候,通常需要自己去通知Auto layout,updateConstraintsIfNeeded。
自定義view的話,通常可以重寫updateConstraints方法,在其中可以添加view需要的局部的contraints。
第二步:layout,其從上向下(from super view to subview),此步主要應用上一步的信息去設置view的center和bounds。可以通過調用setNeedsLayout去觸發此步驟,此方法不會立即應用layout。如果想要系統立即的更新layout,可以調用layoutIfNeeded。另外,自定義view可以重寫方法layoutSubViews來在layout的工程中得到更多的定制化效果。
第三步:display,此步時把view渲染到屏幕上,它與你是否使用Auto layout無關,其操作是從上向下(from super view to subview),通過調用setNeedsDisplay觸發,
因為每一步都依賴前一步,因此一個display可能會觸發layout,當有任何layout沒有被處理的時候,同理,layout可能會觸發updating constraints,當constraint system更新改變的時候。
需要注意的是,這三步不是單向的,constraint-based layout是一個迭代的過程,layout過程中,可能去改變constraints,有一次觸發updating constraints,進行一輪layout過程。
注意:如果你每一次調用自定義layoutSubviews都會導致另一個布局傳遞,那么你將會陷入一個無限循環中。

相關參考

  • VFL的簡單使用教程

  • iOS-手動添加限制-constraintsWithVisualForm

  • translatesAutoresizingMaskIntoConstraints 詳解

  • 自動布局之-NSLayoutConstraint

  • Autoresize和Autolayout 布局的實現

  • iOS AutoLayout全解

  • setNeedsUpdateConstraints,needsUpdateConstraints等基于約束的AutoLayer的方法

  • ios – setNeedsLayout vs. setNeedsUpdateConstraints and layoutIfNeeded vs updateConstraintsIfNeeded

  • MY_updateConstraintsIfNeeded,setNeedsLayout, layoutIfNeeded 和 layoutSubviews 方法之間的關系解釋

  • iOS自動約束】四個重要的系統方法

  • UIStackView

  • Stack

  • 相關源碼(包括AutoLayout,Masonry,SnapKit):AutoLayoutStudy

總結

以上是生活随笔為你收集整理的iOS AutoLayout的全部內容,希望文章能夠幫你解決所遇到的問題。

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