112

フレームプロパティについては話していません。それから、ビューのサイズはxibでしか取得できないためです。ビューが制約のためにサイズ変更されるとき(おそらく回転後、またはイベントへの応答)について話します。現在の幅と高さを取得する方法はありますか?

幅と高さの制約を探して制約を繰り返してみましたが、それはあまりきれいではなく、固有の制約がある場合は失敗します(2つを区別できないため)。また、これは実際に幅と高さの制約がある場合にのみ機能しますが、サイズ変更を他の制約に依存している場合は機能しません。

なぜこれが私にとってとても難しいのですか。ARG!

4

5 に答える 5

251

答えは[view layoutIfNeeded]です。

理由は次のとおりです。

view.bounds.size.widthand view.bounds.size.height(またはフレームで遊んでいない限り同等です)を調べることで、ビューの現在の幅と高さを取得できますview.transform

必要なのが既存の制約によって暗示される幅と高さである場合、答えは手動で制約を検査しないことです。これは、それらを解釈するために、自動レイアウトシステムの制約解決ロジック全体を再実装する必要があるためです。制約。代わりに、自動レイアウトにそのレイアウトを更新するように依頼するだけで、制約が解決され、view.boundsの値が正しいソリューションで更新されてから、view.boundsが検査されます。

自動レイアウトにレイアウトを更新するようにどのように依頼しますか?自動レイアウトで実行ループの次のターンにレイアウトを更新する場合は、を呼び出し[view setNeedsLayout]ます。

ただし、レイアウトをすぐに更新して、後で現在の関数内で、または実行ループが開始する前の別の時点で新しい境界値にすぐにアクセスできるようにする場合は[view setNeedsLayout]、とを呼び出す必要があり[view layoutIfNeeded]ます。

2番目の質問をしました:「高さ/幅の制約を直接参照していない場合、どうすれば変更できますか?」

IBで制約を作成する場合、最良の解決策は、ビューコントローラまたはビューでIBOutletを作成して、それを直接参照できるようにすることです。コードで制約を作成した場合は、作成時に内部のweakプロパティの参照を保持する必要があります。他の誰かが制約を作成した場合は、ビューのview.constraintsプロパティ、場合によってはビュー階層全体を調べ、重要なNSLayoutConstraintを見つけるロジックを実装して制約を見つける必要があります。その質問に対する単純な答えが保証されていない場合、どの特定の制約が境界サイズを決定したかを効果的に決定する必要があるため、これはおそらく間違った方法です。最終的な境界値は、複数の制約を持つ非常に複雑なシステムの解決策になる可能性があります。

于 2012-11-24T15:23:13.040 に答える
8

UITableViewで設定された制約に基づいてサイズを変更するに上と下の境界線を追加する必要があるという同様の問題がありましたUIStoryboard。で更新された制約にアクセスできました- (void)viewDidLayoutSubviews。これは、ビューをサブクラス化してそのレイアウトメソッドをオーバーライドする必要がないようにするために役立ちます。

/*** SET TOP AND BOTTOM BORDERS ON TABLE VIEW ***/
- (void)addBorders
{
    CALayer *topBorder           = [CALayer layer];
    topBorder.frame              = CGRectMake(0.0f, self.tableView.frame.origin.y, 320.0f, 0.5f);
    topBorder.backgroundColor    = [UIColor redColor].CGColor;

    CALayer *bottomBorder        = [CALayer layer];
    bottomBorder.frame           = CGRectMake(0.0f, (self.tableView.frame.origin.y + self.tableView.frame.size.height), 320.0f, 0.5f);
    bottomBorder.backgroundColor = [UIColor redColor].CGColor;

    [self.view.layer addSublayer:topBorder];
    [self.view.layer addSublayer:bottomBorder];
}

/*** GET AUTORESIZED FRAME DIMENSIONS ***/
- (void)viewDidLayoutSubviews{
    [self addBorders];
}

メソッドからメソッドを呼び出さなくviewDidLayoutSubviewても、下部の境界線が画面外にあるため、上部の境界線のみが正しく描画されます。

于 2014-01-16T12:02:58.043 に答える
5

特にTableviewCellで、まだそのような問題に直面している可能性がある人のために。

メソッドをオーバーライドするだけです。

-(void)layoutSubviews
{
//your code here like drawing a shadow
}

UITableViewCellまたはUICollectionViewCellの場合、セルのサブクラスを作成し、同じメソッドをオーバーライドします。

-(void)layoutSubviews
{
//your code here like drawing a shadow
}
于 2016-03-30T10:14:56.580 に答える
3

使用-(void)viewWillAppear:(BOOL)animatedして電話 する[self.view layoutIfNeeded];-それは私が試したように動作します。

使用-(void)viewDidLayoutSubviewsすると確実に機能しますが、UIが更新/変更を要求するたびにこのメソッドが呼び出されるためです。これは管理が難しくなります。ソフトキーは、bool変数を使用して、このような呼び出しのループを回避することです。より良い使用viewWillAppearviewWillAppearビューが(再割り当てせずに)再度ロードされた場合にも呼び出されることを忘れないでください。

于 2015-03-03T18:04:03.447 に答える
2

フレームはまだ有効です。最後に、ビューはそのframeプロパティを使用してレイアウトします。すべての制約に基づいてそのフレームを計算します。制約は初期レイアウトにのみ使用されます(回転後のように、layoutSubviewsがビューで呼び出されるときはいつでも)。その後、位置情報はframeプロパティにあります。それとも他の方法で見ていますか?

于 2012-11-19T02:43:42.913 に答える