3

为了实现灵活的布局,我想创建一个 UIView 子类,layoutSubviews:它会自动覆盖其所有子视图的布局,并且每次调整其子视图的大小时都会继续这样做。

但是,我能想到的让超级视图知道它应该调用layoutSubviews:的唯一方法是在其每个子视图中覆盖该方法,这是我想尝试避免的(我希望人们能够添加任意 UIView到superview并处理这个问题)。

有没有办法让超级视图layoutSubviews:在子视图更改其大小时调用,而无需向相关子视图添加任何代码?

4

2 回答 2

0

您可以向该类添加一个类别并尝试layoutSubviews:从该类别中覆盖。(此技术已被建议用于自定义导航栏,它也可以在这里工作。)

以下是你如何制作一个类别,取自我在这里的回答。在您的情况下,请记住替换UIViewUINavigationController.

点击 Command+N 或打开“新建文件”对话框。接下来,从 Cocoa Touch 菜单中选择“Objective-C 类别”:

创建类别

单击下一步,系统将提示您输入要作为类别添加方法的类的名称。它应该看起来像这样:

在导航栏上创建一个类别

然后,您应该会看到一个保存文件对话框。这里是关于约定的快速说明。约定是在原始类、加号之后命名一个类别,然后是您要添加的内容的描述。您的可能如下所示:

类别命名约定

保存文件后,您将需要获得以下内容:

空类别

编辑:

如果您想在没有类别的情况下继续执行此操作,那么您最好的选择是创建一个 UIView 的子类,然后将该类子类化到您想要自定义行为的任​​何位置。与类别相比的另一个优点是,您的方法仅适用于您明确使用自定义类的情况。在类别中,该方法被添加到任何地方。

祝你好运!

于 2011-08-10T13:20:16.623 回答
0

您可以使用 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
}
于 2011-08-10T14:09:18.360 回答