Android - 动画边距/一次更改多个视图的位置
Android - Animate margin / change position of multiple views at once
我有一个 RelativeLayout 并排有 4 个 Button。在某些情况下,我希望通过动画更改所有四个按钮的位置/更改边距。
我目前正在使用以下代码
final RelativeLayout.MarginLayoutParams params1 = (RelativeLayout.MarginLayoutParams) button1.getLayoutParams();
final RelativeLayout.MarginLayoutParams params2 = (RelativeLayout.MarginLayoutParams) button2.getLayoutParams();
final RelativeLayout.MarginLayoutParams params3 = (RelativeLayout.MarginLayoutParams) button3.getLayoutParams();
final RelativeLayout.MarginLayoutParams params4 = (RelativeLayout.MarginLayoutParams) button4.getLayoutParams();
final RelativeLayout.MarginLayoutParams params5 = (RelativeLayout.MarginLayoutParams) button5.getLayoutParams();
ValueAnimator animator1 = ValueAnimator.ofInt(params1.rightMargin, (deviceWidth - availableWithForTabs + spaceForTabs));
ValueAnimator animator2 = ValueAnimator.ofInt(params2.rightMargin, dpToPx(78));
ValueAnimator animator3 = ValueAnimator.ofInt(params3.rightMargin, dpToPx(52));
ValueAnimator animator4 = ValueAnimator.ofInt(params4.rightMargin, dpToPx(26));
ValueAnimator animator5 = ValueAnimator.ofInt(params5.rightMargin, dpToPx(0));
animator5.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
params5.rightMargin = (Integer) valueAnimator.getAnimatedValue();
}
});
animator5.setDuration(150);
animator5.start();
animator4.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
params4.rightMargin = (Integer) valueAnimator.getAnimatedValue();
}
);
animator4.setDuration(150);
animator4.start();
animator3.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
params3.rightMargin = (Integer) valueAnimator.getAnimatedValue();
}
});
animator3.setDuration(150);
animator3.start();
animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
params2.rightMargin = (Integer) valueAnimator.getAnimatedValue();
}
});
animator2.setDuration(150);
animator2.start();
animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
params1.rightMargin = (Integer) valueAnimator.getAnimatedValue();
button1.requestLayout();
}
});
animator1.setDuration(150);
animator1.start();
我觉得上面的代码太多了,无法为 5 个按钮设置边距变化动画。任何人都可以告诉我一种更好的方法吗?或者我还有什么其他选择?我必须支持 sdk 16 +
您为什么不只为包含 4 个按钮的整个相关布局设置动画。
另外我建议使用View.animate方法
public ViewPropertyAnimator animate ()
Added in API level 12
This method returns a ViewPropertyAnimator object, which can be used to animate specific properties on this View.
Returns
ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
您可能想重新考虑您的设计,使用 ViewPropertyAnimator 可以为您节省很多代码行并且非常 readable/maintainable。
使用 ViewPropertyAnimator 非常简单:
Button button1 = (Button) findViewById(R.id.button1);
button1.animate()
.translationX(toX)
.translationY(toY)
.setDuration(milliseconds); // add more if you
// like (alpha, startDelay)
// check the docs for available methods
动画总是从视图的当前位置开始。
为了更简洁的代码,你为什么不尝试这样的事情:
编写你自己的动画方法,它接受一个视图(在你的例子中是一个按钮),以及你需要的所有值作为参数(在 x 和 y 轴上移动视图的最小实现):
private void animateView(View view, float toX, float toY, int duration) {
view.animate()
.translationX(toX)
.translationY(toY)
.setDuration(duration);
}
然后您可以简单地在您的按钮上调用此方法来为它们单独设置动画 f.e。 :
animateView(button1, 5.0f, 2.5f, 150);
animateView(button2, 2.5f, 1.0f, 150);
当然5.0f,2.5f等只是虚构的数字,你必须自己填写你想移动视图的位置。
额外建议:使用插值器让你的动画更像 f 总是很好的。 e. :
view.animate()
.translationX(...)
.translationY(...)
.setInterpolator(new AccelerateDecelerateInterpolator())
.setDuration(...);
如果这不够彻底或有任何不清楚的地方,请告诉我。
更新:
如果你想设置一个监听器,你可以在你的 class 中实现 Animator.AnimatorListener 接口,如下所示:
public class yourClass extends AppCompatActivity implements Animator.AnimatorListener {...
然后你被迫执行以下方法:
@Override
public void onAnimationEnd(Animator animation) {
// here you can call stuff that should happen when the animation ends,
// f.e. start the next animation
// the method names explain themselves
}
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
然后你所要做的就是在你的 animateView 方法中添加另一行:
view.animate()
...
...
.setListener(this);
或者您可以在匿名内部 class 中这样做:
view.animate()
...
...
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
}
// same methods as above ...
...
)};
我有一个 RelativeLayout 并排有 4 个 Button。在某些情况下,我希望通过动画更改所有四个按钮的位置/更改边距。
我目前正在使用以下代码
final RelativeLayout.MarginLayoutParams params1 = (RelativeLayout.MarginLayoutParams) button1.getLayoutParams();
final RelativeLayout.MarginLayoutParams params2 = (RelativeLayout.MarginLayoutParams) button2.getLayoutParams();
final RelativeLayout.MarginLayoutParams params3 = (RelativeLayout.MarginLayoutParams) button3.getLayoutParams();
final RelativeLayout.MarginLayoutParams params4 = (RelativeLayout.MarginLayoutParams) button4.getLayoutParams();
final RelativeLayout.MarginLayoutParams params5 = (RelativeLayout.MarginLayoutParams) button5.getLayoutParams();
ValueAnimator animator1 = ValueAnimator.ofInt(params1.rightMargin, (deviceWidth - availableWithForTabs + spaceForTabs));
ValueAnimator animator2 = ValueAnimator.ofInt(params2.rightMargin, dpToPx(78));
ValueAnimator animator3 = ValueAnimator.ofInt(params3.rightMargin, dpToPx(52));
ValueAnimator animator4 = ValueAnimator.ofInt(params4.rightMargin, dpToPx(26));
ValueAnimator animator5 = ValueAnimator.ofInt(params5.rightMargin, dpToPx(0));
animator5.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
params5.rightMargin = (Integer) valueAnimator.getAnimatedValue();
}
});
animator5.setDuration(150);
animator5.start();
animator4.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
params4.rightMargin = (Integer) valueAnimator.getAnimatedValue();
}
);
animator4.setDuration(150);
animator4.start();
animator3.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
params3.rightMargin = (Integer) valueAnimator.getAnimatedValue();
}
});
animator3.setDuration(150);
animator3.start();
animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
params2.rightMargin = (Integer) valueAnimator.getAnimatedValue();
}
});
animator2.setDuration(150);
animator2.start();
animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
params1.rightMargin = (Integer) valueAnimator.getAnimatedValue();
button1.requestLayout();
}
});
animator1.setDuration(150);
animator1.start();
我觉得上面的代码太多了,无法为 5 个按钮设置边距变化动画。任何人都可以告诉我一种更好的方法吗?或者我还有什么其他选择?我必须支持 sdk 16 +
您为什么不只为包含 4 个按钮的整个相关布局设置动画。
另外我建议使用View.animate方法
public ViewPropertyAnimator animate ()
Added in API level 12 This method returns a ViewPropertyAnimator object, which can be used to animate specific properties on this View.
Returns ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
您可能想重新考虑您的设计,使用 ViewPropertyAnimator 可以为您节省很多代码行并且非常 readable/maintainable。
使用 ViewPropertyAnimator 非常简单:
Button button1 = (Button) findViewById(R.id.button1);
button1.animate()
.translationX(toX)
.translationY(toY)
.setDuration(milliseconds); // add more if you
// like (alpha, startDelay)
// check the docs for available methods
动画总是从视图的当前位置开始。
为了更简洁的代码,你为什么不尝试这样的事情:
编写你自己的动画方法,它接受一个视图(在你的例子中是一个按钮),以及你需要的所有值作为参数(在 x 和 y 轴上移动视图的最小实现):
private void animateView(View view, float toX, float toY, int duration) {
view.animate()
.translationX(toX)
.translationY(toY)
.setDuration(duration);
}
然后您可以简单地在您的按钮上调用此方法来为它们单独设置动画 f.e。 :
animateView(button1, 5.0f, 2.5f, 150);
animateView(button2, 2.5f, 1.0f, 150);
当然5.0f,2.5f等只是虚构的数字,你必须自己填写你想移动视图的位置。
额外建议:使用插值器让你的动画更像 f 总是很好的。 e. :
view.animate()
.translationX(...)
.translationY(...)
.setInterpolator(new AccelerateDecelerateInterpolator())
.setDuration(...);
如果这不够彻底或有任何不清楚的地方,请告诉我。
更新: 如果你想设置一个监听器,你可以在你的 class 中实现 Animator.AnimatorListener 接口,如下所示:
public class yourClass extends AppCompatActivity implements Animator.AnimatorListener {...
然后你被迫执行以下方法:
@Override
public void onAnimationEnd(Animator animation) {
// here you can call stuff that should happen when the animation ends,
// f.e. start the next animation
// the method names explain themselves
}
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
然后你所要做的就是在你的 animateView 方法中添加另一行:
view.animate()
...
...
.setListener(this);
或者您可以在匿名内部 class 中这样做:
view.animate()
...
...
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
}
// same methods as above ...
...
)};