@@ -21,15 +21,16 @@ import android.content.Context
21
21
import android.content.Intent
22
22
import android.content.Intent.createChooser
23
23
import android.graphics.Bitmap
24
- import android.graphics.Picture
25
24
import android.media.MediaScannerConnection
26
25
import android.net.Uri
27
26
import android.os.Build
28
27
import android.os.Environment
29
28
import android.provider.MediaStore
30
29
import androidx.compose.foundation.Image
31
30
import androidx.compose.foundation.background
31
+ import androidx.compose.foundation.clickable
32
32
import androidx.compose.foundation.layout.Arrangement
33
+ import androidx.compose.foundation.layout.Box
33
34
import androidx.compose.foundation.layout.Column
34
35
import androidx.compose.foundation.layout.aspectRatio
35
36
import androidx.compose.foundation.layout.fillMaxSize
@@ -44,18 +45,17 @@ import androidx.compose.material3.SnackbarHostState
44
45
import androidx.compose.material3.SnackbarResult
45
46
import androidx.compose.material3.Text
46
47
import androidx.compose.runtime.Composable
47
- import androidx.compose.runtime.getValue
48
48
import androidx.compose.runtime.remember
49
49
import androidx.compose.runtime.rememberCoroutineScope
50
- import androidx.compose.runtime.setValue
51
50
import androidx.compose.ui.Alignment
52
51
import androidx.compose.ui.Modifier
53
52
import androidx.compose.ui.draw.drawWithCache
53
+ import androidx.compose.ui.draw.drawWithContent
54
54
import androidx.compose.ui.graphics.Brush
55
55
import androidx.compose.ui.graphics.Color
56
- import androidx.compose.ui.graphics.drawscope.draw
57
- import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
58
- import androidx.compose.ui.graphics.nativeCanvas
56
+ import androidx.compose.ui.graphics.asAndroidBitmap
57
+ import androidx.compose.ui.graphics.layer.drawLayer
58
+ import androidx.compose.ui.graphics.rememberGraphicsLayer
59
59
import androidx.compose.ui.layout.ContentScale
60
60
import androidx.compose.ui.platform.LocalContext
61
61
import androidx.compose.ui.res.painterResource
@@ -87,14 +87,44 @@ import kotlinx.coroutines.suspendCancellableCoroutine
87
87
* limitations under the License.
88
88
*/
89
89
90
+ @Preview
91
+ @Composable
92
+ private fun CreateBitmapFromGraphicsLayer () {
93
+ // [START android_compose_graphics_layer_bitmap_basics]
94
+ val coroutineScope = rememberCoroutineScope()
95
+ val graphicsLayer = rememberGraphicsLayer()
96
+ Box (
97
+ modifier = Modifier
98
+ .drawWithContent {
99
+ // call record to capture the content in the graphics layer
100
+ graphicsLayer.record {
101
+ // draw the contents of the composable into the graphics layer
102
+ this @drawWithContent.drawContent()
103
+ }
104
+ // draw the graphics layer on the visible canvas
105
+ drawLayer(graphicsLayer)
106
+ }
107
+ .clickable {
108
+ coroutineScope.launch {
109
+ val bitmap = graphicsLayer.toImageBitmap()
110
+ // do something with the newly acquired bitmap
111
+ }
112
+ }
113
+ .background(Color .White )
114
+ ) {
115
+ Text (" Hello Android" , fontSize = 26 .sp)
116
+ }
117
+ // [END android_compose_graphics_layer_bitmap_basics]
118
+ }
119
+
90
120
@OptIn(ExperimentalPermissionsApi ::class )
91
121
@Preview
92
122
@Composable
93
- fun BitmapFromComposableSnippet () {
123
+ fun BitmapFromComposableFullSnippet () {
94
124
val context = LocalContext .current
95
125
val coroutineScope = rememberCoroutineScope()
96
126
val snackbarHostState = remember { SnackbarHostState () }
97
- val picture = remember { Picture () }
127
+ val graphicsLayer = rememberGraphicsLayer()
98
128
99
129
val writeStorageAccessState = rememberMultiplePermissionsState(
100
130
if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .Q ) {
@@ -104,14 +134,15 @@ fun BitmapFromComposableSnippet() {
104
134
listOf (Manifest .permission.WRITE_EXTERNAL_STORAGE )
105
135
}
106
136
)
137
+
107
138
// This logic should live in your ViewModel - trigger a side effect to invoke URI sharing.
108
139
// checks permissions granted, and then saves the bitmap from a Picture that is already capturing content
109
140
// and shares it with the default share sheet.
110
141
fun shareBitmapFromComposable () {
111
142
if (writeStorageAccessState.allPermissionsGranted) {
112
143
coroutineScope.launch {
113
- val bitmap = createBitmapFromPicture(picture )
114
- val uri = bitmap.saveToDisk(context)
144
+ val bitmap = graphicsLayer.toImageBitmap( )
145
+ val uri = bitmap.asAndroidBitmap(). saveToDisk(context)
115
146
shareBitmap(context, uri)
116
147
}
117
148
} else if (writeStorageAccessState.shouldShowRationale) {
@@ -140,39 +171,22 @@ fun BitmapFromComposableSnippet() {
140
171
}
141
172
}
142
173
) { padding ->
143
- // [START android_compose_draw_into_bitmap]
144
174
Column (
145
175
modifier = Modifier
146
176
.padding(padding)
147
177
.fillMaxSize()
148
178
.drawWithCache {
149
- // Example that shows how to redirect rendering to an Android Picture and then
150
- // draw the picture into the original destination
151
- val width = this .size.width.toInt()
152
- val height = this .size.height.toInt()
153
-
154
179
onDrawWithContent {
155
- val pictureCanvas =
156
- androidx.compose.ui.graphics.Canvas (
157
- picture.beginRecording(
158
- width,
159
- height
160
- )
161
- )
162
- // requires at least 1.6.0-alpha01+
163
- draw(this , this .layoutDirection, pictureCanvas, this .size) {
180
+ graphicsLayer.record {
164
181
this @onDrawWithContent.drawContent()
165
182
}
166
- picture.endRecording()
167
-
168
- drawIntoCanvas { canvas -> canvas.nativeCanvas.drawPicture(picture) }
183
+ drawLayer(graphicsLayer)
169
184
}
170
185
}
171
186
172
187
) {
173
188
ScreenContentToCapture ()
174
189
}
175
- // [END android_compose_draw_into_bitmap]
176
190
}
177
191
}
178
192
@@ -207,25 +221,6 @@ private fun ScreenContentToCapture() {
207
221
}
208
222
}
209
223
210
- private fun createBitmapFromPicture (picture : Picture ): Bitmap {
211
- // [START android_compose_draw_into_bitmap_convert_picture]
212
- val bitmap = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .P ) {
213
- Bitmap .createBitmap(picture)
214
- } else {
215
- val bitmap = Bitmap .createBitmap(
216
- picture.width,
217
- picture.height,
218
- Bitmap .Config .ARGB_8888
219
- )
220
- val canvas = android.graphics.Canvas (bitmap)
221
- canvas.drawColor(android.graphics.Color .WHITE )
222
- canvas.drawPicture(picture)
223
- bitmap
224
- }
225
- // [END android_compose_draw_into_bitmap_convert_picture]
226
- return bitmap
227
- }
228
-
229
224
private suspend fun Bitmap.saveToDisk (context : Context ): Uri {
230
225
val file = File (
231
226
Environment .getExternalStoragePublicDirectory(Environment .DIRECTORY_PICTURES ),
0 commit comments