Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create 3D animtation for Android Apps

I need to create a 3D flip/rotate animation based on the speed of the swipe of user on screen, I was able to create this animation using ObjectAnimator and its associated properties but I need suggestions how can we create a 3D animation in android for the above.I also to need to perform some animations that are partially rotated

Though for android we can use OPENGL but for a simple animation OPENGL is too heavy as we are not designing a real game. I have referred the following links:

  • https://2cupsoftech.wordpress.com/2012/09/18/3d-flip-between-two-view-or-viewgroup-on-android/
  • http://www.inter-fuser.com/2009/08/android-animations-3d-flip.html
like image 328
Akshay Mukadam Avatar asked Nov 02 '16 12:11

Akshay Mukadam


People also ask

Can I make 3D animation on Android?

Toontastic 3D This app allows you to draw, animate, and narrate cartoons. Toontastic is the best 3D animation app that can record your voice and animations and store your animations on your device.

Can I make animation on Android?

With over a million downloads, Animation Desk is one of the best animation apps for Android that you can try. It has all the things that make an animation app great—a clutter-free user interface, an adequate amount of options, and a handful of ways to export the finished animation.

Is Prisma 3D free?

Prisma 3D models ready to view, buy, and download for free.


2 Answers

Try using this

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.replace(R.id.layout_main, ExampleFragment.newInstance(ExampleFragment.NODIR));
    ft.commit();
}

ExampleFragment.java

public class ExampleFragment extends Fragment {

    @IntDef({NONE, FLIP})
    public @interface AnimationStyle {}
    public static final int NONE     = 0;
    public static final int FLIP     = 2;

    @IntDef({NODIR, UP, DOWN, LEFT, RIGHT})
    public @interface AnimationDirection {}
    public static final int NODIR = 0;
    public static final int UP    = 1;
    public static final int DOWN  = 2;
    public static final int LEFT  = 3;
    public static final int RIGHT = 4;

    private static final long DURATION = 500;

    @AnimationStyle
    private static int sAnimationStyle = FLIP;

    public static ExampleFragment newInstance(@AnimationDirection int direction) {
        ExampleFragment f = new ExampleFragment();
        f.setArguments(new Bundle());
        f.getArguments().putInt("direction", direction);
        return f;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.content_anim, null);

        // For generating random Colors
        int color = Color.rgb((int) Math.floor(Math.random() * 128) + 64,
                (int) Math.floor(Math.random() * 128) + 64,
                (int) Math.floor(Math.random() * 128) + 64);
        view.setBackgroundColor(color);

        ButterKnife.bind(this, view);
        return view;
    }


@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
    switch (sAnimationStyle) {
        case FLIP:
            switch (getArguments().getInt("direction")) {
                case UP:
                    return FlipAnimation.create(FlipAnimation.UP, enter, DURATION);
                case DOWN:
                    return FlipAnimation.create(FlipAnimation.DOWN, enter, DURATION);
                case LEFT:
                    return FlipAnimation.create(FlipAnimation.LEFT, enter, DURATION);
                case RIGHT:
                    return FlipAnimation.create(FlipAnimation.RIGHT, enter, DURATION);
            }
            break;
    }
    return null;
}


    @OnClick(R.id.buttonUp)
    void onButtonUp() {
        getArguments().putInt("direction", UP);
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.replace(R.id.layout_main, ExampleFragment.newInstance(UP));
        ft.commit();
    }

    @OnClick(R.id.buttonDown)
    void onButtonDown() {
        getArguments().putInt("direction", DOWN);
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.replace(R.id.layout_main, ExampleFragment.newInstance(DOWN));
        ft.commit();
    }

    @OnClick(R.id.buttonLeft)
    void onButtonLeft() {
        getArguments().putInt("direction", LEFT);
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.replace(R.id.layout_main, ExampleFragment.newInstance(LEFT));
        ft.commit();
    }

    @OnClick(R.id.buttonRight)
    void onButtonRight() {
        getArguments().putInt("direction", RIGHT);
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.replace(R.id.layout_main, ExampleFragment.newInstance(RIGHT));
        ft.commit();
    }
}

FlipAnimation.java

public class FlipAnimation extends ViewPropertyAnimation {

    @IntDef({UP, DOWN, LEFT, RIGHT})
    @interface Direction {}
    public static final int UP    = 1;
    public static final int DOWN  = 2;
    public static final int LEFT  = 3;
    public static final int RIGHT = 4;

    protected final @Direction int mDirection;
    protected final boolean mEnter;

    public static FlipAnimation create(@Direction int direction, boolean enter, long duration) {
        switch (direction) {
            case UP:
            case DOWN:
                return new VerticalFlipAnimation(direction, enter, duration);
            case LEFT:
            case RIGHT:
                return new HorizontalFlipAnimation(direction, enter, duration);
        }
        return null;
    }

    private FlipAnimation(@Direction int direction, boolean enter, long duration) {
        mDirection = direction;
        mEnter = enter;
        setDuration(duration);
    }

    private static class VerticalFlipAnimation extends FlipAnimation {

        public VerticalFlipAnimation(@Direction int direction, boolean enter, long duration) {
            super(direction, enter, duration);
        }

        @Override
        public void initialize(int width, int height, int parentWidth, int parentHeight) {
            super.initialize(width, height, parentWidth, parentHeight);
            mPivotX = width * 0.5f;
            mPivotY = (mEnter == (mDirection == UP)) ? 0.0f : height;
            mCameraZ = -height * 0.015f;
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            float value = mEnter ? (interpolatedTime - 1.0f) : interpolatedTime;
            if (mDirection == DOWN) value *= -1.0f;
            mRotationX = value * 180.0f;
            mTranslationY = -value * mHeight;

            super.applyTransformation(interpolatedTime, t);

            // Hide exiting view after half point.
            if (interpolatedTime >= 0.5f && !mEnter) {
                mAlpha = 0.0f;
            }
            applyTransformation(t);
        }
    }

    private static class HorizontalFlipAnimation extends FlipAnimation {

        public HorizontalFlipAnimation(@Direction int direction, boolean enter, long duration) {
            super(direction, enter, duration);
        }

        @Override
        public void initialize(int width, int height, int parentWidth, int parentHeight) {
            super.initialize(width, height, parentWidth, parentHeight);
            mPivotX = (mEnter == (mDirection == LEFT)) ? 0.0f : width;
            mPivotY = height * 0.5f;
            mCameraZ = -width * 0.015f;
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            float value = mEnter ? (interpolatedTime - 1.0f) : interpolatedTime;
            if (mDirection == RIGHT) value *= -1.0f;
            mRotationY = -value * 180.0f;
            mTranslationX = -value * mWidth;

            super.applyTransformation(interpolatedTime, t);

            // Hide exiting view after half point.
            if (interpolatedTime >= 0.5f && !mEnter) {
                mAlpha = 0.0f;
            }
            applyTransformation(t);
        }
    }
}

ViewPropertyAnimation.java

public class ViewPropertyAnimation extends Animation {

    private final Camera mCamera = new Camera();
    protected int mWidth  = 0;
    protected int mHeight = 0;
    protected float mAlpha = 1.0f;
    protected float mPivotX = 0.0f;
    protected float mPivotY = 0.0f;
    protected float mScaleX = 1.0f;
    protected float mScaleY = 1.0f;
    protected float mRotationX = 0.0f;
    protected float mRotationY = 0.0f;
    protected float mRotationZ = 0.0f;
    protected float mTranslationX = 0.0f;
    protected float mTranslationY = 0.0f;
    protected float mTranslationZ = 0.0f;
    protected float mCameraX = 0.0f;
    protected float mCameraY = 0.0f;
    protected float mCameraZ = -8.0f;

    private float mFromAlpha = -1.0f;
    private float mToAlpha   = -1.0f;

    public ViewPropertyAnimation fading(@FloatRange(from=0.0f,to=1.0f) float fromAlpha, @FloatRange(from=0.0f,to=1.0f) float toAlpha) {
        mFromAlpha = fromAlpha;
        mToAlpha = toAlpha;
        return this;
    }

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        mWidth = width;
        mHeight = height;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);
        if (mFromAlpha >= 0 && mToAlpha >= 0) {
            mAlpha = mFromAlpha + (mToAlpha - mFromAlpha) * interpolatedTime;
        }
    }

    protected void applyTransformation(Transformation t) {
        final Matrix m = t.getMatrix();
        final float w = mWidth;
        final float h = mHeight;
        final float pX = mPivotX;
        final float pY = mPivotY;

        final float rX = mRotationX;
        final float rY = mRotationY;
        final float rZ = mRotationZ;
        if ((rX != 0) || (rY != 0) || (rZ != 0)) {
            final Camera camera = mCamera;
            camera.save();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
                camera.setLocation(mCameraX, mCameraY, mCameraZ);
            }
            if (mTranslationZ != 0) {
                camera.translate(0, 0, mTranslationZ);
            }
            camera.rotateX(rX);
            camera.rotateY(rY);
            camera.rotateZ(-rZ);
            camera.getMatrix(m);
            camera.restore();
            m.preTranslate(-pX, -pY);
            m.postTranslate(pX, pY);
        }

        final float sX = mScaleX;
        final float sY = mScaleY;
        if ((sX != 1.0f) || (sY != 1.0f)) {
            m.postScale(sX, sY);
            final float sPX = -(pX / w) * ((sX * w) - w);
            final float sPY = -(pY / h) * ((sY * h) - h);
            m.postTranslate(sPX, sPY);
        }

        m.postTranslate(mTranslationX, mTranslationY);

        t.setAlpha(mAlpha);
    }
}
like image 135
MashukKhan Avatar answered Sep 17 '22 11:09

MashukKhan


Actually,you have mentioned this:

3D flip/rotate animation based on the speed of the swipe of user on screen

So,I don't think Android Animation suits your situations.But if you have experience in custom view,a class from android.graphics.Camera will help you.

At first,you need declare

camera = new Camera();

Then override OnDraw .

canvas.save();
Matrix matrix = new Matrix(); 
camera.save();
camera.rotateY(rotateAngle);
camera.getMatrix(matrix);
camera.restore();

mPaint.setColor(textBackgroundColor);
int centerX = diameter / 2;
int centerY = diameter / 2;
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
canvas.concat(matrix);
canvas.drawCircle(diameter / 2, diameter / 2, diameter / 2, mPaint);
canvas.restore();

Now you can see we rotated a circle rotateAngle degrees around the y-axis.And you can change the value rotateAngle to adjust angle .

You are free to refer my lastest article here,and the source code is on github link.

like image 21
orzangleli Avatar answered Sep 20 '22 11:09

orzangleli