Android 显示DialogFragment,动画从一点开始增长

Android 显示DialogFragment,动画从一点开始增长,android,android-fragments,android-animation,Android,Android Fragments,Android Animation,当用户点击列表视图中的一行时,我正在显示一个对话框片段。我想设置对话框显示的动画,使其从行的中心开始增长。从启动器打开文件夹时,也可以看到类似的效果 我的一个想法是将TranslateAnimation和ScaleAnimation结合起来。还有别的方法吗?你看过Android开发者的培训吗?这可能是一个很好的起点 您可能希望创建一个扩展DialogFragment的自定义类来实现此功能 另外,看看Jake Whartons的蜂巢动画API兼容性,一路回到API级别1。作为对话框类的包装器,您应

当用户点击
列表视图中的一行时,我正在显示一个
对话框片段
。我想设置对话框显示的动画,使其从行的中心开始增长。从启动器打开文件夹时,也可以看到类似的效果


我的一个想法是将
TranslateAnimation
ScaleAnimation
结合起来。还有别的方法吗?

你看过Android开发者的培训吗?这可能是一个很好的起点

您可能希望创建一个扩展
DialogFragment
的自定义类来实现此功能


另外,看看Jake Whartons的蜂巢动画API兼容性,一路回到API级别1。

作为
对话框
类的包装器,您应该为基础
对话框
设置一个主题,以获得您想要的动画:

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>    
anim_out.xml


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

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

这不是一个完美的解决方案,但可以为您带来好处。如果您不喜欢结果,那么我建议您忘记
对话框片段
,并设置一个简单的
视图
的动画,该视图从行的确切中心开始生长


祝你好运

看看这段代码,它适合我

//向上滑动动画

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

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

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

DialogFragment有一个公共getTheme()方法,正是出于这个原因,您可以使用它。此解决方案使用更少的代码行:

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

如果您想使用API,您必须在对话框Fragemnt->onStart中执行,而不是在onCreateDialog中执行

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

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

        super.onStart();
    }

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

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


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

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

}

要获得带有动画的全屏对话框,请编写以下内容

样式:

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

在值动画中添加此代码

 <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"/>
方法上的设置:

alertDialog.getWindow().getAttributes().windowAnimations = type;

注意:这只是对其他答案的补充

无论你选择哪种解决方案,你都可能和我有同样的问题

在安装新版本之前,我需要从我的开发设备卸载游戏,以便动画更改生效



我不知道为什么,但我想这与Android studio上的优化部署没有认识到这些变化有关。

请参阅DialogFragment上的动画。对于屏幕上不同位置的多个动画,这是个好主意。这是一个黑客攻击,但似乎是唯一的方法。这只适用于>API 11@Kiran Babu。答案是一个解决办法。你知道当这些动画完成时,是否有可能获得回调?我想做一个由两部分组成的动画,其中对话框滑入,然后淡入视图。如何将侦听器连接到windowAnimations?Exelent!这正是我一直在寻找的!设置主题可以像在
onCreate(bundle)
上执行
setStyle(DialogFragment.STYLE\u NORMAL,R.STYLE.MyCustomTheme)
一样简单。请看:对不起,这根本不能回答我的问题。这可能不是OP想要的,但我认为这是一个很好的切入点。很好的例子!唯一适合我的样本。诀窍是在onActivityCreated(…)方法中设置动画/主题这可能很有用,但根本无法回答问题。您知道在这些动画完成后是否有可能获得回调吗?我想做一个由两部分组成的动画,其中对话框滑入,然后淡入视图。如何将侦听器连接到windowAnimations?不再担心。。。简单明了的解决方案。这是我最好的答案!虽然与原始问题无关,但我在MainacitCity中显示了一个图库,用户单击该图库将激活DialogFragment中的幻灯片。然而,每当从幻灯片中返回时,主活动中都会出现一个抖动。这是由于MainActivity使用的是
AppTheme.NoActionBar
,而DialogFragment使用的是默认的
AppTheme
。上面的方法解决了我的问题,在片段和活动中都有一致的主题。兄弟,你是天才。这个解决方案对我有效。然而有一件事让我困惑;直接在主题中设置windowEnterAnimation或windowExitAnimation不会对我的DialogFragments动画产生影响。唯一对我有效的方法是将windowAnimationStyle设置为一个单独的XML文件,该文件定义了样式,并将输入和退出动画设置为我认为最好的解决方案。它也适用于AlertDialogs,只需在onShowListener中使用它即可。谢谢之后,基础视图似乎不可单击
<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>
<?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>
<?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>
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());
}
 <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"/>
<style name="DialogScale">
    <item name="android:windowEnterAnimation">@anim/scale_in</item>
    <item name="android:windowExitAnimation">@anim/scale_out</item>
</style>
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;