我将一系列图像绘制到各个CALayer
子层,然后将这些子层添加到中superlayer
:
- (void)renderImagesFromArray:(NSArray *)array {
CALayer *superLayer = [CALayer layer];
for (id object in array) {
CALayer* subLayer = [CALayer layer];
// Disregard...
NSURL *path = [NSURL fileURLWithPathComponents:@[NSHomeDirectory(), @"Desktop", object]];
NSImage *image = [[NSImage alloc] initWithContentsOfURL:path];
[self positionImage:image layer:subLayer];
subLayer.contents = image;
subLayer.hidden = YES;
[superLayer addSublayer:subLayer];
}
[self.view setLayer:superLayer];
[self.view setWantsLayer:YES];
// Show top layer
CALayer *top = superLayer.sublayers[0];
top.hidden = NO;
}
然后[self positionImage: layer:]
,我调用将其拉伸CALayer
到最大范围(本质上使用CSScover
属性的算法),并将其放置在窗口的中央:
- (void)positionImage:(NSImage *)image layer:(CALayer *)layer{
float imageWidth = image.size.width;
float imageHeight = image.size.height;
float frameWidth = self.view.frame.size.width;
float frameHeight = self.view.frame.size.height;
float aspectRatioFrame = frameWidth/frameHeight;
float aspectRatioImage = imageWidth/imageHeight;
float computedImageWidth;
float computedImageHeight;
float verticalSpace;
float horizontalSpace;
if (aspectRatioImage <= aspectRatioFrame){
computedImageWidth = frameHeight * aspectRatioImage;
computedImageHeight = frameHeight;
verticalSpace = 0;
horizontalSpace = (frameWidth - computedImageWidth)/2;
} else {
computedImageWidth = frameWidth;
computedImageHeight = frameWidth / aspectRatioImage;
horizontalSpace = 0;
verticalSpace = (frameHeight - computedImageHeight)/2;
}
[CATransaction flush];
[CATransaction begin];
CATransaction.disableActions = YES;
layer.frame = CGRectMake(horizontalSpace, verticalSpace, computedImageWidth, computedImageHeight);
[CATransaction commit];
}
一切正常,除非调整窗口大小。我通过子类化(以非常丑陋的方式)解决了这个问题NSView
,然后实现了在调整窗口大小时实际调用的唯一方法viewWillDraw:
:
- (void)viewWillDraw{
[super viewWillDraw];
[self redraw];
}
- (void)redraw{
AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
CALayer *superLayer = self.layer;
NSArray *sublayers = superLayer.sublayers;
NSImage *image;
CALayer *current;
for (CALayer *view in sublayers){
if (!view.isHidden){
current = view;
image = view.contents;
}
}
[appDelegate positionImage:image layer:current];
}
那么...什么是正确的方法呢?viewWillDraw:
get的调用次数过多,这意味着我必须执行不必要的和多余的计算,并且我无法使用,viewWillStartLiveResize:
因为我需要不断将图像保持在正确的位置。我在俯视什么?
彼得·霍西(Peter Hosey)是对的;我原来的方法笨拙,我不应该压倒一切setNeedsDisplayInRect:
。我首先确保我在我的应用程序中使用了自动布局,然后实施了以下操作:
subLayer.layoutManager = [CAConstraintLayoutManager layoutManager];
subLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
subLayer.contentsGravity = kCAGravityResizeAspect;
基本上,我将子层设置为autoResizingMask
水平和垂直拉伸,然后设置contentsGravity
为保留宽高比。
我偶然发现了最后一个变量,但值得注意的是,如果仅将几个contentsGravity
常量用于,例如在我的情况下,将a设置NSImage
为图层的contents
:
该方法创建的图像适合用作图层的内容,并且支持该图层的所有重力模式。相比之下,NSImage类仅支持kCAGravityResize,kCAGravityResizeAspect和kCAGravityResizeAspectFill模式。
当复杂的解决方案可以简化为3行代码时,总是很有趣。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句