1

I have the following class to slide up a FrameLayout. It basically reduces height of the views. It works very well but the only thing is that the animation doesn't satisfy me on smoothness. It gives 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();
}
}

I set duration to 1000 milliseconds. Here's my 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
Paul Podgorsek
  • 2,416
  • 3
  • 19
  • 22
Emre A
  • 71
  • 7

3 Answers3

0

You can slide a View down a distance with view.animate().translationY(distance);

Then slide it back to its original position with: view.animate().translationY(0);

You can also make some interesting combinations such as:

// 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);

That will slide down by its height and then fade away.

You could fade that view back to its original position as well.

With AnimatorListener you can set the view to 'gone' after the animation has finished as well.

reference here : Show hide view with animation

If you want to go the XML route. This may also be a good option here:

  <?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%" />

These deltas can be changed for a different effect/direction

A. Petrizza
  • 3,202
  • 2
  • 15
  • 24
0

I tried everything to make Animation class feed interpolatedTime more often to get smooth results of my animation but nothing worked. So I found the solution on creating my own Thread to animate object. The below animation works well at 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;
    }
}

WARNING: Don't mix this with other animations. Because its work handled by CPU so it can lag the entire device for 1 second.

Emre A
  • 71
  • 7
0

You can use android transition classes https://developer.android.com/reference/android/transition/Transition.html. They are smooth and you can also apply 4 types of transitions:

  • Exit Transition

  • Enter Transition

  • Return Transition

  • Re-enter Transition

They also give you independence to perform transition in java class or xml file.

Snippet of using them in java class

ENTER 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);
    }

For xml files, you'll have to create Transition resource file and inflate it in your java class.

Hope it helps!!

  • Thanks but my application should support back to API 14. This Transition class come into business at API 19. – Emre A Jun 29 '17 at 12:52