Pertanyaan Apakah ada acara pengubahan ukuran UIView?


Saya memiliki pandangan yang memiliki baris dan kolom tampilan gambar di dalamnya.

Jika tampilan ini diubah ukurannya, saya perlu mengatur ulang posisi tampilan gambar.

Tampilan ini adalah subview dari tampilan lain yang diubah ukurannya.

Apakah ada cara untuk mendeteksi ketika tampilan ini diubah ukurannya?


75
2017-10-22 20:21


asal


Jawaban:


Seperti Uli berkomentar di bawah ini, cara yang tepat untuk melakukannya adalah menimpa layoutSubviews dan tata letak gambarDilihat di sana.

Jika, karena alasan tertentu, Anda tidak dapat melakukan subkelas dan menimpanya layoutSubviews, mengamati bounds harus bekerja, bahkan ketika menjadi kotor. Lebih buruk lagi, ada risiko dengan mengamati - Apple tidak menjamin KVO bekerja di kelas UIKit. Baca diskusi dengan insinyur Apple di sini: Kapan suatu objek terkait dilepaskan?

jawaban asli:

Anda dapat menggunakan pengamatan nilai kunci:

[yourView addObserver:self forKeyPath:@"bounds" options:0 context:nil];

dan implementasikan:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (object == yourView && [keyPath isEqualToString:@"bounds"]) {
        // do your stuff, or better schedule to run later using performSelector:withObject:afterDuration:
    }
}

82
2017-10-22 20:38



Di sebuah UIView subkelas, pengamat properti dapat digunakan:

override var bounds: CGRect {
    didSet {
        // ...
    }
}

Tanpa subclassing, observasi nilai kunci dengan jalur kunci pintar akan melakukan:

var boundsObservation: NSKeyValueObservation?

func beginObservingBounds() {
    boundsObservation = observe(\.bounds) { capturedSelf, _ in
        // ...
    }
}

63
2017-12-21 15:41



Buat subkelas dari UIView, dan timpa layoutSubview


26
2018-02-15 11:53



Anda dapat membuat subkelas dari UIView dan menimpa

setFrame: (CGRect) bingkai

metode. Ini adalah metode yang disebut ketika frame (yaitu ukuran) dari tampilan diubah. Lakukan sesuatu seperti ini:

- (void) setFrame:(CGRect)frame
{
  // Call the parent class to move the view
  [super setFrame:frame];

  // Do your custom code here.
}

6
2018-05-04 18:18



Cukup tua tapi masih pertanyaan yang bagus. Dalam kode contoh Apple, dan dalam beberapa subclass UIView pribadi mereka, mereka mengesampingkan setBounds kira-kira seperti:

-(void)setBounds:(CGRect)newBounds {
    BOOL const isResize = !CGSizeEqualToSize(newBounds.size, self.bounds.size);
    if (isResize) [self prepareToResizeTo:newBounds.size]; // probably saves 
    [super setBounds:newBounds];
    if (isResize) [self recoverFromResizing];
}

Utama setFrame: BUKAN ide yang bagus. frame berasal dari center, bounds, dan transform, jadi iOS tidak akan selalu memanggil setFrame:.


6
2018-04-24 18:39



Swift 4 keypath KVO - Ini adalah cara saya mendeteksi autorotate dan pindah ke panel samping iPad. Harus bekerja, bekerja apa saja. Harus mengamati lapisan UIView.

private var observer: NSKeyValueObservation?

override func viewDidLoad() {
    super.viewDidLoad()
    observer = view.layer.observe(\.bounds) { object, _ in
        print(object.bounds)
    }
    // ...
}
override func viewWillDisappear(_ animated: Bool) {
    observer?.invalidate()
    //...
}

5
2017-12-06 22:46



Jika Anda berada dalam instance UIViewController, menimpa viewDidLayoutSubviews melakukan triknya.

override func viewDidLayoutSubviews() {
    // update subviews
}

-3
2018-04-21 05:44