項目中的飄屏場景比較多,但出現的數量一般,另外每個場景的view樣式不統一,行數不統一,動畫時間也不統一,所以對項目中所有飄屏相關做了重構,不管什麼飄屏類型只需調用addFloatView即可
支持單行飄屏setSingleLine
支持單一動畫時間setSingleTime
/**
* 飄屏view
* @author https://github.com/lyldding
*/
class FloatScreenView : FrameLayout {
private val times = arrayOf(3500, 4000, 4500, 5000, 5500)
private var mRandom: Random = Random
private var mIsSingleLine: Boolean = false
private var mIsSingleTime: Boolean = false
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(
context,
attributeSet,
defStyleAttr
)
fun addFloatView(view: View) {
if (measuredHeight <= 0 || measuredWidth <= 0) {
LogUtils.e("還未初始化")
return
}
if (view.layoutParams == null) {
view.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
}
val viewSize = SizeUtils.measureView(view)
val viewHeight = viewSize[1]
val viewWidth = viewSize[0]
if (viewHeight > measuredHeight) {
LogUtils.e("viewHeight > measuredHeight : viewHeight = $viewHeight , measuredHeight = $measuredHeight")
return
}
val top = getViewTop(viewHeight)
val animX =
ObjectAnimator.ofFloat(
view,
"translationX",
measuredWidth.toFloat(),
-viewWidth.toFloat()
)
val animY = ObjectAnimator.ofFloat(view, "translationY", top.toFloat(), top.toFloat())
val animatorSet = AnimatorSet()
animatorSet.playTogether(animX, animY)
animatorSet.interpolator = LinearInterpolator()
val duration = times[if (mIsSingleTime) 0 else mRandom.nextInt(times.size)]
animatorSet.duration = (duration + duration * viewWidth / measuredWidth).toLong()
animatorSet.addListener(object : Animator.AnimatorListener {
override fun onAnimationCancel(animation: Animator?) {
removeView(view)
}
override fun onAnimationEnd(animation: Animator?) {
removeView(view)
}
override fun onAnimationRepeat(animation: Animator?) {
}
override fun onAnimationStart(animation: Animator?) {
}
})
if (indexOfChild(view) != -1) {
removeView(view)
}
addView(view)
animatorSet.start()
}
private fun getViewTop(viewHeight: Int): Int {
var top = 0
if (mIsSingleLine) {
top = (measuredHeight - viewHeight) / 2
} else {
val lines = measuredHeight / viewHeight
top = if (lines > 1) (measuredHeight % viewHeight) / 2 else 0
val lineIndex = mRandom.nextInt(lines)
top += lineIndex * viewHeight
}
return top
}
/**
* @param isSingleLine true 單行
*/
fun setSingleLine(isSingleLine: Boolean) {
mIsSingleLine = isSingleLine
}
/**
* @param isSingleTime true 時間固定
*/
fun setSingleTime(isSingleTime: Boolean) {
mIsSingleTime = isSingleTime
}
}