As always, pros do better, but beginners may find it useful
Add a new kt file to your project and copy following code to it
fun backEaseInOut(e: Float, t: Float=0f, n: Float=100f, r: Float=100f):Float {
if (e < r / 2) return backEaseIn(e * 2f, 0f, n, r) * 0.5f + t;
else return backEaseOut(e * 2f - r, 0f, n, r) * 0.5f + n * 0.5f + t
}
fun backEaseOut(e: Float, t: Float=0f, n: Float=100f, r: Float=100f):Float {
return 100-backEaseIn(100-e)
}
fun backEaseIn(e: Float, t: Float=0f, n: Float=100f, r: Float=100f):Float {
var i = 1.70158f
var de=e/r
return (n * de * de * ((i + 1) * de - i) + t)
}
fun EaseInOut(e: Float, t: Float=0f, n: Float=100f, r: Float=100f):Float {
if (e < r / 2) return EaseIn(e * 2f, 0f, n, r) * 0.5f + t;
else return EaseOut(e * 2f - r, 0f, n, r) * 0.5f + n * 0.5f + t
}
fun EaseOut(e: Float, t: Float=0f, n: Float=100f, r: Float=100f):Float {
return 100-EaseIn(100-e)
}
fun EaseIn(e: Float, t: Float=0f, n: Float=100f, r: Float=100f):Float {
return n * e / r + t
}
fun strongEaseInOut(de: Float, t: Float=0f, n: Float=100f, r: Float=100f):Float {
var e=de
if (e < r / 2) return strongEaseIn(e * 2f, 0f, n, r) * 0.5f + t;
else return strongEaseOut(e * 2f - r, 0f, n, r) * 0.5f + n * 0.5f + t
}
fun strongEaseOut(e: Float, t: Float=0f, n: Float=100f, r: Float=100f):Float {
if(e>99){return 100f}
var de=e/r
return 100-strongEaseIn(100-e)
}
fun strongEaseIn(e: Float, t: Float=0f, n: Float=100f, r: Float=100f):Float {
var de=e
de /= r
return (n * de * e * e * e * e + t)/100000000
}
fun regularEaseInOut(de: Float, t: Float=0f, n: Float=100f, r: Float=100f):Float {
var e=de
if (e < r / 2) return regularEaseIn(e * 2f, 0f, n, r) * 0.5f + t;
else return regularEaseOut(e * 2f - r, 0f, n, r) * 0.5f + n * 0.5f + t
}
fun regularEaseOut(de: Float, t: Float=0f, n: Float=100f, r: Float=100f):Float {
var e=de
e /= r
return (- n * de * (e - 2) + t)/100
}
fun regularEaseIn(de: Float, t: Float=0f, n: Float=100f, r: Float=100f):Float {
var e=de
e /= r
return (n * e * de + t)/100
}
fun elasticIn(dt: Float): Float {
if(dt>99){return 100f}
var t=dt
t /= 100
if (t == 0f || t == 1f) return t
val pi2 = Math.PI * 2
val s = .3 / pi2 * Math.asin(1.0)
val o = t - 1f
return -(1 * Math.pow(2.0, 10.0 * o) * Math.sin((o - s) * pi2 / .3)).toFloat()*100
}
fun elasticOut(dt: Float): Float {
if(dt>99){return 100f}
var t=dt
t /= 100
if (t == 0f || t == 1f) return t
val pi2 = Math.PI * 2
val s = .3 / pi2 * Math.asin(1.0)
return (Math.pow(2.0, (-10 * t).toDouble()) * Math.sin((t - s) * pi2 / .3) + 1).toFloat()*100
}
fun elasticEaseInOut(dt:Float, e:Float=0f, n:Float=100f, r:Float=100f):Float {
if(dt>99){return 100f}
var t=dt
t /= r
val pi2 = Math.PI * 2
val s = .45 / pi2 * Math.asin(1.0)
var o = t * 2f
return if (o < 1) {
o -= 1f
(-0.5f * (Math.pow(2.0, (10 * o).toDouble()) * Math.sin((o - s) * pi2 / .45))).toFloat()*100
} else {
o -= 1f
(Math.pow(2.0, (-10 * o).toDouble()) * Math.sin((o - s) * pi2 / .45) * 0.5 + 1).toFloat()*100
}
}
fun bounceEaseInOut(e:Float, t:Float=0f, n:Float=100f, r:Float=100f):Float {
if (e < r / 2) return bounceEaseIn(e * 2f, 0f, n, r) * 0.5f + t;
else return bounceEaseOut(e * 2f - r, 0f, n, r) * 0.5f + n * 0.5f + t
}
fun bounceEaseIn(e:Float, t:Float=0f, n:Float=100f, r:Float=100f):Float {
return n - bounceEaseOut(r - e, 0f, n, r) + t
}
fun bounceEaseOut(dt:Float, b:Float=0f, c:Float=100f, d:Float=100f):Float {
var t=dt
t /= d
if (t < (1/2.75f)) {
return c*(7.5625f*t*t) + b
} else if (t < (2/2.75f)) {
var dt=t-(1.5f/2.75f)
return c*(7.5625f*(dt)*dt + .75f) + b
} else if (t < (2.5/2.75)) {
var dt=t-(2.25f/2.75f)
return c*(7.5625f*(dt)*dt + .9375f) + b
} else {
var dt=t-(2.625f/2.75f)
return c*(7.5625f*(dt)*dt + .984375f) + b
}
}
class AC (ele: View){
var time: Long =800
var x: Float? = null
var y: Float? = null
var rotation: Float? = null
var rotationx: Float? = null
var rotationy: Float? = null
var element = ele
var perc:Float?=null
var onFinish:()->(Unit)?= { }
var onAnimation:()->(Unit)?= { }
}
fun prepareAnimation(ob: AC,el: Any) : MutableList<Any>{
var back:MutableList<Any> = mutableListOf()
var type : String ="NULL"
var start : Float? = null
var end : Float? = null
var o=el
if (ob.x != null) {
type="X"
start=ob.element.x
end = ob.x
back.add("$type|$start|$end")
}
if (ob.y != null) {
type="Y"
start=ob.element.y
end = ob.y
back.add("$type|$start|$end")
}
if (ob.rotation != null) {
type="rotation"
start=ob.element.rotation
end = ob.rotation
back.add("$type|$start|$end")
}
if (ob.rotationy != null) {
type="rotationy"
start=ob.element.rotationY
end = ob.rotationy
back.add("$type|$start|$end")
}
if (ob.rotationx != null) {
type="rotationx"
start=ob.element.rotationX
end = ob.rotationx
back.add("$type|$start|$end")
}
return back
}
fun valback(e:Float, t:Float, n:Float = 0f):Float {
var r =e
var i = t
var s = abs(i - r)
var o = (s / 100 * n)
if (r > i) {
return (r - o)
} else {
return (r + o)
}
}
fun <T :Any> T.CLICK(function:()->(Unit)):T{
var ob = this as View
ob.setOnClickListener{
function()
}
return this
}
fun <T : Any> T.jmation(function:(ob:AC)->(Unit),ease: (Float)->(Float) = :: noEase): T {
var ob:AC=AC(this as View)
function(ob)
mation(this, ob,ease)
return this
}
fun positionSet(i: Any, ob: AC,aPz:Float){
var s:String = i as String
var arr = s.split("|").toTypedArray()
var typ=arr[0]
if(typ=="X") {
var sx = arr[1].toFloat()
var ex = arr[2].toFloat()
var posX = valback(sx, ex, aPz)
ob.element.x = posX
}
if(typ=="Y") {
var sy = arr[1].toFloat()
var ey = arr[2].toFloat()
var posY = valback(sy, ey, aPz)
ob.element.y = posY
}
if(typ=="rotation") {
var sy = arr[1].toFloat()
var ey = arr[2].toFloat()
var posY = valback(sy, ey, aPz)
ob.element.setRotation(posY)
}
if(typ=="rotationy") {
var sy = arr[1].toFloat()
var ey = arr[2].toFloat()
var posY = valback(sy, ey, aPz)
ob.element.setRotationY(posY)
}
if(typ=="rotationx") {
var sy = arr[1].toFloat()
var ey = arr[2].toFloat()
var posY = valback(sy, ey, aPz)
ob.element.setRotationX(posY)
}
}
fun noEase(f:Float):Float{
return f
}
fun mation(el: Any, ob: AC,ease: (Float)->(Float) = :: noEase) = GlobalScope.launch {
var perc:Float =0F
var timer:Long =(ob.time/100)
var animation=prepareAnimation(ob,el)
while(perc<101){
var aPz=ease(perc)
var rotation:Float=valback(0f,360f,aPz)
ob.perc=perc
for(i in animation){
positionSet(i,ob,aPz)
}
ob.onAnimation()
if(perc>=100){
println("Durch")
ob.perc=perc
ob.onFinish()
for(i in animation){
positionSet(i,ob,100f)
}
}
perc++
delay(timer)
}
}
How to use:
jmation can handle all types of Views (TextView, Editable, Buttons, ImageViews and so on.
To animate your View Element just use this
yourViewElement.jmation({
it.x = 900f //optional to animate it on X Axis to 900f
it.y = 800f //optional to animate it on Y Axis to 800f
it.time = 1800 //optional time in millisecconds, default is 800
it.rotationx = 180f //optional rotate on X Axis to 180f
it.rotationy = 180f //optional rotate on Y Axis to 180f
it.rotation = 180f //optional just rotate for 180F
it.onAnimation = { //optional If you want to do some more with while animation
println("Current percentage of animation " + it.perc)
}
it.onFinish = {//optional If you want to do something when animation has finished
println("Im done on " + it.perc)
}
},::elasticEaseInOut) //parameter is optional. No parameter means no easing. Or add an function from above for easing as in this case elasticEaseInOut
})
Another usefull functions included
valback(from float, to float, by percentage as float 0..100)
//returns the needed value between those arguments
yourElement.CLICK({//do something with it
})
//same as yourElement.setOnClickListener, but shorter and chainable
So yourElement.CLICK({/*whatever*/}).jmation(args) should work as well