Wyświetlam, DialogFragment
gdy użytkownik dotyka wiersza w a ListView
. Chciałbym ożywić wyświetlanie okna dialogowego, aby rosło od środka wiersza. Podobny efekt można zobaczyć podczas otwierania folderu z programu uruchamiającego.
Jeden pomysł, który miałem, to połączenie TranslateAnimation
i ScaleAnimation
. Czy jest inny sposób?
android
android-fragments
android-animation
Edward Dale
źródło
źródło
Odpowiedzi:
Będąc
DialogFragment
opakowaniem dlaDialog
klasy, powinieneś ustawić motyw do swojej bazy,Dialog
aby uzyskać pożądaną animację: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(); } }
Następnie wystarczy zdefiniować motyw, który będzie zawierał żądaną animację. W styles.xml dodaj własny motyw:
<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>
Teraz dodaj pliki animacji w folderze res / anim :
(to
android:pivotY
jest klucz)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>
Wreszcie, najtrudniejsze jest to, aby animacja rosła od środka każdego rzędu. Przypuszczam, że wiersz wypełnia ekran w poziomie, więc z jednej strony
android:pivotX
wartość będzie statyczna. Z drugiej strony nie możnaandroid:pivotY
programowo modyfikować wartości.Sugeruję, aby zdefiniować kilka animacji, z których każda ma inną wartość procentową
android:pivotY
atrybutu (i kilka motywów odnoszących się do tych animacji). Następnie, gdy użytkownik dotknie wiersza, oblicz pozycję Y w procentach wiersza na ekranie. Znając pozycję w procentach, przypisz temat do swojego okna dialogowego, który ma odpowiedniąandroid:pivotY
wartość.Nie jest to idealne rozwiązanie, ale może załatwić sprawę. Jeśli nie podoba ci się wynik, proponuję zapomnieć
DialogFragment
i ożywić prostyView
wzrost z dokładnego środka rzędu.Powodzenia!
źródło
setStyle(DialogFragment.STYLE_NORMAL, R.style.MyCustomTheme)
na stronieonCreate(bundle)
See: developer.android.com/reference/android/app/DialogFragment.htmlSprawdź ten kod, to działa dla mnie
// Animacja w górę
<?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>
// Animacja slajdów
<?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>
// Styl
<style name="DialogAnimation"> <item name="android:windowEnterAnimation">@anim/slide_up</item> <item name="android:windowExitAnimation">@anim/slide_down</item> </style>
// Fragment wewnętrznego okna dialogowego
@Override public void onActivityCreated(Bundle arg0) { super.onActivityCreated(arg0); getDialog().getWindow() .getAttributes().windowAnimations = R.style.DialogAnimation; }
źródło
DialogFragment ma publiczną metodę getTheme (), którą można zmienić z tego powodu. To rozwiązanie wykorzystuje mniej wierszy kodu:
public class MyCustomDialogFragment extends DialogFragment{ ... @Override public int getTheme() { return R.style.MyThemeWithCustomAnimation; } }
źródło
AppTheme.NoActionBar
gdy DialogFragment używa domyślnejAppTheme
. Powyższa metoda rozwiązała mój problem, mając spójny temat zarówno w fragmencie, jak i działaniu.Aby uzyskać pełnoekranowe okno dialogowe z animacją, napisz ...
Style:
<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>
Kod 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()); }
źródło
Użyj widoku dekoru wewnątrz onStart w swoim fragmencie okna dialogowego
@Override public void onStart() { super.onStart(); final View decorView = getDialog() .getWindow() .getDecorView(); decorView.animate().translationY(-100) .setStartDelay(300) .setDuration(300) .start(); }
źródło
W DialogFragment animacja niestandardowa nosi nazwę onCreateDialog. „DialogAnimation” to niestandardowy styl animacji w poprzedniej odpowiedzi.
public Dialog onCreateDialog(Bundle savedInstanceState) { final Dialog dialog = super.onCreateDialog(savedInstanceState); dialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; return dialog; }
źródło
Czy obejrzałeś szkolenie dla programistów Androida na temat powiększania widoku ? To może być dobry punkt wyjścia.
Prawdopodobnie chcesz utworzyć rozszerzającą klasę niestandardową
DialogFragment
aby ta działała.Przyjrzyj się również Jake Whartons NineOldAndroids pod kątem zgodności z interfejsem API Honeycomb Animation aż do poziomu API 1.
źródło
Jeśli chcesz pracować nad interfejsami API, musisz to zrobić w swoim DialogFragemnt-> onStart, a nie w onCreateDialog
@Override public void onStart() { if (getDialog() == null) { return; } getDialog().getWindow().setWindowAnimations( R.style.DlgAnimation); super.onStart(); }
źródło
Dodaj ten kod do wartości anim
<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"/>
zadzwoń na styles.xml
<style name="DialogScale"> <item name="android:windowEnterAnimation">@anim/scale_in</item> <item name="android:windowExitAnimation">@anim/scale_out</item> </style>
W kodzie java: ustaw Onclick
public void onClick(View v) { fab_onclick(R.style.DialogScale, "Scale" ,(Activity) context,getWindow().getDecorView().getRootView()); // Dialogs.fab_onclick(R.style.DialogScale, "Scale"); }
konfiguracja według metody:
alertDialog.getWindow().getAttributes().windowAnimations = type;
źródło