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 = 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) ) } }