2016-02-26 48 views
1

我想關閉一段時間的自動佈局,並使用其bounds,centertransformation來處理UIView的大小和位置。爲什麼不設置UIView的邊界限制其大小

我有一個非常簡單的'Single View Application'示例。我的應用程序擁有一個託管主視圖的視圖控制器。在這種觀點有兩個按鈕,和另一種觀點(與背景設置爲粉紅色),後者又包含一個圖像視圖(設置方面配合):

Xcode screenshot showing storyboard

我蒸餾我的問題成爲一個非常簡單的UIViewController:

@IBOutlet weak var imageHolderView: UIView! 
@IBOutlet weak var imageView: UIImageView! 

@IBAction func loadImageButtonClicked(sender: AnyObject) { 
    let url = NSURL(string: "https://c2.staticflickr.com/4/3909/15110089915_21a12eba6a_k.jpg") 
    let data = NSData(contentsOfURL: url!) 
    self.imageView.image = UIImage(data: data!) 
} 

@IBAction func clearConstraintsButtonClicked(sender: AnyObject) { 
    let bounds:CGRect = self.imageHolderView.bounds 
    let center:CGPoint = self.imageHolderView.center 
    NSLayoutConstraint.deactivateConstraints(self.imageHolderView.constraints) 
    self.imageHolderView.bounds = bounds 
    self.imageHolderView.center = center 
} 

NB我試圖在一個更復雜的項目中理解這個,這裏的例子只是爲了演示這個問題。

當我運行的圖像沒有來源,所以粉紅色的UIView(imageHolderView)如預期佔據了大部分屏幕的項目:

simulator screenshot before image loaded

當我點擊加載圖像按鈕控制器負載將圖像從網頁拖入UIImageView。由於限制都還到位自動佈局保證了畫面方面配合在以約束其超視圖imageHolderView的UIImageView的:

simulator screenshot after image loaded

如果我現在明確限制,我希望看到沒有什麼區別因爲由自動佈局設置的約束會立即在代碼中被相同的值替換。但是,這不是我所看到的:

simulator screenshot after constraints are cleared

如何搶邊界和一個UIView的中心,通過自動佈局設置,關閉自動佈局了UIView,然後重新建立邊界和中心從我自己的swift代碼?

看在調試器上的UIImageView imageView上的UIView imageHolderView是正確的界限,約束幾乎是(*)仍然存在(這我倒是希望將約束的UIImageView以適應裏面的UIView),但UIImageView的界限已經增長到適應全尺寸的圖像。爲什麼? (在更復雜的應用程序中,我繼續調整大小,旋轉視圖並轉換視圖,Apple's documentation指出「如果transform屬性包含非標識轉換,frame屬性的值是未定義的,並且在這種情況下,您可以使用中心屬性重新定位視圖,並使用bounds屬性調整大小。「示例代碼不使用轉換,但正如我所說的我的真實代碼所做的;我認爲這樣做會排除我設置框架。)

(*)我說的差不多,因爲UIImageView有四個約束,但在調試器中的計數是兩個。

+0

還有更多的信息在後續問題[here](http://stackoverflow.com/q/35687251/575530) – dumbledad

+0

您是否嘗試將Clip Subviews選項設置爲true? – ChikabuZ

+0

是的 - 它買了我一個邊框,但我仍然瘋狂調整大小 – dumbledad

回答

1

UIImageView根據其大小調整掩碼及其contentMode自動添加約束。嘗試將其內容模式設置爲AspectFitAspectFill並操縱其frame而不是其bounds

+0

它被設置爲AspectFit,它被設置在其超級視圖(即圖像持有者視圖)範圍內。我很擔心操作框架,因爲文檔中並沒有說如果您正在更改「self.imageHolderView.frame = bounds」的轉換 – dumbledad

+0

並刪除您的中心操作。 – tgyhlsb

+0

沒有工作:同樣的問題。你的意思是'self.imageHolderView.frame = bounds'或'self.imageView.frame = bounds'?我希望將UIImageView子視圖作爲自動佈局的一部分,並設置其超級視圖的大小和位置 – dumbledad

2

不設置邊界,而是設置邊框。試試這個:

@IBAction func clearConstraintsButtonClicked(sender: AnyObject) { 
    let frame = self.imageHolderView.frame 
    NSLayoutConstraint.deactivateConstraints(self.imageHolderView.constraints) 
    self.imageHolderView. frame = frame 
} 
+0

這是正確的嗎? [Apple的文檔](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/index.html#//apple_ref/doc/uid/TP40006816-CH3-SW5)聲明「如果transform屬性包含非標識轉換,frame屬性的值未定義,不應修改。在這種情況下,您可以使用中心屬性重新定位視圖,並使用bounds屬性調整大小。「示例代碼不使用轉換,但我提到我的真實代碼的確如此,我認爲這阻止了我設置框架 – dumbledad

+0

你試過嗎? – Casey

+0

我懷疑當你清除約束的時候,視圖的原點和大小都在變化,這會在嘗試改變視圖的邊界時導致一些奇怪的行爲,因爲根據蘋果的說法, 「更改邊界大小相對於其中心點增大或縮小視圖」 – PeejWeej

3

有幾件事你忘了。

首先,在:

NSLayoutConstraint.deactivateConstraints(self.imageHolderView.constraints) 

確保您不會停用,你需要約束。例如。如果您在imageHolderView上有寬度或高度限制,則可以使用此呼叫停用它。

在:

let bounds:CGRect = self.imageHolderView.bounds 
let center:CGPoint = self.imageHolderView.center 
NSLayoutConstraint.deactivateConstraints(self.imageHolderView.constraints) 
self.imageHolderView.bounds = bounds 
self.imageHolderView.center = center 

你得到的imageHolderViewboundscenter,然後你想將它們分配回imageHolderView。這是錯誤的,因爲您正在取消激活爲imageView設置位置的約束條件。您不必更改self.imageHolderView的位置,因爲它的約束條件保存在其超級視圖中。在另一方面,self.imageView可能已經停用所有的約束,所以您應該設置自己的立場:

self.imageView.bounds = bounds 
self.imageView.center = center 

center設置,因爲imageHolderView.center是它的父座標系中指定的是錯誤的。你應該從bounds手動計算中心。

self.imageView.center = CGPointMake(bounds.size.width/2, bounds.size.height/2) 

然而,最大的問題可能是一個事實,即boundscenter(或frame)默認情況下,在從情節提要/廈門國際銀行與自動佈局啓用創建的任何觀點忽略。

您必須手動將imageView.translatesAutoresizingMaskIntoConstraints設置爲true。否則frame將被佈局管理器忽略。

+0

這是正確的嗎?[Apple的文檔](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/index。 html#// apple_ref/doc/uid/TP40006816-CH3-SW5)聲明「如果transform屬性包含非標識轉換,frame屬性的值是未定義的,不應該修改。在這種情況下,您可以使用中心屬性重新定位視圖,並使用bounds屬性調整大小。「示例代碼不使用轉換,但我提到我的真實代碼的確如此,我認爲這阻止了我設置框架。 – dumbledad

+0

@dumbledad你說得對,'frame'只在你不使用轉換的情況下才有效,我會從我的答案中刪除它。 – Sulthan

2

由於您正在清除視圖的包含,它將刪除其子視圖的垂直和水平擁抱約束。您可以通過自定義你的持有人,我們作爲,

class CustomHolderView: UIView { 
    @IBOutlet weak var imageView: UIImageView! 

    override func layoutSubviews() { 
     super.layoutSubviews() 
     self.imageView.frame = self.bounds 
    } 
} 

內支架意見layoutSubviews方法,你應該爲您的圖像視圖幀解決這個問題。

+0

我認爲你使用的是layoutSubview覆蓋。 – dumbledad

相關問題