2016-09-19 58 views
2

我正在使用iMessage應用程序,並通過編程添加了一個視圖。然而,我似乎無法制定正確的限制,使其始終保持正確的尺寸。例如,如果我將擴展名留給另一個擴展名並返回,視圖會下移幾百px。我認爲這與.isActive有關。我的目標是使視圖自動調整大小以始終保持正確的大小或佔用全部可用的高度和寬度。以編程方式在swift中添加全尺寸視圖

func createBrowser() { 
    let controller = MSStickerBrowserViewController(stickerSize: .small) 
    addChildViewController(controller) 
    view.addSubview(controller.view) 

    controller.view.translatesAutoresizingMaskIntoConstraints = false 
    controller.stickerBrowserView.backgroundColor = UIColor.blue 
    controller.stickerBrowserView.dataSource = self 

    view.topAnchor.constraint(equalTo: controller.view.topAnchor).isActive = true 
    view.bottomAnchor.constraint(equalTo: controller.view.bottomAnchor).isActive = true 
    view.leftAnchor.constraint(equalTo: controller.view.leftAnchor).isActive = true 
    view.rightAnchor.constraint(equalTo: controller.view.rightAnchor).isActive = true 
    view.centerXAnchor.constraint(equalTo: controller.view.centerXAnchor).isActive = true 
    view.centerYAnchor.constraint(equalTo: controller.view.centerYAnchor).isActive = true 
} 

截圖:https://d17oy1vhnax1f7.cloudfront.net/items/1F2B0s3v0s1k3E2L0Z07/Screen%20Shot%202016-09-19%20at%2011.42.51%20AM.png

+0

這可能是一個愚蠢的問題/我可能無法正確讀取你的代碼,但是有你錯誤地解決了你的限制?您是否應該根據舊視圖的約束條件來設置新視圖的約束條件?它看起來好像你是基於新的子控制器的視圖爲父控制器的視圖設置約束。 – Sparky

+0

@Sparky你的意思是這樣嗎? controller.view.topAnchor.constraint(equalTo:view.topAnchor).isActive = true。我這樣做,行爲是一樣的。 –

+0

@Sparky?對不起,我對iOS開發比較陌生。律'的幫助?謝謝! –

回答

0

更好地解釋事情下面我已經把。這演示了修復子視圖佈局的兩種方法。在使用約束時,我更願意將約束作爲數組創建,並一次性激活它們,正如您將在createredSquareWithConstraints的代碼中看到的一樣。一個約束只是一個線性方程,將一個視圖的特徵與另一個視圖的特徵相關聯。例如,在「僞代碼」中,我的數組中的第一個約束可寫爲:

「將子視圖的前導邊距設置爲等於容器視圖的前導邊距的1倍加上常數0。

(這就是我爲什麼,因爲它看着我,彷彿你是基於它的子視圖的一個特點設置包含視圖的約束是越來越早混淆。)

雖然仍完全有效利用佈局約束條件,我認爲現在的首選方法是重寫viewWillTransitionToSize()委託方法,它只是簡單地要求您在給定包含視圖的大小的情況下指定視圖控制器子視圖的框架應該是什麼。因此,我也包含了一個實現,創建一個初始幀的黃色方塊,然後在調用viewWillTransitionToSize時進行修改。我個人覺得使用佈局約束要少得多。

如果你隨着按鈕放置並旋轉屏幕,你會發現任何一種方法都能達到同樣的效果。 [注:我已經將一個方格標記爲受限制,而另一個標記爲不受約束,但實際上它們當然都受到約束,只是以不同的方式。我會補充一點,這顯然不是你在實踐中將如何做的事情 - 你應該選擇一種方法並堅持下去,否則你的代碼將會遍佈全球!]。

希望有幫助!

import UIKit 

class ViewController: UIViewController { 

    var constrainedredSquare : UIView! 
    var unconstrainedRedSquare : UIView! 
    var methodOneButton : UIButton! 
    var methodTwoButton : UIButton! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 
     self.view.backgroundColor = UIColor.blue 

     func getButton(name: String) -> UIButton { 
      let button : UIButton = UIButton() 
      button.backgroundColor = UIColor.white 
      button.layer.cornerRadius = 3 
      button.clipsToBounds = true 
      button.setTitle(name, for: UIControlState.normal) 
      button.setTitleColor(UIColor.black, for: UIControlState.normal) 
      return button 
     } 

     self.methodOneButton = getButton(name: "Red - Constraints") 
     self.methodTwoButton = getButton(name: "Yellow - viewWillTransitionToSize") 

     self.methodOneButton.addTarget(self, action: #selector(self.createRedSquareWithConstraints), for: .touchUpInside) 
     self.methodTwoButton.addTarget(self, action: #selector(self.createYellowSquareWithoutConstraints), for: .touchUpInside) 
     self.methodOneButton.frame = CGRect(origin: CGPoint(x: 200, y: 100), size: CGSize(width: 300, height: 300)) 
     self.methodTwoButton.frame = CGRect(origin: CGPoint(x: self.view.frame.width - 500, y: 100), size: CGSize(width: 300, height: 300)) 
     self.view.addSubview(self.methodOneButton) 
     self.view.addSubview(self.methodTwoButton) 

    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 
     if let _ = self.unconstrainedRedSquare { 
      self.unconstrainedRedSquare.frame = CGRect(origin: CGPoint.zero, size: size) 
     } 
     self.methodOneButton.frame = CGRect(origin: CGPoint(x: 200, y: 100), size: CGSize(width: 300, height: 300)) 
     self.methodTwoButton.frame = CGRect(origin: CGPoint(x: size.width - 500, y: 100), size: CGSize(width: 300, height: 300)) 
    } 


    func createYellowSquareWithoutConstraints() { 
     if let _ = self.unconstrainedRedSquare { 
      self.unconstrainedRedSquare.removeFromSuperview() 
     } 
     else 
     { 
      if let _ = constrainedredSquare { 
       self.constrainedredSquare.removeFromSuperview() 
      } 
      self.unconstrainedRedSquare = UIView() 
      self.unconstrainedRedSquare.backgroundColor = UIColor.yellow 
      self.unconstrainedRedSquare.frame = CGRect(origin: CGPoint.zero, size: self.view.frame.size) 
      self.view.addSubview(self.unconstrainedRedSquare) 

      self.view.bringSubview(toFront: self.methodOneButton) 
      self.view.bringSubview(toFront: self.methodTwoButton) 
     } 

    } 

    func createRedSquareWithConstraints() { 
     if let _ = self.constrainedredSquare { 
      self.constrainedredSquare.removeFromSuperview() 
     } 
     else 
     { 
      if let _ = self.unconstrainedRedSquare { 
       self.unconstrainedRedSquare.removeFromSuperview() 
      } 
      let redSquare : UIView = UIView() 
      redSquare.backgroundColor = UIColor.red 

      self.view.addSubview(redSquare) 

      self.view.bringSubview(toFront: self.methodOneButton) 
      self.view.bringSubview(toFront: self.methodTwoButton) 

      let rsConstraints : [NSLayoutConstraint] = [NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.leading, multiplier: 1.0, constant: 0), 
               NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.trailing, multiplier: 1.0, constant: 0), 
               NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.top, multiplier: 1.0, constant: 0), 
               NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.bottom, multiplier: 1.0, constant: 0), 
               NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.width, multiplier: 1.0, constant: 0), 
               NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.height, multiplier: 1.0, constant: 0)] 
      redSquare.translatesAutoresizingMaskIntoConstraints = false 
      NSLayoutConstraint.activate(rsConstraints) 
     } 
    } 
} 
0

您可以使用我的擴展名爲UIView。它允許添加額外填充任何端(僅如果你想):

public extension UIView { 
    typealias ConstraintsTupleStretched = (top:NSLayoutConstraint, bottom:NSLayoutConstraint, leading:NSLayoutConstraint, trailing:NSLayoutConstraint) 
    func addSubviewStretched(subview:UIView?, insets: UIEdgeInsets = UIEdgeInsets()) -> ConstraintsTupleStretched? { 
     guard let subview = subview else { 
      return nil 
     } 

     subview.translatesAutoresizingMaskIntoConstraints = false 
     addSubview(subview) 

     let constraintLeading = NSLayoutConstraint(item: subview, 
                attribute: .Left, 
                relatedBy: .Equal, 
                toItem: self, 
                attribute: .Left, 
                multiplier: 1, 
                constant: insets.left) 
     addConstraint(constraintLeading) 

     let constraintTrailing = NSLayoutConstraint(item: self, 
                attribute: .Right, 
                relatedBy: .Equal, 
                toItem: subview, 
                attribute: .Right, 
                multiplier: 1, 
                constant: insets.right) 
     addConstraint(constraintTrailing) 

     let constraintTop = NSLayoutConstraint(item: subview, 
               attribute: .Top, 
               relatedBy: .Equal, 
               toItem: self, 
               attribute: .Top, 
               multiplier: 1, 
               constant: insets.top) 
     addConstraint(constraintTop) 

     let constraintBottom = NSLayoutConstraint(item: self, 
                attribute: .Bottom, 
                relatedBy: .Equal, 
                toItem: subview, 
                attribute: .Bottom, 
                multiplier: 1, 
                constant: insets.bottom) 
     addConstraint(constraintBottom) 
     return (constraintTop, constraintBottom, constraintLeading, constraintTrailing) 
    } 

} 

用法:

view.addSubviewStretched(tableView) 

let BorderedBackgroundInset = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1) 
view?.addSubviewStretched(calendar.view, insets: BorderedBackgroundInset) 
+0

不得不調整約束中的代碼以符合最新版本的swift,但這個工作完美無缺,謝謝! –

+0

獲取此消息「調用'addSubvieStretched(subview:insets :)'的結果未被使用。那是什麼意思? –

+0

下面是使用上述方法生成的錯誤的更好屏幕截圖:https://www.dropbox.com/s/8gi67ulcjuldm4k/Screenshot%202016-10-05%2012.24.48.png?dl=0和https:/ /www.dropbox.com/s/t9ks7d02coycicb/Screenshot%202016-10-05%2012.26.34.png?dl=0 –

相關問題