@@ -9,6 +9,7 @@ import androidx.compose.foundation.Canvas
99import androidx.compose.foundation.Image
1010import androidx.compose.foundation.background
1111import androidx.compose.foundation.border
12+ import androidx.compose.foundation.clickable
1213import androidx.compose.foundation.layout.Arrangement
1314import androidx.compose.foundation.layout.Column
1415import androidx.compose.foundation.layout.Spacer
@@ -63,6 +64,11 @@ import com.smarttoolfactory.tutorial1_1basics.chapter6_graphics.randomInRange
6364import com.smarttoolfactory.tutorial1_1basics.chapter6_graphics.scale
6465import com.smarttoolfactory.tutorial1_1basics.ui.Pink400
6566import kotlinx.coroutines.CancellationException
67+ import kotlinx.coroutines.Dispatchers
68+ import kotlinx.coroutines.android.awaitFrame
69+ import kotlinx.coroutines.async
70+ import kotlinx.coroutines.delay
71+ import kotlinx.coroutines.withContext
6672import kotlin.math.roundToInt
6773import kotlin.random.Random
6874
@@ -227,24 +233,27 @@ fun ParticleAnimationSample() {
227233 mutableFloatStateOf(0f )
228234 }
229235
230-
231- SentMessageRowAlt (
232- modifier = Modifier .disintegrate(
233- // progress = progress,
234- particleState = particleState,
235- onStart = {
236- Toast .makeText(context, " Animation started..." , Toast .LENGTH_SHORT ).show()
237- },
238- onEnd = {
239- particleState.animationStatus = AnimationStatus .Idle
240- Toast .makeText(context, " Animation ended..." , Toast .LENGTH_SHORT ).show()
241- }
242- ),
243- quotedImage = R .drawable.avatar_4_raster,
244- text = " Some long message" ,
245- messageTime = " 11.02.2024" ,
246- messageStatus = MessageStatus .READ
247- )
236+ // SentMessageRowAlt(
237+ // modifier = Modifier
238+ // .clickable {
239+ // particleState.startAnimation()
240+ // }
241+ // .disintegrate(
242+ // // progress = progress,
243+ // particleState = particleState,
244+ // onStart = {
245+ // Toast.makeText(context, "Animation started...", Toast.LENGTH_SHORT).show()
246+ // },
247+ // onEnd = {
248+ // particleState.animationStatus = AnimationStatus.Idle
249+ // Toast.makeText(context, "Animation ended...", Toast.LENGTH_SHORT).show()
250+ // }
251+ // ),
252+ // quotedImage = R.drawable.avatar_4_raster,
253+ // text = "Some long message",
254+ // messageTime = "11.02.2024",
255+ // messageStatus = MessageStatus.READ
256+ // )
248257
249258 Spacer (Modifier .height(16 .dp))
250259
@@ -253,14 +262,17 @@ fun ParticleAnimationSample() {
253262 modifier = Modifier
254263 .border(2 .dp, Color .Red )
255264 .size(widthDp)
265+ .clickable {
266+ particleState2.startAnimation()
267+ }
256268 .disintegrate(
257- // progress = progress,
269+ progress = progress,
258270 particleState = particleState2,
259271 onStart = {
260272 Toast .makeText(context, " Animation started..." , Toast .LENGTH_SHORT ).show()
261273 },
262274 onEnd = {
263- particleState2.animationStatus = AnimationStatus .Idle
275+ // particleState2.animationStatus = AnimationStatus.Idle
264276 Toast .makeText(context, " Animation ended..." , Toast .LENGTH_SHORT ).show()
265277 }
266278 ),
@@ -275,15 +287,6 @@ fun ParticleAnimationSample() {
275287 progress = it
276288 }
277289 )
278- Button (
279- modifier = Modifier .fillMaxWidth(),
280- onClick = {
281- particleState.startAnimation()
282- particleState2.startAnimation()
283- }
284- ) {
285- Text (" Convert graphicsLayer to particles" )
286- }
287290 }
288291}
289292
@@ -337,28 +340,37 @@ fun Modifier.disintegrate(
337340 LaunchedEffect (animationStatus != AnimationStatus .Idle ) {
338341 if (animationStatus != AnimationStatus .Idle ) {
339342
340- if (particleState.bitmap == null || particleState.bitmap?.isRecycled == true ) {
341- val bitmap = graphicsLayer
342- .toImageBitmap()
343- .asAndroidBitmap()
344- .copy(Bitmap .Config .ARGB_8888 , false )
345-
346- bitmap.prepareToDraw()
347-
348- particleState.bitmap = bitmap
343+ withContext(Dispatchers .Default ) {
344+ val bitmap =
345+ if (particleState.bitmap == null || particleState.bitmap?.isRecycled == true ) {
346+
347+ val bitmap = graphicsLayer
348+ .toImageBitmap()
349+ .asAndroidBitmap()
350+ .copy(Bitmap .Config .ARGB_8888 , false )
351+ .apply {
352+ this .prepareToDraw()
353+ }
354+ bitmap
355+
356+ } else particleState.bitmap
357+
358+ bitmap?.let {
359+ particleState.createParticles(
360+ particleList = particleState.particleList,
361+ particleSize = particleSizePx,
362+ bitmap = bitmap
363+ )
349364
350- particleState.createParticles(
351- particleList = particleState.particleList,
352- particleSize = particleSizePx,
353- bitmap = bitmap
354- )
365+ withContext(Dispatchers .Main ) {
366+ particleState.animationStatus = AnimationStatus .Playing
367+ particleState.animate(
368+ onStart = onStart,
369+ onEnd = onEnd
370+ )
371+ }
372+ }
355373 }
356-
357- particleState.animationStatus = AnimationStatus .Playing
358- particleState.animate(
359- onStart = onStart,
360- onEnd = onEnd
361- )
362374 }
363375 }
364376
@@ -370,19 +382,19 @@ fun Modifier.disintegrate(
370382 graphicsLayer.record {
371383 this @onDrawWithContent.drawContent()
372384 }
385+ } else {
386+ particleState.updateAndDrawParticles(
387+ drawScope = this ,
388+ particleList = particleState.particleList,
389+ progress = progress
390+ )
373391 }
374-
375- particleState.updateAndDrawParticles(
376- drawScope = this ,
377- particleList = particleState.particleList,
378- progress = progress
379- )
380392 }
381393 }
382394}
383395
384396@Composable
385- fun rememberParticleState (particleSize : Dp = 1 .dp): ParticleState {
397+ fun rememberParticleState (particleSize : Dp = 2 .dp): ParticleState {
386398 return remember {
387399 ParticleState (particleSize)
388400 }
@@ -405,6 +417,7 @@ class ParticleState internal constructor(particleSize: Dp) {
405417 var bitmap: Bitmap ? = null
406418 internal set
407419
420+
408421 var animationSpec = tween<Float >(
409422 durationMillis = 2000 ,
410423 easing = FastOutSlowInEasing
@@ -431,6 +444,7 @@ class ParticleState internal constructor(particleSize: Dp) {
431444 val position = particle.currentPosition
432445 val alpha = particle.alpha
433446
447+ // Destination
434448 drawCircle(
435449 color = color,
436450 radius = radius,
@@ -442,10 +456,12 @@ class ParticleState internal constructor(particleSize: Dp) {
442456 clipRect(
443457 left = progress * size.width
444458 ) {
459+
460+ // Source
445461 bitmap?.asImageBitmap()?.let {
446462 drawImage(
447463 image = it,
448- blendMode = BlendMode .SrcIn
464+ blendMode = BlendMode .SrcOut
449465 )
450466 }
451467 }
@@ -467,6 +483,8 @@ class ParticleState internal constructor(particleSize: Dp) {
467483 particleSize : Int ,
468484 bitmap : Bitmap
469485 ) {
486+
487+ println (" CREATE particles thread: ${Thread .currentThread().name} " )
470488 particleList.clear()
471489
472490 val width = bitmap.width
0 commit comments