Android:在标签更改时为 FAB 设置动画
Android: Animate FAB on tab change
我有一个 Android 带有选项卡 activity 的应用程序。现在,如果我切换选项卡,我想更改浮动操作按钮的图标。它应该类似于 Material 设计指南中的内容:
我没有使用支持库中的 FAB,而是使用这个,因为我还需要 FAB 菜单:
我查看了源代码,发现它基本上使用一个图像按钮作为 FAB 的形状,另一个图像按钮作为图标。通过使用缩放动画,我已经设法创建了按钮本身的收缩和缩放动画:
ScaleAnimation shrink = new ScaleAnimation(1f, 0.2f, 1f, 0.2f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
shrink.setDuration(150);
shrink.setInterpolator(new DecelerateInterpolator());
shrink.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
ScaleAnimation expand = new ScaleAnimation(0.2f, 1f, 0.2f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
expand.setDuration(150);
expand.setInterpolator(new AccelerateInterpolator());
animBtn.startAnimation(expand);
}
});
animBtn.startAnimation(shrink);
现在我想知道如何像指南中那样创建一个 'uncover'(我现在不知道如何称呼它)动画。我不想为每一帧创建多个图标图像。这是我想到的:
- 使用从中心开始的动画将图标的颜色从透明更改为白色
- 在图标上画一个圆弧并用动画减小圆弧宽度
- 使用比例动画
我找不到第一个的解决方案。第二种可能是可行的,但我认为必须有更好的解决方案。第三个不够。
有人可以帮助我吗?
编辑: 我找到了第一种方法。请参阅下面我的回答。
编辑 2: 我改进了我的方法。现在它看起来与指南中的动画非常相似。请在下面查看我编辑过的答案。你怎么看?
好的,我已经很接近了。慢动作看完视频,我觉得除了缩放还有旋转。感谢 cYrixmorten,我现在得到了这个:
ScaleAnimation btnAnim = new ScaleAnimation (1f, 0.1f, 1f, 0.1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
btnAnim.setDuration(150);
btnAnim.setInterpolator(new DecelerateInterpolator());
btnAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
ScaleAnimation expand = new ScaleAnimation(0.1f, 1f, 0.1f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
expand.setDuration(150);
expand.setInterpolator(new AccelerateInterpolator());
animBtn.startAnimation(expand);
}
});
ScaleAnimation iconAnim = new ScaleAnimation(1f, 0.1f, 1f, 0.1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
iconAnim.setDuration(150);
iconAnim.setInterpolator(new DecelerateInterpolator());
iconAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
animIcon.setImageResource(fabIconIntArray[position]);
Animation expand = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
animIcon.setScaleX(0.1f + 0.9f * interpolatedTime);
animIcon.setScaleY(0.1f + 0.9f * interpolatedTime);
animIcon.setRotation(-20f + interpolatedTime * 20);
animIcon.setAlpha(0.5f + 0.5f * interpolatedTime);
}
};
expand.setDuration(150);
expand.setStartOffset(100);
expand.setInterpolator(new AccelerateInterpolator());
animIcon.startAnimation(expand);
}
});
animBtn.startAnimation(btnAnim);
animIcon.startAnimation(iconAnim);
看起来像this。
我尝试了很多变体,但我认为它在指南中看起来更流畅。有人对我如何改进它有什么建议吗?
编辑: 在非常彻底地分析了指南中的视频后,我能够改进我的动画:
ScaleAnimation btnAnim = new ScaleAnimation(1f, 0f, 1f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
btnAnim.setDuration(250);
btnAnim.setInterpolator(new AccelerateInterpolator());
btnAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
ScaleAnimation expand = new ScaleAnimation(0f, 1f, 0f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
expand.setDuration(195);
expand.setInterpolator(new DecelerateInterpolator());
animBtn.startAnimation(expand);
}
});
ScaleAnimation iconAnim = new ScaleAnimation(1f, 0f, 1f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
iconAnim.setDuration(250);
iconAnim.setInterpolator(new AccelerateInterpolator());
iconAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
animIcon.setImageResource(fabIconIntArray[position]);
Animation expand = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
animIcon.setScaleX(interpolatedTime);
animIcon.setScaleY(interpolatedTime);
animIcon.setRotation(-20f + interpolatedTime * 20);
}
};
expand.setStartOffset(135);
expand.setDuration(215);
expand.setInterpolator(new DecelerateInterpolator());
animIcon.startAnimation(expand);
}
});
animBtn.startAnimation(btnAnim);
animIcon.startAnimation(iconAnim);
现在看起来像 this。你怎么看?
我有一个 Android 带有选项卡 activity 的应用程序。现在,如果我切换选项卡,我想更改浮动操作按钮的图标。它应该类似于 Material 设计指南中的内容:
我没有使用支持库中的 FAB,而是使用这个,因为我还需要 FAB 菜单:
我查看了源代码,发现它基本上使用一个图像按钮作为 FAB 的形状,另一个图像按钮作为图标。通过使用缩放动画,我已经设法创建了按钮本身的收缩和缩放动画:
ScaleAnimation shrink = new ScaleAnimation(1f, 0.2f, 1f, 0.2f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
shrink.setDuration(150);
shrink.setInterpolator(new DecelerateInterpolator());
shrink.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
ScaleAnimation expand = new ScaleAnimation(0.2f, 1f, 0.2f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
expand.setDuration(150);
expand.setInterpolator(new AccelerateInterpolator());
animBtn.startAnimation(expand);
}
});
animBtn.startAnimation(shrink);
现在我想知道如何像指南中那样创建一个 'uncover'(我现在不知道如何称呼它)动画。我不想为每一帧创建多个图标图像。这是我想到的:
- 使用从中心开始的动画将图标的颜色从透明更改为白色
- 在图标上画一个圆弧并用动画减小圆弧宽度
- 使用比例动画
我找不到第一个的解决方案。第二种可能是可行的,但我认为必须有更好的解决方案。第三个不够。
有人可以帮助我吗?
编辑: 我找到了第一种方法。请参阅下面我的回答。
编辑 2: 我改进了我的方法。现在它看起来与指南中的动画非常相似。请在下面查看我编辑过的答案。你怎么看?
好的,我已经很接近了。慢动作看完视频,我觉得除了缩放还有旋转。感谢 cYrixmorten,我现在得到了这个:
ScaleAnimation btnAnim = new ScaleAnimation (1f, 0.1f, 1f, 0.1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
btnAnim.setDuration(150);
btnAnim.setInterpolator(new DecelerateInterpolator());
btnAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
ScaleAnimation expand = new ScaleAnimation(0.1f, 1f, 0.1f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
expand.setDuration(150);
expand.setInterpolator(new AccelerateInterpolator());
animBtn.startAnimation(expand);
}
});
ScaleAnimation iconAnim = new ScaleAnimation(1f, 0.1f, 1f, 0.1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
iconAnim.setDuration(150);
iconAnim.setInterpolator(new DecelerateInterpolator());
iconAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
animIcon.setImageResource(fabIconIntArray[position]);
Animation expand = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
animIcon.setScaleX(0.1f + 0.9f * interpolatedTime);
animIcon.setScaleY(0.1f + 0.9f * interpolatedTime);
animIcon.setRotation(-20f + interpolatedTime * 20);
animIcon.setAlpha(0.5f + 0.5f * interpolatedTime);
}
};
expand.setDuration(150);
expand.setStartOffset(100);
expand.setInterpolator(new AccelerateInterpolator());
animIcon.startAnimation(expand);
}
});
animBtn.startAnimation(btnAnim);
animIcon.startAnimation(iconAnim);
看起来像this。
我尝试了很多变体,但我认为它在指南中看起来更流畅。有人对我如何改进它有什么建议吗?
编辑: 在非常彻底地分析了指南中的视频后,我能够改进我的动画:
ScaleAnimation btnAnim = new ScaleAnimation(1f, 0f, 1f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
btnAnim.setDuration(250);
btnAnim.setInterpolator(new AccelerateInterpolator());
btnAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
ScaleAnimation expand = new ScaleAnimation(0f, 1f, 0f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
expand.setDuration(195);
expand.setInterpolator(new DecelerateInterpolator());
animBtn.startAnimation(expand);
}
});
ScaleAnimation iconAnim = new ScaleAnimation(1f, 0f, 1f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
iconAnim.setDuration(250);
iconAnim.setInterpolator(new AccelerateInterpolator());
iconAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
animIcon.setImageResource(fabIconIntArray[position]);
Animation expand = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
animIcon.setScaleX(interpolatedTime);
animIcon.setScaleY(interpolatedTime);
animIcon.setRotation(-20f + interpolatedTime * 20);
}
};
expand.setStartOffset(135);
expand.setDuration(215);
expand.setInterpolator(new DecelerateInterpolator());
animIcon.startAnimation(expand);
}
});
animBtn.startAnimation(btnAnim);
animIcon.startAnimation(iconAnim);
现在看起来像 this。你怎么看?