Change DialogFragment enter/exit transition at just before dismissing
Asked Answered
S

6

52

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();
    }
Senecal answered 2/10, 2015 at 13:29 Comment(2)
try this adtandroid.blogspot.com/2014/12/…Rabideau
The blog u posted does'nt seem to have an answerCrimp
P
61

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),
Passant answered 25/10, 2015 at 18:1 Comment(5)
When i do it on a decorView my issue is that the window is only as big as the dialog.so the animation goes outside the window.Crimp
Actually i am using a translate and rotate animation i gave the example of a alpha animation to keep things simpleCrimp
This is the right solution +1, @DominicD'Souza if you want, you can play the animation on any view from your DialogFragment's layout. If you check the sources of 'Dialog' class, you will see that all manipulations is doing with decor view.Ilocano
What if it doesn't have a negative or positive button?Albric
How could be this posible but from bottom to top? Like slide up?Counterspy
K
36

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;
}
Kuvasz answered 21/10, 2015 at 7:27 Comment(7)
I have done this my problem is want to have 2 different exit animations one for the positive button click and one for the negative button click.Crimp
you can call the slide up/down in your postive/negative button clickKuvasz
The main problem i am facing is that you cannot change windowAnimations after the dialog is createdCrimp
so calling getDialog().getWIndow().getAttributes().windowAnimations=R.style.DialogCancelAnimation wont work in the cancel button on ClickCrimp
worked for me, replace 'android:toXDelta' in slideUp with 'android:toYDelta'Barrios
@Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Window window = getDialog().getWindow(); if (window!=null) window.getAttributes() .windowAnimations = R.style.DialogAnimation; } use this to avoid null pointer.Moonshot
Since onActivityCreated has been deprecated, place that code into onViewCreated instead.Flaunt
C
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 :)

Chargeable answered 21/10, 2015 at 7:23 Comment(2)
I have tried the above code as mentioned in my quesiton.. It seems that you can only set the windowAnimation in the onCreate of the Dialog..so the above code does'nt work for me..Have you tried it.? and is it working for you?Crimp
onClockListeners are always se in an onCreate, OnCreateView or onStart method. I have edited the answer to provide you with the solution.Chargeable
P
2

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.

Punctual answered 26/10, 2015 at 6:56 Comment(0)
S
0

You should set a theme for your base dialog

let say :-

public class CustomDialogFragment extends DialogFragment implements OnEditorActionListener
{
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) 
    {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) 
    {
        // Set a theme on the dialog builder constructor!
        AlertDialog.Builder builder = 
            new AlertDialog.Builder( getActivity(), R.style.MyCustomTheme );

        builder  
        .setTitle( "Your title" )
        .setMessage( "Your message" )
        .setPositiveButton( "OK" , new DialogInterface.OnClickListener() 
            {      
              @Override
              public void onClick(DialogInterface dialog, int which) {
              dismiss();                  
            }
        });
        return builder.create();
    }
}

Then you just need to define the theme that will include your desired animation. In styles.xml add your custom theme:

<style name="MyCustomTheme" parent="@android:style/Theme.Panel">
    <item name="android:windowAnimationStyle">@style/MyAnimation.Window</item>
</style>

<style name="MyAnimation.Window" parent="@android:style/Animation.Activity"> 
    <item name="android:windowEnterAnimation">@anim/anim_in</item>
    <item name="android:windowExitAnimation">@anim/anim_out</item>
</style> 

refer this

Sturgis answered 23/10, 2015 at 7:9 Comment(0)
N
0

If any one ends up using the onCreateDialog answer in many dialogs, then you can use this Kotlin extension function.

//ExtensionFunctions.kt file
fun Dialog.setWindowAnimations(@StyleRes id: Int): Dialog {
    this.window?.attributes?.windowAnimations = id
    return this
}

and in your onCreateDialog function

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return super.onCreateDialog(savedInstanceState)
        .setWindowAnimations(R.style.MyDialogAnimation)
}
Negris answered 13/6, 2021 at 13:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.