【发布时间】:2011-05-05 10:28:15
【问题描述】:
我正在设计一个包含多个标签和文本字段的用户界面。我想这样设计 UI:
- 为我的
NSWindow的内容视图设置背景图案 - 在左上角的背景中添加自定义图标
我通过将内容视图设置为 layer-backed view 解决了第一个问题,如Apple's documentation of NSView 中所述:
layer-backed view 是由 Core Animation 层支持的视图。视图完成的任何绘图都缓存在支持层中。您只需调用具有
YES值的setWantsLayer:,即可配置支持层的视图。视图类会自动为您创建一个支持层,并且您使用视图类的绘图机制。 当使用图层支持的视图时,您不应该直接与图层交互。layer-hosting view 是一个包含你打算直接操作的 Core Animation 层的视图。您可以通过实例化 Core Animation 图层类的实例并使用视图的
setLayer:方法设置该图层来创建图层托管视图。完成此操作后,您将调用setWantsLayer:,其值为YES。 在使用 layer-hosting view 时,您不应依赖 view 进行绘图,也不应将子视图添加到 layer-hosting view。
然后从CGPattern 中生成一个CGColorRef,这会吸引我的CGImage:
NSView *mainView = [[self window]contentView];
[mainView setWantsLayer:YES];
为了将背景图像设置为图案,我使用了来自How to tile the contents of a CALayer 的答案,以完成第一个任务。
但是对于第二个任务,我使用下面的代码添加图标:
CGImageRef iconImage = NULL;
NSString *path = [[NSBundle mainBundle] pathForResource:@"icon_128" ofType:@"png"];
if(path != nil) {
NSURL *imageURL = [NSURL fileURLWithPath:path];
provider = CGDataProviderCreateWithURL((CFURLRef)imageURL);
iconImage = CGImageCreateWithPNGDataProvider(provider,NULL,FALSE,kCGRenderingIntentDefault);
CFRelease(provider);
}
CALayer *iconLayer = [[CALayer alloc] init];
// layer is the mainView's layer
CGRect layerFrame = layer.frame;
CGFloat iconWidth = 128.f;
iconLayer.frame = CGRectMake(0.f, CGRectGetHeight(layerFrame)-iconWidth, 128.f, 128.f);
iconLayer.contents = (id)iconImage;
CGImageRelease(iconImage);
[layer insertSublayer:iconLayer atIndex:0];
[iconLayer release];
问题
- 我不确定我是否违反了 Apple 关于 layer-backed 视图的限制,即您永远不应直接与图层交互。设置图层的背景颜色时我直接与图层交互还是我在这里弄错了?
- 我对直接与 layer-backed 视图的层层次结构进行交互并插入一个新层(就像我在第二个任务中所做的那样)有一种不好的感觉。这是可能的还是违反了苹果的指导方针?我想指出,这个内容视图当然有几个子视图,例如标签、文本视图和按钮。
- 在我看来,仅使用一个 layer-hosting
NSView似乎是最干净的解决方案。然后可以将所有文本标签添加为CATextLayers等。但是,如果我正确理解 Apple 的文档,我将无法再向视图添加任何控件。我是否必须自己在自定义CALayers中编写所有控件才能使其正常工作?听起来像是在重新发明轮子豪华。我也不知道如何仅在 CoreAnimation 中编写NSTextField。
感谢任何关于如何使用 CoreAnimation 和标准控件拆分设计用户界面的建议。
请注意,我在这里谈论的是 Mac。
【问题讨论】:
标签: objective-c macos core-animation calayer