首先我们需要创建一个基类Dialog,方便子dialog进行统一集成
package com.example.commonlib.dialog;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import androidx.annotation.AnimRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import com.example.commonlib.R;
import java.lang.ref.WeakReference;
/**
* Created by malei on 2019-12-06
* Describe:
*
*该弹出框的特点是:
* 当有新的弹出框时,会根据久的弹出框的level进行比较,判断是否需要马上展示。
* 三个弹出框需要展示时候,每次只展示一个,每次消失一个在弹下一个
*
*/
public abstract class BaseDialogFragment extends DialogFragment implements DialogInterface.OnKeyListener, Comparable<BaseDialogFragment> {
protected final String TAG = getClass().getSimpleName() + System.currentTimeMillis();
protected Window mWindow;
private WeakReference<IInnerDialogCallback> mInnerDialogCallbackRef;
private WeakReference<IDialogCallback> mDialogCallbackRef;
protected View mDialogView;
private boolean mCanceledOnTouchOutside;
private volatile boolean mIsClosing;
private volatile boolean mShowNextDialogAfterClosed = true;
private int mPriorityLevel = DialogPriority.LEVEL_DEFAULT;
private boolean mDisableEnterAnim;
private boolean mDisableExitAnim;
private @AnimRes int mDialogEnterAnimResId = R.anim.dialog_zoom_in;
private @AnimRes int mDialogExitAnimResId = R.anim.dialog_zoom_out;
private boolean mDisableBackPress;
private boolean mEnableFullScreen;
protected void onShow(){} //当dialog显示的时候触发
protected void onConfirm(){} //确定按钮点击
protected void onClose(){} //取消按钮点击
protected void onBackPressed(){} //点击back的触发
protected void onDismiss(){} //当前dailog消失的时候触发
protected void clearDisposable() { } //当点击确定,取消,back,等消失的时候触发
/**
* 用于部分定制弹窗在从后台切回前台重新展示时的数据设置
*/
protected void onDialogInit() {}
protected abstract View createLayout(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState);
protected abstract void initView(View dialogView);
@Override
public void onActivityCreated(Bundle savedInstanceState) {
if (getDialog() == null) {
Context context = getContext();
while (context instanceof ContextWrapper) {
if (context instanceof FragmentActivity) {
break;
}
context = ((ContextWrapper) context).getBaseContext();
}
if (context instanceof FragmentActivity) {
((FragmentActivity) context).finish();
return;
} else {
setShowsDialog(false);
}
}
super.onActivityCreated(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mDialogView = createLayout(inflater, container, savedInstanceState);
initView(mDialogView);
return mDialogView;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mWindow = getDialog().getWindow();
if (mWindow != null) {
mWindow.setWindowAnimations(mDisableEnterAnim ? R.style.dialog_without_anim_style : mDialogEnterAnimResId);
mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
if (mEnableFullScreen) {
mWindow.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
}
}
getDialog().setOnKeyListener(this);
}
public View getDialogView() {
return mDialogView;
}
public void enableFullScreen(boolean enableFullScreen) {
mEnableFullScreen = enableFullScreen;
}
/**
* @Time: 2019-12-06 16:23
* @Des: 点击周边是否消失
*/
public BaseDialogFragment setCanceledOnTouchOutside(boolean canceledOnTouchOutside) {
mCanceledOnTouchOutside = canceledOnTouchOutside;
return this;
}
/**
* @Time: 2019-12-06 16:24
* @Des: 是否可以点击返回键
*/
public BaseDialogFragment disableBackPress(boolean disableBackPress) {
mDisableBackPress = disableBackPress;
return this;
}
@Override
public void onStart() {
super.onStart();
mWindow = getDialog().getWindow();
if (mWindow != null) {
mWindow.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
int width = ViewGroup.LayoutParams.MATCH_PARENT;
int height = ViewGroup.LayoutParams.MATCH_PARENT;
mWindow.setLayout(width, height);
mWindow.setGravity(Gravity.CENTER);
}
}
@Override
public void onResume() {
super.onResume();
getDialog().setCanceledOnTouchOutside(mCanceledOnTouchOutside);
}
@Override
@SuppressLint("RestrictedApi")
public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, STYLE_NO_FRAME);
}
/**
* 按全局优先级统一管理弹窗
*/
public final void show() {
DialogManager.INSTANCE.showDialog(this);
}
/**
* NOTE: 外部直接调用此方法则对应dialog不受统一调配,如需要使用优先级统一调配,请使用{@link #show()}
*/
public void show(FragmentManager manager, String tag) {
if (manager == null || manager.isDestroyed() || manager.isStateSaved()) {
return;
}
super.show(manager, TextUtils.isEmpty(tag) ? TAG : tag);
onShow();
if (mDialogCallbackRef != null) {
IDialogCallback callback = mDialogCallbackRef.get();
if (callback != null) {
callback.onShow();
}
}
}
/**
* NOTE: 外部直接调用此方法则对应dialog不受统一调配,如需要使用优先级统一调配,请使用{@link #show()}
*/
public void showAllowingStateLoss(FragmentManager manager, String tag) {
try {
FragmentTransaction ft = manager.beginTransaction();
String tagV = TextUtils.isEmpty(tag) ? TAG : tag;
if (!isAdded() && null == manager.findFragmentByTag(tagV)) {
ft.add(this, tagV);
} else {
ft.show(this);
}
ft.commitAllowingStateLoss();
manager.executePendingTransactions();
onShow();
if (mDialogCallbackRef != null) {
IDialogCallback callback = mDialogCallbackRef.get();
if (callback != null) {
callback.onShow();
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (mDisableBackPress) {
return true;
}
if (!mIsClosing) {
clearDisposable();
if (mDialogCallbackRef != null) {
IDialogCallback callback = mDialogCallbackRef.get();
if (callback != null) {
callback.onBackPressed();
}
}
onBackPressed();
closeDialog(true);
return true;
}
return true;
}
return false;
}
public boolean isClosing() {
return mIsClosing;
}
public BaseDialogFragment setDialogArguments(@Nullable Bundle args) {
super.setArguments(args);
return this;
}
public BaseDialogFragment disableEnterAnim(boolean disableEnterAnim) {
mDisableEnterAnim = disableEnterAnim;
return this;
}
public BaseDialogFragment disableExitAnim(boolean disableExitAnim) {
mDisableExitAnim = disableExitAnim;
return this;
}
public BaseDialogFragment setDialogEnterAnimResId(@StyleRes int dialogEnterAnimResId) {
mDialogEnterAnimResId = dialogEnterAnimResId;
return this;
}
public BaseDialogFragment setDialogExitAnimResId(@AnimRes int dialogExitAnimResId) {
mDialogExitAnimResId = dialogExitAnimResId;
return this;
}
/**
* 自定义dialog请勿使用
*/
void setInnerDialogCallback(IInnerDialogCallback dialogCallback) {
if (dialogCallback != null) {
mInnerDialogCallbackRef = new WeakReference<>(dialogCallback);
} else {
mInnerDialogCallbackRef = null;
}
}
/**
* 自定义dialog选用,需额外回调时使用,否则仅override同名abstract方法即可
*/
public BaseDialogFragment setDialogCallback(IDialogCallback dialogCallback) {
if (dialogCallback != null) {
mDialogCallbackRef = new WeakReference<>(dialogCallback);
} else {
mDialogCallbackRef = null;
}
return this;
}
/**
* perform confirm button or confirm zone
* 确定按钮点击
*/
public void performConfirm() {
if (mIsClosing) {
return;
}
clearDisposable();
onConfirm();
if (mDialogCallbackRef != null) {
IDialogCallback callback = mDialogCallbackRef.get();
if (callback != null) {
callback.onConfirm();
}
}
closeDialog(true);
}
/**
* perform close button or close zone
* 取消按钮点击
*/
public void performClose() {
if (mIsClosing) {
return;
}
clearDisposable();
onClose();
if (mDialogCallbackRef != null) {
IDialogCallback callback = mDialogCallbackRef.get();
if (callback != null) {
callback.onClose();
}
}
closeDialog(true);
}
void closeDialogForNow() {
if (getFragmentManager() != null) {
dismissAllowingStateLoss();
}
}
void closeDialogImmediately() {
if (mIsClosing) {
return;
}
mIsClosing = true;
closeDialogImmediately(mShowNextDialogAfterClosed);
}
private void closeDialogImmediately(boolean showNextDialog) {
clearDisposable();
if (getFragmentManager() != null) {
dismissAllowingStateLoss();
}
if (mDialogCallbackRef != null) {
IDialogCallback callback = mDialogCallbackRef.get();
if (callback != null) {
callback.onDismiss();
}
mDialogCallbackRef = null;
}
if (mInnerDialogCallbackRef != null) {
IInnerDialogCallback dialogCallback = mInnerDialogCallbackRef.get();
if (dialogCallback != null) {
dialogCallback.onDismiss(showNextDialog);
}
mInnerDialogCallbackRef = null;
}
onDismiss();
}
public void closeDialog(final boolean showNextDialog) {
if (mIsClosing) {
return;
}
mIsClosing = true;
mShowNextDialogAfterClosed = showNextDialog;
if (mDisableExitAnim) {
closeDialogImmediately(showNextDialog);
} else {
if (mDialogView != null) {
Animation closeAnim = AnimationUtils.loadAnimation(DialogManager.mAppContext, mDialogExitAnimResId);
closeAnim.setFillAfter(true);
closeAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
mDialogView.postDelayed(new Runnable() {
@Override
public void run() {
closeDialogImmediately(showNextDialog);
}
}, 50);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
mDialogView.startAnimation(closeAnim);
} else {
closeDialogImmediately(showNextDialog);
}
}
}
/**
* @Time: 2019-12-06 16:25
* @Des: 设置级别
*/
public BaseDialogFragment setPriorityLevel(int priorityLevel) {
mPriorityLevel = priorityLevel;
return this;
}
public int getPriorityLevel() {
return mPriorityLevel;
}
@Override
public final int compareTo(BaseDialogFragment dialogFragment) {
return dialogFragment != null ? Integer.compare(mPriorityLevel, dialogFragment.mPriorityLevel) : 1;
}
}
2.创建dialog的统一管理类
package com.example.commonlib.dialog;
import android.app.Application;
import android.content.Intent;
import androidx.annotation.NonNull;
import java.lang.ref.WeakReference;
import java.util.concurrent.PriorityBlockingQueue;
/**
* Created by malei on 2019-12-06
* Describe:
*/
public enum DialogManager {
INSTANCE;
private static final int CUR_CONTAINER_STATE_ON_INIT = 0; // 当前dialog容器处于初始化过程中
private static final int CUR_CONTAINER_STATE_AVAILABLE = 1; // 当前有可用dialog容器
private static final int CUR_CONTAINER_STATE_INVALID = 2; // 当前无可用dialog容器
public static Application mAppContext ;
private PriorityBlockingQueue<BaseDialogFragment> mDialogFragmentsQueue = new PriorityBlockingQueue<>();
private WeakReference<DialogActivity> mCurDialogContainer;
private volatile boolean mIsInterrupted;
private volatile int mCurContainerState = CUR_CONTAINER_STATE_INVALID;
DialogManager() {
}
public synchronized boolean isNonValidDialog() {
return mIsInterrupted || mDialogFragmentsQueue.isEmpty();
}
public synchronized BaseDialogFragment peekTopDialog() {
return mDialogFragmentsQueue.peek();
}
public synchronized void removeCertainDialog(BaseDialogFragment dialogFragment) {
if (dialogFragment == null) {
return;
}
mDialogFragmentsQueue.remove(dialogFragment);
}
public synchronized void showDialog(@NonNull BaseDialogFragment dialogFragment) {
mDialogFragmentsQueue.put(dialogFragment);
tryShowDialog();
}
private synchronized void tryShowDialog() {
if (mIsInterrupted) {
return;
}
if (mCurContainerState == CUR_CONTAINER_STATE_AVAILABLE) {
triggerShowNextDialog();
} else if (mCurContainerState == CUR_CONTAINER_STATE_INVALID) {
if (!mDialogFragmentsQueue.isEmpty()) {
createNewDialogContainer();
}
} else if (mCurContainerState == CUR_CONTAINER_STATE_ON_INIT) {
// do nothing
} else {
// do nothing
}
}
private synchronized void triggerShowNextDialog() {
if (mCurDialogContainer != null) {
DialogActivity container = mCurDialogContainer.get();
if (container != null) {
container.showNextDialog();
return;
}
}
mCurContainerState = CUR_CONTAINER_STATE_INVALID;
}
private synchronized void createNewDialogContainer() {
mCurContainerState = CUR_CONTAINER_STATE_ON_INIT;
Intent intent = new Intent(mAppContext, DialogActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mAppContext.startActivity(intent);
}
/**
* NOTE: pls use it carefully !!! and pls remember to call this method again at another time to invoke dialog-queue !!!
*
* @param interrupt stop showing rest dialog for now or not
*/
public synchronized void setInterruptState(boolean interrupt) {
mIsInterrupted = interrupt;
tryShowDialog();
}
public synchronized void clearDialogContainer(@NonNull DialogActivity source) {
boolean validClear = true;
if (mCurDialogContainer != null) {
DialogActivity container = mCurDialogContainer.get();
if (container != null) {
if (!container.equals(source)) {
validClear = false;
}
}
}
if (validClear) {
mCurDialogContainer = null;
mCurContainerState = CUR_CONTAINER_STATE_INVALID;
}
}
public synchronized void setCurDialogContainer(DialogActivity container) {
mCurDialogContainer = new WeakReference<>(container);
mCurContainerState = CUR_CONTAINER_STATE_AVAILABLE;
tryShowDialog();
}
public synchronized void clear() {
if (!mDialogFragmentsQueue.isEmpty()) {
mDialogFragmentsQueue.clear();
}
mCurDialogContainer = null;
mCurContainerState = CUR_CONTAINER_STATE_INVALID;
mIsInterrupted = false;
}
}
3. dialig的几个接口类
package com.example.commonlib.dialog;
/**
* Created by malei on 2019-12-06
* Describe:当前和新的弹出框进行比较,根据级别处理两者之间的关系
*/
public class DialogUtil {
public static int compareDialogPriority(BaseDialogFragment curDialog, BaseDialogFragment newDialog) {
int result = PriorityCompareResult.INVALID_COMPARE;
if (newDialog != null && curDialog != null) {
int curPriority = curDialog.getPriorityLevel();
int newPriority = newDialog.getPriorityLevel();
if (curPriority == DialogPriority.LEVEL_0) {
// 清空现有弹窗栈,并展示新弹窗
result = PriorityCompareResult.SHOW_NEW_DIALOG_AND_CLEAR_ALREADY_SHOWN;
} else if (newPriority < curPriority) {
//如果新弹窗的级别小于当前弹窗,就展示新弹窗
result = PriorityCompareResult.SHOW_NEW_DIALOG;
} else {
//如果新弹窗的级别大于当前弹窗,新弹窗不会展示,还是会展示当前弹窗
result = PriorityCompareResult.HOLD_CUR_DIALOG;
}
} else if (newDialog != null) { // 展示新弹窗 只有新弹窗
result = PriorityCompareResult.SHOW_NEW_DIALOG;
} else if (curDialog != null) { // 维持当前弹窗状态不变 只有当前弹窗
result = PriorityCompareResult.HOLD_CUR_DIALOG;
}
return result;
}
}
/**
* Created by malei on 2019-12-06
* Describe:自定义dialog选用,需额外回调时使用,否则仅override同名abstract方法即可
*/
public interface IDialogCallback {
void onShow();
void onConfirm();
void onClose();
void onBackPressed();
void onDismiss();
}
/**
* Created by malei on 2019-12-06
* Describe:自定义dialog请勿使用
*/
public interface IInnerDialogCallback {
void onDismiss(boolean showNextDialog);
}
/**
* Created by malei on 2019-12-06
* Describe:
*/
public interface PriorityCompareResult {
int INVALID_COMPARE = -1;
int SHOW_NEW_DIALOG_AND_CLEAR_ALREADY_SHOWN = 0; // 只有新创建的弹窗设置为DialogPriority.LEVEL_0时,会清空所有旧的弹框,只展示新的弹窗
int SHOW_NEW_DIALOG = 1; // 有旧的弹窗,又创建新弹窗,展示新弹窗
int HOLD_CUR_DIALOG = 2; // 没有新弹窗,只有旧的弹窗没有销毁
}
/**
* Created by malei on 2019-12-06
* Describe:
*/
/**
*
* 弹窗优先级规则:
*
* 1)LEVEL_0的弹窗会关闭掉所有其他弹窗(包含已弹出但未关闭的其它LEVEL_0弹窗),并弹出自身
* 2)除LEVEL_0外,其余等级弹窗弹出时均不会关闭当前已弹出的弹窗
* 3)除LEVEL_0外,已弹出未关闭的弹窗不能被等于或小于其优先级的弹窗覆盖
*/
public class DialogPriority {
/**
* 默认优先级,普通弹窗(如规则说明弹窗、未明确要求优先级的弹窗等)使用
*/
public static final int LEVEL_DEFAULT = Integer.MAX_VALUE;
/**
* 谨慎使用!
*
* 立即弹出,并关闭目前已弹出的所有弹窗
*/
public static final int LEVEL_0 = 0;
/**
* 目前涵盖:热启动闪屏
*/
public static final int LEVEL_1000 = 1000;
}
4.创建一个Activity的中转类
package com.example.commonlib.dialog;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import java.lang.ref.WeakReference;
import java.util.Stack;
/**
* Created by malei on 2019-12-06
* Describe:
*/
public class DialogActivity extends AppCompatActivity {
private static final String TAG = DialogActivity.class.getSimpleName();
private Stack<WeakReference<BaseDialogFragment>> mDialogBeanStack = new Stack<>(); // 已弹出的弹窗栈
private BaseDialogFragment mCurDialog;
private volatile boolean mIsActive;
private IInnerDialogCallback mCurInnerCallback = new IInnerDialogCallback() {
@Override
public void onDismiss(boolean showNextDialog) {
if (showNextDialog) {
closeCurDialog(false); // 重置当前弹窗状态
fetchAndShowTopDialogBean();
}
}
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(new View(this));
}
private void fetchAndShowTopDialogBean() {
if (DialogManager.INSTANCE.isNonValidDialog() && mDialogBeanStack.isEmpty()) {
finish();
} else {
BaseDialogFragment queueDialog = DialogManager.INSTANCE.peekTopDialog();
if (mCurDialog == null) {
mCurDialog = getTopValidDialogFromStack();
}
int compareResult = DialogUtil.compareDialogPriority(mCurDialog, queueDialog);
switch (compareResult) {
case PriorityCompareResult.SHOW_NEW_DIALOG_AND_CLEAR_ALREADY_SHOWN:
case PriorityCompareResult.SHOW_NEW_DIALOG:
DialogManager.INSTANCE.removeCertainDialog(queueDialog);
if (compareResult == PriorityCompareResult.SHOW_NEW_DIALOG_AND_CLEAR_ALREADY_SHOWN) {
closeCurDialog(false);
clearDialogStack();
}
queueDialog.setInnerDialogCallback(mCurInnerCallback);
mDialogBeanStack.push(new WeakReference<>(queueDialog));
mCurDialog = queueDialog;
showDialog();
break;
case PriorityCompareResult.INVALID_COMPARE:
closeCurDialog(false); // 重置当前弹窗状态
fetchAndShowTopDialogBean();
break;
case PriorityCompareResult.HOLD_CUR_DIALOG:
default:
showDialog();
break;
}
}
}
private void showDialog() {
try {
if (mCurDialog == null || mCurDialog.isAdded() || mCurDialog.isRemoving() || mCurDialog.isVisible() || isFinishing()) {
return;
}
mCurDialog.onDialogInit();
mCurDialog.setInnerDialogCallback(mCurInnerCallback);
mCurDialog.showAllowingStateLoss(getSupportFragmentManager(), null);
} catch (Throwable e) {
e.printStackTrace();
}
}
private void closeCurDialog(boolean showNextDialog) {
if (!mDialogBeanStack.isEmpty()) {
mDialogBeanStack.pop();
}
clearCurDialogDisposable();
if (mCurDialog != null) {
mCurDialog.closeDialog(showNextDialog);
mCurDialog = null;
}
}
/**
* 取出当前已弹出的弹窗栈顶未被释放掉的弹窗
*/
private BaseDialogFragment getTopValidDialogFromStack() {
if (mDialogBeanStack == null || mDialogBeanStack.isEmpty()) {
return null;
}
WeakReference<BaseDialogFragment> stackDialogBean = mDialogBeanStack.peek();
BaseDialogFragment dialog;
if (stackDialogBean != null) {
dialog = stackDialogBean.get();
if (dialog != null) {
return dialog;
}
}
mDialogBeanStack.pop();
if (mDialogBeanStack.isEmpty()) {
return null;
} else {
return getTopValidDialogFromStack();
}
}
private void clearDialogStack() {
if (mDialogBeanStack.isEmpty()) {
return;
}
WeakReference<BaseDialogFragment> dialogBean = mDialogBeanStack.pop();
if (dialogBean != null) {
BaseDialogFragment dialog = dialogBean.get();
if (dialog != null) {
dialog.closeDialog(false);
}
}
clearDialogStack();
}
private void clearCurDialogDisposable() {
if (mCurDialog != null) {
mCurDialog.clearDisposable();
}
}
@Override
protected void onResume() {
super.onResume();
mIsActive = true;
DialogManager.INSTANCE.setCurDialogContainer(this);
}
@Override
protected void onPause() {
mIsActive = false;
if (mCurDialog != null) {
if (mCurDialog.isClosing()) {
mCurDialog.closeDialogImmediately();
} else {
mCurDialog.closeDialogForNow();
}
}
super.onPause();
}
public void showNextDialog() {
if (mIsActive) {
fetchAndShowTopDialogBean();
}
}
@Override
protected void onDestroy() {
DialogManager.INSTANCE.clearDialogContainer(this);
closeCurDialog(false);
clearDialogStack();
mCurInnerCallback = null;
super.onDestroy();
}
@Override
public void finish() {
DialogManager.INSTANCE.clearDialogContainer(this);
super.finish();
overridePendingTransition(0, 0);
}
}
5.动画相关的资源文件
dialog_zoom_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/overshoot_interpolator"
>
<scale
android:duration="300"
android:fillAfter="false"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0"
/>
</set>
dialog_zoom_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/anticipate_interpolator"
>
<scale
android:duration="200"
android:fillAfter="true"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.0"
android:toYScale="0.0"
/>
<alpha
android:duration="200"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
主题
<style name="dialog_without_anim_style" parent="@android:style/Animation.Translucent">
<item name="android:windowEnterAnimation">@null</item>
<item name="android:windowExitAnimation">@null</item>
</style>