写一个Dialog动画,动画实现弹出和隐藏都是从某一控件位置出现

1,需求

        这里是需要写一个dialog,添加一个动画。要求:弹出时从外部控件处放大显示,几秒后缩小隐藏到外部控件出。

2,实现

这里只需要使用一个组合动画就行实现想要的效果,效果如下(控件在屏幕右下方):

        

1,创建一个dialog

        代码中添加了,显示及隐藏动画

class TestDialog(context: Context) : Dialog(context, R.style.Dialog) {
    private var showAnimSet: AnimatorSet? = null
    private var dismissAnimSet: AnimatorSet? = null
    /**
     * 动画时间
     */
    private val DEFAULT_DURATION: Long = 800

    private var transX: Float = 0f
    private var transY: Float = 0f

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.dialog_test)
    }
    /**
     * show之后,先隐藏布局,通过动画展来展示布局
     */
    override fun show() {
        try {
            super.show()
            val contentView = findViewById<View>(R.id.dialog_test)
            contentView?.visibility = View.INVISIBLE
            showAnim()
        } catch (e: Throwable) {
            e.printStackTrace()
        }
    }

    /**
     * 延时隐藏
     */
    fun dismissView(){
        Handler().postDelayed({dismissAnim()},3000)
    }

    override fun dismiss() {
        try {
            super.dismiss()
        } catch (e: Throwable) {
            e.printStackTrace()
        }
    }

    /**
     * 显示动画
     */
    private fun showAnim() {
        val contentView = findViewById<View>(R.id.dialog_test) ?: return
        if (showAnimSet == null) {
            showAnimSet = AnimatorSet()
            val transXAnim = ObjectAnimator.ofFloat(contentView, "translationX", transX, 0f)
            val transYAnim = ObjectAnimator.ofFloat(contentView, "translationY", transY, 0f)
            val scaleXAnim = ObjectAnimator.ofFloat(contentView, "scaleX", 0f, 1f)
            val scaleYAnim = ObjectAnimator.ofFloat(contentView, "scaleY", 0f, 1f)
            showAnimSet?.playTogether(transXAnim, transYAnim, scaleXAnim, scaleYAnim)
            showAnimSet?.addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationStart(animation: Animator) {
                    super.onAnimationStart(animation)
                    contentView.visibility = View.VISIBLE
                    dismissView()
                }
            })
            showAnimSet?.duration = DEFAULT_DURATION
        }
        if (showAnimSet?.isRunning == true) {
            return
        }
        showAnimSet?.start()
    }

    /**
     * 隐藏动画
     */
    fun dismissAnim() {
        val contentView = findViewById<View>(R.id.dialog_test) ?: return
        if (dismissAnimSet == null) {
            dismissAnimSet = AnimatorSet()
            val transXAnim = ObjectAnimator.ofFloat(contentView, "translationX", 0f, transX)
            val transYAnim = ObjectAnimator.ofFloat(contentView, "translationY", 0f, transY)
            val scaleXAnim = ObjectAnimator.ofFloat(contentView, "scaleX", 1f, 0f)
            val scaleYAnim = ObjectAnimator.ofFloat(contentView, "scaleY", 1f, 0f)
            dismissAnimSet?.playTogether(transXAnim, transYAnim, scaleXAnim, scaleYAnim)
            dismissAnimSet?.addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator) {
                    super.onAnimationEnd(animation)
                    dismiss()
                }
            })
            dismissAnimSet?.duration = DEFAULT_DURATION
        }
        if (dismissAnimSet?.isRunning == true) {
            return
        }
        dismissAnimSet?.start()
    }

    /**
     * show之前调用
     */
    fun setAnchorInfo(view:View) {
        val location = IntArray(2)
        view.getLocationOnScreen(location)
        val x = location[0]
        val y = location[1]
        // 获取的值为px,需要转换单位
        transX =  (x + view.width).pxToDp(context).toFloat()
        transY = y.pxToDp(context).toFloat()
    }
}

2,使用setAnchorInfo传入外部控件

此处使用时注意setAnchorInfo方法需要在show()之前调用,这里请确保传入view的宽高位置等属性已经可以获取(即布局绘制的onLayout()方法之后)

使用实例:

        dialog = TestDialog(this@MainActivity)
        findViewById<Button>(R.id.test_button).let {
            it.setOnClickListener {
                dialog?.show()
            }
        }
        findViewById<Button>(R.id.test_button).post {
            dialog?.setAnchorInfo(findViewById<Button>(R.id.test_button))
        }

3,结言

这里只是粗略的实现了动画效果,弹出的锚点位置需根据需求自行调节,修改setAnchorInfo()方法中的计算方法即可

  • 22
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值