2012-11-01 50 views
60

我想添加填充到我的所有按鈕,所以我subclassed UIButton和其他更改,我想通過使用setFrame方法添加一個固定的填充。除了setFrame之外,一切都正常。我檢查了一下,發現如果我在該視圖中取消選中「使用AutoLayout」,那麼我可以使用setFrame,它可以工作。有沒有解決的辦法?我真的很想使用自動佈局,因爲它有助於使iPhone 5和更早版本的設備看起來很漂亮。但我也想在我的子類中使用setFrame,以使我的生活更輕鬆。我可以在同一個視圖上使用setFrame和自動佈局嗎?

總結一下,我的問題是:我可以使用autolayout,並以編程方式調整UIView的框架?

回答

193

是的,這可以做到。

如果您設置視圖的translatesAutoresizingMaskIntoConstraints = YES,則在運行時將自動將setFrame:的調用轉換爲基於視圖的當前autoresizingMask的佈局約束。這使您可以將基於框架的佈局與基於約束的佈局混合。

例如,您可以使用自動佈局來定義視圖的所有子視圖的佈局,但仍然調用setFrame:來設置視圖本身的大小和位置。從你的角度來看,你正在使用自動佈局和直接幀操作混合進行佈局。但系統實際上使用約束來處理所有事情。

但是,有一個關於使用translatesAutoresizingMaskIntoConstraints的重要警告。

當你這樣做,你仍然需要確保這些自動約束可以滿足其他約束

所以,舉例來說,假設有已經決定您的視圖的大小和位置的限制,然後你設置translatesAutoresizingMaskIntoConstraints = YES並呼籲setFrame:。對setFrame:的調用將對該視圖產生新的約束,這可能與已經存在的約束相沖突。 (事實上​​,這個錯誤經常發生,如果你看到一條日誌消息抱怨衝突約束,並且其中一個約束是NSAutoresizingMaskLayoutConstraint,那麼你看到的是與自動約束的衝突。一個簡單的錯誤,因爲translatesAutoresizingMaskIntoConstraints = YES是默認值,所以如果你在代碼中配置約束條件,如果你不想要這些自動約束條件,則需要記住將它關閉。)

與此相反,假設有已經存在確定您的視圖的大小和位置的約束條件,但在您致電setFrame:之前,請設置translatesAutoresizingMaskIntoConstraints = NO。在這種情況下,您的setFrame:調用不會產生新的約束,因此在單獨的約束之間不會產生衝突。但是,在這種情況下,在約束和您設置的框架值之間仍存在「衝突」。在下一次調用自動佈局時,它會在視圖中看到已經存在的約束條件,計算它們所需的幀值,並將幀設置爲所需的值,並手動設置您設置的值。

有關更多詳細信息,請參閱Apple的Cocoa Auto Layout Guide中的「採用自動佈局」部分。

+2

這個工程,但我看到很多日誌中的警告。任何人都可以建議使用這種方法的正確方法是什麼?或者我應該忽略這些警告?謝謝 – Husyn

+4

如果您看到不可滿足約束條件的警告,那麼這些警告可能是有意義的。如果您在視圖上使用'compiledAutoresizingMaskIntoConstraints = true'來查看它們,那麼您可能正在發生的事情*已經*有一些約束(可能設置在IB中)試圖控制該視圖的框架。框架上的那些舊約束與自動調整掩碼中自動生成的約束相互作用。在那種情況下,答案就是消除那些舊約束。如果您將它們添加到IB中,只是爲了讓IB在設計時閉嘴,您可以讓它們「佔位符」丟失它們。 – algal

+1

幹得好!好的答案! – Developer

16

原來對我來說最簡單的事情是刪除我想從其超級視圖中移動/調整大小的視圖,將其設置爲frame,然後將其添加回來。例如,採取定製UILabelUITableViewCell子類:

[cell.myLabel removeFromSuperview]; 
cell.myLabel.frame = someFrameIGenerated; 
[cell.contentView addSubview:cell.myLabel]; 
+0

哦,真好!爲我工作。謝謝! – Marky

+2

沒問題。雖然我覺得有義務告訴你,我最終擺脫了這一點,並實際學習如何在IB中使用約束。我不知道它們是否存在,現在製作複雜的佈局似乎更合理。 – Andrew

+0

是的,我嘗試過,但無法得到在表頭視圖上工作的約束。也許我應該再試一次。 – Marky

0

如果您的應用程序並不多裝置定向支持。

viewDidLoad中設置要調整

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view. 
    [aView setFrame:CGRectMake(15, 15, 100, 100)]; 
} 

然後在viewDidLayoutSubviews視圖的框架:

-(void)viewDidLayoutSubviews 
{ 
    [self.view setTranslatesAutoresizingMaskIntoConstraints:NO]; 
} 

我不知道,但我認爲,如果你使用此解決方案將一個方向切換爲另一個方向可能會導致問題

2

對我而言,一件簡單的事情就是爲我的約束添加IBOutlet到視圖控制器,然後更改插座上的constant屬性。

例如,要更改視圖的x原點,請將該視圖的主要約束的出口設置爲您的控制器。換句話說,創建一個插座@IBOutlet var labelXOrigin: NSLayoutConstraint!。然後,當你想調整x位置,只需做一些這樣設置子畫面的幀

self.labelXOrigin.constant = 20.0 // Or whatever origin you want to set. 
2

最好的辦法是在 自動佈局項目viewWillLayoutSubviews方法。

設置屬性translationAutoresizingMaskIntoConstraints = true這個 將在視圖確實出現或工作按鈕設置後出現,緊接着 視圖確實出現。

相關問題