lebonprix.apk/java/io/xdrm/lebonprix/anim/HomeFilterAnimation.kt

216 lines
6.2 KiB
Kotlin

package io.xdrm.lebonprix.anim
import android.content.Context
import android.graphics.*
import android.graphics.drawable.Drawable
import android.support.v4.content.res.ResourcesCompat
import android.util.Log
import android.view.animation.Animation
import android.view.animation.Transformation
import android.widget.ImageView
import android.util.TypedValue
import io.xdrm.lebonprix.R
class HomeFilterAnimation(
val ctx: Context,
val target: ImageView
) : Animation(){
companion object {
// stage 1 : clean the page
val STAGE_CLEAN = 0
// stage 2 : move to center
val STAGE_CENTER = 1
// stage 3 : loading animation
val STAGE_LOAD = 2
// stage 4 : clean the page for next activity
val STAGE_END = 3
val CLEAR_ALL = 4
}
// PARAMS
private val dpIconSize: Int = 44
private val dpIconTop: Int = 8
private val dpIconRight: Int = 8
// FIXED/PROCESSED VALUES
private val iconSize: Float = dptopx(dpIconSize)
private val iconTop: Float = dptopx(dpIconTop)
private val iconRight: Float = dptopx(dpIconRight)
// VARIABLES
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 icon: Drawable?
// ANIMATION
private var stage: Int = HomeFilterAnimation.STAGE_CLEAN
private var progress: Float = 0F
init {
icon = ResourcesCompat.getDrawable(ctx.resources, R.drawable.ic_search, 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)
}
}
// Convert dp to pixels
private fun dptopx(dp: Int) : Float{
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp.toFloat(), ctx.resources.displayMetrics)
}
fun stage(s: Int) : HomeFilterAnimation{
stage = s
return this
}
fun during(d: Long) : HomeFilterAnimation {
super.setDuration(d)
return this
}
override fun start() {
target.startAnimation(this)
}
override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
super.applyTransformation(interpolatedTime, t)
progress = interpolatedTime
draw()
}
private fun draw(){
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
// Clean the page
if( stage == HomeFilterAnimation.STAGE_CLEAN ) {
drawPageCleaner(progress)
drawCenterIconBackground(0F)
drawCenterIcon(0F)
} else if( stage == HomeFilterAnimation.STAGE_CENTER ){
drawPageCleaner(1F)
drawCenterIconBackground(progress)
drawCenterIcon(progress)
} else if( stage == HomeFilterAnimation.STAGE_LOAD ){
drawPageCleaner(1F)
drawLoadingIconBackground(progress)
drawCenterIcon(1F)
} else if( stage == HomeFilterAnimation.STAGE_END ){
drawPageCleaner(1F)
drawClearingIconBackground(progress)
drawCenterIcon(1F)
}
target.setImageBitmap(bitmap)
}
private fun drawPageCleaner(prog: Float){
val bg = Paint()
bg.color = Color.WHITE
// max radius to hide the whole screen
val maxRad = Math.sqrt( Math.pow(width.toDouble(),2.toDouble()) + Math.pow(height.toDouble(), 2.toDouble())) * 1.5F // security of 1.5x the max radius
val rad = prog * maxRad
val x = width - iconRight - iconSize/2F
val y = iconTop + iconSize/2F
canvas.drawCircle(x, y, rad.toFloat(), bg)
}
private fun drawClearingIconBackground(prog: Float){
val bg = Paint()
bg.color = ResourcesCompat.getColor(ctx.resources, R.color.colorBackground, null)
// max radius to hide the whole screen
val maxRad = Math.sqrt( Math.pow(width.toDouble(),2.toDouble()) + Math.pow(height.toDouble(), 2.toDouble())) * 1.5F // security of 1.5x the max radius
val rad = prog * maxRad
val x = width.toFloat() / 2F
val y = height.toFloat() / 2F
canvas.drawCircle(x, y, rad.toFloat(), bg)
}
private fun drawCenterIconBackground(prog: Float){
val bg = Paint()
bg.color = ResourcesCompat.getColor(ctx.resources, R.color.colorBackground, null)
val rad = iconSize/2F
// get start / end position (end = centered)
val startx = width - iconRight - rad
val starty = iconTop + rad
val endx = width.toFloat() / 2F
val endy = height.toFloat() / 2F
val x = startx + prog * (endx - startx)
val y = starty + prog * (endy - starty)
canvas.drawCircle(x, y, rad, bg)
}
private fun drawCenterIcon(prog: Float) {
if( icon == null )
return
// get start / end position (end = centered)
val startx = width - iconRight - iconSize
val starty = iconTop
val endx = width.toFloat() / 2F - iconSize/2F
val endy = height.toFloat() / 2F - iconSize/2F
// get x,y from start position to center
val x = (startx + prog * (endx - startx)).toInt()
val y = (starty + prog * (endy - starty)).toInt()
icon!!.setBounds(x, y, x + iconSize.toInt(), y + iconSize.toInt())
icon!!.draw(canvas)
}
private fun drawLoadingIconBackground(prog: Float){
val bg = Paint()
bg.color = ResourcesCompat.getColor(ctx.resources, R.color.colorBackground, null)
var rad = iconSize/2F
// evoluting size
rad *= ( 1F + (0.5F + 0.5F * Math.sin((0.5+prog)*2*Math.PI).toFloat()) )
// centered
val x = width.toFloat() / 2F
val y = height.toFloat() / 2F
canvas.drawCircle(x, y, rad, bg)
}
}