浮动操作按钮动画
Floating Action Button Animation
当 fab 出现时,它在动画中使用比例动画,当它隐藏时,它使用横向扩展动画。
所以,这是一个缩放动画。
如何制作这个动画?
按钮只是通过 OvershootInterpolator 从 0 缩放到 1。它应该是这样的:
ScaleAnimation anim = new ScaleAnimation(0,1,0,1);
anim.setFillBefore(true);
anim.setFillAfter(true);
anim.setFillEnabled(true);
anim.setDuration(300);
anim.setInterpolator(new OvershootInterpolator());
fab.startAnimation(anim);
http://developer.android.com/reference/android/view/animation/OvershootInterpolator.html
根据@Zielony 的回答,我把它放在了我想要的地方。
下面是正确应用效果的代码。
scale_fab_in.xml
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1"
android:interpolator="@android:interpolator/overshoot"/>
scale_fab_out.xml
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="400"
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0"
android:toYScale="0"
android:interpolator="@android:interpolator/overshoot"/>
编辑 2/16/2016 - 另一种方法:
将下面的代码放入您的 FAB 代码或任何其他视图中。
//global
private static final int FAB_ANIM_DURATION = 200;
public void hide() {
// Only use scale animation if FAB is visible
if (getVisibility() == View.VISIBLE) {
// Pivots indicate where the animation begins from
float pivotX = getPivotX() + getTranslationX();
float pivotY = getPivotY() + getTranslationY();
// Animate FAB shrinking
ScaleAnimation anim = new ScaleAnimation(1, 0, 1, 0, pivotX, pivotY);
anim.setDuration(FAB_ANIM_DURATION);
anim.setInterpolator(getInterpolator());
startAnimation(anim);
}
setVisibility(View.INVISIBLE);
}
public void show() {
show(0, 0);
}
public void show(float translationX, float translationY) {
// Set FAB's translation
setTranslation(translationX, translationY);
// Only use scale animation if FAB is hidden
if (getVisibility() != View.VISIBLE) {
// Pivots indicate where the animation begins from
float pivotX = getPivotX() + translationX;
float pivotY = getPivotY() + translationY;
ScaleAnimation anim;
// If pivots are 0, that means the FAB hasn't been drawn yet so just use the
// center of the FAB
if (pivotX == 0 || pivotY == 0) {
anim = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
} else {
anim = new ScaleAnimation(0, 1, 0, 1, pivotX, pivotY);
}
// Animate FAB expanding
anim.setDuration(FAB_ANIM_DURATION);
anim.setInterpolator(getInterpolator());
startAnimation(anim);
}
setVisibility(View.VISIBLE);
}
private void setTranslation(float translationX, float translationY) {
if (Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) {
animate().setInterpolator(getInterpolator()).setDuration(FAB_ANIM_DURATION)
.translationX(translationX).translationY(translationY);
}
}
private Interpolator getInterpolator() {
return AnimationUtils.loadInterpolator(getContext(), R.interpolator.fab_interpolator);
}
<item name="fab_interpolator" type="interpolator">@android:interpolator/decelerate_cubic</item>
对我来说,设置 startOffset
值后,这种比例动画效果更好。这对我很有用:
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="400"
android:fillBefore="true"
android:fillAfter="true"
android:fillEnabled="true"
android:startOffset="500"
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1"
android:interpolator="@android:interpolator/overshoot"/>
您可以使用此方法以动画方式放大任何视图。如果你反转 0 和 1 你会得到按比例缩小的动画
public static void scale(View view, long delay) {
view.setScaleX(0);
view.setScaleY(0);
view.animate()
.scaleX(1)
.scaleY(1)
.setDuration(500)
.setStartDelay(delay)
.setInterpolator(new OvershootInterpolator())
.start();
}
使用下面的代码可以达到同样的效果。
ScaleAnimation anim = new ScaleAnimation(0, 1, 0, 1, 50, 50);
anim.setFillBefore(true);
anim.setFillAfter(true);
anim.setFillEnabled(true);
anim.setDuration(400);
anim.setInterpolator(new OvershootInterpolator());
imageView.startAnimation(anim);
假设要求为 FloatingActionButton 调整大小设置动画,我首先将 Animation 子类化以通常处理 View(改编自 this answer 的 Kotlin)...
open class ResizeAnimation(
private val view: View,
private val toHeight: Float,
private val fromHeight: Float,
private val toWidth: Float,
private val fromWidth: Float,
duration: Long
) : Animation() {
init {
this.duration = duration
}
override fun applyTransformation(
interpolatedTime: Float,
t: Transformation?
) {
val height = (toHeight - fromHeight) * interpolatedTime + fromHeight
val width = (toWidth - fromWidth) * interpolatedTime + fromWidth
val layoutParams = view.layoutParams
layoutParams.height = height.toInt()
layoutParams.width = width.toInt()
view.requestLayout()
}
}
...为了具体处理 FloatingActionButton,我对 _ResizeAnimation_ 进行了子类化(主要是为了更新 customSize 属性浮动操作按钮)...
class FabResizeAnimation(
private val view: FloatingActionButton,
private val toSize: Float,
private val fromSize: Float,
duration: Long
) : ResizeAnimation(
view,
toSize,
fromSize,
toSize,
fromSize,
duration
) {
override fun applyTransformation(
interpolatedTime: Float,
t: Transformation?
) {
val fabSize = ((toSize - fromSize) * interpolatedTime + fromSize).toInt()
view.customSize = fabSize
super.applyTransformation(interpolatedTime, t)
}
}
...用法...
val animation = FabResizeAnimation(fab, 800.0f, 100.0f, 2000)
fab.startAnimation(animation)
当 fab 出现时,它在动画中使用比例动画,当它隐藏时,它使用横向扩展动画。
所以,这是一个缩放动画。
如何制作这个动画?
按钮只是通过 OvershootInterpolator 从 0 缩放到 1。它应该是这样的:
ScaleAnimation anim = new ScaleAnimation(0,1,0,1);
anim.setFillBefore(true);
anim.setFillAfter(true);
anim.setFillEnabled(true);
anim.setDuration(300);
anim.setInterpolator(new OvershootInterpolator());
fab.startAnimation(anim);
http://developer.android.com/reference/android/view/animation/OvershootInterpolator.html
根据@Zielony 的回答,我把它放在了我想要的地方。
下面是正确应用效果的代码。
scale_fab_in.xml
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1"
android:interpolator="@android:interpolator/overshoot"/>
scale_fab_out.xml
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="400"
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0"
android:toYScale="0"
android:interpolator="@android:interpolator/overshoot"/>
编辑 2/16/2016 - 另一种方法:
将下面的代码放入您的 FAB 代码或任何其他视图中。
//global
private static final int FAB_ANIM_DURATION = 200;
public void hide() {
// Only use scale animation if FAB is visible
if (getVisibility() == View.VISIBLE) {
// Pivots indicate where the animation begins from
float pivotX = getPivotX() + getTranslationX();
float pivotY = getPivotY() + getTranslationY();
// Animate FAB shrinking
ScaleAnimation anim = new ScaleAnimation(1, 0, 1, 0, pivotX, pivotY);
anim.setDuration(FAB_ANIM_DURATION);
anim.setInterpolator(getInterpolator());
startAnimation(anim);
}
setVisibility(View.INVISIBLE);
}
public void show() {
show(0, 0);
}
public void show(float translationX, float translationY) {
// Set FAB's translation
setTranslation(translationX, translationY);
// Only use scale animation if FAB is hidden
if (getVisibility() != View.VISIBLE) {
// Pivots indicate where the animation begins from
float pivotX = getPivotX() + translationX;
float pivotY = getPivotY() + translationY;
ScaleAnimation anim;
// If pivots are 0, that means the FAB hasn't been drawn yet so just use the
// center of the FAB
if (pivotX == 0 || pivotY == 0) {
anim = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
} else {
anim = new ScaleAnimation(0, 1, 0, 1, pivotX, pivotY);
}
// Animate FAB expanding
anim.setDuration(FAB_ANIM_DURATION);
anim.setInterpolator(getInterpolator());
startAnimation(anim);
}
setVisibility(View.VISIBLE);
}
private void setTranslation(float translationX, float translationY) {
if (Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) {
animate().setInterpolator(getInterpolator()).setDuration(FAB_ANIM_DURATION)
.translationX(translationX).translationY(translationY);
}
}
private Interpolator getInterpolator() {
return AnimationUtils.loadInterpolator(getContext(), R.interpolator.fab_interpolator);
}
<item name="fab_interpolator" type="interpolator">@android:interpolator/decelerate_cubic</item>
对我来说,设置 startOffset
值后,这种比例动画效果更好。这对我很有用:
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="400"
android:fillBefore="true"
android:fillAfter="true"
android:fillEnabled="true"
android:startOffset="500"
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1"
android:interpolator="@android:interpolator/overshoot"/>
您可以使用此方法以动画方式放大任何视图。如果你反转 0 和 1 你会得到按比例缩小的动画
public static void scale(View view, long delay) {
view.setScaleX(0);
view.setScaleY(0);
view.animate()
.scaleX(1)
.scaleY(1)
.setDuration(500)
.setStartDelay(delay)
.setInterpolator(new OvershootInterpolator())
.start();
}
使用下面的代码可以达到同样的效果。
ScaleAnimation anim = new ScaleAnimation(0, 1, 0, 1, 50, 50);
anim.setFillBefore(true);
anim.setFillAfter(true);
anim.setFillEnabled(true);
anim.setDuration(400);
anim.setInterpolator(new OvershootInterpolator());
imageView.startAnimation(anim);
假设要求为 FloatingActionButton 调整大小设置动画,我首先将 Animation 子类化以通常处理 View(改编自 this answer 的 Kotlin)...
open class ResizeAnimation(
private val view: View,
private val toHeight: Float,
private val fromHeight: Float,
private val toWidth: Float,
private val fromWidth: Float,
duration: Long
) : Animation() {
init {
this.duration = duration
}
override fun applyTransformation(
interpolatedTime: Float,
t: Transformation?
) {
val height = (toHeight - fromHeight) * interpolatedTime + fromHeight
val width = (toWidth - fromWidth) * interpolatedTime + fromWidth
val layoutParams = view.layoutParams
layoutParams.height = height.toInt()
layoutParams.width = width.toInt()
view.requestLayout()
}
}
...为了具体处理 FloatingActionButton,我对 _ResizeAnimation_ 进行了子类化(主要是为了更新 customSize 属性浮动操作按钮)...
class FabResizeAnimation(
private val view: FloatingActionButton,
private val toSize: Float,
private val fromSize: Float,
duration: Long
) : ResizeAnimation(
view,
toSize,
fromSize,
toSize,
fromSize,
duration
) {
override fun applyTransformation(
interpolatedTime: Float,
t: Transformation?
) {
val fabSize = ((toSize - fromSize) * interpolatedTime + fromSize).toInt()
view.customSize = fabSize
super.applyTransformation(interpolatedTime, t)
}
}
...用法...
val animation = FabResizeAnimation(fab, 800.0f, 100.0f, 2000)
fab.startAnimation(animation)