Skip to content

Commit 504cd58

Browse files
add ScreenshotLayout
1 parent 622c4f1 commit 504cd58

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
package com.smarttoolfactory.colorpicker.widget
2+
3+
import android.graphics.Bitmap
4+
import android.graphics.Canvas
5+
import androidx.compose.foundation.layout.Box
6+
import androidx.compose.runtime.*
7+
import androidx.compose.ui.Modifier
8+
import androidx.compose.ui.geometry.Rect
9+
import androidx.compose.ui.graphics.ImageBitmap
10+
import androidx.compose.ui.graphics.asImageBitmap
11+
import androidx.compose.ui.layout.boundsInRoot
12+
import androidx.compose.ui.layout.onGloballyPositioned
13+
import androidx.compose.ui.platform.LocalView
14+
import kotlinx.coroutines.delay
15+
import kotlinx.coroutines.flow.flow
16+
17+
@Composable
18+
fun rememberScreenshotState(timeInMillis: Long = 20) = remember {
19+
ScreenshotState(timeInMillis)
20+
}
21+
22+
class ScreenshotState(
23+
private val timeInMillis: Long = 20
24+
) {
25+
internal var callback: (() -> Bitmap?)? = null
26+
27+
private val bitmapState = mutableStateOf(callback?.invoke())
28+
29+
fun refresh() {
30+
bitmapState.value = callback?.invoke()
31+
}
32+
33+
val liveScreenshotState = flow {
34+
while (true) {
35+
delay(timeInMillis)
36+
val bmp = callback?.invoke()
37+
bmp?.let {
38+
emit(it)
39+
}
40+
}
41+
}
42+
43+
val bitmap: Bitmap?
44+
get() = bitmapState.value
45+
46+
val imageBitmap: ImageBitmap?
47+
get() = bitmap?.asImageBitmap()
48+
}
49+
50+
51+
@Composable
52+
fun ScreenshotBox(
53+
modifier: Modifier = Modifier,
54+
screenshotState: ScreenshotState,
55+
content: @Composable () -> Unit,
56+
) {
57+
val view = LocalView.current
58+
59+
var composableBounds by remember {
60+
mutableStateOf<Rect?>(null)
61+
}
62+
63+
DisposableEffect(Unit) {
64+
65+
var bitmap: Bitmap? = null
66+
67+
screenshotState.callback = {
68+
69+
composableBounds?.let { bounds ->
70+
71+
bitmap = Bitmap.createBitmap(
72+
bounds.width.toInt(),
73+
bounds.height.toInt(),
74+
Bitmap.Config.ARGB_8888
75+
)
76+
77+
bitmap?.let { bmp ->
78+
val canvas = Canvas(bmp)
79+
.apply {
80+
translate(-bounds.left, -bounds.top)
81+
}
82+
view.draw(canvas)
83+
}
84+
}
85+
bitmap
86+
}
87+
88+
onDispose {
89+
bitmap?.apply {
90+
if (!isRecycled) {
91+
recycle()
92+
bitmap = null
93+
}
94+
}
95+
screenshotState.callback = null
96+
}
97+
}
98+
99+
Box(modifier = modifier
100+
.onGloballyPositioned {
101+
composableBounds = it.boundsInRoot()
102+
}
103+
) {
104+
content()
105+
}
106+
}
107+
108+
109+
@Composable
110+
fun ScreenshotBox(
111+
modifier: Modifier = Modifier,
112+
content: @Composable ScreenshotScope.() -> Unit,
113+
) {
114+
115+
val view = LocalView.current
116+
117+
var composableBounds by remember {
118+
mutableStateOf<Rect?>(null)
119+
}
120+
var bitmap by remember {
121+
mutableStateOf<Bitmap?>(
122+
null
123+
)
124+
}
125+
126+
var callback: (() -> Bitmap?)? = remember {
127+
{
128+
composableBounds?.let { bounds ->
129+
bitmap = Bitmap.createBitmap(
130+
bounds.width.toInt(),
131+
bounds.height.toInt(),
132+
Bitmap.Config.ARGB_8888
133+
)
134+
135+
bitmap?.let { bmp ->
136+
val canvas = Canvas(bmp)
137+
.apply {
138+
translate(-bounds.left, -bounds.top)
139+
}
140+
view.draw(canvas)
141+
}
142+
}
143+
bitmap
144+
}
145+
}
146+
147+
val screenShotScopeImpl = remember {
148+
ScreenShotScopeImpl(callback)
149+
}
150+
151+
DisposableEffect(Unit) {
152+
onDispose {
153+
bitmap?.apply {
154+
if (!isRecycled) recycle()
155+
bitmap = null
156+
}
157+
158+
callback = null
159+
}
160+
}
161+
162+
163+
Box(modifier = modifier
164+
.onGloballyPositioned {
165+
composableBounds = it.boundsInRoot()
166+
}
167+
) {
168+
screenShotScopeImpl.content()
169+
}
170+
}
171+
172+
173+
internal class ScreenShotScopeImpl(private val callback: (() -> Bitmap?)?) : ScreenshotScope {
174+
override fun getBitmap(): Bitmap? {
175+
return callback?.invoke()
176+
}
177+
}
178+
179+
interface ScreenshotScope {
180+
fun getBitmap(): Bitmap?
181+
}

0 commit comments

Comments
 (0)