DialogFragment
当用户点击 a 中的一行时,我正在显示a ListView
。我想为对话框的显示设置动画,使其从行的中心开始增长。从启动器打开文件夹时可以看到类似的效果。
我的一个想法是TranslateAnimation
和的组合ScaleAnimation
。还有其他方法吗?
DialogFragment
当用户点击 a 中的一行时,我正在显示a ListView
。我想为对话框的显示设置动画,使其从行的中心开始增长。从启动器打开文件夹时可以看到类似的效果。
我的一个想法是TranslateAnimation
和的组合ScaleAnimation
。还有其他方法吗?
作为该类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>
动画输出.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
增长。
祝你好运!
看看这段代码,它对我有用
// 上滑动画
<?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>
// 向下滑动动画
<?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;
}
DialogFragment 有一个公共的 getTheme() 方法,您可以出于这个确切原因覆盖该方法。此解决方案使用更少的代码行:
public class MyCustomDialogFragment extends DialogFragment{
...
@Override
public int getTheme() {
return R.style.MyThemeWithCustomAnimation;
}
}
要获得带有动画的全屏对话框,请编写以下...
款式:
<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());
}
在 DialogFragment 中,自定义动画被称为 onCreateDialog。'DialogAnimation' 是上一个答案中的自定义动画样式。
public Dialog onCreateDialog(Bundle savedInstanceState)
{
final Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;
return dialog;
}
在对话框片段的 onStart 中使用装饰视图
@Override
public void onStart() {
super.onStart();
final View decorView = getDialog()
.getWindow()
.getDecorView();
decorView.animate().translationY(-100)
.setStartDelay(300)
.setDuration(300)
.start();
}
如果你想处理 API,你必须在 DialogFragemnt->onStart 内部而不是在 onCreateDialog 内部进行
@Override
public void onStart()
{
if (getDialog() == null)
{
return;
}
getDialog().getWindow().setWindowAnimations(
R.style.DlgAnimation);
super.onStart();
}
注意:这只是对其他答案的补充。
无论您选择哪种解决方案,您都可能遇到与我相同的问题。
在安装新版本之前,我需要从我的开发设备卸载游戏以使动画更改生效。
我不知道为什么,但我想这与 Android Studio 上的优化部署有关,无法识别这些更改。
你看过关于缩放视图的 Android 开发者培训吗?可能是一个很好的起点。
您可能想要创建一个自定义类来扩展DialogFragment
以使其正常工作。
此外,请查看 Jake Whartons NineOldAndroids的 Honeycomb Animation API 兼容性,一直到 API 级别 1。
在值动画上添加此代码
<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;