|
package com.webserveis.testbannerview |
|
|
|
import android.animation.Animator |
|
import android.animation.AnimatorListenerAdapter |
|
import android.content.Context |
|
import android.os.Handler |
|
import android.os.Parcel |
|
import android.os.Parcelable |
|
import android.util.AttributeSet |
|
import android.util.Log |
|
import android.view.View |
|
import android.view.ViewAnimationUtils |
|
import android.view.animation.AccelerateDecelerateInterpolator |
|
import android.widget.LinearLayout |
|
import androidx.core.view.isVisible |
|
import kotlinx.coroutines.CoroutineScope |
|
import kotlinx.coroutines.Dispatchers |
|
import kotlinx.coroutines.Job |
|
import kotlin.math.hypot |
|
|
|
|
|
/* |
|
https://github.com/xiprox/NamazVakitleri/blob/master/mobile/src/main/kotlin/tr/xip/prayertimes/ui/widget/RelativeTimeTextView.kt |
|
*/ |
|
|
|
open class RevealCircleView : LinearLayout { |
|
|
|
interface RevealListener { |
|
fun onHide() |
|
} |
|
|
|
private var isRevelating = false |
|
private var callback: RevealListener? = null |
|
private var isAutoHide = false |
|
|
|
private var mHandler: Handler = Handler() |
|
|
|
constructor(context: Context) : super(context) |
|
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) |
|
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super( |
|
context, |
|
attrs, |
|
defStyle |
|
) |
|
|
|
init { |
|
Log.d(TAG, "Init component: ") |
|
runAutoHide() |
|
} |
|
|
|
override fun onSaveInstanceState(): Parcelable? { |
|
val savedState = SavedState(super.onSaveInstanceState()) |
|
savedState.isVisible = this.isVisible |
|
return savedState |
|
} |
|
|
|
override fun onRestoreInstanceState(state: Parcelable?) { |
|
if (state is SavedState) { |
|
super.onRestoreInstanceState(state.superState) |
|
this.visibility = if (state.isVisible) View.VISIBLE else View.INVISIBLE |
|
|
|
} else { |
|
super.onRestoreInstanceState(state) |
|
} |
|
|
|
} |
|
|
|
override fun onDetachedFromWindow() { |
|
super.onDetachedFromWindow() |
|
mHandler.removeCallbacksAndMessages(null) |
|
} |
|
|
|
fun setOnRevealListener(callback: RevealListener) { |
|
this.callback = callback |
|
} |
|
|
|
fun showWithRevealEffect() { |
|
val view = this |
|
if (view.isVisible) return |
|
val cx = view.width / 2 |
|
val cy = view.height / 2 |
|
|
|
// get the final radius for the clipping circle |
|
val finalRadius = hypot( |
|
view.width.toDouble(), |
|
view.height.toDouble() |
|
).toFloat() |
|
|
|
// create the animator for this view (the start radius is zero) |
|
if (!isAttachedToWindow) return |
|
val anim = |
|
ViewAnimationUtils.createCircularReveal(view, cx, cy, 0F, finalRadius).apply { |
|
interpolator = AccelerateDecelerateInterpolator() |
|
} |
|
//anim.duration = 1200 |
|
|
|
// make the view visible and start the animation |
|
view.visibility = View.VISIBLE |
|
anim.start() |
|
runAutoHide() |
|
} |
|
|
|
private fun runAutoHide() { |
|
mHandler = Handler() |
|
mHandler.postDelayed({ |
|
hideWithRevealEffect() |
|
}, 5000) |
|
} |
|
|
|
fun hideWithRevealEffect() { |
|
val view = this |
|
|
|
if (!view.isVisible || isRevelating) return |
|
isRevelating = true |
|
|
|
val cx = view.width / 2 |
|
val cy = view.height / 2 |
|
|
|
// get the initial radius for the clipping circle |
|
val initialRadius = hypot( |
|
view.width.toDouble(), |
|
view.height.toDouble() |
|
).toFloat() |
|
|
|
// create the animation (the final radius is zero) |
|
if (!isAttachedToWindow) return |
|
val anim = |
|
ViewAnimationUtils.createCircularReveal(view, cx, cy, initialRadius, 0F).apply { |
|
interpolator = AccelerateDecelerateInterpolator() |
|
//duration = 5000 |
|
} |
|
|
|
// make the view invisible when the animation is done |
|
anim.addListener(object : AnimatorListenerAdapter() { |
|
override fun onAnimationEnd(animation: Animator) { |
|
super.onAnimationEnd(animation) |
|
callback?.onHide() |
|
view.visibility = View.INVISIBLE |
|
isRevelating = false |
|
} |
|
}) |
|
|
|
// start the animation |
|
|
|
anim.start() |
|
} |
|
|
|
|
|
companion object { |
|
private val TAG = RevealCircleView::class.java.simpleName |
|
} |
|
|
|
|
|
internal class SavedState : BaseSavedState { |
|
var isVisible = false |
|
|
|
constructor(source: Parcel) : super(source) { |
|
isVisible = source.readByte().toInt() != 0 |
|
} |
|
|
|
constructor(superState: Parcelable?) : super(superState) |
|
|
|
override fun writeToParcel(out: Parcel, flags: Int) { |
|
super.writeToParcel(out, flags) |
|
out.writeByte((if (isVisible) 1 else 0).toByte()) |
|
|
|
} |
|
|
|
companion object { |
|
@JvmField |
|
val CREATOR: Parcelable.Creator<SavedState> = object : Parcelable.Creator<SavedState> { |
|
override fun createFromParcel(source: Parcel): SavedState? { |
|
return SavedState(source) |
|
} |
|
|
|
override fun newArray(size: Int): Array<SavedState?> { |
|
return arrayOfNulls(size) |
|
} |
|
} |
|
} |
|
} |
|
|
|
} |