我正在使用 Jetpack Compose 开发一个 Android 应用程序。
我有一个简单的页面。 它有一个可滚动的列,例如:
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.fillMaxSize()
.padding(it)
.padding(bottom = 32.dp)
) {
if (!dataMap.isNullOrEmpty()) {
dataMap.entries.forEachIndexed { index, (key, value) ->
val header = key
val list = value
Text(text = title)
list.forEach { item ->
ItemUi(item)
}
}
}
}
其实
dataMap
并不简单,它有嵌套列表。
反正dataMap
的尺寸有限,没有那么大。
所以我只使用 Column 而不是 LazyColumn。
我有一个 FAB 按钮来共享屏幕。 我可以在当前屏幕上编写代码,并且工作正常。
但问题是它只截取当前可见区域而不是完全滚动的区域。
我的
takeScreenshot
功能在这里:
private fun takeScreenShot(view: View, dir: File): File? {
try {
view.isDrawingCacheEnabled = true
val bitmap: Bitmap = Bitmap.createBitmap(view.drawingCache)
view.isDrawingCacheEnabled = false
val dateText = DateFormat.format("yyyy-MM-dd_hh:mm:ss", Date())
val imageFile = File("$dir/result-$dateText.jpeg")
FileOutputStream(imageFile).use { fos ->
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, fos)
fos.flush()
}
return imageFile
} catch (e: FileNotFoundException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
return null
}
这被称为:
@Composable
fun MyScreen() {
val activity = LocalContext.current as Activity
val requestPermissionLauncher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
if (isGranted) {
takeScreenShot(activity.window.decorView.rootView, activity.filesDir)
}
}
}
看看这个 jetpack-composable-to-bitmap-image
您可以膨胀一个无界的 AndroidView 并使用
drawToBitmap
将其转换为位图
@Composable
fun screenshotableComposable(content : @Composable () -> Unit): () -> Bitmap {
val context = LocalContext.current
val composeView = remember { ComposeView(context = context) }
fun captureBitmap(): Bitmap = composeView.drawToBitmap()
AndroidView(
factory = {
composeView.apply {
setContent {
content()
/*...content...*/
}
}
},
modifier = Modifier.wrapContentSize(unbounded = true) // Make sure to set unbounded true to draw beyond screen area
)
return ::captureBitmap
}
并从 onClick 方法所在的位置声明
screenshotableComposable
,您可以使用 screenshotableComposable.invoke()
从 onClick 调用它,它将返回位图
val screenshotableComposable = screenshotableComposable(
content = {
/*...composable content...*/
}
)
onClick = {
val bitmap = screenshotableComposable.invoke()
}
存在一个问题,您需要绘制内容两次,一次实际在屏幕上渲染,另一次在
screenshotableComposable
内渲染
从 Compose 1.6.0-alpha01+ 开始,Compose 中有一种新的本机方法可以执行此操作:https://developer.android.com/jetpack/compose/graphics/draw/modifiers#composable-to-bitmap
Column(
modifier = Modifier
.padding(padding)
.fillMaxSize()
.drawWithCache {
// Example that shows how to redirect rendering to an Android Picture and then
// draw the picture into the original destination
val width = this.size.width.toInt()
val height = this.size.height.toInt()
onDrawWithContent {
val pictureCanvas =
androidx.compose.ui.graphics.Canvas(
picture.beginRecording(
width,
height
)
)
// requires at least 1.6.0-alpha01+
draw(this, this.layoutDirection, pictureCanvas, this.size) {
[email protected]()
}
picture.endRecording()
drawIntoCanvas { canvas -> canvas.nativeCanvas.drawPicture(picture) }
}
}
) {
ScreenContentToCapture()
}
将图片转换为位图:
val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
Bitmap.createBitmap(picture)
} else {
val bitmap = Bitmap.createBitmap(
picture.width,
picture.height,
Bitmap.Config.ARGB_8888
)
val canvas = android.graphics.Canvas(bitmap)
canvas.drawColor(android.graphics.Color.WHITE)
canvas.drawPicture(picture)
bitmap
}