Pregunta Mostrar DialogFragment con una animación que crece desde un punto


Estoy mostrando un DialogFragment cuando el usuario toca una fila en un ListView. Me gustaría animar la presentación del diálogo para que crezca desde el centro de la fila. Se puede ver un efecto similar al abrir una carpeta desde el iniciador.

Una idea que tuve fue una combinación de TranslateAnimation y ScaleAnimation. ¿Hay otra manera?


73
2017-11-15 17:17


origen


Respuestas:


Siendo DialogFragment una envoltura para el Dialog clase, deberías establecer un tema para tu base Dialog para obtener la animación que desea:

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

Entonces solo necesita definir el tema que incluirá su animación deseada. En styles.xml agrega tu tema personalizado:

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

Ahora agregue los archivos de animación en res / anim carpeta:

( el android:pivotY es la llave )

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>

Finalmente, lo difícil aquí es hacer crecer tu animación desde el centro de cada fila. Supongo que la fila está llenando la pantalla horizontalmente, así que, por un lado, android:pivotX el valor será estático. Por otro lado, no puede modificar el android:pivotY valor programáticamente.

Lo que sugiero es que defina varias animaciones, cada una de las cuales tiene un valor de porcentaje diferente en el android:pivotY atributo (y varios temas que hacen referencia a esas animaciones). Luego, cuando el usuario toque la fila, calcule la posición Y en porcentaje de la fila en la pantalla. Conociendo la posición en porcentaje, asigne un tema a su diálogo que tenga el apropiado android:pivotY valor.

No es una solución perfecta, pero podría hacer el truco para ti. Si no te gusta el resultado, te sugiero que olvides DialogFragment y animando un simple View creciendo desde el centro exacto de la fila.

¡Buena suerte!


140
2017-11-24 00:33



Mira este código, funciona para mí

// Deslice la animación

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

// Deslice la animación de 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>

// Estilo

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

// Fragmento de diálogo interior

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

89
2018-04-04 16:04



DialogFragment tiene un método público getTheme () que puede sobrepasar por esta razón exacta. Esta solución usa menos líneas de código:

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

14
2018-04-10 08:51



Para obtener un cuadro de diálogo de pantalla completa con animación, escriba lo siguiente ...

Estilos:

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

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

6
2017-08-03 23:15



En DialogFragment, la animación personalizada se llama onCreateDialog. 'DialogAnimation' es un estilo de animación personalizado en la respuesta anterior.

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

2
2017-12-16 07:32



Utilice la vista de decoración en el interior enInicio en su fragmento de diálogo

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


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

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

}

2
2017-08-25 17:18



¿Has visto la capacitación de desarrolladores de Android en Acercar una vista? Puede ser un buen punto de partida.

Es probable que desee crear una clase personalizada que se extienda DialogFragment para hacer que esto funcione

Además, eche un vistazo a Jake Whartons NineOldAndroids para la compatibilidad de Honeycomb Animation API desde el nivel 1 de API.


1
2017-11-21 20:29



Si desea trabajar con API, debe hacerlo dentro de DialogFragemnt-> onStart y no dentro de CreateDialog

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

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

        super.onStart();
    }

0
2017-07-22 22:07