Изменить переход DialogFragment для входа/выхода непосредственно перед закрытием

У меня есть DialogFragment, и я установил анимацию для входа/выхода в методе onActivityCreated, как показано ниже:

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

Мои файлы стиля DialogAnimation выглядят следующим образом:

<style name="DialogAnimation">
        <item name="android:windowEnterAnimation">@android:anim/fade_in</item>
        <item name="android:windowExitAnimation">@android:anim/fade_out</item>
    </style>

Это работает для меня сейчас ...

Теперь моя проблема в том, что я хочу иметь две разные анимации выхода: одну для нажатия кнопки «ОК» и одну для кнопки отмены. Итак, что я сделал, так это попытался изменить переход непосредственно перед увольнением, но это не сработало.

Любое решение о том, как это может быть достигнуто?

Вот что я пробовал:

  @Override
    public void onClick(View v) {
        getDialog().getWindow()
                .getAttributes().windowAnimations = R.style.DialogAnimation2;
        this.dismiss();
    }

person Dominic D'Souza    schedule 02.10.2015    source источник
comment
попробуйте это adtandroid.blogspot.com/2014/12/   -  person Mohammad Hossein Gerami    schedule 20.10.2015
comment
В блоге, который вы разместили, похоже, нет ответа   -  person Dominic D'Souza    schedule 21.10.2015


Ответы (6)


Вы можете сделать это внутри своего DialogFragment, не меняя

getDialog().getWindow()
            .getAttributes().windowAnimations

Вы должны анимировать вид декора в onStart и onClick.

Это вырезанный код:

Сначала создайте диалоговое окно

@Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity())
                .setTitle("Hello from animated dialog :)")
                .setNegativeButton("Cancel",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {
                                //we have to add button here and then override it's click in onStart
                            }
                        }
                )
                .setCancelable(false)
                .create();
    }

Затем переопределить метод onStart

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

        AlertDialog dialog = (AlertDialog)getDialog();

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

        ObjectAnimator scaleDown = ObjectAnimator.ofPropertyValuesHolder(decorView,
                PropertyValuesHolder.ofFloat("scaleX", 0.0f, 1.0f),
                PropertyValuesHolder.ofFloat("scaleY", 0.0f, 1.0f),
                PropertyValuesHolder.ofFloat("alpha", 0.0f, 1.0f));
        scaleDown.setDuration(2000);
        scaleDown.start();


        Button positiveButton = dialog.getButton(Dialog.BUTTON_NEGATIVE);
        positiveButton.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                final View decorView = getDialog()
                        .getWindow()
                        .getDecorView();

                ObjectAnimator scaleDown = ObjectAnimator.ofPropertyValuesHolder(decorView,
                        PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.0f),
                        PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0.0f),
                        PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.0f));
                scaleDown.addListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        dismiss();
                    }

                    @Override
                    public void onAnimationStart(Animator animation) {
                    }
                    @Override
                    public void onAnimationCancel(Animator animation) {
                    }
                    @Override
                    public void onAnimationRepeat(Animator animation) {
                    }
                });
                scaleDown.setDuration(2000);
                scaleDown.start();
            }
        });
    }

Вот анимация результата

Демонстрация результата


И если вы удалите свойства масштаба из моего кода, вы получите только альфа-анимацию. Именно так, как вы хотели.

Удали это:

PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.0f),
PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0.0f),
person Danylo Volokh    schedule 25.10.2015
comment
Когда я делаю это в decorView, моя проблема заключается в том, что размер окна равен размеру диалога, поэтому анимация выходит за пределы окна. - person Dominic D'Souza; 27.10.2015
comment
На самом деле я использую анимацию перевода и вращения. Я привел пример альфа-анимации, чтобы все было просто. - person Dominic D'Souza; 27.10.2015
comment
Это правильное решение +1, @DominicD'Souza, если хотите, вы можете воспроизводить анимацию в любом представлении из макета вашего DialogFragment. Если вы проверите исходники класса 'Dialog', то увидите, что все манипуляции выполняются с представлением декора. - person romtsn; 27.10.2015
comment
Что, если у него нет отрицательной или положительной кнопки? - person X09; 22.06.2016
comment
Как это возможно, если не снизу вверх? Нравится скользить вверх? - person Armando Esparza García; 01.11.2019

Вы можете установить анимацию вверх и вниз для фрагмента диалога. В 'res/anim' добавьте два файла:

// Анимация слайда вверх

<?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:toYDelta="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>

// Стиль

<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;
}
person Akhil Jayakumar    schedule 21.10.2015
comment
Я сделал это, моя проблема заключается в том, чтобы иметь 2 разные анимации выхода: одну для положительного нажатия кнопки и одну для отрицательного нажатия кнопки. - person Dominic D'Souza; 21.10.2015
comment
вы можете вызвать слайд вверх/вниз при нажатии положительной/отрицательной кнопки - person Akhil Jayakumar; 21.10.2015
comment
Основная проблема, с которой я сталкиваюсь, заключается в том, что вы не можете изменить windowAnimations после создания диалогового окна. - person Dominic D'Souza; 21.10.2015
comment
поэтому вызов getDialog().getWIndow().getAttributes().windowAnimations=R.style.DialogCancelAnimation не будет работать в кнопке отмены при нажатии - person Dominic D'Souza; 21.10.2015
comment
у меня сработало, замените «android: toXDelta» в slideUp на «android: toYDelta» - person Usman Rana; 22.08.2016
comment
@Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Window window = getDialog().getWindow(); if (window!=null) window.getAttributes() .windowAnimations = R.style.DialogAnimation; } используйте это, чтобы избежать нулевого указателя. - person Sai; 13.08.2017

Я думаю, что лучший подход — вызывать различные анимации при нажатии кнопки. Следовательно, у вас будет что-то похожее на следующее:

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button OkButton = (Button) findViewById(R.id.btnOk);
        Button CancelButton = (Button) findViewById(R.id.btnCancel);

        OkButton.setOnClickListener(new OnClickListener() {

            @Override    
            public void onClick(View view) {
                    getDialog().getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;    
            }
        });
        return true;

        CancelButton.setOnClickListener(new OnClickListener() {

            @Override    
            public void onClick(View view) {
                getDialog().getWindow().getAttributes().windowAnimations = R.style.DialogAnimation2;    
            }
        });
        return true;
    }

На вашем месте я бы также использовал правильные соглашения об именах для дальнейшего использования. Например, установка DialogAnimation на OkAnimation и DialogAnimation2 на CancelAnimation.

Дома это помогает :)

person Michele La Ferla    schedule 21.10.2015
comment
Я пробовал приведенный выше код, как указано в моем вопросе. Кажется, вы можете установить только windowAnimation в onCreate диалогового окна.. поэтому приведенный выше код не работает для меня.. Вы пробовали.? а у вас работает? - person Dominic D'Souza; 21.10.2015
comment
OnClockListeners всегда используются в методах onCreate, OnCreateView или onStart. Я отредактировал ответ, чтобы предоставить вам решение. - person Michele La Ferla; 23.10.2015

Один простой способ сделать то, что вы хотите, — это использовать прослушиватели анимации.

    animation.setAnimationListener(new AnimationListener() {

        @Override
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationEnd(Animation animation) {
            // TODO Auto-generated method stub
            // dismiss your dialog in here and it will work
        }
    });

Запустите анимацию в методе onclick и закройте диалоговое окно в методе onAnimationEnd(). Возможно, вам придется создавать объекты анимации и запускать их вручную с помощью метода View startAnimation(animation).

person Arslan Ashraf    schedule 26.10.2015

Вы должны установить тему для своего базового диалога

пусть говорят:-

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> 

обратитесь к этому

person Praveen Sharma    schedule 23.10.2015

Если кто-то в конечном итоге использует ответ onCreateDialog во многих диалогах, вы можете использовать эту функцию расширения Kotlin.

//ExtensionFunctions.kt file
fun Dialog.setWindowAnimations(@StyleRes id: Int): Dialog {
    this.window?.attributes?.windowAnimations = id
    return this
}

и в вашей функции onCreateDialog

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return super.onCreateDialog(savedInstanceState)
        .setWindowAnimations(R.style.MyDialogAnimation)
}
person 9paradox    schedule 13.06.2021