【问题标题】:UIView's contentScaleFactor depends on implementing drawRect:?UIView 的 contentScaleFactor 依赖于实现 drawRect:?
【发布时间】:2012-02-28 09:01:17
【问题描述】:

我偶然发现了一件奇怪的事情。看起来 UIViewcontentScaleFactor 始终为 1,即使在 Retina 设备上也是如此,除非您实现 drawRect:。考虑这段代码:

@interface MyView : UIView
@end

@implementation MyView

- (id) initWithFrame: (CGRect) frame
{
    self = [super initWithFrame: frame];
    if (self) {
        NSLog(@"%s %g %g %g", __PRETTY_FUNCTION__, self.contentScaleFactor, self.layer.contentsScale, [UIScreen mainScreen].scale);
    }
    return self;
}

- (void) didMoveToWindow
{
    if (self.window)
        NSLog(@"%s %g %g %g", __PRETTY_FUNCTION__, self.contentScaleFactor, self.layer.contentsScale, [UIScreen mainScreen].scale);
}

@end

在 Retina 设备上,它会打印以下内容:

-[MyView initWithFrame:] 1 1 2
-[MyView didMoveToWindow] 1 1 2

如果我像这样添加drawRect: 的空实现:

- (void) drawRect: (CGRect) rect
{
}

它按预期工作:

-[MyView initWithFrame:] 2 2 2
-[MyView didMoveToWindow] 2 2 2

所以看起来视图是否在任何视图层次结构中以及它显示在什么样的屏幕上并不重要。唯一重要的是视图是否实现了drawRect:

这是错误还是功能?我知道我可以更改didMoveToWindow 来修复它

- (void) didMoveToWindow
{
    if (self.window)
        self.contentScaleFactor = self.window.screen.scale;
}

但默认行为仍然困扰着我。

如果我不画任何东西,你可能会问我为什么需要contentScaleFactor。那是因为我只是将self.layer.contents 设置为一个现成的图像,然后用contentStretch 拉伸图像。但是,除非正确设置了 contentScaleFactor,否则即使使用了 @2x 图像,图像也不会在 Retina 设备上正确拉伸。准确地说,它可以正常工作除非使用@2x 图像。我猜这是一个错误。

任何人都可以分享您对contentScaleFactor 为何如此行事的见解吗?它是否仅适用于 iOS 5?

【问题讨论】:

    标签: ios uiview retina-display


    【解决方案1】:

    大概,如果你不覆盖drawRect:,那么 UIKit 知道 UIView 不会绘制任何东西,所以它需要(大概)快速的情况,即拥有一个内容比例为 1 的图层。尽快但是,当您覆盖 drawRect: 时,它知道它需要设置一个具有正确内容比例的图层,您可以根据需要绘制该图层。它不知道你在drawRect: 中什么都不做,所以它不能做出和以前一样的假设。

    事实上,文档中提到的所有内容:

    对于实现自定义 drawRect: 方法并与窗口相关联的视图,此属性的默认值是与当前显示视图的屏幕相关联的比例因子。

    您为什么不直接覆盖drawRect: 并在其中绘制您的图像?或者你可能会摆脱你目前正在做的事情并拥有一个存根drawRect:。鉴于文档所说的,我认为假设它会继续工作并且是正确的行为是完全合理的。

    【讨论】:

    • 非常感谢!本质上,我也是这么认为的,但是“对于实现自定义 drawRect: 方法并且 与窗口相关联 的视图”(强调我的)意味着只有在添加视图后才能做出决定到一个窗口。如您所见,它与一个被忽略的窗口关联。也许只是一个文档错误。至于在drawRect: 中绘图,我避免使用它,因为视图非常大,而且我有十几个,而我正在拉伸的图像是 31x31 像素。基本上,我只是尽量减少内存占用。
    • 谢谢。我在自定义 CALayer 中绘制了所有绘图,并且它的 contentScale 始终重置为 1。现在它看起来非常清晰锐利。
    【解决方案2】:

    Core Graphics 等原生绘图技术会为您考虑当前的比例因子。例如,如果您的一个视图实现了 drawRect: 方法,UIKit 会自动将该视图的比例因子设置为屏幕的比例因子。此外,UIKit 会自动修改绘图期间使用的任何图形上下文的当前转换矩阵,以考虑视图的比例因子。因此,您在 drawRect: 方法中绘制的任何内容都会针对底层设备的屏幕进行适当缩放。

    【讨论】:

      猜你喜欢
      • 2015-05-06
      • 1970-01-01
      • 1970-01-01
      • 2015-08-25
      • 1970-01-01
      • 1970-01-01
      • 2016-09-23
      • 2011-07-14
      • 1970-01-01
      相关资源
      最近更新 更多