Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d2f5cd7

Browse files
implement strategy pattern
1 parent 3ea54cf commit d2f5cd7

File tree

1 file changed

+115
-78
lines changed
  • Tutorial1-1Basics/src/main/java/com/smarttoolfactory/tutorial1_1basics/chapter9_animation

1 file changed

+115
-78
lines changed

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

Lines changed: 115 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -308,16 +308,13 @@ fun Modifier.disintegrate(
308308
withContext(Dispatchers.Default) {
309309
val bitmap =
310310
if (particleState.bitmap == null || particleState.bitmap?.isRecycled == true) {
311-
312-
val bitmap = graphicsLayer
311+
graphicsLayer
313312
.toImageBitmap()
314313
.asAndroidBitmap()
315314
.copy(Bitmap.Config.ARGB_8888, false)
316315
.apply {
317316
this.prepareToDraw()
318317
}
319-
bitmap
320-
321318
} else particleState.bitmap
322319

323320
bitmap?.let {
@@ -352,6 +349,7 @@ fun Modifier.disintegrate(
352349
particleState.updateAndDrawParticles(
353350
drawScope = this,
354351
particleList = particleState.particleList,
352+
bitmap = particleState.bitmap,
355353
progress = progress
356354
)
357355
}
@@ -401,61 +399,67 @@ class ParticleState internal constructor(particleSize: Dp) {
401399
easing = FastOutSlowInEasing
402400
)
403401

402+
private val strategy = DisintegrateStrategy()
403+
404404
fun addParticle(particle: Particle) {
405405
particleList.add(particle)
406406
}
407407

408408
fun updateAndDrawParticles(
409409
drawScope: DrawScope,
410410
particleList: SnapshotStateList<Particle>,
411+
bitmap: Bitmap?,
411412
progress: Float
412413
) {
413-
with(drawScope) {
414-
if (animationStatus !=AnimationStatus.Idle) {
415-
416-
drawWithLayer {
417-
particleList.forEach { particle ->
418-
updateParticle(progress, particle)
414+
if (animationStatus !=AnimationStatus.Idle) {
415+
bitmap?.let {
416+
strategy.updateAndDrawParticles(drawScope, particleList, bitmap, progress)
417+
}
418+
}
419+
}
419420

420-
val color = particle.color
421-
val radius = particle.currentSize.width * .5f
422-
val position = particle.currentPosition
423-
val alpha = particle.alpha
421+
fun createParticles(
422+
particleList: SnapshotStateList<Particle>,
423+
particleSize: Int,
424+
bitmap: Bitmap
425+
) {
426+
strategy.createParticles(particleList, particleSize, bitmap)
427+
}
424428

425-
// Destination
426-
drawCircle(
427-
color = color,
428-
radius = radius,
429-
center = position,
430-
alpha = alpha
431-
)
432-
}
429+
fun updateParticle(progress: Float, particle: Particle) {
430+
strategy.updateParticle(progress, particle)
431+
}
433432

434-
clipRect(
435-
left = progress * size.width * 2f
436-
) {
437-
bitmap?.asImageBitmap()?.let {
438-
// Source
439-
drawImage(
440-
image = it,
441-
blendMode = BlendMode.SrcOut
442-
)
443-
}
444-
}
433+
fun startAnimation() {
434+
animationStatus = AnimationStatus.Initializing
435+
}
445436

446-
// For debugging
447-
drawRect(
448-
color = Color.Black,
449-
topLeft = Offset(progress * size.width, 0f),
450-
size = Size(size.width - progress * size.width, size.height),
451-
style = Stroke(4.dp.toPx())
452-
)
453-
}
454-
}
437+
suspend fun animate(
438+
onStart: () -> Unit,
439+
onEnd: () -> Unit
440+
) {
441+
try {
442+
onStart()
443+
animatable.snapTo(0f)
444+
animatable.animateTo(
445+
targetValue = 1f,
446+
animationSpec = animationSpec
447+
)
448+
} catch (e: CancellationException) {
449+
println("FAILED: ${e.message}")
450+
} finally {
451+
onEnd()
455452
}
456453
}
457454

458-
fun createParticles(
455+
fun dispose() {
456+
bitmap?.recycle()
457+
}
458+
}
459+
460+
open class DisintegrateStrategy : ParticleStrategy {
461+
462+
override fun createParticles(
459463
particleList: SnapshotStateList<Particle>,
460464
particleSize: Int,
461465
bitmap: Bitmap
@@ -494,15 +498,14 @@ class ParticleState internal constructor(particleSize: Dp) {
494498

495499
// Get trajectory for each 5 percent of the image in x direction
496500
// This creates wave effect where particles at the start animation earlier
497-
val sectionFraction = 0.05f
498-
val particleTimeEnd = 0.5f
501+
val sectionFraction = ParticleCreationFraction / 10f
499502

500503
// This range is between 0-0.5f to display all of the particles
501504
// until half of the progress is reached
502505
var trajectoryProgressRange = getTrajectoryRange(
503506
fraction = fractionToImageWidth,
504507
sectionFraction = sectionFraction,
505-
until = particleTimeEnd
508+
until = ParticleCreationFraction
506509
)
507510

508511
// Add randomization for trajectory so particles don't start
@@ -555,7 +558,56 @@ class ParticleState internal constructor(particleSize: Dp) {
555558
}
556559
}
557560

558-
fun updateParticle(progress: Float, particle: Particle) {
561+
override fun updateAndDrawParticles(
562+
drawScope: DrawScope,
563+
particleList: SnapshotStateList<Particle>,
564+
bitmap: Bitmap,
565+
progress: Float,
566+
) {
567+
with(drawScope) {
568+
569+
drawWithLayer {
570+
particleList.forEach { particle ->
571+
updateParticle(progress, particle)
572+
573+
val color = particle.color
574+
val radius = particle.currentSize.width * .5f
575+
val position = particle.currentPosition
576+
val alpha = particle.alpha
577+
578+
// Destination
579+
drawCircle(
580+
color = color,
581+
radius = radius,
582+
center = position,
583+
alpha = alpha
584+
)
585+
}
586+
587+
clipRect(
588+
left = progress * size.width * 2f
589+
) {
590+
bitmap?.asImageBitmap()?.let {
591+
// Source
592+
drawImage(
593+
image = it,
594+
blendMode = BlendMode.SrcOut
595+
)
596+
}
597+
}
598+
599+
// For debugging
600+
drawRect(
601+
color = Color.Black,
602+
topLeft = Offset(progress * size.width, 0f),
603+
size = Size(size.width - progress * size.width, size.height),
604+
style = Stroke(4.dp.toPx())
605+
)
606+
}
607+
}
608+
}
609+
610+
override fun updateParticle(progress: Float, particle: Particle) {
559611
particle.run {
560612
// Trajectory progress translates progress from 0f-1f to
561613
// trajectoryStart-trajectoryEnd
@@ -573,7 +625,6 @@ class ParticleState internal constructor(particleSize: Dp) {
573625
initialSize.width + (endSize.width - initialSize.width) * currentTime * .5f
574626
val height =
575627
initialSize.height + (endSize.height - initialSize.height) * currentTime * .5f
576-
577628
currentSize = Size(width, height)
578629

579630
// Set alpha
@@ -587,46 +638,30 @@ class ParticleState internal constructor(particleSize: Dp) {
587638
val horizontalDisplacement = velocity.x * currentTime
588639
val verticalDisplacement =
589640
velocity.y * currentTime + 0.5f * acceleration * currentTime * currentTime
641+
590642
currentPosition = Offset(
591643
x = initialCenter.x + horizontalDisplacement,
592644
y = initialCenter.y + verticalDisplacement
593645
)
594646
}
595647
}
596-
597-
fun startAnimation() {
598-
animationStatus = AnimationStatus.Initializing
599-
}
600-
601-
suspend fun animate(
602-
onStart: () -> Unit,
603-
onEnd: () -> Unit
604-
) {
605-
try {
606-
onStart()
607-
animatable.snapTo(0f)
608-
animatable.animateTo(
609-
targetValue = 1f,
610-
animationSpec = animationSpec
611-
)
612-
} catch (e: CancellationException) {
613-
println("FAILED: ${e.message}")
614-
} finally {
615-
onEnd()
616-
}
617-
}
618-
619-
fun dispose() {
620-
bitmap?.recycle()
621-
}
622648
}
623649

624-
interface DisintegrationStrategy {
625-
fun updateParticle(progress: Float, particle: Particle)
650+
interface ParticleStrategy {
651+
fun createParticles(
652+
particleList: SnapshotStateList<Particle>,
653+
particleSize: Int,
654+
bitmap: Bitmap
655+
)
626656

627-
fun createParticles(particleSize: Int, imageBitmap: ImageBitmap)
657+
fun updateAndDrawParticles(
658+
drawScope: DrawScope,
659+
particleList: SnapshotStateList<Particle>,
660+
bitmap: Bitmap,
661+
progress: Float
662+
)
628663

629-
fun updateAndDrawParticles(drawScope:DrawScope)
664+
fun updateParticle(progress:Float, particle:Particle)
630665
}
631666

632667
/**
@@ -704,3 +739,5 @@ private fun DrawScope.drawWithLayer(block: DrawScope.() -> Unit) {
704739
restoreToCount(checkPoint)
705740
}
706741
}
742+
743+
private const val ParticleCreationFraction = 0.5f

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /