Показать диалоговое окно с анимацией, растущей с точки
Я показываю DialogFragment
, когда пользователь нажимает на строку в ListView
. Я хотел бы оживить показ диалога, чтобы он вырос из центра строки. Аналогичный эффект можно увидеть при открытии папки из панели запуска.
Одна идея, которую я имел, это комбинация TranslateAnimation
и ScaleAnimation
. Есть ли другой способ?
Ответы
Ответ 1
Будучи 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();
}
}
Затем вам просто нужно определить тему, которая будет включать вашу желаемую анимацию. В 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>
Теперь добавьте файлы анимации в папку 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
, растущий из точного центра строки.
Удачи!
Ответ 2
Проверьте этот код, он работает для меня
//Слайд анимации
<?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;
}
Ответ 3
DialogFragment имеет общедоступный метод getTheme(), который вы можете преодолеть по этой точной причине. Это решение использует меньше строк кода:
public class MyCustomDialogFragment extends DialogFragment{
...
@Override
public int getTheme() {
return R.style.MyThemeWithCustomAnimation;
}
}
Ответ 4
В DialogFragment пользовательская анимация называется onCreateDialog. "DialogAnimation" - это стиль пользовательской анимации в предыдущем ответе.
public Dialog onCreateDialog(Bundle savedInstanceState)
{
final Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;
return dialog;
}
Ответ 5
Посмотрели ли вы на Android Developers Training на Масштабирование вида? Может быть хорошей отправной точкой.
Вероятно, вы хотите создать пользовательский класс, расширяющий DialogFragment
, чтобы это работало.
Кроме того, посмотрите на Jake Whartons NineOldAndroids для совместимости API совместимости Honeycomb с API-интерфейсом API уровня 1.
Ответ 6
Использовать декорирование внутри onStart в фрагменте диалога
@Override
public void onStart() {
super.onStart();
final View decorView = getDialog()
.getWindow()
.getDecorView();
decorView.animate().translationY(-100)
.setStartDelay(300)
.setDuration(300)
.start();
}
Ответ 7
Чтобы получить полноэкранный диалог с анимацией, напишите следующее...
Стили:
<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>
Рез /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>
Рез /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());
}
Ответ 8
Если вы хотите работать с API-интерфейсами, вам нужно сделать внутри DialogFragemnt- > onStart, а не внутри onCreateDialog
@Override
public void onStart()
{
if (getDialog() == null)
{
return;
}
getDialog().getWindow().setWindowAnimations(
R.style.DlgAnimation);
super.onStart();
}