【问题标题】:How to interact with layer-backed views on the Mac如何在 Mac 上与支持层的视图交互
【发布时间】:2011-05-05 10:28:15
【问题描述】:

我正在设计一个包含多个标签和文本字段的用户界面。我想这样设计 UI:

  1. 为我的NSWindow 的内容视图设置背景图案
  2. 在左上角的背景中添加自定义图标

我通过将内容视图设置为 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];

问题

  1. 我不确定我是否违反了 Apple 关于 layer-backed 视图的限制,即您永远不应直接与图层交互。设置图层的背景颜色时直接与图层交互还是我在这里弄错了?
  2. 我对直接与 layer-backed 视图的层层次结构进行交互并插入一个新层(就像我在第二个任务中所做的那样)有一种不好的感觉。这是可能的还是违反了苹果的指导方针?我想指出,这个内容视图当然有几个子视图,例如标签、文本视图和按钮。
  3. 在我看来,仅使用一个 layer-hosting NSView 似乎是最干净的解决方案。然后可以将所有文本标签添加为CATextLayers 等。但是,如果我正确理解 Apple 的文档,我将无法再向视图添加任何控件。我是否必须自己在自定义CALayers 中编写所有控件才能使其正常工作?听起来像是在重新发明轮子豪华。我也不知道如何仅在 CoreAnimation 中编写 NSTextField

感谢任何关于如何使用 CoreAnimation 和标准控件拆分设计用户界面的建议。

请注意,我在这里谈论的是 Mac。

【问题讨论】:

    标签: objective-c macos core-animation calayer


    【解决方案1】:

    恕我直言,无需层支持:

    1.我做图案图片

    NSImage *patternImage = [NSImage imageNamed:@"pattern"];
    [window setBackgroungdColor:[NSColor colorWithPatternImage:patternImage]];
    

    对于2.添加一个NSImageView作为contentview的子视图

    NSImageView *v = ...
    [[window contentView] addSubview:v]; 
    

    在 mac 上,某些视图在 IF 层支持时响应不佳 :: 例如pdf查看

    【讨论】:

      【解决方案2】:

      制作一个超级视图容器 A。将子视图 B 添加到 A 以满足您的所有 NSView 需求(按钮等)。将子视图 C 添加到 A 以满足您的所有核心动画需求。

      编辑: 更好的是:使用父视图 A 满足所有 NSView 需求,使用子视图 C 满足核心动画需求,完全忽略视图 B。

      【讨论】:

      • 感谢您的回答。您的答案是有问题的,因为同级视图的分层行为是未定义的。请参阅View programming guide
      • 这是一个有嚼劲的链接。也许您可以指导我到哪个部分说子视图不能附加图层。如果他们不能,那么任何视图怎么会有层?
      • 不,这不是我想要表达的意思。兄弟视图的剪切和重绘行为是未定义的。这意味着在您的编辑中,如果子视图 C 与 B 重叠,您会遇到麻烦
      • 我明白你的意思。我不知道你的程序到底做了什么,但与其“重新发明豪华轮子”并弄清楚如何使用 CALayers 对文本字段和按钮进行编码,也许你应该重新发明另一个轮子并弄清楚如何获得你的背景图案和不使用图层的视图上的图标,或者可能让步并且不让您的 CALayers 与您的视图重叠。
      • 是的,这基本上就是我所做的。我使用 Quartz 处理自定义视图并绘制所有内容。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-26
      • 1970-01-01
      • 1970-01-01
      • 2011-08-25
      • 2011-08-19
      • 2010-10-27
      相关资源
      最近更新 更多