显示DialogFragment,动画从一点开始


93

DialogFragment当用户在中点击某行时,我正在显示一个ListView。我想对对话框的显示进行动画处理,以使其从行的中央开始增长。从启动器打开文件夹时,可以看到类似的效果。

,我已经有一个想法是组合TranslateAnimationScaleAnimation。还有另一种方法吗?


1
请参阅DialogFragment上的动画链接

Answers:


168

作为该类DialogFragment的包装Dialog,您应该为您的基础设置一个主题Dialog以获得所需的动画:

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>    

现在,将动画文件添加到res / anim文件夹中:

android:pivotY关键是)

anim_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:interpolator="@android:anim/linear_interpolator"
        android:fromXScale="0.0"
        android:toXScale="1.0"
        android:fromYScale="0.0"
        android:toYScale="1.0"
        android:fillAfter="false"
        android:startOffset="200"
        android:duration="200" 
        android:pivotX = "50%"
        android:pivotY = "-90%"
    />
    <translate
        android:fromYDelta="50%"
        android:toYDelta="0"
        android:startOffset="200"
        android:duration="200"
    />
</set>

anim_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:interpolator="@android:anim/linear_interpolator"
        android:fromXScale="1.0"
        android:toXScale="0.0"
        android:fromYScale="1.0"
        android:toYScale="0.0"
        android:fillAfter="false"
        android:duration="200" 
        android:pivotX = "50%"        
        android:pivotY = "-90%"        
    />
    <translate
        android:fromYDelta="0"
        android:toYDelta="50%"
        android:duration="200"
    />
</set>

最后,这里棘手的事情是使动画从每一行的中心开始增长。我认为该行是水平填充屏幕,因此,一方面该android:pivotX值是静态的。另一方面,您不能以android:pivotY编程方式修改该值。

我建议您定义几个动画,每个动画在 android:pivotY属性(以及引用这些动画的几个主题)。然后,当用户点击该行时,以屏幕上该行的百分比计算Y位置。知道位置百分比后,为对话框分配一个具有适当android:pivotY值的主题。

这不是一个完美的解决方案,但可以为您解决问题。如果您不喜欢这种结果,那么我建议您忘掉,然后DialogFragment为简单的动画设置动画View从行的确切中心开始为。

祝好运!


在屏幕上的不同位置具有多个动画的好主意。这是一个hack,但这似乎是唯一的方法。
爱德华·戴尔

这只会使用> API 11来启动@Kiran Babu答案是一个变通方案
Blundell

您知道这些动画完成后是否有可能获取回调?我想制作一个分为两部分的动画,其中一个对话框会滑入其中,然后使视图淡入。我该如何将侦听器附加到windowAnimations?
android_student 2015年

太棒了!正是我一直在寻找!
Aleksey Timoshchenko '16

2
设置主题可以简单的做setStyle(DialogFragment.STYLE_NORMAL, R.style.MyCustomTheme)onCreate(bundle)见:developer.android.com/reference/android/app/DialogFragment.html
tropicalfish

117

看看这段代码,它对我有用

//向上滑动动画

<?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:toXDelta="0" />

</set>

//滑动dowm动画

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

8
抱歉,这根本无法回答我的问题。
爱德华·戴尔

3
这可能不是OP所要求的,但是我认为这是一个很好的切入点。
mdelolmo 2013年

2
很好的例子!对我有用的唯一样本。技巧是在onActivityCreated(...)方法中设置动画/主题
tomurka 2014年

3
这可能很有用,但根本无法回答问题。
Olayinka 2014年

您知道这些动画完成后是否有可能获取回调?我想制作一个分为两部分的动画,其中一个对话框会滑入其中,然后使视图淡入。我该如何将侦听器附加到windowAnimations?
android_student 2015年

22

DialogFragment有一个公共的getTheme()方法,您可以出于这个确切原因而过度使用它。此解决方案使用较少的代码行:

public class MyCustomDialogFragment extends DialogFragment{
    ...
    @Override
    public int getTheme() {
        return R.style.MyThemeWithCustomAnimation;
    }
}

1
不用担心...简单而直接的解决方案。
Noundla Sandeep

这是对我最好的答案!
超级用户

虽然与原始问题无关,但我在MainAcitvity中显示了一个图库,用户单击该图库即可激活DialogFragment中的幻灯片。但是,每当从幻灯片放映返回时,MainActivity中都会有一个混蛋。这是由于AppTheme.NoActionBarDialogFragment使用default时使用了MainActivity AppTheme。上面的方法通过在片段和活动上具有一致的主题解决了我的问题。
tingyik90 '18

兄弟,你真是天才
杰基·庄

这个解决方案对我有用。然而有一件事使我困惑。直接在主题中设置windowEnterAnimation或windowExitAnimation不会对我的DialogFragments动画产生影响。对我唯一有效的方法是将windowAnimationStyle设置为一个单独的XML文件,该文件定义样式并在其中设置输入和退出动画
szaske

9

要获得带有动画的全屏对话框,请编写以下代码...

样式:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="actionModeBackground">?attr/colorPrimary</item>
    <item name="windowActionModeOverlay">true</item>
</style>

<style name="AppTheme.NoActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
</style>

<style name="AppTheme.NoActionBar.FullScreenDialog">
    <item name="android:windowAnimationStyle">@style/Animation.WindowSlideUpDown</item>
</style>

<style name="Animation.WindowSlideUpDown" parent="@android:style/Animation.Activity">
    <item name="android:windowEnterAnimation">@anim/slide_up</item>
    <item name="android:windowExitAnimation">@anim/slide_down</item>
</style>

res / anim / slide_up.xml

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

    <translate
        android:duration="@android:integer/config_shortAnimTime"
        android:fromYDelta="100%"
        android:toYDelta="0%"/>
</set>

res / anim / slide_down.xml

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

    <translate
        android:duration="@android:integer/config_shortAnimTime"
        android:fromYDelta="0%"
        android:toYDelta="100%"/>
</set>

Java代码:

public class MyDialog extends DialogFragment {

    @Override
    public int getTheme() {
        return R.style.AppTheme_NoActionBar_FullScreenDialog;
    }
}

private void showDialog() {
    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    Fragment previous = getSupportFragmentManager().findFragmentByTag(MyDialog.class.getName());
    if (previous != null) {
        fragmentTransaction.remove(previous);
    }
    fragmentTransaction.addToBackStack(null);

    MyDialog dialog = new MyDialog();
    dialog.show(fragmentTransaction, MyDialog.class.getName());
}

4

在对话框片段的onStart内使用装饰视图

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


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

    decorView.animate().translationY(-100)
            .setStartDelay(300)
            .setDuration(300)
            .start();

}

1
此后似乎无法点击该基本视图
HaydenKai

3

在DialogFragment中,自定义动画称为onCreateDialog。“ DialogAnimation”是上一个答案中的自定义动画样式。

public Dialog onCreateDialog(Bundle savedInstanceState) 
{
    final Dialog dialog = super.onCreateDialog(savedInstanceState);
    dialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;
    return dialog;
}

1

您是否看过Android开发人员关于缩放视图的培训?可能是一个很好的起点。

您可能想创建一个自定义类扩展 DialogFragment以其功能。

另外,看看Jake Whartons NineOldAndroids与Honeycomb Animation API的兼容性,直到API Level 1。


1

如果要使用API​​,则必须在DialogFragemnt-> onStart而不是onCreateDialog内进行

@Override
    public void onStart() 
    {
        if (getDialog() == null) 
        {
            return;
        }

        getDialog().getWindow().setWindowAnimations(
                  R.style.DlgAnimation);

        super.onStart();
    }

我认为最好的解决方案。它也适用于AlertDialogs,只需在onShowListener中使用它即可。谢谢!
加博尔诺瓦克

0

将此代码添加到值动画上

 <scale
    android:duration="@android:integer/config_longAnimTime"
    android:fromXScale="0.2"
    android:fromYScale="0.2"
    android:toXScale="1.0"
    android:toYScale="1.0"
    android:pivotX="50%"
    android:pivotY="50%"/>
<alpha
    android:fromAlpha="0.1"
    android:toAlpha="1.0"
    android:duration="@android:integer/config_longAnimTime"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"/>

调用styles.xml

<style name="DialogScale">
    <item name="android:windowEnterAnimation">@anim/scale_in</item>
    <item name="android:windowExitAnimation">@anim/scale_out</item>
</style>

在Java代码上:设置Onclick

public void onClick(View v) {
        fab_onclick(R.style.DialogScale, "Scale" ,(Activity) context,getWindow().getDecorView().getRootView());
      //  Dialogs.fab_onclick(R.style.DialogScale, "Scale");

    }

设置方法:

alertDialog.getWindow().getAttributes().windowAnimations = type;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.