2010-10-22 34 views
71

Tôi có chế độ xem có hàng và cột số lần xem hình ảnh trong đó.Có sự kiện thay đổi kích thước UIView không?

Nếu chế độ xem này được thay đổi kích thước, tôi cần sắp xếp lại vị trí số lần xem hình ảnh.

Chế độ xem này là chế độ xem phụ của chế độ xem khác được thay đổi kích thước.

Có cách nào để phát hiện khi chế độ xem này đang được thay đổi kích thước không?

+0

Khi nào chế độ xem được thay đổi kích thước?Khi thiết bị quay hoặc khi người dùng xoay thiết bị bằng cảm ứng đa điểm? –

+0

Chế độ xem này được thay đổi kích thước khi người dùng chạm vào nút trên chế độ xem khác (chế độ xem chính). –

Trả lời

76

Như Uli đã nhận xét dưới đây, cách thích hợp để thực hiện việc này là ghi đè layoutSubviews và bố cục imageViews tại đó.

Nếu vì một lý do nào đó, bạn không thể phân lớp và ghi đè layoutSubviews, việc quan sát bounds sẽ hoạt động, ngay cả khi bị bẩn. Thậm chí tệ hơn, có một rủi ro khi quan sát - Apple không đảm bảo KVO hoạt động trên các lớp UIKit. Đọc thảo luận với Apple kỹ sư ở đây: When does an associated object get released?

gốc câu trả lời:

Bạn có thể sử dụng giá trị khóa quan sát:

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

và thực hiện:

- (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: 
    } 
} 
+2

Thực sự, việc đặt ra các bản xem trước chính xác là những gì layoutSubviews dành cho, vì vậy việc quan sát các thay đổi về kích thước, trong khi chức năng, là thiết kế xấu của IMO. – uliwitness

+0

@uliwitness cũng họ tiếp tục thay đổi công cụ này. Dù sao, bây giờ bạn nên sử dụng 'viewWillTransition' vv v.v. –

+0

viewWillTransition cho UIViewControllers, chứ không phải UIView. – Armand

24

Tạo lớp con của UIView và ghi đè bố cụcSubviews

+9

sự cố với điều này là các cuộc phỏng vấn không chỉ có thể thay đổi kích thước của chúng, mà chúng còn có thể làm thay đổi kích thước đó. Khi UIView chạy hoạt ảnh, nó không gọi layoutSubviews mỗi lần. –

6

Bạn có thể tạo một lớp con của UIView và ghi đè lên

setFrame: (CGRect) khung

phương pháp. Đây là phương thức được gọi khi khung (tức là kích thước) của chế độ xem được thay đổi. Làm điều gì đó như sau:

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

    // Do your custom code here. 
} 
+0

Hợp lý và chức năng. Cuộc gọi tốt. –

+1

FYI Điều này không hoạt động đối với lớp con UIImageView. Xem thêm thông tin ở đây: http://stackoverflow.com/questions/19216684/uiimageview-subclass-needs-to-handle-resize –

+0

Ngoài ra, 'setFrame:' ​​không được gọi trên lớp con 'UITextView' của tôi trong khi thay đổi kích thước do tự động ghi trong khi 'layoutSubviews:' là. Lưu ý: Tôi đang sử dụng bố cục tự động và iOS 7.0. – ma11hew28

5

Khá cũ nhưng vẫn là một câu hỏi hay. Trong mã mẫu của Apple, và trong một số lớp con UIView tin của họ, họ ghi đè setBounds khoảng như:

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

Trọng setFrame: KHÔNG phải là một ý tưởng tốt. frame có nguồn gốc từ center, boundstransform, vì vậy iOS sẽ không nhất thiết phải gọi setFrame:.

+1

Điều này đúng (theo lý thuyết). Tuy nhiên, 'setBounds:' không được gọi là khi thiết lập thuộc tính frame (ít nhất là trên iOS 7.1). Đây có thể là một tối ưu hóa mà Apple đã thêm vào để tránh thông báo bổ sung. – nschum

+1

... và thiết kế kém trên Apple không được gọi là người truy cập của riêng họ. – osxdirk

+0

Trên thực tế, _both_ 'frame' và' bounds' được lấy từ phần 'CALayer' bên dưới của khung nhìn; họ chỉ cần gọi cho bộ thu thập của lớp. Và 'setFrame:' ​​đặt khung của lớp, trong khi 'setBounds:' đặt các giới hạn của lớp. Vì vậy, bạn không thể chỉ ghi đè lên một hoặc khác. Ngoài ra, 'layoutSubviews' được gọi quá mức (không chỉ trên các thay đổi hình học), do đó, nó có thể không phải lúc nào cũng là một lựa chọn tốt. Vẫn đang tìm kiếm ... –

56

Trong Swift, bạn có thể làm:

override var bounds: CGRect { 
    didSet { 
     // do stuff here 
    } 
} 

Without subclassing:

private var boundsObservation: NSKeyValueObservation? 

private func beginObservingBounds() { 
    boundsObservation = observe(\.bounds) { capturedSelf, _ in 
     // do stuff here 
    } 
} 
+3

Tôi nghĩ rằng 'khung' hoạt động tốt hơn – Ali

+2

@Ali Tại sao bạn nghĩ như vậy? –

+0

trên khung tải thay đổi nhưng có vẻ như giới hạn không (tôi biết nó là lạ và có lẽ tôi đồng một cái gì đó sai) – Ali

-2

Nếu bạn đang ở trong một trường hợp UIViewController, trọng viewDidLayoutSubviews hiện các trick.

override func viewDidLayoutSubviews() { 
    // update subviews 
} 
+0

Kích thước UIView thay đổi cần thiết, không phải UIViewController. –

+0

@ GastónAntonioMontes cảm ơn vì điều đó! Bạn có thể đã nhận thấy một mối quan hệ giữa các trường hợp 'UIView' và' UIViewController'. Vì vậy, nếu bạn có một trường hợp 'UIView' không có VC đính kèm, các câu trả lời khác là tuyệt vời, nhưng nếu bạn tình cờ được gắn vào VC, đây là người của bạn. Xin lỗi, nó không áp dụng cho trường hợp của bạn. –

2

Swift 4 keypath KVO - Đây là cách tôi phát hiện autorotate và di chuyển sang bảng điều khiển bên iPad. Nên làm việc làm việc xem nào. Đã phải quan sát lớp của 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() 
    //... 
} 
+0

Giải pháp này làm việc cho tôi. Tôi mới sử dụng Swift và tôi không chắc chắn về cú pháp \ .bounds mà bạn đã sử dụng ở đây. điều đó chính xác có nghĩa là gì? – WBuck

+0

đây là thảo luận thêm: https://github.com/ole/whats-new-in-swift-4/blob/master/Whats-new-in-Swift-4.playground/Pages/Key%20paths.xcplaygroundpage/ Contents.swift –

+0

'.layer' đã thực hiện thủ thuật! Bạn có biết tại sao sử dụng 'view.observe' không hoạt động? – d4Rk

Các vấn đề liên quan