swift 如何以编程方式精确查找PPI

hrysbysz  于 2023-06-21  发布在  Swift
关注(0)|答案(4)|浏览(126)

我想在iOS中找到PPI(Pixels Per Inch)。
我找不到任何直接的方法来查询这个,就像我们查询显示大小一样

UIScreen.mainScreen().bounds

有一个way to do it乘以比例与标准通用PPI的iPhone(163)或iPad(132),但它是不准确的。
如果公式正确,则iPhone 6 plus的PPI为489,但实际上PPI为401这里是reference
目前看来,硬编码是一条可行之路。
但我想用一个公式来编程。

uurity8g

uurity8g1#

我刚刚将我的一个旧ObjC库移植并更新到Swift。您可以使用它或获取您需要的部分代码。在这里获取:https://github.com/marchv/UIScreenExtension
该库使用UIScreen.main.nativeScale从每英寸像素(PPI)转换为每英寸点数。
使用Cocoapods安装库,然后导入:

import UIScreenExtension

然后利用它:

if let pointsPerCentimeter = UIScreen.pointsPerCentimeter {
   // code
}
6yt4nkrj

6yt4nkrj2#

我相信没有公共API可以获得PPI或屏幕的物理尺寸。
唯一的方法是用它们的物理大小和/或PPI硬编码设备列表(并且您可以从UIDevice类中获取设备类型)。
顺便说一句。这是一个问题,几乎是问同样的事情(不同的方式):How do ruler apps stay accurate on all devices?

s71maibg

s71maibg3#

iPhone Plus的Scale为3,但nativeScale为2.6。
UIKit对这些内容进行采样,以适应实际的屏幕尺寸。Metal或OpenGL ES内容应该以精确的尺寸渲染。

int screenPPI() {
    return [[UIScreen mainScreen] nativeScale] * ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 132 : 163);
}
2w3rbyxf

2w3rbyxf4#

在为同一个问题寻找答案之后,很明显没有简单的答案,并且如前所述,这需要为设备进行硬编码。最翔实的网站与设备尺寸和PPI,我发现是在https://www.ios-resolution.com
在电子表格中列出这一点,很明显可以从屏幕点和像素大小确定设备PPI。它并不完美,但它适用于我测试过的所有设备,除了iPad Mini(但我的应用程序不需要包含它们)。

// MARK: Screen Points Per Inch (PoPI)
// ----------------------------------------------------------------------------------------------------------------------------------
func screenPtsPerInch() -> Double {
    
    // Screen points per inch are derived from https://www.ios-resolution.com
    // For Pixels per Inch, multiply PoPI by UIScreen().scale
            
    // Almost all of the current iPads are simply 132.0 popi
    // iPad mini's are 163.0 but I have not found a way to differentiate them!
    
    // iPad
    guard UIDevice.current.userInterfaceIdiom == .phone else { return 132.0 }
    
    // iPhone
    guard let screen = self.window?.windowScene?.screen else { return 152.67 }
    let points       = screen.bounds
    let pixels       = screen.nativeBounds

    // Pixel width across screen (doesn't change with device rotation)
    let pixelWidth   = pixels.width
    
    // Point width and height across screen
    var screenWidth  = points.width
    var screenHeight = points.height
    if screenWidth > screenHeight {     // Points change with screen rotation
        screenWidth  = points.height
        screenHeight = points.width
    }

    print("Pixel  Width:  \(pixelWidth)")
    print("Screen Width:  \(screenWidth)")
    print("Screen Height: \(screenHeight)")
    
    if pixelWidth < 1100 {
        switch (screenWidth, screenHeight) {
            case (320.0, 480.0):
                return 163.0
            case (320.0, 568.0):
                return 163.0
            case (375.0, 667.0):
                return 163.0
            case (375.0, 812.0):
                return 158.67
            case (414.0, 736.0):
                return 133.67
            default:
                return 163.0
        }
    } else {
        switch (screenWidth, screenHeight) {
            case (375.0, 812.0):
                return 152.67
            case (390.0, 844.0):
                return 153.33
            case (393.0, 852.0):
                return 153.33
            case (414.0, 896.0):
                return 152.67
            case (428.0, 926.0):
                return 152.67
            case (430.0, 932.0):
                return 153.33
            default:
                return 152.67
        }
    }
}

此函数返回每英寸点数。如果你想要每英寸的像素数,然后将其乘以设备比例因子。

// MARK: Screen Device Scale (pixels/point)
// ----------------------------------------------------------------------------------------------------------------------------------
func screenScale() -> Double {
    guard let screen = self.window?.windowScene?.screen else { return 2.0 }
    print("Native Scale:  \(screen.nativeScale)")
    return screen.nativeScale
}

相关问题