Android动画全篇系列(八)——揭露动画

一、揭露动画(CircularReveal)介绍

当您显示或隐藏一组界面元素时,揭露动画可为用户提供视觉连续性。让您能够为裁剪圆形添加动画以揭露或隐藏视图。此动画在 ViewAnimationUtils 类中提供,适用于 Android 5.0(API 级别 21)及更高版本。——亲爸爸谷歌

揭露动画的实现比较简单,只需要几行代码就可以完成。

所以我们直接先看效果图:
展示

二、介绍和简单实现

1、简单介绍

创建一个揭露动画需要用到系统提供的ViewAnimationUtils类,这个类是个final类,并且私有化了构造方法,对外仅仅提供一个方法createCircularReveal(),所以我们可以直接使用下方一行代码就可以创建揭露动画:

 val anim = ViewAnimationUtils.createCircularReveal(
 view,centerX,centerY,startRadius,endRad)
  • view 传入你想要实现揭露动画的View
  • centerX,centerY 这两个参数组成一个点,是揭露动画圆形的圆心点。
  • startRadius 表示圆形的起始半径
  • endRadius 表示圆形的结束半径,当到达结束半径的时候,即表示揭露动画结束,不管View有没有完整展示出来,View都会直接全部显示。
2、简单实现
    testView.post {	//1
        val width = testView.width
        val height = testView.height
        val viewHypotenuse = 
        Math.hypot(width.toDouble(), height.toDouble()) //2
        val anim = ViewAnimationUtils.createCircularReveal(
        testView,0,0,0f,viewHypotenuse.toFloat())
        anim.duration = 1000
        btn_start.setOnClickListener {
            anim.start()
        }
    }
  1. 为了获取view的宽高,我们在给其post一个代码域。
  2. 通过宽高,我们得到其斜边的值。
3、小小的优化

当我们用上面的代码实现了揭露动画后,总觉得哪里不对劲~
不对劲.png
在最开始的时候,当我们还没有点击按钮执行动画,View就已经显示了~,这时候你再来个揭露动画有嘛意思嘛?就像你媳妇自己把头盖掀了,你觉得不过瘾亲手将头盖盖了回去,然后再自己掀开 ~

所以我们做一些小小的调整:


	//1.手动将 View 变成 View.INVISIBLE 不可见的状态
	//或者在XML中设置
    testView.visibility = View.INVISIBLE
    testView.post {
        val width = testView.width
        val height = testView.height
        val viewHypotenuse = Math.hypot(width.toDouble(), height.toDouble())
        val anim = ViewAnimationUtils.createCircularReveal(testView,0,0,0f,
            viewHypotenuse.toFloat()
        )
        anim.duration = 1000
        btn_start.setOnClickListener {
        	//2.在动画执行之前,手动将 View 变成 View.VISIBLE 可见的状态
            testView.visibility = View.VISIBLE
            anim.start()
        }
    }

再来看看一看你亲自掀头盖骨的感觉:
掀起你滴头盖骨
在本例中,注意别设置成了 View.GONE ,否则你就获取不到宽高了~
如果你只是想随便看看效果,无论你传啥值都没关系。

4、简单的看看源码

我们找到ViewAnimationUtils类,是个很寒酸的家伙~
只有两个方法,一个是私有构造函数,另一个就是上面用到的createCircularReveal()

    public static Animator createCircularReveal(View view,int centerX,  int centerY, float startRadius, float endRadius) {
        return new RevealAnimator(view, centerX, centerY, startRadius, endRadius);
    }

这个方法也很寒酸~直接返回RevealAnimator,再看看返回值,是Animator,看到这里基本上就知道揭露动画是个什么原理了,搞半天原来你就是官方提供封装的属性动画啊!

另外这个RevealAnimator类被官方@hide了,无法查看,有兴趣的小伙伴自己去看看源码吧。

三、结合Activity

揭露动画还能够和Activity相结合,先看看效果图:
效果
实现的效果如图所示,根据手指点击的地方,展开圆显示跳转的Activity,当Activity返回的时候,又缩回去~

注意要点:是在被打开的Activity中实现揭露动画

1、获取手指点击的位置并打开Activity

因为动画是在第二个Activity中执行的,所以我们得先把圆心位置的参数 x 和 y 传过去。

我是在 Fragmnet 进行的操作,所以是拿到rootView来进行onTouch的监听,如果你是Activity中,可以重写其 onTouchEvent() 方法,来替换下面的 rootView!!.setOnTouchListener

   val gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
           override fun onDown(e: MotionEvent?): Boolean = true
           override fun onSingleTapUp(e: MotionEvent): Boolean {
               val x = e.rawX
               val y = e.rawY
               val intent = Intent(context,Anim2Activity::class.java)
               intent.putExtra("x",x)
               intent.putExtra("y",y)
               context!!.startActivity(intent)
               return true
           }
       })
       
	rootView!!.setOnTouchListener { v, event ->
    	return@setOnTouchListener gestureDetector.onTouchEvent(event)
	}
2、第二个Activity的代码
class Anim2Activity : AppCompatActivity() {

    //屏幕的 x 和 y ,以及屏幕斜边
    private var x = 0
    private var y = 0
    private var viewHypotenuse = 0.0f
    
    //根 View
    private lateinit var rootView:View

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_anim2)

        //初始化一些值
        x = intent.getFloatExtra("x",0f).toInt()
        y = intent.getFloatExtra("y",0f).toInt()
        val screenPoint = Point()
        windowManager.defaultDisplay.getSize(screenPoint)
        viewHypotenuse = Math.hypot(screenPoint.x.toDouble(), screenPoint.y.toDouble()).toFloat()
       
        rootView = findViewById<View>(R.id.rootView)
        //先将rootView 变为 不可见
        rootView.visibility = View.INVISIBLE
        
        rootView.post {
            val anim = createCircleAnimator(0f,viewHypotenuse)
            rootView.visibility = View.VISIBLE
            anim.start()
        }
    }

    /**
     * 创建揭露动画
     * @param startRadius 起始半径
     * @param endRadius 结束半径
     * @return 返回一个揭露动画
     */
    private fun createCircleAnimator(startRadius:Float,endRadius:Float): Animator {
        val anim = ViewAnimationUtils.createCircularReveal(rootView,x,y,startRadius,endRadius)
        anim.duration = 1000
        return anim
    }

	/**
	 * 重写 finish() 
	 */
    override fun finish() {
        val anim = createCircleAnimator(viewHypotenuse,0f)
        anim.start()
        anim.addListener(onEnd = {
        	//监听动画结束的时候,再调用 finish 以关闭 Activity
            rootView.visibility = View.INVISIBLE
            super.finish()
        })
    }
}
3、优化

当你直接运行的时候,你会发现,和想象的不一样……

为什么你的Activity会有跳转动画?为什么你的Activity背景是白的?

所以我们还要对这个Activity进行一些设置,把他的跳转动画变消失!把他的背景变成透明!

所以我们需要自定义一个style

    <style name="AppTheme.NoAnimation" parent="AppTheme">
        <item name="android:windowAnimationStyle">@null</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
    </style>

然后设置Activity的theme:

<activity android:name=".module.anim.Anim2Activity"
          android:theme="@style/AppTheme.NoAnimation"></activity>
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值