添加游戏加载完成提醒浮窗工具类
This commit is contained in:
263
app/src/main/java/com/gh/vspace/LoadCompleteWindowHelper.kt
Normal file
263
app/src/main/java/com/gh/vspace/LoadCompleteWindowHelper.kt
Normal file
@ -0,0 +1,263 @@
|
||||
package com.gh.vspace
|
||||
|
||||
import android.animation.*
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.get
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.gh.common.util.ClickUtils
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.common.util.doOnEnd
|
||||
import com.gh.common.util.toBinding
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.ItemFloatGameLoadCompleteBinding
|
||||
import com.gh.gamecenter.databinding.LayoutFloatLoadCompleteBinding
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
import com.lzf.easyfloat.EasyFloat
|
||||
import com.lzf.easyfloat.enums.SidePattern
|
||||
import com.lzf.easyfloat.interfaces.OnFloatAnimator
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
object LoadCompleteWindowHelper {
|
||||
private const val LOAD_COMPLETE_WINDOW = "load_complete_window"
|
||||
private const val LOOP_TIME = 2000L
|
||||
private const val LOOP_DURATION = 200L
|
||||
private const val AUTO_DISMISS_TIME = 3000L
|
||||
|
||||
private val mDismissTask = Runnable { EasyFloat.dismiss(LOAD_COMPLETE_WINDOW) }
|
||||
|
||||
fun showFloatingWindow(activity: Activity, gameEntity: GameEntity) = showFloatingWindow(activity, listOf(gameEntity))
|
||||
|
||||
fun showFloatingWindow(activity: Activity, gameEntityList: List<GameEntity> = emptyList()) {
|
||||
val floatingView = EasyFloat.getFloatView(LOAD_COMPLETE_WINDOW)
|
||||
if (floatingView != null) {
|
||||
if (!EasyFloat.isShow(LOAD_COMPLETE_WINDOW)) EasyFloat.show(LOAD_COMPLETE_WINDOW)
|
||||
floatingView.findViewById<ConstraintLayout>(R.id.container)?.let {
|
||||
val binding = LayoutFloatLoadCompleteBinding.bind(it)
|
||||
binding.viewPager.run {
|
||||
val adapter = adapter
|
||||
var isLastItem = false
|
||||
if (adapter is GameLoadCompleteAdapter) {
|
||||
if (currentItem == adapter.gameEntityList.size - 1) isLastItem = true
|
||||
adapter.submitList(gameEntityList)
|
||||
}
|
||||
removeCallbacks(mDismissTask)
|
||||
if (isLastItem) {
|
||||
val mLoopTask = object : Runnable {
|
||||
private val reference: WeakReference<ViewPager2> = WeakReference(binding.viewPager)
|
||||
|
||||
override fun run() {
|
||||
val vp: ViewPager2? = reference.get()
|
||||
if (vp != null) {
|
||||
val count = binding.viewPager.adapter?.itemCount ?: 0
|
||||
if (count == 0) return
|
||||
val next = vp.currentItem + 1
|
||||
if (next < count) {
|
||||
vp.setCurrentItem(next, LOOP_DURATION)
|
||||
vp.postDelayed(this, LOOP_TIME)
|
||||
} else {
|
||||
vp.postDelayed(mDismissTask, AUTO_DISMISS_TIME)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post(mLoopTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
EasyFloat.with(activity)
|
||||
.setLayout(R.layout.layout_float_load_complete)
|
||||
.setTag(LOAD_COMPLETE_WINDOW)
|
||||
.setDragEnable(false)
|
||||
.setMatchParent(widthMatch = true, heightMatch = false)
|
||||
.setGravity(Gravity.BOTTOM, 0, (-70F).dip2px())
|
||||
.setAnimator(LoadCompleteFloatAnimator())
|
||||
.registerCallback {
|
||||
createResult { _, _, view ->
|
||||
view?.findViewById<ConstraintLayout>(R.id.container)?.let {
|
||||
initFloatingView(it, activity, gameEntityList)
|
||||
}
|
||||
}
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun initFloatingView(view: ConstraintLayout, activity: Activity, entityList: List<GameEntity>) {
|
||||
val mBinding = LayoutFloatLoadCompleteBinding.bind(view)
|
||||
val mAdapter = GameLoadCompleteAdapter(activity, entityList)
|
||||
val mLoopTask = object : Runnable {
|
||||
private val reference: WeakReference<ViewPager2> = WeakReference(mBinding.viewPager)
|
||||
|
||||
override fun run() {
|
||||
val vp: ViewPager2? = reference.get()
|
||||
if (vp != null) {
|
||||
val count = mBinding.viewPager.adapter?.itemCount ?: 0
|
||||
if (count == 0) return
|
||||
val next = vp.currentItem + 1
|
||||
if (next < count) {
|
||||
vp.setCurrentItem(next, LOOP_DURATION)
|
||||
vp.postDelayed(this, LOOP_TIME)
|
||||
} else {
|
||||
vp.postDelayed(mDismissTask, AUTO_DISMISS_TIME)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mBinding.viewPager.run {
|
||||
adapter = mAdapter
|
||||
isUserInputEnabled = false
|
||||
orientation = ViewPager2.ORIENTATION_VERTICAL
|
||||
offscreenPageLimit = entityList.size
|
||||
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
|
||||
val layoutManager = (get(0) as RecyclerView).layoutManager as LinearLayoutManager
|
||||
layoutManager.findViewByPosition(position)?.alpha = 1 - positionOffset
|
||||
layoutManager.findViewByPosition(position + 1)?.alpha = positionOffset
|
||||
}
|
||||
})
|
||||
if (entityList.size > 1) {
|
||||
postDelayed(mLoopTask, LOOP_TIME)
|
||||
} else {
|
||||
postDelayed(mDismissTask, AUTO_DISMISS_TIME)
|
||||
}
|
||||
}
|
||||
mBinding.closeIv.setOnClickListener {
|
||||
if (!ClickUtils.isFastDoubleClick(it.id)) {
|
||||
mBinding.viewPager.removeCallbacks(mLoopTask)
|
||||
mBinding.viewPager.removeCallbacks(mDismissTask)
|
||||
EasyFloat.dismiss(LOAD_COMPLETE_WINDOW)
|
||||
}
|
||||
}
|
||||
mBinding.launchTv.setOnClickListener {
|
||||
VHelper.launch(activity, mAdapter.gameEntityList[mBinding.viewPager.currentItem].getApk()[0].packageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LoadCompleteFloatAnimator : OnFloatAnimator {
|
||||
override fun enterAnim(
|
||||
view: View,
|
||||
params: WindowManager.LayoutParams,
|
||||
windowManager: WindowManager,
|
||||
sidePattern: SidePattern
|
||||
): Animator = getEnterAnimator(view)
|
||||
|
||||
override fun exitAnim(
|
||||
view: View,
|
||||
params: WindowManager.LayoutParams,
|
||||
windowManager: WindowManager,
|
||||
sidePattern: SidePattern
|
||||
): Animator = getExitAnimator(view)
|
||||
|
||||
private fun getEnterAnimator(view: View): Animator {
|
||||
val alphaAnimator = ObjectAnimator.ofFloat(view, "alpha", 0F, 1F).apply {
|
||||
duration = DURATION
|
||||
interpolator = AccelerateDecelerateInterpolator()
|
||||
}
|
||||
val scaleXAnimator = ObjectAnimator.ofFloat(view, "scaleX", 0.8F, 1F).apply {
|
||||
duration = DURATION
|
||||
interpolator = AccelerateDecelerateInterpolator()
|
||||
}
|
||||
val scaleYAnimator = ObjectAnimator.ofFloat(view, "scaleY", 0.8F, 1F).apply {
|
||||
duration = DURATION
|
||||
interpolator = AccelerateDecelerateInterpolator()
|
||||
}
|
||||
view.pivotX = view.width / 2F
|
||||
view.pivotY = view.height / 2F
|
||||
return AnimatorSet().apply { playTogether(alphaAnimator, scaleXAnimator, scaleYAnimator) }
|
||||
}
|
||||
|
||||
private fun getExitAnimator(view: View): Animator {
|
||||
val alphaAnimator = ObjectAnimator.ofFloat(view, "alpha", 1F, 0F).apply {
|
||||
duration = DURATION
|
||||
interpolator = AccelerateDecelerateInterpolator()
|
||||
}
|
||||
val scaleXAnimator = ObjectAnimator.ofFloat(view, "scaleX", 1F, 0.8F).apply {
|
||||
duration = DURATION
|
||||
interpolator = AccelerateDecelerateInterpolator()
|
||||
}
|
||||
val scaleYAnimator = ObjectAnimator.ofFloat(view, "scaleY", 1F, 0.8F).apply {
|
||||
duration = DURATION
|
||||
interpolator = AccelerateDecelerateInterpolator()
|
||||
}
|
||||
view.pivotX = view.width / 2F
|
||||
view.pivotY = view.height / 2F
|
||||
return AnimatorSet().apply {
|
||||
playTogether(alphaAnimator, scaleXAnimator, scaleYAnimator)
|
||||
doOnEnd {
|
||||
view.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DURATION = 200L
|
||||
}
|
||||
}
|
||||
|
||||
class GameLoadCompleteAdapter(context: Context, var gameEntityList: List<GameEntity> = emptyList()): BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
|
||||
|
||||
fun submitList(entityList: List<GameEntity>) {
|
||||
if (entityList.isNotEmpty()) {
|
||||
gameEntityList = arrayListOf<GameEntity>().apply {
|
||||
addAll(gameEntityList)
|
||||
addAll(entityList)
|
||||
}
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = GameLoadCompleteViewHolder(parent.toBinding())
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is GameLoadCompleteViewHolder) {
|
||||
val gameEntity = gameEntityList[position]
|
||||
holder.binding.gameIconIv.displayGameIcon(gameEntity)
|
||||
holder.binding.gameNameTv.text = gameEntity.name
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = gameEntityList.size
|
||||
|
||||
class GameLoadCompleteViewHolder(val binding: ItemFloatGameLoadCompleteBinding): RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
}
|
||||
|
||||
private fun ViewPager2.setCurrentItem(
|
||||
item: Int,
|
||||
duration: Long,
|
||||
interpolator: TimeInterpolator = AccelerateDecelerateInterpolator(),
|
||||
pagePxHeight: Int = height
|
||||
) {
|
||||
val pxToDrag: Int = pagePxHeight * (item - currentItem)
|
||||
val animator = ValueAnimator.ofInt(0, pxToDrag)
|
||||
var previousValue = 0
|
||||
animator.addUpdateListener { valueAnimator ->
|
||||
val currentValue = valueAnimator.animatedValue as Int
|
||||
val currentPxToDrag = (currentValue - previousValue).toFloat()
|
||||
fakeDragBy(-currentPxToDrag)
|
||||
previousValue = currentValue
|
||||
}
|
||||
animator.addListener(object : Animator.AnimatorListener {
|
||||
override fun onAnimationStart(animation: Animator?) { beginFakeDrag() }
|
||||
override fun onAnimationEnd(animation: Animator?) { endFakeDrag() }
|
||||
override fun onAnimationCancel(animation: Animator?) { }
|
||||
override fun onAnimationRepeat(animation: Animator?) { }
|
||||
})
|
||||
animator.interpolator = interpolator
|
||||
animator.duration = duration
|
||||
animator.start()
|
||||
}
|
||||
Reference in New Issue
Block a user