在设计工具、图片编辑器、主题定制类应用中,跨应用取色一直是个刚需但又极其难搞的功能。
Android 17(API 37)带来了全新的 Eye Dropper API,用一行 Intent 就能调起系统取色器,无需任何权限申请。
以前有多麻烦?
想在 Android 上实现跨应用取色,传统方案需要借助 MediaProjection 截屏再取像素色值:
bash
// 传统方案:复杂、侵入、吓人
val projectionManager = getSystemService(MediaProjectionManager::class.java)
val intent = projectionManager.createScreenCaptureIntent()
// → 弹出系统录屏警告对话框
// → 用户看到"将开始录制屏幕上显示的所有内容"
// → 大量用户直接拒绝退出
这个方案有三个致命问题:
1. 权限恐吓
需要 MEDIA_PROJECTION 权限,系统会弹出录屏警告对话框。用户看到"录制屏幕上显示的所有内容"这种措辞,转化率直接腰斩。
2. 实现复杂
拿到 MediaProjection 后,还要创建 VirtualDisplay、ImageReader,处理像素缓冲区,管理生命周期,代码量至少上百行。
3. 隐私过度
你只需要一个像素的颜色值,却要请求整个屏幕的录制权限,属于典型的"杀鸡用牛刀"。
Eye Dropper API:极简方案
Android 17 的 Eye Dropper API 把这一切简化到了极致。核心就两个常量:
Compose 完整实现
bash
@Composable
fun EyeDropperScreen() {
var pickedColor by remember { mutableStateOf(Color.Gray) }
var colorHex by remember { mutableStateOf("#808080") }
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val colorInt = result.data?.getIntExtra(
"android.intent.extra.COLOR",
android.graphics.Color.BLACK
) ?: android.graphics.Color.BLACK
pickedColor = Color(colorInt)
colorHex = String.format("#%06X", 0xFFFFFF and colorInt)
}
}
Column(
modifier = Modifier.fillMaxSize().padding(32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
// 颜色预览
Box(
modifier = Modifier
.size(120.dp)
.clip(CircleShape)
.background(pickedColor)
.border(2.dp, Color.White, CircleShape)
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = colorHex,
style = MaterialTheme.typography.headlineMedium,
fontFamily = FontFamily.Monospace
)
Spacer(modifier = Modifier.height(32.dp))
// 取色按钮
Button(
onClick = {
launcher.launch(
Intent("android.intent.action.OPEN_EYE_DROPPER")
)
},
enabled = Build.VERSION.SDK_INT >= 37
) {
Text("Pick a Color")
}
}
}
没看错,完整功能代码不到 50 行。

它是怎么工作的?
Eye Dropper API 的设计哲学是最小化数据暴露:
bash
┌──────────────┐ Intent ┌──────────────┐
│ │ ─────────────→│ │
│ 你的 App │ │ 系统取色器 │
│ │←─────────────│ │
└──────────────┘ Color Int └──────────────┘
│
│ 系统级
│ 像素读取
↓
┌──────────────┐
│ 屏幕像素 │
└──────────────┘
关键点在于:
对比一下两种方案的差异:

版本兼容处理
由于该 API 要求 API 37,建议做好版本判断和降级处理:
bash
fun isEyeDropperAvailable(): Boolean {
return Build.VERSION.SDK_INT >= 37
}
// 在 UI 中
Button(
onClick = { /* launch eye dropper */ },
enabled = isEyeDropperAvailable()
) {
Text(
if (isEyeDropperAvailable()) "Pick a Color"
else "Requires Android 17+"
)
}
也可以用 Intent.resolveActivity() 做更精确的判断:
bash
val intent = Intent("android.intent.action.OPEN_EYE_DROPPER")
val isAvailable = intent.resolveActivity(packageManager) != null
适合哪些场景?
-
• 设计工具:从任意 App 中采集品牌色、UI 配色
-
• 图片编辑器:从照片或其他应用中精准取色
-
• 主题生成器:根据壁纸或任意界面自动提取主题色
-
• 无障碍工具:帮助色觉异常用户识别屏幕颜色
-
• 开发调试:快速获取任意界面元素的颜色值
总结
Android 17 的 Eye Dropper API 是一个小而美的 API 设计典范:
-
• 零权限:不需要声明任何权限
-
• 零隐私风险:App 只拿到一个颜色值,无法窥探屏幕内容
-
• 零学习成本:一个 Intent 发出去,一个 Int 拿回来
如果你的应用有取色需求,这将是 Android 17 最值得适配的 API 之一。