我有一个包含多个图片视图的行和列的视图。
如果这个视图被重新调整大小,我需要重新排列这些图片视图的位置。
这个视图是另一个被调整大小的视图的子视图。
是否有一种方法可以检测到这个视图正在被调整大小?
如果这个视图被重新调整大小,我需要重新排列这些图片视图的位置。
这个视图是另一个被调整大小的视图的子视图。
是否有一种方法可以检测到这个视图正在被调整大小?
layoutSubviews
并在那里布置imageViews。layoutSubviews
,观察bounds
应该可以工作,即使有点不太好。更糟糕的是,观察存在风险 - 苹果不保证KVO适用于UIKit类。请阅读与苹果工程师的讨论: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:
}
}
viewWillTransition
等等。 - Dan RosenstarklayoutSubviews
方法呢? - Chris PrinceUIView
子类中,可以使用属性观察器:override var bounds: CGRect {
didSet {
// ...
}
}
不需要子类化,使用智能键路径进行键值观察即可:
Without subclassing, key-value observation with smart key-paths will do:
var boundsObservation: NSKeyValueObservation?
func beginObservingBounds() {
boundsObservation = observe(\.bounds) { capturedSelf, _ in
// ...
}
}
override var bounds: CGRect { didSet { layer.cornerRadius = bounds.size.width / 2 }}
。 - SimplGy创建UIView的子类,并重写layoutSubviews方法
Swift 4键路径 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()
//...
}
虽然较老,但仍是一个好问题。在苹果的示例代码和一些私有的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:
。
setBounds:
也不会被调用(至少在iOS 7.1上)。这可能是苹果为避免额外消息而添加的优化。 - nschumframe
和bounds
都是从视图的底层CALayer
派生出来的;它们只是调用了层的getter方法。而setFrame:
设置了层的框架,而setBounds:
设置了层的边界。因此,您不能仅覆盖其中一个。另外,layoutSubviews
会被过度调用(不仅在几何变化时),因此它也可能不是一个好的选择。还在寻找更好的解决方案... - big_m你可以创建一个UIView的子类并重写setFrame:(CGRect)frame方法。当视图的frame(即大小)发生变化时,该方法会被调用。做如下操作:
- (void) setFrame:(CGRect)frame
{
// Call the parent class to move the view
[super setFrame:frame];
// Do your custom code here.
}
setFrame:
方法,因为frame
是一个派生属性。请参考我的回答。 - Adlai Holler如果您在UIViewController实例中,覆盖viewDidLayoutSubviews方法就可以解决问题。
override func viewDidLayoutSubviews() {
// update subviews
}
UIView
实例和 UIViewController
实例之间的关系。因此,如果你有一个没有 VC 附加的 UIView
实例,其他答案都很好,但如果你恰好附加到一个 VC 上,这就是你需要的。抱歉它不适用于你的情况。 - Dan Rosenstark