Показати DialogFragment з анімацією, що зростає з точки


93

Я показую, DialogFragmentколи користувач натискає на рядок у ListView. Я хотів би анімувати показ діалогового вікна, щоб воно зростало від центру рядка. Подібний ефект можна побачити при відкритті папки з панелі запуску.

Одна ідея, яку я мав, - це поєднання TranslateAnimationі ScaleAnimation. Чи є інший спосіб?


1
Зверніться до посилання для анімації на DialogFragment.
ASH

Відповіді:


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

Тоді вам просто потрібно визначити тему, яка буде включати бажану анімацію. У style.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вирощування з точного центру рядка.

Удачі!


Гарна ідея з кількома анімаціями для різних місць на екрані. Це хакерство, але, здається, це єдиний спосіб.
Едвард Дейл,

Це відбудеться лише з> API 11 @Kiran Babu відповідь - це обхід
Blundell

Чи знаєте ви, чи є можливий спосіб отримати зворотний дзвінок, коли ці анімації завершені? Я хотів би зробити анімацію з двох частин, в якій діалогове вікно вбудовується, а потім зникає подання. Як я можу прив’язати слухача до віконних анімацій?
android_student

Чудово! Це саме те, що я шукав!
Олексій Тимощенко

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
Можливо, це не зовсім те, про що вимагає ОП, але, я думаю, це хороша точка входу.
mdelolmo

2
Прекрасний приклад! Єдиний зразок, який працював у мене. Фокус полягає у встановленні анімації / теми в методі onActivityCreated (...)
tomurka

3
Це може бути корисно, але це взагалі не відповідає на питання.
Олайїнка

Чи знаєте ви, чи є можливий спосіб отримати зворотний дзвінок, коли ці анімації завершені? Я хотів би зробити анімацію з двох частин, в якій діалогове вікно вбудовується, а потім зникає подання. Як я можу прив’язати слухача до віконних анімацій?
android_student

22

У DialogFragment є загальнодоступний метод getTheme (), за яким ви можете переїхати саме з цієї причини. Це рішення використовує менше рядків коду:

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

1
Більше не турбуйтесь ... Просте і пряме рішення.
Noundla Sandeep

Це найкраща відповідь для мене!
суперкористувач

Хоча це не пов'язано з початковим запитанням, у мене була галерея, показана в MainAcitvity, де клік користувача активує слайд-шоу в DialogFragment. Однак у MainActivity є поштовхи, коли вони повертаються із слайд-шоу. Це пов’язано з використанням MainActivity, AppTheme.NoActionBarпоки DialogFragment використовує за замовчуванням AppTheme. Наведений вище метод вирішив мою проблему, маючи узгоджену тему як у фрагменті, так і в діяльності.
tingyik90

Брате, ти геній
Jacky Chong

Це рішення спрацювало для мене. Однак одне мене бентежило; встановлення 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();

}


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 for Honeycomb Animation API сумісність аж до API рівня 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

Додайте цей код до значень 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"/>

дзвінок на 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;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.