package com.flyco.dialog.widget.base; import android.animation.Animator; import android.app.Dialog; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.util.DisplayMetrics; import android.util.Log; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager.LayoutParams; import android.widget.LinearLayout; import com.flyco.animation.BaseAnimatorSet; import com.flyco.dialog.utils.StatusBarUtils; public abstract class BaseDialog<T extends BaseDialog<T>> extends Dialog { /** mTag(日志) */ protected String mTag; /** mContext(上下文) */ protected Context mContext; /** (DisplayMetrics)设备密度 */ protected DisplayMetrics mDisplayMetrics; /** enable dismiss outside dialog(设置点击对话框以外区域,是否dismiss) */ protected boolean mCancel; /** dialog width scale(宽度比例) */ protected float mWidthScale = 1; /** dialog height scale(高度比例) */ protected float mHeightScale; /** mShowAnim(对话框显示动画) */ private BaseAnimatorSet mShowAnim; /** mDismissAnim(对话框消失动画) */ private BaseAnimatorSet mDismissAnim; /** top container(最上层容器) */ protected LinearLayout mLlTop; /** container to control dialog height(用于控制对话框高度) */ protected LinearLayout mLlControlHeight; /** the child of mLlControlHeight you create.(创建出来的mLlControlHeight的直接子View) */ protected View mOnCreateView; /** is mShowAnim running(显示动画是否正在执行) */ private boolean mIsShowAnim; /** is DismissAnim running(消失动画是否正在执行) */ private boolean mIsDismissAnim; /** max height(最大高度) */ protected float mMaxHeight; /** show Dialog as PopupWindow(像PopupWindow一样展示Dialog) */ private boolean mIsPopupStyle; /** automatic dimiss dialog after given delay(在给定时间后,自动消失) */ private boolean mAutoDismiss; /** delay (milliseconds) to dimiss dialog(对话框消失延时时间,毫秒值) */ private long mAutoDismissDelay = 1500; private Handler mHandler = new Handler(Looper.getMainLooper()); /** * method execute order: * show:constrouctor---show---oncreate---onStart---onAttachToWindow * dismiss:dismiss---onDetachedFromWindow---onStop */ public BaseDialog(Context context) { super(context); setDialogTheme(); mContext = context; mTag = getClass().getSimpleName(); setCanceledOnTouchOutside(true); Log.d(mTag, "constructor"); } public BaseDialog(Context context, boolean isPopupStyle) { this(context); mIsPopupStyle = isPopupStyle; } /** set dialog theme(设置对话框主题) */ private void setDialogTheme() { requestWindowFeature(Window.FEATURE_NO_TITLE);// android:windowNoTitle getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));// android:windowBackground getWindow().addFlags(LayoutParams.FLAG_DIM_BEHIND);// android:backgroundDimEnabled默认是true的 } /** * inflate layout for dialog ui and return (填充对话框所需要的布局并返回) * <pre> * public View onCreateView() { * View inflate = View.inflate(mContext, R.layout.dialog_share, null); * return inflate; * } * </pre> */ public abstract View onCreateView(); public void onViewCreated(View inflate) { } /** set Ui data or logic opreation before attatched window(在对话框显示之前,设置界面数据或者逻辑) */ public abstract void setUiBeforShow(); @Override protected void onCreate(Bundle savedInstanceState) { Log.d(mTag, "onCreate"); mDisplayMetrics = mContext.getResources().getDisplayMetrics(); mMaxHeight = mDisplayMetrics.heightPixels - StatusBarUtils.getHeight(mContext); // mMaxHeight = mDisplayMetrics.heightPixels; mLlTop = new LinearLayout(mContext); mLlTop.setGravity(Gravity.CENTER); mLlControlHeight = new LinearLayout(mContext); mLlControlHeight.setOrientation(LinearLayout.VERTICAL); mOnCreateView = onCreateView(); mLlControlHeight.addView(mOnCreateView); mLlTop.addView(mLlControlHeight); onViewCreated(mOnCreateView); if (mIsPopupStyle) { setContentView(mLlTop, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } else { setContentView(mLlTop, new ViewGroup.LayoutParams(mDisplayMetrics.widthPixels, (int) mMaxHeight)); } mLlTop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mCancel) { dismiss(); } } }); mOnCreateView.setClickable(true); } /** get actual created view(获取实际创建的View) */ public View getCreateView() { return mOnCreateView; } /** * when dailog attached to window,set dialog width and height and show anim * (当dailog依附在window上,设置对话框宽高以及显示动画) */ @Override public void onAttachedToWindow() { super.onAttachedToWindow(); Log.d(mTag, "onAttachedToWindow"); setUiBeforShow(); int width; if (mWidthScale == 0) { width = ViewGroup.LayoutParams.WRAP_CONTENT; } else { width = (int) (mDisplayMetrics.widthPixels * mWidthScale); } int height; if (mHeightScale == 0) { height = ViewGroup.LayoutParams.WRAP_CONTENT; } else if (mHeightScale == 1) { // height = ViewGroup.LayoutParams.MATCH_PARENT; height = (int) mMaxHeight; } else { height = (int) (mMaxHeight * mHeightScale); } mLlControlHeight.setLayoutParams(new LinearLayout.LayoutParams(width, height)); if (mShowAnim != null) { mShowAnim.listener(new BaseAnimatorSet.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { mIsShowAnim = true; } @Override public void onAnimationRepeat(Animator animator) { } @Override public void onAnimationEnd(Animator animator) { mIsShowAnim = false; delayDismiss(); } @Override public void onAnimationCancel(Animator animator) { mIsShowAnim = false; } }).playOn(mLlControlHeight); } else { BaseAnimatorSet.reset(mLlControlHeight); delayDismiss(); } } @Override public void setCanceledOnTouchOutside(boolean cancel) { this.mCancel = cancel; super.setCanceledOnTouchOutside(cancel); } @Override public void show() { Log.d(mTag, "show"); super.show(); } @Override protected void onStart() { super.onStart(); Log.d(mTag, "onStart"); } @Override protected void onStop() { super.onStop(); Log.d(mTag, "onStop"); } @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); Log.d(mTag, "onDetachedFromWindow"); } @Override public void dismiss() { Log.d(mTag, "dismiss"); if (mDismissAnim != null) { mDismissAnim.listener(new BaseAnimatorSet.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { mIsDismissAnim = true; } @Override public void onAnimationRepeat(Animator animator) { } @Override public void onAnimationEnd(Animator animator) { mIsDismissAnim = false; superDismiss(); } @Override public void onAnimationCancel(Animator animator) { mIsDismissAnim = false; superDismiss(); } }).playOn(mLlControlHeight); } else { superDismiss(); } } /** dismiss without anim(无动画dismiss) */ public void superDismiss() { super.dismiss(); } /** dialog anim by styles(动画弹出对话框,style动画资源) */ public void show(int animStyle) { Window window = getWindow(); window.setWindowAnimations(animStyle); show(); } /** show at location only valid for mIsPopupStyle true(指定位置显示,只对isPopupStyle为true有效) */ public void showAtLocation(int gravity, int x, int y) { if (mIsPopupStyle) { Window window = getWindow(); LayoutParams params = window.getAttributes(); window.setGravity(gravity); params.x = x; params.y = y; } show(); } /** show at location only valid for mIsPopupStyle true(指定位置显示,只对isPopupStyle为true有效) */ public void showAtLocation(int x, int y) { int gravity = Gravity.LEFT | Gravity.TOP;//Left Top (坐标原点为右上角) showAtLocation(gravity, x, y); } /** set window dim or not(设置背景是否昏暗) */ public T dimEnabled(boolean isDimEnabled) { if (isDimEnabled) { getWindow().addFlags(LayoutParams.FLAG_DIM_BEHIND); } else { getWindow().clearFlags(LayoutParams.FLAG_DIM_BEHIND); } return (T) this; } /** set dialog width scale:0-1(设置对话框宽度,占屏幕宽的比例0-1) */ public T widthScale(float widthScale) { this.mWidthScale = widthScale; return (T) this; } /** set dialog height scale:0-1(设置对话框高度,占屏幕宽的比例0-1) */ public T heightScale(float heightScale) { mHeightScale = heightScale; return (T) this; } /** set show anim(设置显示的动画) */ public T showAnim(BaseAnimatorSet showAnim) { mShowAnim = showAnim; return (T) this; } /** set dismiss anim(设置隐藏的动画) */ public T dismissAnim(BaseAnimatorSet dismissAnim) { mDismissAnim = dismissAnim; return (T) this; } /** automatic dimiss dialog after given delay(在给定时间后,自动消失) */ public T autoDismiss(boolean autoDismiss) { mAutoDismiss = autoDismiss; return (T) this; } /** set dealy (milliseconds) to dimiss dialog(对话框消失延时时间,毫秒值) */ public T autoDismissDelay(long autoDismissDelay) { mAutoDismissDelay = autoDismissDelay; return (T) this; } private void delayDismiss() { if (mAutoDismiss && mAutoDismissDelay > 0) { mHandler.postDelayed(new Runnable() { @Override public void run() { dismiss(); } }, mAutoDismissDelay); } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (mIsDismissAnim || mIsShowAnim || mAutoDismiss) { return true; } return super.dispatchTouchEvent(ev); } @Override public void onBackPressed() { if (mIsDismissAnim || mIsShowAnim || mAutoDismiss) { return; } super.onBackPressed(); } /** dp to px */ protected int dp2px(float dp) { final float scale = mContext.getResources().getDisplayMetrics().density; return (int) (dp * scale + 0.5f); } }