524 lines
15 KiB
Markdown
524 lines
15 KiB
Markdown
# DisplayInfo 屏幕尺寸功能使用示例
|
||
|
||
## 新增功能说明
|
||
|
||
`DisplayInfo` 类新增了获取屏幕物理尺寸的功能,支持以下单位:
|
||
- **英寸 (inches)**: 国际通用的屏幕尺寸单位
|
||
- **毫米 (mm)**: 公制单位,更精确的物理尺寸
|
||
|
||
可以获取:
|
||
- 对角线尺寸(屏幕大小)
|
||
- 宽度尺寸
|
||
- 高度尺寸
|
||
|
||
## 核心数据类
|
||
|
||
### ScreenSize
|
||
```kotlin
|
||
data class ScreenSize(
|
||
val diagonalInches: Double, // 对角线尺寸(英寸)
|
||
val diagonalMm: Double, // 对角线尺寸(毫米)
|
||
val widthInches: Double, // 宽度(英寸)
|
||
val widthMm: Double, // 宽度(毫米)
|
||
val heightInches: Double, // 高度(英寸)
|
||
val heightMm: Double // 高度(毫米)
|
||
)
|
||
```
|
||
|
||
### DefaultDisplayInfo (已更新)
|
||
现在包含 `screenSize: ScreenSize` 字段,提供完整的屏幕物理尺寸信息。
|
||
|
||
## 使用示例
|
||
|
||
### 1. 获取完整的屏幕尺寸信息
|
||
|
||
```kotlin
|
||
val displayInfo = DisplayInfo(context)
|
||
|
||
// 获取完整的屏幕尺寸信息
|
||
val screenSize = displayInfo.getScreenSize()
|
||
|
||
screenSize?.let {
|
||
println("=== Screen Size ===")
|
||
println("Diagonal: ${String.format("%.2f", it.diagonalInches)}\" (${String.format("%.1f", it.diagonalMm)} mm)")
|
||
println("Width: ${String.format("%.2f", it.widthInches)}\" (${String.format("%.1f", it.widthMm)} mm)")
|
||
println("Height: ${String.format("%.2f", it.heightInches)}\" (${String.format("%.1f", it.heightMm)} mm)")
|
||
}
|
||
```
|
||
|
||
输出示例:
|
||
```
|
||
=== Screen Size ===
|
||
Diagonal: 6.67" (169.4 mm)
|
||
Width: 2.91" (73.9 mm)
|
||
Height: 6.32" (160.5 mm)
|
||
```
|
||
|
||
### 2. 获取屏幕对角线尺寸
|
||
|
||
```kotlin
|
||
val displayInfo = DisplayInfo(context)
|
||
|
||
// 获取对角线尺寸(英寸)
|
||
val diagonalInches = displayInfo.getScreenDiagonalInches()
|
||
println("Screen Size: ${String.format("%.2f", diagonalInches)}\"")
|
||
|
||
// 获取对角线尺寸(毫米)
|
||
val diagonalMm = displayInfo.getScreenDiagonalMm()
|
||
println("Screen Size: ${String.format("%.1f", diagonalMm)} mm")
|
||
```
|
||
|
||
输出示例:
|
||
```
|
||
Screen Size: 6.67"
|
||
Screen Size: 169.4 mm
|
||
```
|
||
|
||
### 3. 获取屏幕宽度和高度
|
||
|
||
```kotlin
|
||
val displayInfo = DisplayInfo(context)
|
||
|
||
// 获取宽度
|
||
val widthInches = displayInfo.getScreenWidthInches()
|
||
val widthMm = displayInfo.getScreenWidthMm()
|
||
println("Screen Width: ${String.format("%.2f", widthInches)}\" / ${String.format("%.1f", widthMm)} mm")
|
||
|
||
// 获取高度
|
||
val heightInches = displayInfo.getScreenHeightInches()
|
||
val heightMm = displayInfo.getScreenHeightMm()
|
||
println("Screen Height: ${String.format("%.2f", heightInches)}\" / ${String.format("%.1f", heightMm)} mm")
|
||
```
|
||
|
||
输出示例:
|
||
```
|
||
Screen Width: 2.91" / 73.9 mm
|
||
Screen Height: 6.32" / 160.5 mm
|
||
```
|
||
|
||
### 4. 从 DefaultDisplayInfo 获取完整信息
|
||
|
||
```kotlin
|
||
val displayInfo = DisplayInfo(context)
|
||
|
||
val defaultDisplayInfo = displayInfo.getDefaultDisplayInfo()
|
||
|
||
defaultDisplayInfo?.let { info ->
|
||
println("=== Display Information ===")
|
||
println("Name: ${info.name}")
|
||
println("Resolution: ${info.widthPixels} x ${info.heightPixels}")
|
||
println("Density: ${info.densityDpi} dpi")
|
||
println("PPI: ${String.format("%.1f", info.ppi)}")
|
||
println("Refresh Rate: ${info.refreshRate} Hz")
|
||
|
||
// 屏幕尺寸
|
||
println("\n=== Screen Size ===")
|
||
println("Diagonal: ${String.format("%.2f", info.screenSize.diagonalInches)}\"")
|
||
println("Size: ${String.format("%.2f", info.screenSize.widthInches)}\" x ${String.format("%.2f", info.screenSize.heightInches)}\"")
|
||
println("Size (mm): ${String.format("%.1f", info.screenSize.widthMm)} x ${String.format("%.1f", info.screenSize.heightMm)} mm")
|
||
|
||
// HDR 信息
|
||
if (info.isHdr) {
|
||
println("\n=== HDR Support ===")
|
||
println("HDR Types: ${info.hdrTypes.joinToString(", ")}")
|
||
}
|
||
|
||
// 广色域
|
||
if (info.isWideColorGamut) {
|
||
println("Wide Color Gamut: Supported")
|
||
}
|
||
}
|
||
```
|
||
|
||
输出示例:
|
||
```
|
||
=== Display Information ===
|
||
Name: Built-in Screen
|
||
Resolution: 1080 x 2400
|
||
Density: 393 dpi
|
||
PPI: 395.6
|
||
Refresh Rate: 120.0 Hz
|
||
|
||
=== Screen Size ===
|
||
Diagonal: 6.67"
|
||
Size: 2.91" x 6.32"
|
||
Size (mm): 73.9 x 160.5 mm
|
||
|
||
=== HDR Support ===
|
||
HDR Types: HDR10, HDR10+
|
||
|
||
Wide Color Gamut: Supported
|
||
```
|
||
|
||
### 5. 计算屏幕纵横比
|
||
|
||
```kotlin
|
||
val displayInfo = DisplayInfo(context)
|
||
|
||
val screenSize = displayInfo.getScreenSize()
|
||
|
||
screenSize?.let {
|
||
// 计算纵横比
|
||
val aspectRatio = it.widthInches / it.heightInches
|
||
|
||
// 判断常见纵横比
|
||
val ratioName = when {
|
||
aspectRatio.isCloseTo(9.0 / 16.0, 0.01) -> "16:9"
|
||
aspectRatio.isCloseTo(9.0 / 18.0, 0.01) -> "18:9 (2:1)"
|
||
aspectRatio.isCloseTo(9.0 / 19.5, 0.01) -> "19.5:9"
|
||
aspectRatio.isCloseTo(9.0 / 20.0, 0.01) -> "20:9"
|
||
aspectRatio.isCloseTo(9.0 / 21.0, 0.01) -> "21:9"
|
||
aspectRatio.isCloseTo(3.0 / 4.0, 0.01) -> "4:3"
|
||
else -> String.format("%.2f:1", 1.0 / aspectRatio)
|
||
}
|
||
|
||
println("Screen Aspect Ratio: $ratioName")
|
||
}
|
||
|
||
// 辅助函数
|
||
fun Double.isCloseTo(target: Double, tolerance: Double): Boolean {
|
||
return kotlin.math.abs(this - target) < tolerance
|
||
}
|
||
```
|
||
|
||
### 6. 计算屏幕面积
|
||
|
||
```kotlin
|
||
val displayInfo = DisplayInfo(context)
|
||
|
||
val screenSize = displayInfo.getScreenSize()
|
||
|
||
screenSize?.let {
|
||
// 计算面积(平方英寸)
|
||
val areaInches = it.widthInches * it.heightInches
|
||
|
||
// 计算面积(平方厘米)
|
||
val areaCm = (it.widthMm / 10.0) * (it.heightMm / 10.0)
|
||
|
||
println("Screen Area: ${String.format("%.2f", areaInches)} in²")
|
||
println("Screen Area: ${String.format("%.2f", areaCm)} cm²")
|
||
}
|
||
```
|
||
|
||
输出示例:
|
||
```
|
||
Screen Area: 18.39 in²
|
||
Screen Area: 118.65 cm²
|
||
```
|
||
|
||
### 7. 在 Jetpack Compose 中显示
|
||
|
||
```kotlin
|
||
@Composable
|
||
fun ScreenSizeCard() {
|
||
val context = LocalContext.current
|
||
val displayInfo = remember { DisplayInfo(context) }
|
||
val defaultDisplayInfo = remember { displayInfo.getDefaultDisplayInfo() }
|
||
|
||
defaultDisplayInfo?.let { info ->
|
||
Card(
|
||
modifier = Modifier
|
||
.fillMaxWidth()
|
||
.padding(16.dp),
|
||
elevation = CardDefaults.cardElevation(4.dp)
|
||
) {
|
||
Column(modifier = Modifier.padding(16.dp)) {
|
||
Text(
|
||
text = "Display Information",
|
||
style = MaterialTheme.typography.titleLarge,
|
||
fontWeight = FontWeight.Bold
|
||
)
|
||
|
||
Spacer(modifier = Modifier.height(16.dp))
|
||
|
||
// 分辨率和密度
|
||
InfoSection(title = "Resolution & Density") {
|
||
InfoRow("Resolution", "${info.widthPixels} x ${info.heightPixels} px")
|
||
InfoRow("Density", "${info.densityDpi} dpi")
|
||
InfoRow("PPI", String.format("%.1f", info.ppi))
|
||
}
|
||
|
||
Spacer(modifier = Modifier.height(12.dp))
|
||
|
||
// 屏幕尺寸
|
||
InfoSection(title = "Screen Size") {
|
||
InfoRow(
|
||
"Diagonal",
|
||
String.format("%.2f\" (%.1f mm)",
|
||
info.screenSize.diagonalInches,
|
||
info.screenSize.diagonalMm
|
||
)
|
||
)
|
||
InfoRow(
|
||
"Width",
|
||
String.format("%.2f\" (%.1f mm)",
|
||
info.screenSize.widthInches,
|
||
info.screenSize.widthMm
|
||
)
|
||
)
|
||
InfoRow(
|
||
"Height",
|
||
String.format("%.2f\" (%.1f mm)",
|
||
info.screenSize.heightInches,
|
||
info.screenSize.heightMm
|
||
)
|
||
)
|
||
}
|
||
|
||
Spacer(modifier = Modifier.height(12.dp))
|
||
|
||
// 刷新率
|
||
InfoSection(title = "Refresh Rate") {
|
||
InfoRow("Current", "${info.refreshRate.toInt()} Hz")
|
||
if (info.supportedRefreshRates.size > 1) {
|
||
InfoRow(
|
||
"Supported",
|
||
info.supportedRefreshRates.joinToString(", ") { "${it.toInt()} Hz" }
|
||
)
|
||
}
|
||
}
|
||
|
||
// HDR 和色域
|
||
if (info.isHdr || info.isWideColorGamut) {
|
||
Spacer(modifier = Modifier.height(12.dp))
|
||
|
||
InfoSection(title = "Advanced Features") {
|
||
if (info.isHdr) {
|
||
InfoRow("HDR", info.hdrTypes.joinToString(", "))
|
||
}
|
||
if (info.isWideColorGamut) {
|
||
InfoRow("Color Gamut", "Wide Color Gamut")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
@Composable
|
||
fun InfoSection(title: String, content: @Composable () -> Unit) {
|
||
Column {
|
||
Text(
|
||
text = title,
|
||
style = MaterialTheme.typography.titleMedium,
|
||
fontWeight = FontWeight.SemiBold,
|
||
color = MaterialTheme.colorScheme.primary
|
||
)
|
||
Spacer(modifier = Modifier.height(8.dp))
|
||
content()
|
||
}
|
||
}
|
||
|
||
@Composable
|
||
fun InfoRow(label: String, value: String) {
|
||
Row(
|
||
modifier = Modifier
|
||
.fillMaxWidth()
|
||
.padding(vertical = 4.dp),
|
||
horizontalArrangement = Arrangement.SpaceBetween
|
||
) {
|
||
Text(
|
||
text = label,
|
||
style = MaterialTheme.typography.bodyMedium,
|
||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||
)
|
||
Text(
|
||
text = value,
|
||
style = MaterialTheme.typography.bodyMedium,
|
||
fontWeight = FontWeight.Medium,
|
||
textAlign = TextAlign.End,
|
||
modifier = Modifier.weight(1f, fill = false)
|
||
)
|
||
}
|
||
}
|
||
```
|
||
|
||
### 8. 比较设备屏幕大小
|
||
|
||
```kotlin
|
||
fun compareScreenSizes(context: Context) {
|
||
val displayInfo = DisplayInfo(context)
|
||
val screenSize = displayInfo.getScreenSize() ?: return
|
||
|
||
println("=== Screen Size Comparison ===")
|
||
|
||
val diagonal = screenSize.diagonalInches
|
||
|
||
val category = when {
|
||
diagonal < 4.5 -> "Compact Phone (< 4.5\")"
|
||
diagonal < 5.5 -> "Standard Phone (4.5\" - 5.5\")"
|
||
diagonal < 6.5 -> "Large Phone (5.5\" - 6.5\")"
|
||
diagonal < 7.5 -> "Phablet (6.5\" - 7.5\")"
|
||
diagonal < 10.0 -> "Small Tablet (7.5\" - 10\")"
|
||
diagonal < 13.0 -> "Standard Tablet (10\" - 13\")"
|
||
else -> "Large Tablet (> 13\")"
|
||
}
|
||
|
||
println("Device Category: $category")
|
||
println("Screen Diagonal: ${String.format("%.2f", diagonal)}\"")
|
||
|
||
// 与常见设备比较
|
||
println("\nComparison with common sizes:")
|
||
println("iPhone 15 Pro Max: ~6.7\"")
|
||
println("Samsung Galaxy S24 Ultra: ~6.8\"")
|
||
println("iPad Pro 11\": ~11\"")
|
||
println("iPad Pro 12.9\": ~12.9\"")
|
||
}
|
||
```
|
||
|
||
### 9. 计算最佳查看距离
|
||
|
||
```kotlin
|
||
fun calculateOptimalViewingDistance(context: Context) {
|
||
val displayInfo = DisplayInfo(context)
|
||
val defaultInfo = displayInfo.getDefaultDisplayInfo() ?: return
|
||
|
||
// 基于 PPI 和屏幕尺寸计算最佳查看距离
|
||
// 一般建议:对于 300+ PPI,最佳查看距离约为屏幕对角线的 1.5-2 倍
|
||
|
||
val diagonalInches = defaultInfo.screenSize.diagonalInches
|
||
val ppi = defaultInfo.ppi
|
||
|
||
val minDistance = diagonalInches * 1.5
|
||
val maxDistance = diagonalInches * 2.0
|
||
|
||
// 转换为厘米
|
||
val minDistanceCm = minDistance * 2.54
|
||
val maxDistanceCm = maxDistance * 2.54
|
||
|
||
println("=== Optimal Viewing Distance ===")
|
||
println("Screen: ${String.format("%.2f", diagonalInches)}\" @ ${String.format("%.0f", ppi)} PPI")
|
||
println("Recommended distance: ${String.format("%.1f", minDistanceCm)} - ${String.format("%.1f", maxDistanceCm)} cm")
|
||
println(" (${String.format("%.1f", minDistance)} - ${String.format("%.1f", maxDistance)} inches)")
|
||
}
|
||
```
|
||
|
||
### 10. 检测屏幕类型
|
||
|
||
```kotlin
|
||
fun detectScreenType(context: Context): String {
|
||
val displayInfo = DisplayInfo(context)
|
||
val defaultInfo = displayInfo.getDefaultDisplayInfo() ?: return "Unknown"
|
||
|
||
val diagonal = defaultInfo.screenSize.diagonalInches
|
||
val widthPixels = defaultInfo.widthPixels
|
||
val heightPixels = defaultInfo.heightPixels
|
||
val ppi = defaultInfo.ppi
|
||
|
||
// 计算纵横比
|
||
val aspectRatio = widthPixels.toDouble() / heightPixels.toDouble()
|
||
|
||
return buildString {
|
||
// 设备类型
|
||
append(when {
|
||
diagonal < 7.0 -> "Smartphone"
|
||
diagonal < 10.0 -> "Phablet/Small Tablet"
|
||
else -> "Tablet"
|
||
})
|
||
|
||
append(" | ")
|
||
|
||
// 屏幕质量
|
||
append(when {
|
||
ppi >= 500 -> "Ultra High Density"
|
||
ppi >= 400 -> "Very High Density"
|
||
ppi >= 300 -> "High Density"
|
||
ppi >= 200 -> "Medium Density"
|
||
else -> "Low Density"
|
||
})
|
||
|
||
append(" | ")
|
||
|
||
// 纵横比类型
|
||
append(when {
|
||
aspectRatio < 0.5 -> "Ultra-wide (21:9+)"
|
||
aspectRatio < 0.52 -> "Wide (20:9)"
|
||
aspectRatio < 0.54 -> "Wide (19.5:9)"
|
||
aspectRatio < 0.58 -> "Standard (18:9)"
|
||
aspectRatio < 0.60 -> "Standard (16:9)"
|
||
else -> "Traditional (4:3)"
|
||
})
|
||
}
|
||
}
|
||
|
||
// 使用示例
|
||
val screenType = detectScreenType(context)
|
||
println("Screen Type: $screenType")
|
||
// 输出: "Smartphone | Very High Density | Wide (20:9)"
|
||
```
|
||
|
||
## 技术细节
|
||
|
||
### 计算方法
|
||
|
||
1. **对角线尺寸**:
|
||
```
|
||
diagonal_inches = √(width_inches² + height_inches²)
|
||
```
|
||
|
||
2. **宽度/高度转换**:
|
||
```
|
||
width_inches = width_pixels / xdpi
|
||
height_inches = height_pixels / ydpi
|
||
```
|
||
|
||
3. **英寸到毫米转换**:
|
||
```
|
||
millimeters = inches × 25.4
|
||
```
|
||
|
||
### 精确度说明
|
||
|
||
- 计算基于设备报告的 `xdpi` 和 `ydpi` 值
|
||
- 大多数设备提供准确的 DPI 信息
|
||
- 某些低端设备可能报告不准确的 DPI,导致尺寸计算偏差
|
||
- 对角线尺寸通常误差在 ±0.1 英寸以内
|
||
|
||
## 注意事项
|
||
|
||
1. **DPI 准确性**:计算依赖于系统报告的 DPI 值,大多数现代设备提供准确的值
|
||
|
||
2. **单位转换**:
|
||
- 1 英寸 = 25.4 毫米
|
||
- 1 英寸 = 2.54 厘米
|
||
|
||
3. **屏幕对角线**:通常所说的屏幕尺寸指的是对角线长度(如 6.7 英寸手机)
|
||
|
||
4. **无需权限**:获取屏幕尺寸信息不需要任何特殊权限
|
||
|
||
5. **兼容性**:支持所有 Android 版本,使用标准 Android API
|
||
|
||
6. **性能**:计算是轻量级的,可以频繁调用而不影响性能
|
||
|
||
## 常见屏幕尺寸参考
|
||
|
||
### 智能手机
|
||
- **紧凑型**: 4.0" - 5.0"
|
||
- **标准型**: 5.0" - 6.0"
|
||
- **大屏型**: 6.0" - 6.5"
|
||
- **超大屏**: 6.5" - 7.0"
|
||
|
||
### 平板电脑
|
||
- **小型平板**: 7" - 8"
|
||
- **标准平板**: 9" - 10"
|
||
- **大型平板**: 11" - 13"
|
||
|
||
### 物理尺寸示例
|
||
- **iPhone 15 Pro Max**: 6.7" (约 170 mm)
|
||
- **Samsung Galaxy S24 Ultra**: 6.8" (约 173 mm)
|
||
- **iPad Air**: 10.9" (约 277 mm)
|
||
- **iPad Pro**: 12.9" (约 328 mm)
|
||
|
||
## 扩展用途
|
||
|
||
屏幕尺寸信息可以用于:
|
||
- UI 布局自适应
|
||
- 字体大小调整
|
||
- 图片资源选择
|
||
- 视频播放优化
|
||
- 游戏控制布局
|
||
- 阅读体验优化
|
||
- 设备分类统计
|
||
- 用户体验研究
|