gpt4 book ai didi

objective-c - 在窗口调整大小时调整 CALayer 框架大小的方法?

转载 作者:行者123 更新时间:2023-12-03 16:28:35 26 4
gpt4 key购买 nike

我将一系列图像绘制到各个 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;
}

然后,我调用 [selfpositionImage:layer:]CALayer 拉伸(stretch)到其最大边界 ( essentially using the algorithm for the CSS cover property ),并将其放置在窗口的中心:

- (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: 因为我需要不断地将图像保持在其状态正确的位置。我忽略了什么?

最佳答案

彼得·霍西是对的;我原来的方法很笨拙,我不应该覆盖 setNeedsDisplayInRect:。我首先确保我在应用程序中使用自动布局,然后实现以下内容:

subLayer.layoutManager  = [CAConstraintLayoutManager layoutManager];
subLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
subLayer.contentsGravity = kCAGravityResizeAspect;

基本上,我将子图层的 autoResizingMask 设置为水平和垂直拉伸(stretch),然后设置 contentsGravity 以保留宽高比。

最后一个变量是我偶然发现的,但值得注意的是,您可以 only use a few contentsGravity constants if ,就像在我的例子中一样,您将 NSImage 设置为图层的 contents:

That method creates an image that is suited for use as the contents of a layer and that is supports all of the layer’s gravity modes. By contrast, the NSImage class supports only the kCAGravityResize, kCAGravityResizeAspect, and kCAGravityResizeAspectFill modes.

当复杂的解决方案可以简化为 3 行代码时,总是很有趣。

关于objective-c - 在窗口调整大小时调整 CALayer 框架大小的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24100389/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com