Android - 一次动画边距/更改多个 View 的位置

标签 android android-layout android-animation android-view

我有一个relativelayout,有 4 个并排的按钮。在某些事件中,我希望用动画更改所有四个按钮的位置/更改边距。

我目前正在使用以下代码执行此操作

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+

最佳答案

您可能想重新考虑您的设计,使用 ViewPropertyAnimator可以为您节省大量代码,并且非常可读/可维护。

使用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

动画始终从 View 的当前位置开始。

为了更清晰的代码,为什么不尝试这样的事情:

编写您自己的动画方法,该方法采用 View (在您的例子中是按钮)以及您需要的所有值作为参数(在 x 和 y 轴上移动 View 的最小实现):

private void animateView(View view, float toX, float toY, int duration) {
    view.animate()
        .translationX(toX)
        .translationY(toY)
        .setDuration(duration);
}

然后您可以简单地在按钮上调用此方法来单独为它们设置动画。 :

animateView(button1, 5.0f, 2.5f, 150);
animateView(button2, 2.5f, 1.0f, 150);

当然,5.0f、2.5f 等只是虚构的数字,您必须自己填写要移动 View 的位置。

额外建议:使用插值器让你的动画像 f 一样生动总是很好。 e. :

view.animate()
    .translationX(...)
    .translationY(...)
    .setInterpolator(new AccelerateDecelerateInterpolator())
    .setDuration(...);

如果这不够彻底或有任何不清楚的地方,请告诉我。

更新: 如果你想设置一个监听器,你可以实现 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);

或者您可以在匿名内部类中执行此操作,如下所示:

view.animate()
...
...
.setListener(new Animator.AnimatorListener() {

    @Override
    public void onAnimationEnd(Animator animation) {

    }
     // same methods as above ...
    ...
)};

关于Android - 一次动画边距/更改多个 View 的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33070973/

相关文章:

android - textView 上的 setAnimation 无效

android - 如何计算Google Play商店中某个应用的下载次数

android - 从实时相机预览android检测肤色

java - 修复软键盘上方的布局

java - 安卓开发。卡片 View 不起作用?

android - 屏幕底部带有弹出菜单的 ActionBar

android - 使用 View 对象制作简单的 Android 游戏

android - 如何从 Android Studio 构建所有产品风格?

java - 在包含对象的类的当前实例中调用 Java 方法

android - Android 上的 AlertDialog 内部 EditText 扩展太慢