我有一个包含图像视图行和列的视图。
如果调整此视图的大小,我需要重新排列imageviews位置。
此视图是另一个调整大小的视图的子视图。
有没有办法检测何时调整此视图的大小?
答案 0 :(得分:91)
正如Uli在下面评论的那样,正确的方法是覆盖layoutSubviews
并在那里布局imageViews。
如果由于某种原因,您无法继承和覆盖layoutSubviews
,则观察bounds
应该有效,即使是有点脏。更糟糕的是,观察存在风险 - Apple不保证KVO可以在UIKit类上运行。在此处阅读与Apple工程师的讨论:When does an associated object get released?
原始回答:
您可以使用键值观察:
[yourView addObserver:self forKeyPath:@"bounds" options:0 context:nil];
并实施:
- (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:
}
}
答案 1 :(得分:81)
在UIView
子类中,可以使用属性观察者:
override var bounds: CGRect {
didSet {
// ...
}
}
如果没有子类化,使用智能密钥路径的键值观察将会:
var boundsObservation: NSKeyValueObservation?
func beginObservingBounds() {
boundsObservation = observe(\.bounds) { capturedSelf, _ in
// ...
}
}
答案 2 :(得分:26)
创建UIView的子类,并覆盖layoutSubviews
答案 3 :(得分:7)
相当古老,但仍然是个好问题。在Apple的示例代码中,以及在他们的一些私有UIView子类中,它们大致覆盖了setBounds:
-(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];
}
覆盖setFrame:
并不是一个好主意。 frame
源自center
,bounds
和transform
,因此iOS不一定会调用setFrame:
。
答案 4 :(得分:7)
Swift 4 keypath KVO - 这就是我检测自动旋转并移动到iPad侧面板的方法。应该工作任何观点。不得不观察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 :(得分:6)
您可以创建UIView的子类并覆盖
SETFRAME:(的CGRect)帧
方法。这是在改变视图的帧(即大小)时调用的方法。做这样的事情:
- (void) setFrame:(CGRect)frame
{
// Call the parent class to move the view
[super setFrame:frame];
// Do your custom code here.
}
答案 6 :(得分:-3)
如果你在UIViewController实例中,覆盖viewDidLayoutSubviews
就可以了。
override func viewDidLayoutSubviews() {
// update subviews
}