如何使用Animation类获得平滑的动画效果?

时间:2017-06-28 14:58:04

标签: java android animation

我有以下类来向上滑动FrameLayout。它基本上降低了视图的高度。它运作得很好,但唯一的一点是动画并不能让我满足于平滑度。它给出10 FPS。

SlideUpDownAnimation.java

package anim;

import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;

public class SlideUpDownAnimation extends Animation {
private static final String TAG = "ANIMATION";
private View view;
private boolean isUp;
private int startHeight;
private int finalHeight;
private int difference;

public SlideUpDownAnimation(View view, boolean isUp, int finalHeight) {
    this.view = view;
    this.isUp = isUp;
    this.startHeight = view.getMeasuredHeight();
    this.finalHeight = finalHeight;
    this.difference = this.finalHeight - view.getLayoutParams().height;
}

@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
    int newHeight;

    // daha yüksek bir değerden azalarak ilerliyor demektir.
    if (!isUp) {
        newHeight = (int) (this.difference * (1 - interpolatedTime));
        view.getLayoutParams()
                .height = newHeight;
    } else {
        newHeight = (int) (this.startHeight - (this.difference * interpolatedTime));
        view.getLayoutParams()
                .height = newHeight;
    }

    Log.i(TAG, "Start height: " + this.startHeight + " New height: " + newHeight + " interpolated time: " + interpolatedTime);

    view.requestLayout();
}
}

我将持续时间设置为1000毫秒。这是我的logcat:

06-28 17:48:21.876 13403-13403/com.menulux.menu I/ANIMATION: Start height: 800 New height: 800 interpolated time: 0.0
06-28 17:48:21.876 13403-13403/com.menulux.menu I/ANIMATION: Start height: 800 New height: 800 interpolated time: 0.0
06-28 17:48:22.006 13403-13403/com.menulux.menu I/ANIMATION: Start height: 800 New height: 777 interpolated time: 0.061846644
06-28 17:48:22.116 13403-13403/com.menulux.menu I/ANIMATION: Start height: 800 New height: 739 interpolated time: 0.16699407
06-28 17:48:22.236 13403-13403/com.menulux.menu I/ANIMATION: Start height: 800 New height: 679 interpolated time: 0.33210987
06-28 17:48:22.356 13403-13403/com.menulux.menu I/ANIMATION: Start height: 800 New height: 613 interpolated time: 0.51570535
06-28 17:48:22.476 13403-13403/com.menulux.menu I/ANIMATION: Start height: 800 New height: 547 interpolated time: 0.6971313
06-28 17:48:22.591 13403-13403/com.menulux.menu I/ANIMATION: Start height: 800 New height: 493 interpolated time: 0.8468266
06-28 17:48:22.716 13403-13403/com.menulux.menu I/ANIMATION: Start height: 800 New height: 453 interpolated time: 0.9569855
06-28 17:48:22.831 13403-13403/com.menulux.menu I/ANIMATION: Start height: 800 New height: 438 interpolated time: 0.99944496
06-28 17:48:22.961 13403-13403/com.menulux.menu I/ANIMATION: Start height: 800 New height: 438 interpolated time: 1.0
06-28 17:48:23.076 13403-13403/com.menulux.menu I/ANIMATION: Start height: 800 New height: 438 interpolated time: 1.0

3 个答案:

答案 0 :(得分:0)

您可以使用View

view.animate().translationY(distance);向下滑动一段距离

然后使用:view.animate().translationY(0);

将其滑回原始位置

您还可以制作一些有趣的组合,例如:

// Prepare the View for the animation
view.setVisibility(View.VISIBLE);
view.setAlpha(0.0f);

// Start the animation
view.animate()
    .translationY(view.getHeight())
    .alpha(1.0f);

它将向下滑动其高度然后逐渐消失。

您也可以将该视图淡化回原来的位置。

使用AnimatorListener,您可以将view设置为“已消失”。动画完成后也是如此。

此处参考:Show hide view with animation

如果你想走XML路线。这也可能是一个不错的选择:

  <?xml version="1.0" encoding="utf-8"?>

<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromYDelta="100%"
    android:interpolator="@android:anim/decelerate_interpolator"
    android:toYDelta="0%" />

可以针对不同的效果/方向更改这些增量

答案 1 :(得分:0)

我尝试了更频繁地制作动画类动作interpolatedTime以获得动画效果的所有内容,但没有任何效果。所以我找到了创建自己的Thread来设置对象动画的解决方案。以下动画效果很好,为60 FPS。

public class AdjustMediaHeight extends AsyncTask<Void, Void, Void> {
    private View ll_food_media;
    private int videoHeight;
    private final int startHeight;
    private final int difference;

    public AdjustMediaHeight(View view, int height) {
        this.ll_food_media = view;
        this.videoHeight = height;
        this.startHeight = ll_food_media.getMeasuredHeight();
        this.difference = ll_food_media.getMeasuredHeight() - videoHeight;
    }

    @Override
    protected Void doInBackground(Void... params) {
        float i = 1;
        long lastMilli = System.currentTimeMillis();

        while (i < 60) {
            // closest frame rate compared to 33,33333333333
            // 33 comes from 30 / 1000
            if (System.currentTimeMillis() - lastMilli < 16)
                continue;

            final int newHeight = (int) (startHeight - (difference / 60 * i));

            APP.mOrderActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {

                    ll_food_media.setLayoutParams(
                            new RelativeLayout.LayoutParams(
                                    800,
                                    newHeight
                            )
                    );

                    ll_food_media.requestLayout();
                }
            });

            Log.i("ANIMATION", "Frame #" + i + " completed. Height: " + newHeight);
            i++;
            lastMilli = System.currentTimeMillis();
        }


        return null;
    }
}

警告:请勿将其与其他动画混合使用。因为它的工作由CPU处理,所以它可能会滞后整个设备1秒钟。

答案 2 :(得分:0)

您可以使用android过渡类https://developer.android.com/reference/android/transition/Transition.html。 它们很流畅,你也可以应用4种类型的转换:

  • 退出转换

  • 输入转换

  • 返回过渡

  • 重新进入转型

它们还赋予您在java类或xml文件中执行转换的独立性。

在java类中使用它们的片段

输入TANSITION

ACTIVITY A:
ActivityOptionsCompat compat = ActivityOptionsCompat.makeSceneTransitionAnimation(activityA.this,null);

            Intent i = new Intent(activityA.this,activityB.class);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                startActivity(i,compat.toBundle());
            }
            else
                startActivity(i);

ACTIVITY B:

Slide s = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
        s = new Slide();
        s.setDuration(1000);
        getWindow().setEnterTransition(s);
    }

对于xml文件,您必须创建Transition资源文件并在java类中对其进行充气。

希望它有所帮助!!