2017-10-14 63 views
1

我在TabBarController的中間創建了一個UIButton,但由於iPhone X底部的安全區域,它無法正確顯示在iPhone X上。以編程方式在iPhone X上創建UIButton,但安全區域問題

override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 
    //Frame mic button 
    micButton.frame = CGRect.init(x: self.tabBar.center.x - 62, y: self.view.bounds.height - 94, width: 124, height: 124) 
    micButton.layer.cornerRadius = 62   
} 

enter image description here

什麼是繪製這個UIButton而不觸及安全區的正確方法。

+0

您發佈不相關的自動佈局什麼都嘲弄的代碼。 (1)你爲什麼要設置幀值?這可能是最重要的事情。 (2)安全區域通常 - 甚至可能是絕對 - 意味着限制。他們在哪?通過這個我的意思是要求...(3)iPhone X的「安全區域」 - 根據定義,iOS 11 - 意味着「safeAreaLayoutGuide」。那麼,爲什麼你展示的代碼不使用這個或任何其他*自動佈局約束*? – dfd

+0

@dfd這是真的,但我從來沒有做過佈局編程,如果你知道一個很好的編程約束指南或教程,將是偉大的。另外,我認爲會有不同的視圖屬性,我不知道從安全區域開始計算視圖框架。或者這一切都依賴於約束? –

+0

讓我發表一個程序化的答案。它可能不完整甚至毫無價值。但希望它既不會,也會有所幫助。 (如果它缺少一些東西,請發表評論,我會編輯。) – dfd

回答

1

安全區域,特別是safeAreaLayoutGuide涉及約束。

有各種方法來編寫自動佈局約束(視覺格式佈局或VFL,顯式 - 羅嗦 - NSLayoutConstraints),但我的首選是使用「佈局錨點」。

任何佈局的基本思路是位置大小。給一些寬度/高度和x/y軸值,你已經得到了它。非常像框架。

因此奠定了基本的 「錨」 的方式是:

micButton.frame = CGRect.init(x: self.tabBar.center.x - 62, y: self.view.bounds.height - 94, width: 124, height: 124) 

會是這樣:

let micButton = UIButton() 
micButton.translatesAutoresizingMaskIntoConstraints = false 

micButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -94).isActive = true 
micButton.widthAnchor.constraint(equalToConstant: 124).isActive = true 
micButton.heightAnchor.constraint(equalToConstant: 124).isActive = true 
micButton.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: -62).isActive = true 

一些注意事項:

  • 是的,你沒有規定一個幀。事實上,你只是在可能的情況下初始化事物。
  • 由於您未使用IB,因此需要將自動調整大小掩碼標誌設置爲false。即使是最有經驗的開發人員有時會忘記這件事。 (這樣做通常意味着你有「意外」的結果,從看不到東西到錯誤放置。)
  • 我已經設置了底部或Y軸,寬度和高度,最後是X軸。

雖然它比使用框架更多的代碼,但您獲得的是跨屏幕尺寸的一致性。

但您想要更多 - 您需要爲iPhone X安全區域編碼。你有兩個工具蘋果給你:layoutMarginsGuidesafeAreaLayoutGuide。前者是在iOS 9中引入的(以及更簡單的layoutGuide和佈局錨點),後者在iOS 11中引入。

[我的假設,可能是安全的,是所有iPhone X設備都可以運行iOS 11或更高版本。由於「安全區」是真的只需要爲這個設備,下面是你需要的。]

邊距與工作前/後(或水平)邊緣的所有設備。它們也適用於頂部/底部(或垂直)邊緣。但對於iPhone X,您需要關注不同的頂部/底部,因此是「安全區域」。上述

let layoutGuideTop = UILayoutGuide() 
let layoutGuideBottom = UILayoutGuide() 
view.addLayoutGuide(layoutGuideTop) 
view.addLayoutGuide(layoutGuideBottom) 
let margins = view.layoutMarginsGuide 
view.addLayoutGuide(margins) 
if #available(iOS 11, *) { 
    let guide = view.safeAreaLayoutGuide 
    layoutGuideTop.topAnchor.constraintEqualToSystemSpacingBelow(guide.topAnchor, multiplier: 1.0).isActive = true 
    layoutGuideBottom.bottomAnchor.constraintEqualToSystemSpacingBelow(guide.bottomAnchor, multiplier: 1.0).isActive = true 
} else { 
    layoutGuideTop.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor).isActive = true 
    layoutGuideBottom.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor).isActive = true 
} 

該代碼段會產生正確的頂部/底部邊緣變量基於IOS版本(layoutGuideToplayoutGuideBottom)。從那裏,你可以調整你的下錨:

micButton.bottomAnchor.constraint(equalTo: laytouGuideBottom, constant: -94).isActive = true 

哪些應該設置micButton是94點底部安全區域上方。

這裏有幾個環節,應該幫助你與佈局錨和導遊:

Layout Anchors

Layout Guides

Safe Area Layout Guides

編輯:

最後一個關於約束的音符。由於您不依賴幀值,所有這些代碼最好放置在viewDidLoad中,因爲佈局引擎將確定所有內容(並且可能會多次調用viewDidLayoutSubviews)。

0

感謝@dfd指導,這是我作爲一個解決方法。我剛剛檢查了使用該應用的手機是否具有與iPhoneX相同的屏幕尺寸,並且我只是在約束條件中進行了更改。

override func viewDidLoad() { 
    super.viewDidLoad() 

    //Frame mic button 
    micButton.frame = CGRect.init(x: self.tabBar.center.x - 62, y: self.view.bounds.height - 94, width: 124, height: 124) 
    micButton.layer.cornerRadius = 62 
    micButton.translatesAutoresizingMaskIntoConstraints = false 

    micButton.setBackgroundImage(#imageLiteral(resourceName: "micIcon"), for: .normal) 
    //Add to tabbar view 
    self.view.insertSubview(micButton, aboveSubview: self.tabBar) 


    if UIDevice().userInterfaceIdiom == .phone { 
     if UIScreen.main.nativeBounds.height == 2436 { 
      //iPhoneX Device 
      micButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true 
      micButton.widthAnchor.constraint(equalToConstant: 124).isActive = true 
      micButton.heightAnchor.constraint(equalToConstant: 124).isActive = true 
      micButton.centerXAnchor.constraint(equalTo: self.tabBar.centerXAnchor, constant: 0).isActive = true 
     } else { 
      //Not an iPhoneX Device 
      micButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 25).isActive = true 
      micButton.widthAnchor.constraint(equalToConstant: 124).isActive = true 
      micButton.heightAnchor.constraint(equalToConstant: 124).isActive = true 
      micButton.centerXAnchor.constraint(equalTo: self.tabBar.centerXAnchor, constant: 0).isActive = true 
     } 

    } 

    // Do any additional setup after loading the view. 
} 
1

試試這個:

添加在UITabViewController的類

micButton.translatesAutoresizingMaskIntoConstraints = false 
view.addSubview(micButton) 
    if #available(iOS 11, *) { 
     let guide = view.safeAreaLayoutGuide 
     micButton.centerXAnchor.constraint(equalTo: guide.centerXAnchor).isActive = true 
     micButton.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true 
     micButton.heightAnchor.constraint(equalToConstant: 64).isActive = true 
     micButton.widthAnchor.constraint(equalToConstant: 64).isActive = true 

    } else { 
     NSLayoutConstraint(item: micButton, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1.0, constant: 0).isActive = true 
     NSLayoutConstraint(item: micButton, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0).isActive = true 
     micButton.heightAnchor.constraint(equalToConstant: 64).isActive = true 
     micButton.widthAnchor.constraint(equalToConstant: 64).isActive = true 
      }