web-dev-qa-db-ja.com

寸法が変更されたときにサブビューを強制的に再描画(drawRect)するにはどうすればよいですか?

UIViewのサブクラスの行を含むUIViewがあります。サブクラスはdrawRect:をオーバーライドし、contentMode = UIViewContentModeRedrawを設定しました。

ユーザーが親コンテナを押しつぶして伸ばすと、child viewsが押しつぶされて引き伸ばされます。形状が変化したら、drawRectを繰り返し呼び出して、child viewsの内容を変更したいと思います。これまでのところ、私は失敗しています。これを行う正しい方法は何ですか?

乾杯、

ダグ

23
dugla

Cocoaでは、drawRectを呼び出すことはめったにありません。リージョンまたはビューを更新が必要であるとマークするだけで、再描画がスケジュールされます。これにより、複数の無効化の再描画をまとめて折りたたむことができます。

Cocoa Touchの場合、 [view setNeedsDisplay] または setNeedsDisplayinRect:(CGRect) のいずれかが必要です

59
Adam Wright

[view setNeedsLayout]を呼び出す必要があります。これにより、レイアウトが変更された場合にサブビューがdrawRect:呼び出しを受け取るようになります。ただし、これはテストしていません。

3
Pascal

このソリューションは少しおかしなものですが、論理的に意味があり、優れた視覚的結果が得られます。私はNSLayoutManagerといくつかのNSTextContainersを使用して、2列にテキストを配置しています。複数のテキストコンテナを使用しているため(複数のUITextViewが必要かどうかはわかりません)、_MyDrawingView: UIView_のdraw(rect: CGRect)メソッドをオーバーライドしています。

問題は、_self.contentMode = .redraw_を使用すると、ローテーションで若干のストレッチが発生することです。これは、取引を妨げるほど重要です。

_contentMode = .left_、または_contentMode = .scaleAspectFit_の設定が、ピクセル単位の完全な回転という点で、私が望んでいたものに近いことに気づきました。しかし、明らかに、私は必要なドローコールを受けていませんでした。

つまり、layoutSubviews()をオーバーライドし、contentModesuper.layoutSubviews()と呼ばれる_.scaleAspectFit_に切り替えてから、元に戻しました。 :P

_override func layoutSubviews() {
    self.contentMode = .scaleAspectFit

    super.layoutSubviews()
    self.contentMode = .redraw
}
_

それは完璧です。

0
Stan