为了实现灵活的布局,我想创建一个 UIView 子类,layoutSubviews:
它会自动覆盖其所有子视图的布局,并且每次调整其子视图的大小时都会继续这样做。
但是,我能想到的让超级视图知道它应该调用layoutSubviews:
的唯一方法是在其每个子视图中覆盖该方法,这是我想尝试避免的(我希望人们能够添加任意 UIView到superview并处理这个问题)。
有没有办法让超级视图layoutSubviews:
在子视图更改其大小时调用,而无需向相关子视图添加任何代码?
为了实现灵活的布局,我想创建一个 UIView 子类,layoutSubviews:
它会自动覆盖其所有子视图的布局,并且每次调整其子视图的大小时都会继续这样做。
但是,我能想到的让超级视图知道它应该调用layoutSubviews:
的唯一方法是在其每个子视图中覆盖该方法,这是我想尝试避免的(我希望人们能够添加任意 UIView到superview并处理这个问题)。
有没有办法让超级视图layoutSubviews:
在子视图更改其大小时调用,而无需向相关子视图添加任何代码?
您可以向该类添加一个类别并尝试layoutSubviews:
从该类别中覆盖。(此技术已被建议用于自定义导航栏,它也可以在这里工作。)
以下是你如何制作一个类别,取自我在这里的回答。在您的情况下,请记住替换UIView
为UINavigationController
.
点击 Command+N 或打开“新建文件”对话框。接下来,从 Cocoa Touch 菜单中选择“Objective-C 类别”:
单击下一步,系统将提示您输入要作为类别添加方法的类的名称。它应该看起来像这样:
然后,您应该会看到一个保存文件对话框。这里是关于约定的快速说明。约定是在原始类、加号之后命名一个类别,然后是您要添加的内容的描述。您的可能如下所示:
保存文件后,您将需要获得以下内容:
编辑:
如果您想在没有类别的情况下继续执行此操作,那么您最好的选择是创建一个 UIView 的子类,然后将该类子类化到您想要自定义行为的任何位置。与类别相比的另一个优点是,您的方法仅适用于您明确使用自定义类的情况。在类别中,该方法被添加到任何地方。
祝你好运!
您可以使用 KVO 来观察frame
每个子视图的属性。每次添加子视图时,您都需要将自己添加为观察者,并在删除子视图时删除观察 - 您可以覆盖didAddSubview:
并willRemoveSubview:
在您的超级视图中执行此操作。
- (void)didAddSubview:(UIView *)subview {
[subview addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)willRemoveSubview:(UIView *)subview {
[subview removeObserver:self forKeyPath:@"frame"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"frame"]) {
// Do your layout here...
}
}
- (void)dealloc {
// You might need to remove yourself as an observer here, in case
// your subviews are still used by others
}