文章目录
一、揭露动画(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()
}
}
- 为了获取view的宽高,我们在给其post一个代码域。
- 通过宽高,我们得到其斜边的值。
3、小小的优化
当我们用上面的代码实现了揭露动画后,总觉得哪里不对劲~
在最开始的时候,当我们还没有点击按钮执行动画,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>