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

15
我尝试查找iOS中的PPI(每英寸像素数)。

我没有找到像我们查询显示器尺寸那样直接查询它的方法。

UIScreen.mainScreen().bounds

有一种方法可以通过将标准通用iPhone(163)或iPad(132)的PPI乘以比例来实现,但这不是很准确。

如果公式正确,那么iPhone 6 Plus的PPI为489,但实际上PPI为401,这里是参考资料

目前似乎硬编码是可行的方法。

但我想使用一个公式来进行程序化处理。

4个回答

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

然后利用它:

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

6
值得一提的是,UIScreenExtension 在 iPad 2 和 iPad Mini 第一代上错误地报告了像素密度(PPI)。实际上,这两款设备都不是@2x视网膜屏幕,它们的像素密度分别为132和163。请注意修正。 - step_jac
2
@step_jac 我一开始误解了你的评论 - 最好在早上阅读之前先喝杯咖啡:D 现在我可以看到问题了 - 我会尽快修复它 - 感谢你指出。 - Jens Schwarzer

3
我认为没有公共API可以获取屏幕的PPI或物理大小。
唯一的方法是硬编码设备列表及其物理尺寸和/或PPI(您可以从UIDevice类中获取设备类型)。
顺便说一下,这里有一个问题,几乎问了同样的事情(不同的方式):如何使所有设备上的标尺应用程序保持准确?

我猜我们可以通过[UIScreen mainScreen].bounds.size来获得屏幕的物理尺寸,但除了 iPhone 6 Plus 之外的所有设备每个点有多少像素可以找出来,因为它不能像普通的PPI * scale那样被发现,因为iPhone 6 Plus和iPhone 6s Plus引入了新的名为Retina HD的屏幕......所以我认为最好的方法是检查设备是否是iPhone 6 Plus,然后返回401,对于其他设备,我们可以继续使用我想的公式... - Durai Amuthan.H
检测 iPhone 6 和 iPhone 6s 的编程方法(https://dev59.com/M18e5IYBdhLWcg3wcJ8q#26400686) - Durai Amuthan.H

1

在寻找同样问题的答案时,很明显没有简单的答案,正如之前所述,这需要为设备进行硬编码。我发现的最有信息量的网站,提供了设备尺寸和像素密度(PPI)的信息,网址是https://www.ios-resolution.com

将这些信息整理到电子表格中后,可以清楚地看出设备的像素密度可以通过屏幕点数和像素尺寸来确定。虽然不完美,但对我测试过的所有设备都有效,除了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
}

0

iPhone Plus的比例为3,但nativeScale为2.6。

UIKit会将此内容缩小以适应实际屏幕尺寸。Metal或OpenGL ES内容应以精确尺寸呈现。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接