Skip to content

Commit 8c3a0fa

Browse files
refactoring
1 parent b59f127 commit 8c3a0fa

File tree

2 files changed

+79
-51
lines changed

2 files changed

+79
-51
lines changed

Tutorial1-1Basics/src/main/java/com/smarttoolfactory/tutorial1_1basics/chapter6_graphics/ParticlePhysics.kt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.smarttoolfactory.tutorial1_1basics.chapter6_graphics
22

3-
import android.content.res.Resources
43
import androidx.compose.foundation.Canvas
54
import androidx.compose.foundation.border
65
import androidx.compose.foundation.layout.Column
@@ -244,11 +243,6 @@ class ExplodingParticle(
244243
}
245244
}
246245

247-
fun Dp.toPx() = value.dpToPx()
248-
249-
fun Float.dpToPx() = this * Resources.getSystem().displayMetrics.density
250-
251-
252246
private val random = Random()
253247
fun Float.randomTillZero() = this * random.nextFloat()
254248
fun randomInRange(min: Float, max: Float) = min + (max - min).randomTillZero()

Tutorial1-1Basics/src/main/java/com/smarttoolfactory/tutorial1_1basics/chapter9_animation/ParticleAnimations.kt

Lines changed: 79 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import androidx.compose.runtime.mutableStateListOf
3131
import androidx.compose.runtime.mutableStateOf
3232
import androidx.compose.runtime.remember
3333
import androidx.compose.runtime.setValue
34+
import androidx.compose.runtime.snapshots.SnapshotStateList
3435
import androidx.compose.ui.Alignment
3536
import androidx.compose.ui.Modifier
3637
import androidx.compose.ui.composed
@@ -40,20 +41,20 @@ import androidx.compose.ui.geometry.Size
4041
import androidx.compose.ui.graphics.Color
4142
import androidx.compose.ui.graphics.ImageBitmap
4243
import androidx.compose.ui.graphics.asAndroidBitmap
43-
import androidx.compose.ui.graphics.asImageBitmap
44+
import androidx.compose.ui.graphics.drawscope.DrawScope
4445
import androidx.compose.ui.graphics.drawscope.Stroke
4546
import androidx.compose.ui.graphics.rememberGraphicsLayer
4647
import androidx.compose.ui.platform.LocalContext
4748
import androidx.compose.ui.platform.LocalDensity
4849
import androidx.compose.ui.res.painterResource
4950
import androidx.compose.ui.tooling.preview.Preview
51+
import androidx.compose.ui.unit.Dp
5052
import androidx.compose.ui.unit.Velocity
5153
import androidx.compose.ui.unit.dp
5254
import androidx.compose.ui.unit.sp
5355
import com.smarttoolfactory.tutorial1_1basics.R
5456
import com.smarttoolfactory.tutorial1_1basics.chapter6_graphics.randomInRange
5557
import com.smarttoolfactory.tutorial1_1basics.chapter6_graphics.scale
56-
import com.smarttoolfactory.tutorial1_1basics.chapter6_graphics.toPx
5758
import com.smarttoolfactory.tutorial1_1basics.ui.Pink400
5859
import kotlinx.coroutines.CancellationException
5960
import kotlin.random.Random
@@ -85,6 +86,10 @@ fun SingleParticleTrajectorySample() {
8586

8687
val particleState = rememberParticleState()
8788

89+
val particleSize = with(density) {
90+
5.dp.toPx()
91+
}
92+
8893
LaunchedEffect(trajectoryProgressStart, trajectoryProgressEnd) {
8994
particleState.particleList.clear()
9095
particleState.addParticle(
@@ -94,7 +99,7 @@ fun SingleParticleTrajectorySample() {
9499
x = sizePxHalf,
95100
y = sizePxHalf,
96101
),
97-
initialSize = Size(5.dp.toPx(), 5.dp.toPx()),
102+
initialSize = Size(particleSize, particleSize),
98103
endSize = Size(sizePx, sizePx),
99104
velocity = Velocity(
100105
x = sizePxHalf,
@@ -293,18 +298,20 @@ fun Modifier.disintegrate(
293298
LaunchedEffect(animationStatus != AnimationStatus.Idle) {
294299
if (animationStatus != AnimationStatus.Idle) {
295300

296-
if (particleState.imageBitmap == null) {
297-
val imageBitmap = graphicsLayer
301+
if (particleState.bitmap == null || particleState.bitmap?.isRecycled == true) {
302+
val bitmap = graphicsLayer
298303
.toImageBitmap()
299304
.asAndroidBitmap()
300305
.copy(Bitmap.Config.ARGB_8888, false)
301-
.asImageBitmap()
302306

303-
particleState.imageBitmap = imageBitmap
307+
bitmap.prepareToDraw()
308+
309+
particleState.bitmap = bitmap
304310

305311
particleState.createParticles(
312+
particleList = particleState.particleList,
306313
particleSize = particleSizePx,
307-
imageBitmap = imageBitmap
314+
bitmap = bitmap
308315
)
309316
}
310317

@@ -317,21 +324,62 @@ fun Modifier.disintegrate(
317324
}
318325

319326
Modifier.drawWithCache {
320-
321327
onDrawWithContent {
322-
323328
if (animationStatus != AnimationStatus.Playing) {
324329
drawContent()
325330
graphicsLayer.record {
326331
this@onDrawWithContent.drawContent()
327332
}
328333
}
329334

335+
particleState.updateAndDrawParticles(
336+
drawScope = this,
337+
particleList = particleState.particleList,
338+
progress = progress
339+
)
340+
}
341+
}
342+
}
343+
344+
@Composable
345+
fun rememberParticleState(particleSize: Dp = 2.dp): ParticleState {
346+
return remember {
347+
ParticleState(particleSize)
348+
}
349+
}
350+
351+
@Stable
352+
class ParticleState internal constructor(particleSize: Dp) {
353+
354+
var particleSize by mutableStateOf(particleSize)
355+
356+
val animatable = Animatable(0f)
357+
val particleList = mutableStateListOf<Particle>()
358+
359+
var animationStatus by mutableStateOf(AnimationStatus.Idle)
360+
internal set
361+
362+
val progress: Float
363+
get() = animatable.value
364+
365+
var bitmap: Bitmap? = null
366+
internal set
367+
368+
fun addParticle(particle: Particle) {
369+
particleList.add(particle)
370+
}
371+
372+
fun updateAndDrawParticles(
373+
drawScope: DrawScope,
374+
particleList: SnapshotStateList<Particle>,
375+
progress: Float
376+
) {
377+
with(drawScope) {
330378
if (animationStatus != AnimationStatus.Idle) {
331379

332-
particleState.particleList.forEach { particle ->
380+
particleList.forEach { particle ->
333381

334-
particleState.updateParticle(progress, particle)
382+
updateParticle(progress, particle)
335383

336384
val color = particle.color
337385
val radius = particle.currentSize.width * .65f
@@ -363,43 +411,17 @@ fun Modifier.disintegrate(
363411
}
364412
}
365413
}
366-
}
367-
368-
@Composable
369-
fun rememberParticleState(): ParticleState {
370-
return remember {
371-
ParticleState()
372-
}
373-
}
374-
375-
@Stable
376-
class ParticleState internal constructor() {
377-
378-
var particleSize by mutableStateOf(2.dp)
379-
380-
val animatable = Animatable(0f)
381-
val particleList = mutableStateListOf<Particle>()
382-
383-
var animationStatus by mutableStateOf(AnimationStatus.Idle)
384-
internal set
385-
386-
val progress: Float
387-
get() = animatable.value
388-
389-
var imageBitmap: ImageBitmap? = null
390-
internal set
391-
392-
fun addParticle(particle: Particle) {
393-
particleList.add(particle)
394-
}
395414

396-
fun createParticles(particleSize: Int, imageBitmap: ImageBitmap) {
415+
fun createParticles(
416+
particleList: SnapshotStateList<Particle>,
417+
particleSize: Int,
418+
bitmap: Bitmap
419+
) {
397420
particleList.clear()
398421

399-
val width = imageBitmap.width
400-
val height = imageBitmap.height
422+
val width = bitmap.width
423+
val height = bitmap.height
401424

402-
val bitmap: Bitmap = imageBitmap.asAndroidBitmap()
403425

404426
val particleRadius = particleSize / 2
405427

@@ -552,6 +574,18 @@ class ParticleState internal constructor() {
552574
animationStatus = AnimationStatus.Idle
553575
}
554576
}
577+
578+
fun dispose() {
579+
bitmap?.recycle()
580+
}
581+
}
582+
583+
interface DisintegrationStrategy {
584+
fun updateParticle(progress: Float, particle: Particle)
585+
586+
fun createParticles(particleSize: Int, imageBitmap: ImageBitmap)
587+
588+
fun updateAndDrawParticles(drawScope: DrawScope)
555589
}
556590

557591
/**

0 commit comments

Comments
 (0)