可以让 superView 拦截来自子视图的layoutSubviews: 吗?

发布于 2024-11-28 18:16:45 字数 317 浏览 4 评论 0原文

为了实现灵活的布局,我想创建一个子类 UIView 来重写 layoutSubviews: 以自动将其所有子视图相互布局,并且每次调整其中一个子视图的大小时都会继续执行此操作。

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

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

To allow for flexible layouts, I wanted to create a subclass UIView that overrides layoutSubviews: to layout all of its subviews under each other automagically and would continue to do this every time one of its subviews got resized.

However, the only way that I can think of to let the superview know that it should call layoutSubviews: is by overriding that method in each of its subviews, something that I would like to try and avoid (I want people to be able to add arbitrary UIViews to the superview and have this taken care of).

Is there a way for the superview to call layoutSubviews: whenever a subview changes its size, without adding any code to the subview in question?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

轻拂→两袖风尘 2024-12-05 18:16:45

您可以使用 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
}

You could use KVO to observe the frame property of each of your subviews. You would need to add yourself as an observer each time a subview is added and remove the observation when a subview is removed – you can override didAddSubview: and willRemoveSubview: in your superview to do that.

- (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
}
野却迷人 2024-12-05 18:16:45

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

以下是创建类别的方法,摘自我的回答。在您的情况下,请记住用 UIView 替换 UINavigationController

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

创建类别

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

在导航栏上创建类别

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

Category Naming Convention

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

空类别

编辑:

如果您想在没有类别的情况下继续执行此操作,那么您最好的选择是创建 UIView 的子类,然后在您想要自定义行为的任​​何地方创建该类的子类。相对于类别的另一个优点是,您的方法仅在您显式使用自定义类的情况下才有效。在类别中,该方法随处添加。

祝你好运!

You can add a category to the class and try overriding layoutSubviews: from within the category. (This technique has been suggested for customizing navigation bars, and it may well work here too.)

Here's how you'd make a category, taken from my answer here. In your case, remember to substitute UIView for UINavigationController.

Hit Command+N or open the "New File" dialog. Next, choose "Objective-C category" from the Cocoa Touch menu:

Creating a category

Click Next and you will be prompted to enter the name of the class that you would like to add methods to as a category. It should look something like this:

Making a Category on the NavBar

Then, you should end up with a save file dialog. A quick note about convention here. Convention is to name a category after the original class, the plus sign, and then a description of what you're adding. Here's what yours might look like:

Category Naming Convention

Once you save your file, you will need get something like this:

Empty Category

Edit:

If you want to go ahead and do this without a category, then your best bet is to make a subclass of UIView and then subclass that class wherever you want your custom behavior. Another advantage over a category is that your method will only work where you explicitly use the custom class. In categories, the method gets added everywhere.

Good luck!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文