Android Dialog弹出及隐藏动画
Android开发中,Dialog是必不可少的组件之一,通常一些活动、提示等内容的展示依赖于Dialog实现。最近需要实现一个需求,Dialog从某View中心位置弹出,隐藏的时候执行相反的动画。
实现也比较简单,使用属性动画可以轻易实现该效果,这里简要记录一下,便于以后回顾或复用。封装的Dialog代码如下:
public class BaseAnimDialog extends Dialog {
private AnimatorSet showAnimSet;
private AnimatorSet dismissAnimSet;
private static final long DEFAULT_DURATION = 800;
private float transX;
private float transY;
public BaseAnimDialog(@NonNull Context context) {
super(context, R.style.Dialog);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void show() {
try {
super.show();
View contentView = findViewById(R.id.content);
if (contentView != null) {
contentView.setVisibility(View.INVISIBLE);
}
showAnim();
} catch (Throwable e) {
e.printStackTrace();
}
}
@Override
public void dismiss() {
try {
super.dismiss();
} catch (Throwable e) {
e.printStackTrace();
}
}
private void showAnim() {
// dialog主体布局id需要设置为content
View contentView = findViewById(R.id.content);
if (contentView == null) {
return;
}
if (showAnimSet == null) {
showAnimSet = new AnimatorSet();
ObjectAnimator transXAnim = ObjectAnimator.ofFloat(contentView, "translationX", transX, 0);
ObjectAnimator transYAnim = ObjectAnimator.ofFloat(contentView, "translationY", transY, 0);
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(contentView, "scaleX", 0, 1);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(contentView, "scaleY", 0, 1);
showAnimSet.playTogether(transXAnim, transYAnim, scaleXAnim, scaleYAnim);
showAnimSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
contentView.setVisibility(View.VISIBLE);
}
});
showAnimSet.setDuration(DEFAULT_DURATION);
}
if (showAnimSet.isRunning()) {
return;
}
showAnimSet.start();
}
// 外部调用dismissAnim,替代Dialog本身的dismiss方法
public void dismissAnim() {
View contentView = findViewById(R.id.content);
if (contentView == null) {
return;
}
if (dismissAnimSet == null) {
dismissAnimSet = new AnimatorSet();
ObjectAnimator transXAnim = ObjectAnimator.ofFloat(contentView, "translationX", 0, transX);
ObjectAnimator transYAnim = ObjectAnimator.ofFloat(contentView, "translationY", 0, transY);
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(contentView, "scaleX", 1, 0);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(contentView, "scaleY", 1, 0);
dismissAnimSet.playTogether(transXAnim, transYAnim, scaleXAnim, scaleYAnim);
dismissAnimSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
dismiss();
}
});
dismissAnimSet.setDuration(DEFAULT_DURATION);
}
if (dismissAnimSet.isRunning()) {
return;
}
dismissAnimSet.start();
}
// 传入锚点view数据
public void setAnchorInfo(float x, float y, float width, float height) {
// dialog 宽200dp 高230dp
transX = x - (PxUtil.screenWidth() - PxUtil.dp2xp(200)) / 2f - PxUtil.dp2xp(200) / 2f + width / 2f;
transY = y - (PxUtil.screenHeight() - PxUtil.dp2xp(230)) / 2f - PxUtil.dp2xp(230) / 2f + height / 2f;
}
}
Dialog使用Style如下:
<style name="Dialog" parent="@style/Theme.AppCompat.Light.NoActionBar">
<item name="windowNoTitle">true</item><!--没有标题 -->
<item name="windowActionBar">true</item><!--没有ActionBar -->
<item name="android:windowFullscreen">true</item><!--全屏 -->
<item name="android:windowIsFloating">false</item><!-- 浮动在activity之上,左右两边不会填充屏幕 -->
<item name="android:windowIsTranslucent">true</item><!-- 半透明 -->
<item name="android:windowFrame">@null</item><!--无边框 -->
<item name="android:backgroundDimEnabled">true</item><!-- 设置背景模糊-->
<item name="android:padding">0dp</item><!--内边距-->
<item name="android:windowBackground">@android:color/transparent</item><!-- 设置背景模糊-->
</style>
另外,如果项目中本身引入的有FlycoDialog,继承该库中的BaseDialog直接设置showAnim和dismissAnim方法更为简单。