iOS 屏幕坐标和缩放

Posted

技术标签:

【中文标题】iOS 屏幕坐标和缩放【英文标题】:iOS Screen coordinates and scaling 【发布时间】:2016-03-07 23:59:25 【问题描述】:

我正在尝试在 CALayer 中的图像上绘图,但在绘图显示在不同尺寸的显示器上时遇到了问题。

func drawLayer()
    let circleLayer = CAShapeLayer()
    let radius: CGFloat = 30
    let x = Thermo.frame.origin.x
    let y = Thermo.frame.origin.y
    let XX = Thermo.frame.width
    let YY = Thermo.frame.height
    print("X: \(x) Y: \(y) Width: \(XX) Height: \(YY)")
    circleLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 2.0 * radius, height: 2.0 * radius)  , cornerRadius: radius).CGPath
    circleLayer.fillColor = UIColor.redColor().CGColor
    circleLayer.shadowOffset = CGSizeMake(0, 3)
    circleLayer.shadowRadius = 5.0
    circleLayer.shadowColor = UIColor.blackColor().CGColor
    circleLayer.shadowOpacity = 0.8
    circleLayer.frame = CGRectMake(0, 410, 0, 192);
    self.Thermo.layer.addSublayer(circleLayer)
    circleLayer.setNeedsDisplay()

在正确的位置画了一个圆圈……对于 iPhone 6s。但是,当封闭的 UIImageView 组件针对较小的设备进行缩放时,显然不会。我添加了 print() 来查看图像的大小和位置,并且......好吧,它在我在 X:192.0 Y:8.0 宽度:216.0 高度:584.0 上运行的每台设备上都完全相同,但显然它正在被缩放通过 AuoLayout 管理器中的约束。

所以,我的问题是,如果我不能使用封闭视图的尺寸和位置,我该如何确定不同屏幕尺寸的正确收音机和位置,因为这似乎永远不会改变?

这是我开始的图像,在 UIImageView 中,并试图绘制。 我当然会尝试根据来自外部设备的数据对其进行着色。非常感谢任何建议/示例代码!

【问题讨论】:

你在哪里打电话drawLayer()?如果它在 UIView 的子类中,请将其移动到 viewDidLayoutSubviews()layoutSubviews() 它不是 UIView 的子类,反正还不是。调用 setNeedsDisplay() 会导致视图被重新绘制。 调用 setNeedsDisplay 将图层标记为需要重绘(即,您可以连续调用 setNeedsDisplay 三次,并且它只会在像素被推送到屏幕时重绘一次)。您应该将代码移动到viewDidLayoutSubviews(),正如我建议的那样,在自动布局引擎通过后调用它,因此最后一次调用viewDidLayoutSubviews() Thermo.frame 将是正确的。 所以我已按照建议将其移至 viewDidLayoutSubviews() 。然而,仍然有一些奇怪的事情发生。这确实有助于(大部分)正确定位,但由于无论屏幕大小如何,缩放因子都不会改变——直到你使用 iPad 设备——它仍然看起来很奇怪,因为圆圈的大小不合适。显然 ios 正在缩放图像,但 Thermo.image.scale 在所有 iPhone 尺寸上都返回 1.0。这会导致不同屏幕尺寸上的尺寸错误,并且位置也略有错误(因为图像已缩放)。 您必须发布一个屏幕截图,说明最正确的含义以及您认为应该如何。我可能是错的,但我猜 Thermo.image.scale 会告诉你图像是@1x、@2x 还是@3x,如果你只提供一张图像,它总是会返回 1,因此伯爵格雷为什么建议你使用 @ 987654330@ 如果你在 UIView 的子类中进行绘图,除非你打算进行非常精确的绘图,否则你不必注意比例。尽管我怀疑您的绘图不正常可能是由比例以外的其他原因造成的。 【参考方案1】:

CALayer 及其子类,包括。 CAShapeLayer 有一个属性

var contentsScale: CGFloat

来自类参考:

对于您自己创建和管理的图层,您必须根据屏幕分辨率和您提供的内容自行设置此属性的值。 Core Animation 使用您指定的值作为提示来确定如何呈现您的内容。

所以你需要做的是在图层上设置比例,然后从 UIDevice 类中获取设备的比例

circleLayer.scale = UIScreen.mainScreen().scale

【讨论】:

以上是关于iOS 屏幕坐标和缩放的主要内容,如果未能解决你的问题,请参考以下文章

不同屏幕尺寸的 iOS 缩放约束

捏缩放(绘图线)Android Canvas后获取正确的坐标

OpenLayers中地图缩放级别的设置方法

iOS开发:UILabel字号根据屏幕缩放

OpenLayers中地图缩放级别的设置方法

拖动时根据 x 坐标缩放视图