在DialogFragment即将dismiss之前更改进入/退出动画过渡

51

我有一个 DialogFragment,在 onActivityCreated 方法中设置它的进入/退出动画如下:

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

我的DialogAnimation样式文件如下:

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

这对我现在有效...

现在我的问题是,我想要两个不同的退出动画,一个用于单击“确定”按钮时,另一个用于取消按钮。所以我尝试在解雇之前改变过渡,但它没有起作用。

有什么解决办法吗?

这是我尝试过的:

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

尝试这个:http://adtandroid.blogspot.com/2014/12/dialog-fragment-create-and-dismiss.html - Mohammad Hossein Gerami
您发布的博客似乎没有答案。 - Dominic D'Souza
6个回答

59

您可以在DialogFragment内部完成此操作,而无需更改。

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

你应该在 onStart 和 onClick 中动画化 "decor view"。

这是代码片段:

首先创建对话框

@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();
    }

然后覆盖onStart方法

@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();
            }
        });
    }

这是结果动画

结果演示


如果您从我的代码中删除比例属性,您将仅获得alpha动画,就像您所希望的那样。

请删除以下内容:

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

当我在decorView上执行时,我的问题是窗口只有对话框那么大。因此,动画会超出窗口。 - Dominic D'Souza
实际上,我正在使用平移和旋转动画。我给出了一个 alpha 动画的示例,以保持简单。 - Dominic D'Souza
这是正确的解决方案+1,@DominicD'Souza如果你想的话,你可以在DialogFragment的布局中的任何视图上播放动画。如果你检查'Dialog'类的源代码,你会发现所有的操作都是通过装饰视图完成的。 - romtsn
1
如果它没有负面或正面按钮怎么办? - X09
1
这怎么可能呢?从下往上滑动? - Armando Esparza García

35
你可以为对话框片段设置上下动画。在'res/anim'中添加两个文件:
// 向上滑动动画
<?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>

// 下滑动画

<?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 name="DialogAnimation">
    <item name="android:windowEnterAnimation">@anim/slide_up</item>
    <item name="android:windowExitAnimation">@anim/slide_down</item>
</style>

// 在对话框片段内部

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

2
我已经完成了这个,但我的问题是想要有两种不同的退出动画,一种是针对正按钮点击,另一种是针对负按钮点击。 - Dominic D'Souza
1
您可以在正面/负面按钮点击时调用幻灯片上/下滑动。 - Akhil Jayakumar
1
我面临的主要问题是在创建对话框后无法更改windowAnimations。 - Dominic D'Souza
1
因此,在取消按钮的单击事件中调用getDialog().getWindow().getAttributes().windowAnimations=R.style.DialogCancelAnimation是行不通的。 - Dominic D'Souza
1
对我有用,将 slideUp 中的 'android:toXDelta' 替换为 'android:toYDelta'。 - Usman Rana
显示剩余2条评论

3

我认为最好的方法是在按钮点击时调用不同的动画。 因此,您会有类似以下内容的东西:

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

如果我是你,我也会使用正确的命名规范以备将来参考。例如将DialogAnimation设置为OkAnimation,将DialogAnimation2设置为CancelAnimation。
希望这能有所帮助 :)

1
我已按照我的问题中提到的尝试了上述代码。似乎只能在Dialog的onCreate中设置windowAnimation,所以上述代码对我不起作用。你试过吗?它对你有效吗? - Dominic D'Souza
onClockListeners总是在onCreate、OnCreateView或onStart方法中使用。我已经编辑了答案,为您提供了解决方案。 - Michele La Ferla

2
您想要做的一种简单方法是使用动画监听器,例如。
    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
        }
    });

在您的onclick方法中启动动画,并在onAnimationEnd()方法中关闭对话框。您可能需要创建动画对象,并使用View的startAnimation(animation)方法手动启动它们。


0

你应该为你的基础对话框设置一个主题。

比如说:

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

然后您只需要定义包含所需动画的主题。 在 styles.xml 中添加自定义主题:

<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> 

参考this


0
如果有人在许多对话框中使用onCreateDialog答案,那么您可以使用这个Kotlin扩展函数。
//ExtensionFunctions.kt file
fun Dialog.setWindowAnimations(@StyleRes id: Int): Dialog {
    this.window?.attributes?.windowAnimations = id
    return this
}

并且在你的onCreateDialog函数中

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return super.onCreateDialog(savedInstanceState)
        .setWindowAnimations(R.style.MyDialogAnimation)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接