158 lines
4.7 KiB
Kotlin
158 lines
4.7 KiB
Kotlin
|
package io.xdrm.lebonprix.anim
|
||
|
|
||
|
import android.content.res.Resources
|
||
|
import android.graphics.*
|
||
|
import android.graphics.drawable.Drawable
|
||
|
import android.support.v4.content.res.ResourcesCompat
|
||
|
import android.util.Log
|
||
|
import android.view.animation.*
|
||
|
import android.widget.ImageView
|
||
|
import io.xdrm.lebonprix.R
|
||
|
|
||
|
|
||
|
class GooeySplashAnimation(val res: Resources, val target: ImageView) : Animation() {
|
||
|
|
||
|
private var width: Int = 1000
|
||
|
private var height: Int = 1000
|
||
|
|
||
|
private var bitmap : Bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||
|
private var canvas : Canvas = Canvas(bitmap)
|
||
|
|
||
|
private var progress: Float = 0F;
|
||
|
|
||
|
private var icon: Drawable?
|
||
|
|
||
|
data class wave(var relrad: Float, var clockWise: Boolean)
|
||
|
private var waves: MutableList<wave> = mutableListOf()
|
||
|
|
||
|
|
||
|
|
||
|
init {
|
||
|
icon = ResourcesCompat.getDrawable(res, R.mipmap.ic_splash_icon, null)
|
||
|
|
||
|
target.addOnLayoutChangeListener { v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
|
||
|
width = right-left
|
||
|
height = bottom-top
|
||
|
|
||
|
// unregister previous
|
||
|
target.setImageBitmap(null)
|
||
|
canvas.setBitmap(null)
|
||
|
bitmap.recycle()
|
||
|
|
||
|
// build new
|
||
|
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||
|
canvas = Canvas(bitmap)
|
||
|
target.setImageBitmap(bitmap)
|
||
|
|
||
|
generateWaves()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
override fun start() {
|
||
|
target.startAnimation(this)
|
||
|
}
|
||
|
|
||
|
override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
|
||
|
super.applyTransformation(interpolatedTime, t)
|
||
|
progress = interpolatedTime
|
||
|
draw()
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
fun draw(){
|
||
|
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
|
||
|
|
||
|
drawWave()
|
||
|
|
||
|
drawIcon()
|
||
|
|
||
|
target.setImageBitmap(bitmap)
|
||
|
|
||
|
}
|
||
|
|
||
|
private fun drawIcon(){
|
||
|
if( icon == null )
|
||
|
return
|
||
|
|
||
|
val bgSize = 280 + (20 + 20 * Math.sin(2*progress*Math.PI)).toInt()
|
||
|
val bgOffsetX = (width-bgSize)/2
|
||
|
val bgOffsetY = (height-bgSize)/2
|
||
|
|
||
|
icon!!.setBounds( bgOffsetX, bgOffsetY , bgOffsetX+bgSize, bgOffsetY+bgSize)
|
||
|
icon!!.draw(canvas)
|
||
|
}
|
||
|
|
||
|
private fun drawWave(){
|
||
|
val easeProgress = DecelerateInterpolator().getInterpolation(progress)
|
||
|
|
||
|
// -- PARAMETERS
|
||
|
// the wave will have a radius between 2% and -2% of the radius
|
||
|
val relativeRadiusVariation = 0.02F
|
||
|
val wavePerRevolution = 15
|
||
|
val revolutions = 20
|
||
|
val samples = 200
|
||
|
val relativeExpansionStartRadius = 1F // radius to expand from (relative to radius)
|
||
|
|
||
|
// -- PREPROCESSED VALUES
|
||
|
val slice = 2*Math.PI.toFloat() / samples;
|
||
|
val centerx = width * 0.5F
|
||
|
val centery = height * 0.5F
|
||
|
|
||
|
// val gradient: Shader = RadialGradient(x, y, width*0.5F, 0x554e5dff, Color.TRANSPARENT, Shader.TileMode.CLAMP)
|
||
|
// val paint = Paint()
|
||
|
// paint.shader = gradient
|
||
|
val paint = Paint()
|
||
|
paint.style = Paint.Style.STROKE
|
||
|
paint.color = 0x3de0e5
|
||
|
paint.alpha = 127 - (127*Math.sin(Math.PI*(2*progress + 0.5))).toInt()
|
||
|
paint.strokeWidth = width*0.003F * progress
|
||
|
// paint.flags = Paint.ANTI_ALIAS_FLAG
|
||
|
|
||
|
|
||
|
for( w in waves ){
|
||
|
|
||
|
val p = Path()
|
||
|
|
||
|
for( i in 0..samples ) {
|
||
|
val angle = slice * i.toDouble()
|
||
|
var rotation = wavePerRevolution*angle + easeProgress*revolutions*Math.PI
|
||
|
if( w.clockWise ) rotation = wavePerRevolution*angle - easeProgress*revolutions*Math.PI
|
||
|
|
||
|
// calculate proportional progress between minimum radius & end radius
|
||
|
val shiftedProgress = (progress + relativeExpansionStartRadius) / (1F+relativeExpansionStartRadius)
|
||
|
var rad = width*w.relrad * ( 1 + relativeRadiusVariation * (.2+progress*.8).toFloat() * Math.sin(rotation).toFloat() )
|
||
|
|
||
|
val x = centerx + rad*shiftedProgress * Math.cos(angle).toFloat()
|
||
|
val y = centery + rad*shiftedProgress * Math.sin(angle).toFloat()
|
||
|
|
||
|
if( i == 0 ) p.moveTo(x, y)
|
||
|
else p.lineTo(x, y)
|
||
|
}
|
||
|
|
||
|
canvas.drawPath(p, paint)
|
||
|
}
|
||
|
|
||
|
|
||
|
// val offset = ( width * progress ).toInt()
|
||
|
//
|
||
|
// wave1.setBounds(-(width-offset), (height*0.8).toInt(), width+offset, height)
|
||
|
// wave1.draw(canvas)
|
||
|
//
|
||
|
// wave2.setBounds(-offset, (height*0.7).toInt(), 2*width-offset, height)
|
||
|
// wave2.draw(canvas)
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
private fun generateWaves(count: Int = 1){
|
||
|
|
||
|
for( i in 0..count )
|
||
|
waves.add( wave(0.3F, true) )
|
||
|
waves.add( wave(0.5F, false) )
|
||
|
waves.add( wave(0.7F, true) )
|
||
|
|
||
|
}
|
||
|
}
|