Je montre une DialogFragment
lorsque l'utilisateur appuie sur une ligne dans une ListView
. J'aimerais animer l'affichage du dialogue afin qu'il croisse à partir du centre de la ligne. Un effet similaire peut être observé lors de l'ouverture d'un dossier à partir du lanceur.
Une idée que j'ai eu est une combinaison de TranslateAnimation
et ScaleAnimation
. Y a-t-il un autre moyen?
Étant DialogFragment
un wrapper pour la classe Dialog
, vous devez définir un thème pour votre Dialog
de base pour obtenir l'animation souhaitée:
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();
}
}
Ensuite, il vous suffit de définir le thème qui inclura l'animation souhaitée. Dans styles.xml ajoutez votre thème personnalisé:
<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>
Maintenant, ajoutez les fichiers d'animation dans le res/anim dossier:
(le Android:pivotY
est la clé)
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>
Enfin, le plus difficile est de faire en sorte que votre animation grandisse à partir du centre de chaque rangée. Je suppose que la ligne remplit l'écran horizontalement, donc, d'une part, la valeur Android:pivotX
sera statique. D'autre part, vous ne pouvez pas modifier la valeur Android:pivotY
par programme.
Je suggère que vous définissiez plusieurs animations ayant chacune une valeur de pourcentage différente sur l'attribut Android:pivotY
(et plusieurs thèmes référençant ces animations). Ensuite, lorsque l'utilisateur appuie sur la ligne, calculez la position Y en pourcentage de la ligne à l'écran. Connaissant la position en pourcentage, attribuez à votre boîte de dialogue un thème qui possède la valeur Android:pivotY
appropriée.
Ce n'est pas une solution parfaite mais pourrait faire l'affaire pour vous. Si vous n'aimez pas le résultat, je suggérerais alors d'oublier la DialogFragment
et d'animer une simple View
croissant du centre exact de la ligne.
Bonne chance!
Regardez ce code, ça marche pour moi
// animation de diapositives
<?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>
// Diapositive d'animation 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
<style name="DialogAnimation">
<item name="Android:windowEnterAnimation">@anim/slide_up</item>
<item name="Android:windowExitAnimation">@anim/slide_down</item>
</style>
// Fragment de dialogue à l'intérieur
@Override
public void onActivityCreated(Bundle arg0) {
super.onActivityCreated(arg0);
getDialog().getWindow()
.getAttributes().windowAnimations = R.style.DialogAnimation;
}
DialogFragment a une méthode publique getTheme () que vous pouvez utiliser pour cette raison exacte. Cette solution utilise moins de lignes de code:
public class MyCustomDialogFragment extends DialogFragment{
...
@Override
public int getTheme() {
return R.style.MyThemeWithCustomAnimation;
}
}
Pour obtenir un dialogue plein écran avec animation, écrivez ce qui suit ...
Modes:
<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>
Code 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());
}
Utilisez la vue de décor dans onStart dans votre fragment de boîte de dialogue.
@Override
public void onStart() {
super.onStart();
final View decorView = getDialog()
.getWindow()
.getDecorView();
decorView.animate().translationY(-100)
.setStartDelay(300)
.setDuration(300)
.start();
}
Dans DialogFragment, une animation personnalisée est appelée onCreateDialog. 'DialogAnimation' est un style d'animation personnalisé dans la réponse précédente.
public Dialog onCreateDialog(Bundle savedInstanceState)
{
final Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;
return dialog;
}
Avez-vous examiné Formation des développeurs Android sur Zoomer sur une vue ? Peut-être un bon point de départ.
Vous voulez probablement créer une classe personnalisée qui étend DialogFragment
pour que cela fonctionne.
Consultez également Jake Whartons NineOldAndroids pour la compatibilité de l'API Honeycomb Animation jusqu'au niveau 1 de l'API.
Si vous souhaitez utiliser des API, vous devez le faire dans votre DialogFragemnt-> onStart et non dans onCreateDialog
@Override
public void onStart()
{
if (getDialog() == null)
{
return;
}
getDialog().getWindow().setWindowAnimations(
R.style.DlgAnimation);
super.onStart();
}