Change DialogFragment enter/exit transition at just before dismissing

I have a DialogFragment and I set animation for enter/exit in the onActivityCreated method as below:

  @Override
    public void onActivityCreated(Bundle arg0) {
        super.onActivityCreated(arg0);
        getDialog().getWindow()
                .getAttributes().windowAnimations = R.style.DialogAnimation;
    }

My DialogAnimation style files is as follows:

<style name="DialogAnimation">
        <item name="android:windowEnterAnimation">@android:anim/fade_in</item>
        <item name="android:windowExitAnimation">@android:anim/fade_out</item>
    </style>

This works for me now...

Now my problem is i want to have two different exit animation one for when the "OK" button is clicked and one for the cancel button. So what I did was I tried changing the transition just before dismissing but it didn't work.

Any solution on how it can be achieved?

This is what I tried:

  @Override
    public void onClick(View v) {
        getDialog().getWindow()
                .getAttributes().windowAnimations = R.style.DialogAnimation2;
        this.dismiss();
    }

Solution 1:

You can do it inside your DialogFragment, without changing

getDialog().getWindow()
            .getAttributes().windowAnimations

You should animate "decor view" in onStart and onClick.

This is the code snipped :

Create Dialog first

@Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity())
                .setTitle("Hello from animated dialog :)")
                .setNegativeButton("Cancel",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {
                                //we have to add button here and then override it's click in onStart
                            }
                        }
                )
                .setCancelable(false)
                .create();
    }

Then override onStart method

@Override
    public void onStart() {
        super.onStart();

        AlertDialog dialog = (AlertDialog)getDialog();

        final View decorView = getDialog()
                .getWindow()
                .getDecorView();

        ObjectAnimator scaleDown = ObjectAnimator.ofPropertyValuesHolder(decorView,
                PropertyValuesHolder.ofFloat("scaleX", 0.0f, 1.0f),
                PropertyValuesHolder.ofFloat("scaleY", 0.0f, 1.0f),
                PropertyValuesHolder.ofFloat("alpha", 0.0f, 1.0f));
        scaleDown.setDuration(2000);
        scaleDown.start();


        Button positiveButton = dialog.getButton(Dialog.BUTTON_NEGATIVE);
        positiveButton.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                final View decorView = getDialog()
                        .getWindow()
                        .getDecorView();

                ObjectAnimator scaleDown = ObjectAnimator.ofPropertyValuesHolder(decorView,
                        PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.0f),
                        PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0.0f),
                        PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.0f));
                scaleDown.addListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        dismiss();
                    }

                    @Override
                    public void onAnimationStart(Animator animation) {
                    }
                    @Override
                    public void onAnimationCancel(Animator animation) {
                    }
                    @Override
                    public void onAnimationRepeat(Animator animation) {
                    }
                });
                scaleDown.setDuration(2000);
                scaleDown.start();
            }
        });
    }

Here is the result animation

Demo of the result


And if you remove scale properties from my code you will get only alpha animation. Exactly as you wanted.

Remove this:

PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.0f),
PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0.0f),

Solution 2:

You can set an Up & Down animations for dialog fragment. In 'res/anim' add two files:

// Slide up animation

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="@android:integer/config_mediumAnimTime"
        android:fromYDelta="100%"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toYDelta="0" />

</set>

// Slide dowm animation

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="@android:integer/config_mediumAnimTime"
        android:fromYDelta="0%p"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toYDelta="100%p" />

</set>

// Style

<style name="DialogAnimation">
    <item name="android:windowEnterAnimation">@anim/slide_up</item>
    <item name="android:windowExitAnimation">@anim/slide_down</item>
</style>

// Inside Dialog Fragment

@Override
public void onActivityCreated(Bundle arg0) {
    super.onActivityCreated(arg0);
    getDialog().getWindow()
   .getAttributes().windowAnimations = R.style.DialogAnimation;
}

Solution 3:

I think the best approach is to call the different animations on Button click. Hence you would have something similar to the below:

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button OkButton = (Button) findViewById(R.id.btnOk);
        Button CancelButton = (Button) findViewById(R.id.btnCancel);

        OkButton.setOnClickListener(new OnClickListener() {

            @Override    
            public void onClick(View view) {
                    getDialog().getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;    
            }
        });
        return true;

        CancelButton.setOnClickListener(new OnClickListener() {

            @Override    
            public void onClick(View view) {
                getDialog().getWindow().getAttributes().windowAnimations = R.style.DialogAnimation2;    
            }
        });
        return true;
    }

If I were you, I would also use correct naming conventions for future reference. For example setting DialogAnimation to OkAnimation and DialogAnimation2 to CancelAnimation.

Home this helps :)

Solution 4:

One simple way to do what you want is to use animation listeners like.

    animation.setAnimationListener(new AnimationListener() {

        @Override
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationEnd(Animation animation) {
            // TODO Auto-generated method stub
            // dismiss your dialog in here and it will work
        }
    });

Start animation on your onclick method and dismiss dialog on onAnimationEnd() method.You may have to make snimation objects and start them manually with View's startAnimation(animation) method.