web-dev-qa-db-ja.com

同じビューでsetFrameとautolayoutを使用できますか?

すべてのボタンにパディングを追加したいので、UIButtonをサブクラス化し、他の変更の中でも、setFrameメソッドを使用して固定パディングを追加しました。 setFrameを除くすべてが機能していました。いろいろ調べてみたところ、そのビューで「using AutoLayout」のチェックを外すと、setFrameを使用でき、動作することがわかりました。これを回避する方法はありますか? iphone 5とそれ以前のデバイスの両方でアプリの見栄えを良くするのに役立つので、私は本当に自動レイアウトを使用したいと思います。しかし、私の生活を少し楽にするために、サブクラスでsetFrameを使用したいと思います。

要約すると、私の質問は次のとおりです。オートレイアウトを使用して、UIViewのフレームをプログラムで調整することはできますか?

62
SirRupertIII

はい、これを行うことができます。

ビューのtranslatesAutoresizingMaskIntoConstraints = YESを設定すると、setFrame:への呼び出しは、実行時にビューの現在のautoresizingMaskに基づいてレイアウト制約に自動的に変換されます。これにより、フレームベースのレイアウトと制約ベースのレイアウトを混在させることができます。

たとえば、自動レイアウトを使用してビューのすべてのサブビューのレイアウトを定義できますが、setFrame:を呼び出してビュー自体のサイズと位置を設定できます。あなたの観点からは、自動レイアウトと直接のフレーム操作を組み合わせてレイアウトを行っています。しかし、システムは実際にはすべてを処理するために制約を使用しています。

ただし、translatesAutoresizingMaskIntoConstraintsの使用については、大きな注意事項が1つあります。

これを行うとき、これらの自動制約が残りの制約で満足できることを確認する必要があります

したがって、たとえば、ビューのサイズと位置を決定する制約が既にあり、alsotranslatesAutoresizingMaskIntoConstraints = YESを設定し、setFrame:を呼び出したとします。 setFrame:を呼び出すと、ビューに新しい制約が生成されます。これは、既存の制約と競合する可能性があります。

(実際、このエラーは頻繁に発生します。競合する制約について不平を言うログメッセージが表示され、それらの制約の1つがNSAutoresizingMaskLayoutConstraintである場合、表示されるのは自動制約との競合です。 translatesAutoresizingMaskIntoConstraints = YESがデフォルト値であるため、これは簡単な間違いです。したがって、コードで制約を設定している場合、これらの自動制約が必要ない場合は忘れずにオフにする必要があります。

対照的に、ビューのサイズと位置を決定する既存の制約が既に存在すると仮定しますが、translatesAutoresizingMaskIntoConstraints = NOを呼び出す前にsetFrame:を設定します。この場合、setFrame:呼び出しは新しい制約を生成しないので、別々の制約の間で競合はありません。ただし、この場合、制約と設定したフレーム値の間には「競合」がまだあります。次回自動レイアウトが呼び出されると、ビューに既に存在する制約が表示され、必要なフレーム値が計算され、フレームが必要な値に設定され、手動で設定した値が上書きされます。

詳細については、Appleの Cocoa Auto Layout Guide の「Auto Layoutの採用」セクションを参照してください。

203
algal

私にとって最も簡単であることが判明したのは、移動/サイズ変更したいビューをスーパービューから削除し、frameを設定してから追加し直すことでした。たとえば、UILabelサブクラスのカスタムUITableViewCellを使用します。

[cell.myLabel removeFromSuperview];
cell.myLabel.frame = someFrameIGenerated;
[cell.contentView addSubview:cell.myLabel];
16
Andrew

私のために働いたのは、View Controllerに制約のIBOutletを追加してから、アウトレットのconstantプロパティを変更するだけでした。

たとえば、ビューのx原点を変更するには、そのビューの主要な制約からコントローラーにアウトレットを設定します。つまり、アウトレット@IBOutlet var labelXOrigin: NSLayoutConstraint!を作成します。次に、xの位置を調整する場合は、次のようにします。

self.labelXOrigin.constant = 20.0 // Or whatever Origin you want to set.
3
Nick Yap

サブビューのフレームを設定する最良の方法は、自動レイアウトプロジェクトのviewWillLayoutSubviewsメソッドです。

setプロパティtranslateAutoresizingMaskIntoConstraints = trueこれは、ビューが表示された後、または設定するボタンのタブで、ビューが表示された直後に機能します。

2
Ravi Kumar

アプリが複数のデバイスの向きをサポートしていない場合。

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];
}

よくわかりませんが、このソリューションを使用すると、ある方向から別の方向に切り替えると問題が発生する可能性があります

0
EFE