Tampilkan DialogFragment dengan animasi yang berkembang dari satu titik

94

Saya menunjukkan DialogFragmentsaat pengguna mengetuk baris dalam ListView. Saya ingin menganimasikan tampilan dialog sehingga dialog itu tumbuh dari tengah baris. Efek serupa dapat dilihat saat membuka folder dari peluncur.

Satu gagasan yang saya miliki adalah kombinasi dari TranslateAnimationdan ScaleAnimation. Apakah ada cara lain?

Edward Dale
sumber
1
Lihat tautan untuk animasi di DialogFragment.
ASH

Jawaban:

170

Sebagai DialogFragmentpembungkus Dialogkelas, Anda harus menetapkan tema ke basis Anda Dialoguntuk mendapatkan animasi yang Anda inginkan:

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

Kemudian Anda hanya perlu menentukan tema yang akan menyertakan animasi yang Anda inginkan. Di styles.xml tambahkan tema khusus Anda:

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

Sekarang tambahkan file animasi di folder res / anim :

( android:pivotYadalah kuncinya)

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>

Terakhir, hal yang sulit di sini adalah membuat animasi Anda tumbuh dari tengah setiap baris. Saya kira baris tersebut mengisi layar secara horizontal jadi, di satu sisi android:pivotXnilainya akan statis. Di sisi lain, Anda tidak dapat mengubah android:pivotYnilai secara terprogram.

Yang saya sarankan adalah, Anda menentukan beberapa animasi yang masing-masing memiliki nilai persentase yang berbeda pada android:pivotYatribut (dan beberapa tema yang mereferensikan animasi tersebut). Kemudian, saat pengguna mengetuk baris, hitung posisi Y dalam persentase baris di layar. Mengetahui posisi dalam persentase, tetapkan tema ke dialog Anda yang memiliki nilai yang sesuai android:pivotY.

Ini bukan solusi yang tepat tetapi bisa melakukan trik untuk Anda. Jika Anda tidak menyukai hasilnya, maka saya sarankan untuk melupakan DialogFragmentdan menganimasikan Viewpertumbuhan sederhana dari tengah baris yang tepat.

Semoga berhasil!

Xavi Gil
sumber
Ide bagus dengan beberapa animasi untuk lokasi berbeda di layar. Ini peretasan, tapi sepertinya itu satu-satunya cara.
Edward Dale
Ini hanya akan bekerja dengan> API 11 Jawaban @Kiran Babu adalah solusi
Blundell
Apakah Anda tahu jika ada cara yang mungkin untuk mendapatkan panggilan balik saat animasi ini selesai? Saya ingin membuat animasi 2-bagian, di mana dialog masuk, dan kemudian memudarkan tampilan. Bagaimana cara saya mendekati pendengar ke windowAnimations?
android_student
Luar biasa! Sungguh yang saya cari!
Aleksey Timoshchenko
2
Menyetel tema bisa sesederhana melakukannya setStyle(DialogFragment.STYLE_NORMAL, R.style.MyCustomTheme)di onCreate(bundle)Lihat: developer.android.com/reference/android/app/DialogFragment.html
tropicalfish
121

Lihat kode ini, ini berfungsi untuk saya

// Animasi geser ke atas

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

// Animasi dowm geser

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

// Gaya

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

// Di Dalam Fragmen Dialog

@Override
public void onActivityCreated(Bundle arg0) {
    super.onActivityCreated(arg0);
    getDialog().getWindow()
    .getAttributes().windowAnimations = R.style.DialogAnimation;
}
Kiran Babu
sumber
8
Maaf, ini sama sekali tidak menjawab pertanyaan saya.
Edward Dale
3
Ini mungkin tidak persis seperti yang diminta OP, tapi menurut saya ini adalah titik masuk yang bagus.
mdelolmo
2
Contoh yang bagus! Satu-satunya sampel yang berhasil untuk saya. Triknya adalah menyetel animasi / tema dalam metode onActivityCreated (...)
tomurka
3
Ini mungkin berguna tetapi tidak menjawab pertanyaan sama sekali.
Olayinka
Apakah Anda tahu jika ada cara yang mungkin untuk mendapatkan panggilan balik saat animasi ini selesai? Saya ingin membuat animasi 2-bagian, di mana dialog masuk, dan kemudian memudarkan tampilan. Bagaimana cara saya mendekati pendengar ke windowAnimations?
android_student
22

DialogFragment memiliki metode getTheme () publik yang dapat Anda kendalikan karena alasan yang tepat ini. Solusi ini menggunakan lebih sedikit baris kode:

public class MyCustomDialogFragment extends DialogFragment{
    ...
    @Override
    public int getTheme() {
        return R.style.MyThemeWithCustomAnimation;
    }
}
Siavash
sumber
1
Tidak ada lagi kekhawatiran ... Solusi sederhana dan mudah.
Noundla Sandeep
Ini jawaban terbaik untukku!
superuser
Meskipun tidak terkait dengan pertanyaan awal, saya memiliki galeri yang ditampilkan di MainAcitvity di mana klik pengguna akan mengaktifkan tampilan slide di DialogFragment. Namun ada sentakan dalam MainActivity setiap kali kembali dari tayangan slide. Ini karena MainActivity menggunakan AppTheme.NoActionBarsaat DialogFragment menggunakan default AppTheme. Metode di atas memecahkan masalah saya dengan memiliki tema yang konsisten baik dalam fragmen maupun aktivitas.
tingyik90
Bro, kamu jenius
Jacky Chong
Solusi ini berhasil untuk saya. Namun ada satu hal yang membuatku bingung; pengaturan windowEnterAnimation atau windowExitAnimation langsung di Tema tidak akan membuat perbedaan dalam animasi DialogFragments saya. Satu-satunya hal yang berhasil bagi saya adalah menyetel windowAnimationStyle ke file XML terpisah yang menentukan gaya dan menyetel animasi masuk dan keluar di sana
szaske
10

Untuk mendapatkan dialog layar penuh dengan animasi, tulis yang berikut ini ...

Gaya:

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

Kode 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());
}
maXp
sumber
4

Gunakan tampilan dekorasi di dalam onStart di fragmen dialog Anda

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


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

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

}
Horatio
sumber
1
Tampilan yang mendasarinya tampaknya tidak dapat diklik setelah itu
HaydenKai
3

Di DialogFragment, animasi kustom disebut onCreateDialog. 'DialogAnimation' adalah gaya animasi kustom di jawaban sebelumnya.

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

Pernahkah Anda melihat Pelatihan Pengembang Android tentang Memperbesar Tampilan ? Mungkin titik awal yang bagus.

Anda mungkin ingin membuat kelas kustom yang diperluas DialogFragmentagar ini berfungsi.

Selain itu, lihat kompatibilitas Jake Whartons NineOldAndroids for Honeycomb Animation API hingga API Level 1.

Greve
sumber
1

Jika Anda ingin mengerjakan API, Anda harus melakukannya di dalam DialogFragemnt-> onStart dan bukan di dalam onCreateDialog

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

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

        super.onStart();
    }
Tambahan
sumber
Solusi terbaik menurut saya. Ini berfungsi untuk AlertDialogs juga, cukup gunakan di onShowListener. Terima kasih!
Gabor Novak
0

Tambahkan kode ini pada nilai 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"/>

panggil di styles.xml

<style name="DialogScale">
    <item name="android:windowEnterAnimation">@anim/scale_in</item>
    <item name="android:windowExitAnimation">@anim/scale_out</item>
</style>

Pada kode java: setel Onclick

public void onClick(View v) {
        fab_onclick(R.style.DialogScale, "Scale" ,(Activity) context,getWindow().getDecorView().getRootView());
      //  Dialogs.fab_onclick(R.style.DialogScale, "Scale");

    }

pengaturan pada metode:

alertDialog.getWindow().getAttributes().windowAnimations = type;
Mue
sumber