onBindView) {
+ BottomDialog bottomDialog = new BottomDialog(onBindView);
+ bottomDialog.show();
+ return bottomDialog;
+ }
+
+ public void show() {
+ super.beforeShow();
+ int layoutId = isLightTheme() ? R.layout.layout_dialogx_bottom_material : R.layout.layout_dialogx_bottom_material_dark;
+ if (style.overrideBottomDialogRes() != null) {
+ layoutId = style.overrideBottomDialogRes().overrideDialogLayout(isLightTheme());
+ }
+
+ dialogView = createView(layoutId);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(dialogView);
+ }
+
+ public void show(Activity activity) {
+ super.beforeShow();
+ int layoutId = isLightTheme() ? R.layout.layout_dialogx_bottom_material : R.layout.layout_dialogx_bottom_material_dark;
+ if (style.overrideBottomDialogRes() != null) {
+ layoutId = style.overrideBottomDialogRes().overrideDialogLayout(isLightTheme());
+ }
+
+ dialogView = createView(layoutId);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(activity, dialogView);
+ }
+
+ protected DialogImpl dialogImpl;
+
+ public class DialogImpl implements DialogConvertViewInterface {
+
+ private BottomDialogTouchEventInterceptor bottomDialogTouchEventInterceptor;
+
+ public DialogXBaseRelativeLayout boxRoot;
+ public RelativeLayout boxBkg;
+ public MaxRelativeLayout bkg;
+ public ViewGroup boxBody;
+ public ImageView imgTab;
+ public TextView txtDialogTitle;
+ public ScrollView scrollView;
+ public LinearLayout boxContent;
+ public TextView txtDialogTip;
+ public View imgSplit;
+ public RelativeLayout boxList;
+ public RelativeLayout boxCustom;
+ public BlurView blurView;
+ public ViewGroup boxCancel;
+ public TextView btnCancel;
+ public BlurView cancelBlurView;
+
+ public TextView btnSelectOther;
+ public TextView btnSelectPositive;
+
+ public DialogImpl(View convertView) {
+ boxRoot = convertView.findViewById(R.id.box_root);
+ boxBkg = convertView.findViewById(R.id.box_bkg);
+ bkg = convertView.findViewById(R.id.bkg);
+ boxBody = convertView.findViewWithTag("body");
+ imgTab = convertView.findViewById(R.id.img_tab);
+ txtDialogTitle = convertView.findViewById(R.id.txt_dialog_title);
+ scrollView = convertView.findViewById(R.id.scrollView);
+ boxContent = convertView.findViewById(R.id.box_content);
+ txtDialogTip = convertView.findViewById(R.id.txt_dialog_tip);
+ imgSplit = convertView.findViewWithTag("split");
+ boxList = convertView.findViewById(R.id.box_list);
+ boxCustom = convertView.findViewById(R.id.box_custom);
+ blurView = convertView.findViewById(R.id.blurView);
+ boxCancel = convertView.findViewWithTag("cancelBox");
+ btnCancel = convertView.findViewWithTag("cancel");
+
+ btnSelectOther = convertView.findViewById(R.id.btn_selectOther);
+ btnSelectPositive = convertView.findViewById(R.id.btn_selectPositive);
+
+ init();
+ dialogImpl = this;
+ refreshView();
+ }
+
+ public void reBuild() {
+ init();
+ dialogImpl = this;
+ refreshView();
+ }
+
+ /**
+ * 此值记录了BottomDialog启动后的位置
+ * ·当内容高度大于屏幕安全区高度时,BottomDialog会以全屏方式启动,但一开始只会展开到 0.8×屏幕高度,
+ * 此时可以再次上划查看全部内容。
+ * ·当内容高度小于屏幕安全区高度时,BottomDialog会以内容高度启动。
+ *
+ * 记录这个值的目的是,当用户向下滑动时,判断情况该回到这个位置还是关闭对话框,
+ * 并阻止当内容高度已经完全显示时的继续向上滑动操作。
+ */
+ public float bkgEnterAimY = -1;
+
+ @Override
+ public void init() {
+ if (titleTextInfo == null) titleTextInfo = DialogX.menuTitleInfo;
+ if (titleTextInfo == null) titleTextInfo = DialogX.titleTextInfo;
+ if (messageTextInfo == null) messageTextInfo = DialogX.messageTextInfo;
+ if (okTextInfo == null) okTextInfo = DialogX.okButtonTextInfo;
+ if (okTextInfo == null) okTextInfo = DialogX.buttonTextInfo;
+ if (cancelTextInfo == null) cancelTextInfo = DialogX.buttonTextInfo;
+ if (otherTextInfo == null) otherTextInfo = DialogX.buttonTextInfo;
+ if (backgroundColor == -1) backgroundColor = DialogX.backgroundColor;
+ if (cancelText == null) cancelText = DialogX.cancelButtonText;
+
+ txtDialogTitle.getPaint().setFakeBoldText(true);
+ if (btnCancel != null) btnCancel.getPaint().setFakeBoldText(true);
+ if (btnSelectPositive != null) btnSelectPositive.getPaint().setFakeBoldText(true);
+ if (btnSelectOther != null) btnSelectOther.getPaint().setFakeBoldText(true);
+
+ boxRoot.setParentDialog(me);
+ boxRoot.setOnLifecycleCallBack(new DialogXBaseRelativeLayout.OnLifecycleCallBack() {
+ @Override
+ public void onShow() {
+ bkg.setY(getRootFrameLayout().getMeasuredHeight());
+
+ isShow = true;
+ boxRoot.setAlpha(0f);
+
+ boxContent.getViewTreeObserver().addOnGlobalLayoutListener(onContentViewLayoutChangeListener);
+
+ getDialogLifecycleCallback().onShow(me);
+
+ onDialogInit(dialogImpl);
+
+ boxRoot.post(new Runnable() {
+ @Override
+ public void run() {
+ if (style.messageDialogBlurSettings() != null && style.messageDialogBlurSettings().blurBackground() && boxBody != null && boxCancel != null) {
+ int blurFrontColor = getResources().getColor(style.messageDialogBlurSettings().blurForwardColorRes(isLightTheme()));
+ blurView = new BlurView(bkg.getContext(), null);
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(bkg.getWidth(), bkg.getHeight());
+ blurView.setOverlayColor(backgroundColor == -1 ? blurFrontColor : backgroundColor);
+ blurView.setTag("blurView");
+ blurView.setRadiusPx(style.messageDialogBlurSettings().blurBackgroundRoundRadiusPx());
+ boxBody.addView(blurView, 0, params);
+
+ cancelBlurView = new BlurView(boxCancel.getContext(), null);
+ RelativeLayout.LayoutParams cancelButtonLp = new RelativeLayout.LayoutParams(boxCancel.getWidth(), boxCancel.getHeight());
+ cancelBlurView.setOverlayColor(backgroundColor == -1 ? blurFrontColor : backgroundColor);
+ cancelBlurView.setTag("blurView");
+ cancelBlurView.setRadiusPx(style.messageDialogBlurSettings().blurBackgroundRoundRadiusPx());
+ boxCancel.addView(cancelBlurView, 0, cancelButtonLp);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onDismiss() {
+ isShow = false;
+ getDialogLifecycleCallback().onDismiss(me);
+ }
+ });
+
+ if (btnCancel != null) {
+ btnCancel.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (cancelButtonClickListener != null) {
+ if (!cancelButtonClickListener.onClick(me, v)) {
+ dismiss();
+ }
+ } else {
+ dismiss();
+ }
+ }
+ });
+ }
+ if (btnSelectOther != null) {
+ btnSelectOther.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (otherButtonClickListener != null) {
+ if (!otherButtonClickListener.onClick(me, v)) {
+ dismiss();
+ }
+ } else {
+ dismiss();
+ }
+ }
+ });
+ }
+ if (btnSelectPositive != null) {
+ btnSelectPositive.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (okButtonClickListener != null) {
+ if (!okButtonClickListener.onClick(me, v)) {
+ dismiss();
+ }
+ } else {
+ dismiss();
+ }
+ }
+ });
+ }
+
+ if (imgSplit != null) {
+ int dividerRes = style.overrideBottomDialogRes().overrideMenuDividerDrawableRes(isLightTheme());
+ int dividerHeight = style.overrideBottomDialogRes().overrideMenuDividerHeight(isLightTheme());
+ if (dividerRes != 0) imgSplit.setBackgroundResource(dividerRes);
+ if (dividerHeight != 0) {
+ ViewGroup.LayoutParams lp = imgSplit.getLayoutParams();
+ lp.height = dividerHeight;
+ imgSplit.setLayoutParams(lp);
+ }
+ }
+
+ boxRoot.setOnBackPressedListener(new OnBackPressedListener() {
+ @Override
+ public boolean onBackPressed() {
+ if (onBackPressedListener != null && onBackPressedListener.onBackPressed()) {
+ dismiss();
+ return false;
+ }
+ if (isCancelable()) {
+ dismiss();
+ }
+ return false;
+ }
+ });
+
+ bottomDialogTouchEventInterceptor = new BottomDialogTouchEventInterceptor(me, dialogImpl);
+
+ boxRoot.post(new Runnable() {
+ @Override
+ public void run() {
+ long enterAnimDurationTemp = 300;
+ /**
+ * 对于非支持滑动展开的对话框,直接使用从下往上的资源动画实现
+ * 其他情况不适用,请参考 onContentViewLayoutChangeListener 的代码实现。
+ */
+ if (style.overrideBottomDialogRes() == null || !style.overrideBottomDialogRes().touchSlide()) {
+ //bkg.setY(getRootFrameLayout().getMeasuredHeight());
+ Animation enterAnim = AnimationUtils.loadAnimation(getContext(), R.anim.anim_dialogx_bottom_enter);
+ enterAnimDurationTemp = enterAnim.getDuration();
+ if (overrideEnterDuration >= 0) {
+ enterAnimDurationTemp = overrideEnterDuration;
+ }
+ if (enterAnimDuration >= 0) {
+ enterAnimDurationTemp = enterAnimDuration;
+ }
+ enterAnim.setDuration(enterAnimDurationTemp);
+ enterAnim.setInterpolator(new DecelerateInterpolator(2f));
+
+ bkg.setY(bkgEnterAimY);
+ bkg.startAnimation(enterAnim);
+ }
+
+ boxRoot.animate()
+ .setDuration(enterAnimDurationTemp)
+ .alpha(1f)
+ .setInterpolator(new DecelerateInterpolator())
+ .setListener(null);
+ }
+ });
+ }
+
+ private boolean isEnterAnimFinished = false;
+
+ private ViewTreeObserver.OnGlobalLayoutListener onContentViewLayoutChangeListener = new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ if (boxContent != null) {
+ if (style.overrideBottomDialogRes() != null &&style.overrideBottomDialogRes().touchSlide()) {
+ //若内容布已经超出屏幕可用范围,且预设的对话框最大高度已知
+ if (bkg.isChildScrollViewCanScroll() && bottomDialogMaxHeight != 0) {
+ //先将内容布局放置到屏幕底部以外区域,然后执行上移动画
+ if (!isEnterAnimFinished)bkg.setY(getRootFrameLayout().getMeasuredHeight());
+ //执行上移动画
+ if (bottomDialogMaxHeight <= 1) {
+ //bottomDialogMaxHeight 值若为小于 1 的小数,视为比例
+ bkgEnterAimY = boxBkg.getHeight() - bkg.getHeight() * bottomDialogMaxHeight;
+ } else {
+ bkgEnterAimY = boxBkg.getHeight() - bottomDialogMaxHeight;
+ }
+ long enterAnimDurationTemp = 300;
+ if (overrideEnterDuration >= 0) {
+ enterAnimDurationTemp = overrideEnterDuration;
+ }
+ if (enterAnimDuration >= 0) {
+ enterAnimDurationTemp = enterAnimDuration;
+ }
+ ObjectAnimator keepBottomAnim = ObjectAnimator.ofFloat(bkg, "y", bkg.getY(), bkgEnterAimY);
+ keepBottomAnim.setDuration(enterAnimDurationTemp);
+ keepBottomAnim.setInterpolator(new DecelerateInterpolator(2f));
+ keepBottomAnim.start();
+ } else {
+ bkgEnterAimY = boxBkg.getHeight() - bkg.getHeight();
+ if (!isEnterAnimFinished)bkg.setY(boxRoot.getHeight());
+ bkg.post(new Runnable() {
+ @Override
+ public void run() {
+ ObjectAnimator enterAnim = ObjectAnimator.ofFloat(bkg, "y", bkg.getY(), bkgEnterAimY);
+ long enterAnimDurationTemp = 300;
+ if (overrideEnterDuration >= 0) {
+ enterAnimDurationTemp = overrideEnterDuration;
+ }
+ if (enterAnimDuration >= 0) {
+ enterAnimDurationTemp = enterAnimDuration;
+ }
+ enterAnim.setDuration(enterAnimDurationTemp);
+ enterAnim.setInterpolator(new DecelerateInterpolator(2f));
+ enterAnim.start();
+ }
+ });
+ }
+ }else{
+ bkgEnterAimY = boxBkg.getHeight() - bkg.getHeight();
+ }
+ }
+ isEnterAnimFinished = true;
+ }
+ };
+
+ @Override
+ public void refreshView() {
+ if (backgroundColor != -1) {
+ tintColor(bkg, backgroundColor);
+ if (blurView != null && cancelBlurView != null) {
+ blurView.setOverlayColor(backgroundColor);
+ cancelBlurView.setOverlayColor(backgroundColor);
+ }
+ }
+
+ showText(txtDialogTitle, title);
+ showText(txtDialogTip, message);
+
+ useTextInfo(txtDialogTitle, titleTextInfo);
+ useTextInfo(txtDialogTip, messageTextInfo);
+ useTextInfo(btnCancel, cancelTextInfo);
+ useTextInfo(btnSelectOther, otherTextInfo);
+ useTextInfo(btnSelectPositive, okTextInfo);
+
+ if (isCancelable()) {
+ boxRoot.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ doDismiss(v);
+ }
+ });
+ } else {
+ boxRoot.setOnClickListener(null);
+ }
+ boxBkg.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ boxRoot.callOnClick();
+ }
+ });
+
+ if (maskColor != -1) boxRoot.setBackgroundColor(maskColor);
+
+ if (onBindView != null && onBindView.getCustomView() != null) {
+ onBindView.bindParent(boxCustom, me);
+ }
+
+ if (isAllowInterceptTouch() && isCancelable()) {
+ if (imgTab != null) imgTab.setVisibility(View.VISIBLE);
+ } else {
+ if (imgTab != null) imgTab.setVisibility(View.GONE);
+ }
+
+ bottomDialogTouchEventInterceptor.refresh(me, this);
+
+ if (imgSplit != null) {
+ if (txtDialogTitle.getVisibility() == View.VISIBLE || txtDialogTip.getVisibility() == View.VISIBLE) {
+ imgSplit.setVisibility(View.VISIBLE);
+ } else {
+ imgSplit.setVisibility(View.GONE);
+ }
+ }
+
+ if (boxCancel != null) {
+ if (isNull(cancelText)) {
+ boxCancel.setVisibility(View.GONE);
+ } else {
+ boxCancel.setVisibility(View.VISIBLE);
+ }
+ }
+
+ showText(btnSelectPositive, okText);
+ showText(btnCancel, cancelText);
+ showText(btnSelectOther, otherText);
+ }
+
+ @Override
+ public void doDismiss(View v) {
+ if (v != null) v.setEnabled(false);
+
+ if (boxContent != null)
+ boxContent.getViewTreeObserver().removeOnGlobalLayoutListener(onContentViewLayoutChangeListener);
+
+ ObjectAnimator exitAnim = ObjectAnimator.ofFloat(bkg, "y", bkg.getY(), boxBkg.getHeight());
+ long exitAnimDurationTemp = 300;
+ if (overrideExitDuration >= 0) {
+ exitAnimDurationTemp = overrideExitDuration;
+ }
+ if (exitAnimDuration >= 0) {
+ exitAnimDurationTemp = exitAnimDuration;
+ }
+ exitAnim.setDuration(exitAnimDurationTemp);
+ exitAnim.start();
+
+ boxRoot.animate()
+ .alpha(0f)
+ .setInterpolator(new AccelerateInterpolator())
+ .setDuration(exitAnimDurationTemp);
+
+ new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ dismiss(dialogView);
+ }
+ }, exitAnimDurationTemp);
+ }
+
+ public void preDismiss() {
+ if (isCancelable()) {
+ doDismiss(boxRoot);
+ } else {
+ long exitAnimDurationTemp = 300;
+ if (overrideExitDuration >= 0) {
+ exitAnimDurationTemp = overrideExitDuration;
+ }
+ if (exitAnimDuration >= 0) {
+ exitAnimDurationTemp = exitAnimDuration;
+ }
+ ObjectAnimator exitAnim = ObjectAnimator.ofFloat(bkg, "y", bkg.getY(), bkgEnterAimY);
+ exitAnim.setDuration(exitAnimDurationTemp);
+ exitAnim.start();
+ }
+ }
+ }
+
+ protected void onDialogInit(DialogImpl dialog) {
+ }
+
+ public void refreshUI() {
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ if (dialogImpl != null) dialogImpl.refreshView();
+ }
+ });
+ }
+
+ public void dismiss() {
+ if (dialogImpl == null) return;
+ dialogImpl.doDismiss(null);
+ }
+
+ public DialogLifecycleCallback getDialogLifecycleCallback() {
+ return dialogLifecycleCallback == null ? new DialogLifecycleCallback() {
+ } : dialogLifecycleCallback;
+ }
+
+ public BottomDialog setDialogLifecycleCallback(DialogLifecycleCallback dialogLifecycleCallback) {
+ this.dialogLifecycleCallback = dialogLifecycleCallback;
+ if (isShow) dialogLifecycleCallback.onShow(me);
+ return this;
+ }
+
+ public OnBackPressedListener getOnBackPressedListener() {
+ return onBackPressedListener;
+ }
+
+ public BottomDialog setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
+ this.onBackPressedListener = onBackPressedListener;
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setStyle(DialogXStyle style) {
+ this.style = style;
+ return this;
+ }
+
+ public BottomDialog setTheme(DialogX.THEME theme) {
+ this.theme = theme;
+ return this;
+ }
+
+ public boolean isCancelable() {
+ if (privateCancelable != null) {
+ return privateCancelable == BOOLEAN.TRUE;
+ }
+ if (overrideCancelable != null) {
+ return overrideCancelable == BOOLEAN.TRUE;
+ }
+ return cancelable;
+ }
+
+ public BottomDialog setCancelable(boolean cancelable) {
+ this.privateCancelable = cancelable ? BOOLEAN.TRUE : BOOLEAN.FALSE;
+ refreshUI();
+ return this;
+ }
+
+ public DialogImpl getDialogImpl() {
+ return dialogImpl;
+ }
+
+ public CharSequence getTitle() {
+ return title;
+ }
+
+ public BottomDialog setTitle(CharSequence title) {
+ this.title = title;
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setTitle(int titleResId) {
+ this.title = getString(titleResId);
+ refreshUI();
+ return this;
+ }
+
+ public CharSequence getMessage() {
+ return message;
+ }
+
+ public BottomDialog setMessage(CharSequence message) {
+ this.message = message;
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setMessage(int messageResId) {
+ this.message = getString(messageResId);
+ refreshUI();
+ return this;
+ }
+
+ public CharSequence getCancelButton() {
+ return cancelText;
+ }
+
+ public BottomDialog setCancelButton(CharSequence cancelText) {
+ this.cancelText = cancelText;
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setCancelButton(int cancelTextResId) {
+ this.cancelText = getString(cancelTextResId);
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setCancelButton(OnDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ return this;
+ }
+
+ public BottomDialog setCancelButton(CharSequence cancelText, OnDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelText = cancelText;
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setCancelButton(int cancelTextResId, OnDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelText = getString(cancelTextResId);
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setCustomView(OnBindView onBindView) {
+ this.onBindView = onBindView;
+ refreshUI();
+ return this;
+ }
+
+ public View getCustomView() {
+ if (onBindView == null) return null;
+ return onBindView.getCustomView();
+ }
+
+ public BottomDialog removeCustomView() {
+ this.onBindView.clean();
+ refreshUI();
+ return this;
+ }
+
+ public boolean isAllowInterceptTouch() {
+ if (style.overrideBottomDialogRes() == null) {
+ return false;
+ } else {
+ return allowInterceptTouch && style.overrideBottomDialogRes().touchSlide();
+ }
+ }
+
+ public BottomDialog setAllowInterceptTouch(boolean allowInterceptTouch) {
+ this.allowInterceptTouch = allowInterceptTouch;
+ refreshUI();
+ return this;
+ }
+
+ public OnDialogButtonClickListener getCancelButtonClickListener() {
+ return cancelButtonClickListener;
+ }
+
+ public BottomDialog setCancelButtonClickListener(OnDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ return this;
+ }
+
+ public TextInfo getTitleTextInfo() {
+ return titleTextInfo;
+ }
+
+ public BottomDialog setTitleTextInfo(TextInfo titleTextInfo) {
+ this.titleTextInfo = titleTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public TextInfo getMessageTextInfo() {
+ return messageTextInfo;
+ }
+
+ public BottomDialog setMessageTextInfo(TextInfo messageTextInfo) {
+ this.messageTextInfo = messageTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public TextInfo getCancelTextInfo() {
+ return cancelTextInfo;
+ }
+
+ public BottomDialog setCancelTextInfo(TextInfo cancelTextInfo) {
+ this.cancelTextInfo = cancelTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public int getBackgroundColor() {
+ return backgroundColor;
+ }
+
+ public BottomDialog setBackgroundColor(@ColorInt int backgroundColor) {
+ this.backgroundColor = backgroundColor;
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setBackgroundColorRes(@ColorRes int backgroundRes) {
+ this.backgroundColor = getColor(backgroundRes);
+ refreshUI();
+ return this;
+ }
+
+ public CharSequence getOkButton() {
+ return okText;
+ }
+
+ public BottomDialog setOkButton(CharSequence okText) {
+ this.okText = okText;
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setOkButton(int OkTextResId) {
+ this.okText = getString(OkTextResId);
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setOkButton(OnDialogButtonClickListener OkButtonClickListener) {
+ this.okButtonClickListener = OkButtonClickListener;
+ return this;
+ }
+
+ public BottomDialog setOkButton(CharSequence OkText, OnDialogButtonClickListener OkButtonClickListener) {
+ this.okText = OkText;
+ this.okButtonClickListener = OkButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setOkButton(int OkTextResId, OnDialogButtonClickListener OkButtonClickListener) {
+ this.okText = getString(OkTextResId);
+ this.okButtonClickListener = OkButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public CharSequence getOtherButton() {
+ return otherText;
+ }
+
+ public BottomDialog setOtherButton(CharSequence otherText) {
+ this.otherText = otherText;
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setOtherButton(int OtherTextResId) {
+ this.otherText = getString(OtherTextResId);
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setOtherButton(OnDialogButtonClickListener OtherButtonClickListener) {
+ this.otherButtonClickListener = OtherButtonClickListener;
+ return this;
+ }
+
+ public BottomDialog setOtherButton(CharSequence OtherText, OnDialogButtonClickListener OtherButtonClickListener) {
+ this.otherText = OtherText;
+ this.otherButtonClickListener = OtherButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setOtherButton(int OtherTextResId, OnDialogButtonClickListener OtherButtonClickListener) {
+ this.otherText = getString(OtherTextResId);
+ this.otherButtonClickListener = OtherButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public BottomDialog setMaskColor(@ColorInt int maskColor) {
+ this.maskColor = maskColor;
+ refreshUI();
+ return this;
+ }
+
+ public long getEnterAnimDuration() {
+ return enterAnimDuration;
+ }
+
+ public BottomDialog setEnterAnimDuration(long enterAnimDuration) {
+ this.enterAnimDuration = enterAnimDuration;
+ return this;
+ }
+
+ public long getExitAnimDuration() {
+ return exitAnimDuration;
+ }
+
+ public BottomDialog setExitAnimDuration(long exitAnimDuration) {
+ this.exitAnimDuration = exitAnimDuration;
+ return this;
+ }
+
+ @Override
+ public void onUIModeChange(Configuration newConfig) {
+ if (dialogView != null) {
+ dismiss(dialogView);
+ }
+ if (getDialogImpl().boxCustom != null) {
+ getDialogImpl().boxCustom.removeAllViews();
+ }
+ if (getDialogImpl().boxList != null) {
+ getDialogImpl().boxList.removeAllViews();
+ }
+ int layoutId = isLightTheme() ? R.layout.layout_dialogx_bottom_material : R.layout.layout_dialogx_bottom_material_dark;
+ if (style.overrideBottomDialogRes() != null) {
+ layoutId = style.overrideBottomDialogRes().overrideDialogLayout(isLightTheme());
+ }
+
+ enterAnimDuration = 0;
+ dialogView = createView(layoutId);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(dialogView);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomMenu.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomMenu.java
new file mode 100644
index 0000000..110a476
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomMenu.java
@@ -0,0 +1,1065 @@
+package com.kongzue.dialogx.dialogs;
+
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.RelativeLayout;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.ColorRes;
+
+import com.kongzue.dialogx.DialogX;
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.interfaces.BottomMenuListViewTouchEvent;
+import com.kongzue.dialogx.interfaces.DialogLifecycleCallback;
+import com.kongzue.dialogx.interfaces.DialogXStyle;
+import com.kongzue.dialogx.interfaces.OnBackPressedListener;
+import com.kongzue.dialogx.interfaces.OnBindView;
+import com.kongzue.dialogx.interfaces.OnDialogButtonClickListener;
+import com.kongzue.dialogx.interfaces.OnIconChangeCallBack;
+import com.kongzue.dialogx.interfaces.OnMenuItemClickListener;
+import com.kongzue.dialogx.interfaces.OnMenuItemSelectListener;
+import com.kongzue.dialogx.util.NormalMenuArrayAdapter;
+import com.kongzue.dialogx.util.TextInfo;
+import com.kongzue.dialogx.util.views.BottomDialogListView;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static android.view.View.OVER_SCROLL_NEVER;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/6 23:48
+ */
+public class BottomMenu extends BottomDialog {
+
+ public enum SELECT_MODE {
+ NONE,
+ SINGLE,
+ MULTIPLE
+ }
+
+ protected BottomMenu me = this;
+ protected int selectionIndex = -1;
+ protected SELECT_MODE selectMode = SELECT_MODE.NONE;
+ protected ArrayList selectionItems;
+
+ protected OnMenuItemClickListener onMenuItemClickListener;
+
+ public static BottomMenu build() {
+ return new BottomMenu();
+ }
+
+ protected BottomMenu() {
+ super();
+ if (style.overrideBottomDialogRes() != null) {
+ bottomDialogMaxHeight = style.overrideBottomDialogRes().overrideBottomDialogMaxHeight();
+ }
+ if (bottomDialogMaxHeight <= 1 && bottomDialogMaxHeight > 0f) {
+ bottomDialogMaxHeight = (int) (getRootFrameLayout().getMeasuredHeight() * bottomDialogMaxHeight);
+ }
+ }
+
+ private OnIconChangeCallBack onIconChangeCallBack;
+ private BottomDialogListView listView;
+ private BaseAdapter menuListAdapter;
+ private List menuList;
+
+ public static BottomMenu show(List menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(List menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu showStringList(List menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.setMenuStringList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu showStringList(List menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.setMenuStringList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(String[] menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(String[] menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence[] menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence[] menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence title, CharSequence message, List menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence title, CharSequence message, List menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence title, List menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence title, List menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu showStringList(CharSequence title, CharSequence message, List menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuStringList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu showStringList(CharSequence title, CharSequence message, List menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuStringList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence title, CharSequence message, String[] menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence title, CharSequence message, String[] menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence title, CharSequence message, CharSequence[] menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence title, CharSequence message, CharSequence[] menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(String title, String message, List menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(String title, String message, List menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu showStringList(String title, String message, List menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuStringList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu showStringList(String title, String message, List menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuStringList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(String title, String message, String[] menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(String title, String message, String[] menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(String title, String message, CharSequence[] menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(String title, String message, CharSequence[] menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.message = message;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(int titleResId, int messageResId, List menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.message = bottomMenu.getString(messageResId);
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(int titleResId, List menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu showStringList(int titleResId, int messageResId, List menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.message = bottomMenu.getString(messageResId);
+ bottomMenu.setMenuStringList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(int titleResId, int messageResId, String[] menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.message = bottomMenu.getString(messageResId);
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(int titleResId, int messageResId, CharSequence[] menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.message = bottomMenu.getString(messageResId);
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(int titleResId, int messageResId, List menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.message = bottomMenu.getString(messageResId);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(int titleResId, List menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu showStringList(int titleResId, int messageResId, List menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.message = bottomMenu.getString(messageResId);
+ bottomMenu.setMenuStringList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(int titleResId, int messageResId, String[] menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.message = bottomMenu.getString(messageResId);
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(int titleResId, int messageResId, CharSequence[] menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.message = bottomMenu.getString(messageResId);
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence title, CharSequence[] menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence title, String[] menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence title, CharSequence[] menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(CharSequence title, String[] menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = title;
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(int titleResId, CharSequence[] menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(int titleResId, String[] menuList) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(int titleResId, CharSequence[] menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ public static BottomMenu show(int titleResId, String[] menuList, OnMenuItemClickListener onMenuItemClickListener) {
+ BottomMenu bottomMenu = new BottomMenu();
+ bottomMenu.title = bottomMenu.getString(titleResId);
+ bottomMenu.setMenuList(menuList);
+ bottomMenu.setOnMenuItemClickListener(onMenuItemClickListener);
+ bottomMenu.show();
+ return bottomMenu;
+ }
+
+ private float curTouchY;
+
+ public static final int ITEM_CLICK_DELAY = 100;
+ private long lastClickTime = 0;
+
+ @Override
+ protected void onDialogInit(final DialogImpl dialog) {
+ if (dialog != null) {
+ dialog.boxList.setVisibility(View.VISIBLE);
+
+ if (!isAllowInterceptTouch()) {
+ dialog.bkg.setMaxHeight((int) bottomDialogMaxHeight);
+ if (bottomDialogMaxHeight != 0) {
+ dialogImpl.scrollView.setEnabled(false);
+ }
+ }
+
+ int dividerDrawableResId = 0;
+ int dividerHeight = 1;
+ if (style.overrideBottomDialogRes() != null) {
+ dividerDrawableResId = style.overrideBottomDialogRes().overrideMenuDividerDrawableRes(isLightTheme());
+ dividerHeight = style.overrideBottomDialogRes().overrideMenuDividerHeight(isLightTheme());
+ }
+ if (dividerDrawableResId == 0) {
+ dividerDrawableResId = isLightTheme() ? R.drawable.rect_dialogx_material_menu_split_divider : R.drawable.rect_dialogx_material_menu_split_divider_night;
+ }
+
+ listView = new BottomDialogListView(dialog, getContext());
+ listView.setOverScrollMode(OVER_SCROLL_NEVER);
+ listView.setDivider(getResources().getDrawable(dividerDrawableResId));
+ listView.setDividerHeight(dividerHeight);
+
+ listView.setBottomMenuListViewTouchEvent(new BottomMenuListViewTouchEvent() {
+ @Override
+ public void down(MotionEvent event) {
+ curTouchY = dialog.bkg.getY();
+ }
+
+ @Override
+ public void move(MotionEvent event) {
+ curTouchY = event.getRawY();
+ }
+ });
+
+ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ long currentTime = System.currentTimeMillis();
+ if (currentTime - lastClickTime > ITEM_CLICK_DELAY) {
+ lastClickTime = currentTime;
+ float deltaY = Math.abs(curTouchY - dialog.bkg.getY());
+ if (deltaY > dip2px(15)) {
+ return;
+ }
+ switch (selectMode) {
+ case NONE:
+ if (onMenuItemClickListener != null) {
+ if (!onMenuItemClickListener.onClick(me, menuList.get(position), position)) {
+ dismiss();
+ }
+ } else {
+ dismiss();
+ }
+ break;
+ case SINGLE:
+ if (onMenuItemClickListener instanceof OnMenuItemSelectListener) {
+ OnMenuItemSelectListener onMenuItemSelectListener = (OnMenuItemSelectListener) onMenuItemClickListener;
+ if (!onMenuItemSelectListener.onClick(me, menuList.get(position), position)) {
+ dismiss();
+ } else {
+ selectionIndex = position;
+ menuListAdapter.notifyDataSetInvalidated();
+ menuListAdapter.notifyDataSetChanged();
+ onMenuItemSelectListener.onOneItemSelect(me, menuList.get(position), position);
+ }
+ } else {
+ if (onMenuItemClickListener != null) {
+ if (!onMenuItemClickListener.onClick(me, menuList.get(position), position)) {
+ dismiss();
+ }
+ } else {
+ dismiss();
+ }
+ }
+ break;
+ case MULTIPLE:
+ if (onMenuItemClickListener instanceof OnMenuItemSelectListener) {
+ OnMenuItemSelectListener onMenuItemSelectListener = (OnMenuItemSelectListener) onMenuItemClickListener;
+ if (!onMenuItemSelectListener.onClick(me, menuList.get(position), position)) {
+ dismiss();
+ } else {
+ if (selectionItems.contains(position)) {
+ selectionItems.remove(new Integer(position));
+ } else {
+ selectionItems.add(position);
+ }
+ menuListAdapter.notifyDataSetInvalidated();
+ menuListAdapter.notifyDataSetChanged();
+ int[] resultArray = new int[selectionItems.size()];
+ CharSequence[] selectTextArray = new CharSequence[selectionItems.size()];
+ for (int i = 0; i < selectionItems.size(); i++) {
+ resultArray[i] = selectionItems.get(i);
+ selectTextArray[i] = menuList.get(resultArray[i]);
+ }
+ onMenuItemSelectListener.onMultiItemSelect(me, selectTextArray, resultArray);
+ }
+ } else {
+ if (onMenuItemClickListener != null) {
+ if (!onMenuItemClickListener.onClick(me, menuList.get(position), position)) {
+ dismiss();
+ }
+ } else {
+ dismiss();
+ }
+ }
+ break;
+ }
+ }
+ }
+ });
+ if (style.overrideBottomDialogRes() != null) {
+ if (style.overrideBottomDialogRes().overrideMenuItemLayout(true, 0, 0, false) != 0) {
+ listView.setSelector(R.color.empty);
+ }
+ }
+
+ RelativeLayout.LayoutParams listViewLp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ dialog.boxList.addView(listView, listViewLp);
+
+ refreshUI();
+ }
+ }
+
+ @Override
+ public void refreshUI() {
+ if (listView != null) {
+ if (menuListAdapter == null) {
+ menuListAdapter = new NormalMenuArrayAdapter(me, getContext(), menuList);
+ }
+ if (listView.getAdapter() == null) {
+ listView.setAdapter(menuListAdapter);
+ } else {
+ if (listView.getAdapter() != menuListAdapter) {
+ listView.setAdapter(menuListAdapter);
+ } else {
+ menuListAdapter.notifyDataSetChanged();
+ }
+ }
+ }
+ super.refreshUI();
+ }
+
+ public void preRefreshUI(){
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ refreshUI();
+ }
+ });
+ }
+
+ @Override
+ public String dialogKey() {
+ return getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")";
+ }
+
+ public List getMenuList() {
+ return menuList;
+ }
+
+ public BottomMenu setMenuList(List menuList) {
+ this.menuList = menuList;
+ this.menuListAdapter = null;
+ preRefreshUI();
+ return this;
+ }
+
+ private boolean isSameSize(int menuListSize) {
+ if (this.menuList == null || this.menuList.size() == 0) {
+ return true;
+ }
+ return this.menuList.size() == menuListSize;
+ }
+
+ public BottomMenu setMenuStringList(List menuList) {
+ this.menuList = new ArrayList<>();
+ this.menuList.addAll(menuList);
+ this.menuListAdapter = null;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setMenuList(String[] menuList) {
+ this.menuList = new ArrayList<>();
+ this.menuList.addAll(Arrays.asList(menuList));
+ this.menuListAdapter = null;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setMenuList(CharSequence[] menuList) {
+ this.menuList = Arrays.asList(menuList);
+ this.menuListAdapter = null;
+ preRefreshUI();
+ return this;
+ }
+
+ public OnIconChangeCallBack getOnIconChangeCallBack() {
+ return onIconChangeCallBack;
+ }
+
+ public BottomMenu setOnIconChangeCallBack(OnIconChangeCallBack onIconChangeCallBack) {
+ this.onIconChangeCallBack = onIconChangeCallBack;
+ return this;
+ }
+
+ public OnBackPressedListener getOnBackPressedListener() {
+ return onBackPressedListener;
+ }
+
+ public BottomMenu setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
+ this.onBackPressedListener = onBackPressedListener;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setDialogLifecycleCallback(DialogLifecycleCallback dialogLifecycleCallback) {
+ this.dialogLifecycleCallback = dialogLifecycleCallback;
+ if (isShow) dialogLifecycleCallback.onShow(me);
+ return this;
+ }
+
+ public BottomMenu setStyle(DialogXStyle style) {
+ this.style = style;
+ return this;
+ }
+
+ public BottomMenu setTheme(DialogX.THEME theme) {
+ this.theme = theme;
+ return this;
+ }
+
+ public boolean isCancelable() {
+ if (privateCancelable != null) {
+ return privateCancelable == BOOLEAN.TRUE;
+ }
+ if (overrideCancelable != null) {
+ return overrideCancelable == BOOLEAN.TRUE;
+ }
+ return cancelable;
+ }
+
+ public BottomMenu setCancelable(boolean cancelable) {
+ this.privateCancelable = cancelable ? BOOLEAN.TRUE : BOOLEAN.FALSE;
+ preRefreshUI();
+ return this;
+ }
+
+ public DialogImpl getDialogImpl() {
+ return dialogImpl;
+ }
+
+ public CharSequence getTitle() {
+ return title;
+ }
+
+ public BottomMenu setTitle(CharSequence title) {
+ this.title = title;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setTitle(int titleResId) {
+ this.title = getString(titleResId);
+ preRefreshUI();
+ return this;
+ }
+
+ public CharSequence getMessage() {
+ return message;
+ }
+
+ public BottomMenu setMessage(CharSequence message) {
+ this.message = message;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setMessage(int messageResId) {
+ this.message = getString(messageResId);
+ preRefreshUI();
+ return this;
+ }
+
+ public CharSequence getCancelButton() {
+ return cancelText;
+ }
+
+ public BottomMenu setCancelButton(CharSequence cancelText) {
+ this.cancelText = cancelText;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setCancelButton(int cancelTextResId) {
+ this.cancelText = getString(cancelTextResId);
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setCancelButton(OnDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ return this;
+ }
+
+ public BottomMenu setCancelButton(CharSequence cancelText, OnDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelText = cancelText;
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setCancelButton(int cancelTextResId, OnDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelText = getString(cancelTextResId);
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setCustomView(OnBindView onBindView) {
+ this.onBindView = onBindView;
+ preRefreshUI();
+ return this;
+ }
+
+ public View getCustomView() {
+ if (onBindView == null) return null;
+ return onBindView.getCustomView();
+ }
+
+ public BottomMenu removeCustomView() {
+ this.onBindView.clean();
+ preRefreshUI();
+ return this;
+ }
+
+ public boolean isAllowInterceptTouch() {
+ return super.isAllowInterceptTouch();
+ }
+
+ public BottomMenu setAllowInterceptTouch(boolean allowInterceptTouch) {
+ this.allowInterceptTouch = allowInterceptTouch;
+ preRefreshUI();
+ return this;
+ }
+
+ public float getBottomDialogMaxHeight() {
+ return bottomDialogMaxHeight;
+ }
+
+ public BottomMenu setBottomDialogMaxHeight(float bottomDialogMaxHeight) {
+ this.bottomDialogMaxHeight = bottomDialogMaxHeight;
+ return this;
+ }
+
+ public OnMenuItemClickListener getOnMenuItemClickListener() {
+ return onMenuItemClickListener;
+ }
+
+ public BottomMenu setOnMenuItemClickListener(OnMenuItemClickListener onMenuItemClickListener) {
+ this.onMenuItemClickListener = onMenuItemClickListener;
+ return this;
+ }
+
+ public BaseAdapter getMenuListAdapter() {
+ return menuListAdapter;
+ }
+
+ public BottomMenu setMenuListAdapter(BaseAdapter menuListAdapter) {
+ this.menuListAdapter = menuListAdapter;
+ return this;
+ }
+
+ public OnDialogButtonClickListener getCancelButtonClickListener() {
+ return cancelButtonClickListener;
+ }
+
+ public BottomMenu setCancelButtonClickListener(OnDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ return this;
+ }
+
+ public TextInfo getTitleTextInfo() {
+ return titleTextInfo;
+ }
+
+ public BottomMenu setTitleTextInfo(TextInfo titleTextInfo) {
+ this.titleTextInfo = titleTextInfo;
+ preRefreshUI();
+ return this;
+ }
+
+ public TextInfo getMessageTextInfo() {
+ return messageTextInfo;
+ }
+
+ public BottomMenu setMessageTextInfo(TextInfo messageTextInfo) {
+ this.messageTextInfo = messageTextInfo;
+ preRefreshUI();
+ return this;
+ }
+
+ public TextInfo getCancelTextInfo() {
+ return cancelTextInfo;
+ }
+
+ public BottomMenu setCancelTextInfo(TextInfo cancelTextInfo) {
+ this.cancelTextInfo = cancelTextInfo;
+ preRefreshUI();
+ return this;
+ }
+
+ public int getBackgroundColor() {
+ return backgroundColor;
+ }
+
+ public BottomMenu setBackgroundColor(@ColorInt int backgroundColor) {
+ this.backgroundColor = backgroundColor;
+ preRefreshUI();
+ return this;
+ }
+
+ public int getSelection() {
+ return selectionIndex;
+ }
+
+ public ArrayList getSelectionList() {
+ return selectionItems;
+ }
+
+ public BottomMenu setSelection(int selectionIndex) {
+ this.selectMode = SELECT_MODE.SINGLE;
+ this.selectionIndex = selectionIndex;
+ this.selectionItems = null;
+ menuListAdapter = null;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setSingleSelection() {
+ this.selectMode = SELECT_MODE.SINGLE;
+ this.selectionIndex = -1;
+ this.selectionItems = null;
+ menuListAdapter = null;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setSelection(int[] selectionItems) {
+ this.selectMode = SELECT_MODE.MULTIPLE;
+ this.selectionIndex = -1;
+ this.selectionItems = new ArrayList<>();
+ if (selectionItems != null) {
+ for (int itemIndex : selectionItems) {
+ this.selectionItems.add(itemIndex);
+ }
+ }
+ menuListAdapter = null;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setMultiSelection() {
+ this.selectMode = SELECT_MODE.MULTIPLE;
+ this.selectionIndex = -1;
+ this.selectionItems = new ArrayList<>();
+ menuListAdapter = null;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setSelection(List selectionItems) {
+ this.selectMode = SELECT_MODE.MULTIPLE;
+ this.selectionIndex = -1;
+ this.selectionItems = new ArrayList<>(selectionItems);
+ menuListAdapter = null;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setNoSelect() {
+ this.selectMode = SELECT_MODE.NONE;
+ this.selectionIndex = -1;
+ this.selectionItems = null;
+ menuListAdapter = null;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setBackgroundColorRes(@ColorRes int backgroundRes) {
+ this.backgroundColor = getColor(backgroundRes);
+ preRefreshUI();
+ return this;
+ }
+
+ public CharSequence getOkButton() {
+ return okText;
+ }
+
+ public BottomMenu setOkButton(CharSequence okText) {
+ this.okText = okText;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setOkButton(int OkTextResId) {
+ this.okText = getString(OkTextResId);
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setOkButton(OnDialogButtonClickListener OkButtonClickListener) {
+ this.okButtonClickListener = OkButtonClickListener;
+ return this;
+ }
+
+ public BottomMenu setOkButton(CharSequence OkText, OnDialogButtonClickListener OkButtonClickListener) {
+ this.okText = OkText;
+ this.okButtonClickListener = OkButtonClickListener;
+ return this;
+ }
+
+ public BottomMenu setOkButton(int OkTextResId, OnDialogButtonClickListener OkButtonClickListener) {
+ this.okText = getString(OkTextResId);
+ this.okButtonClickListener = OkButtonClickListener;
+ return this;
+ }
+
+ public CharSequence getOtherButton() {
+ return otherText;
+ }
+
+ public BottomMenu setOtherButton(CharSequence otherText) {
+ this.otherText = otherText;
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setOtherButton(int OtherTextResId) {
+ this.otherText = getString(OtherTextResId);
+ preRefreshUI();
+ return this;
+ }
+
+ public BottomMenu setOtherButton(OnDialogButtonClickListener OtherButtonClickListener) {
+ this.otherButtonClickListener = OtherButtonClickListener;
+ return this;
+ }
+
+ public BottomMenu setOtherButton(CharSequence OtherText, OnDialogButtonClickListener OtherButtonClickListener) {
+ this.otherText = OtherText;
+ this.otherButtonClickListener = OtherButtonClickListener;
+ return this;
+ }
+
+ public BottomMenu setOtherButton(int OtherTextResId, OnDialogButtonClickListener OtherButtonClickListener) {
+ this.otherText = getString(OtherTextResId);
+ this.otherButtonClickListener = OtherButtonClickListener;
+ return this;
+ }
+
+ public BottomMenu setMaskColor(@ColorInt int maskColor) {
+ this.maskColor = maskColor;
+ preRefreshUI();
+ return this;
+ }
+
+ public long getEnterAnimDuration() {
+ return enterAnimDuration;
+ }
+
+ public BottomMenu setEnterAnimDuration(long enterAnimDuration) {
+ this.enterAnimDuration = enterAnimDuration;
+ return this;
+ }
+
+ public long getExitAnimDuration() {
+ return exitAnimDuration;
+ }
+
+ public BottomMenu setExitAnimDuration(long exitAnimDuration) {
+ this.exitAnimDuration = exitAnimDuration;
+ return this;
+ }
+
+ public SELECT_MODE getSelectMode() {
+ return selectMode;
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/CustomDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/CustomDialog.java
new file mode 100644
index 0000000..8e25f7c
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/CustomDialog.java
@@ -0,0 +1,477 @@
+package com.kongzue.dialogx.dialogs;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Color;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.RelativeLayout;
+
+import androidx.annotation.ColorInt;
+
+import com.kongzue.dialogx.DialogX;
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.interfaces.BaseDialog;
+import com.kongzue.dialogx.interfaces.DialogConvertViewInterface;
+import com.kongzue.dialogx.interfaces.DialogLifecycleCallback;
+import com.kongzue.dialogx.interfaces.DialogXStyle;
+import com.kongzue.dialogx.interfaces.OnBackPressedListener;
+import com.kongzue.dialogx.interfaces.OnBindView;
+import com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/20 11:59
+ */
+public class CustomDialog extends BaseDialog {
+
+ public static int overrideEnterDuration = -1;
+ public static int overrideExitDuration = -1;
+ public static int overrideEnterAnimRes = 0;
+ public static int overrideExitAnimRes = 0;
+ public static int overrideMaskEnterAnimRes = R.anim.anim_dialogx_default_alpha_enter;
+ public static int overrideMaskExitAnimRes = R.anim.anim_dialogx_default_exit;
+ public static BOOLEAN overrideCancelable;
+ protected OnBindView onBindView;
+ protected DialogLifecycleCallback dialogLifecycleCallback;
+ protected CustomDialog me = this;
+ protected DialogImpl dialogImpl;
+ protected int enterAnimResId = R.anim.anim_dialogx_default_enter;
+ protected int exitAnimResId = R.anim.anim_dialogx_default_exit;
+ protected ALIGN align = ALIGN.CENTER;
+ protected boolean autoUnsafePlacePadding = true;
+ private View dialogView;
+ protected int maskColor = Color.TRANSPARENT;
+ protected BOOLEAN privateCancelable;
+
+ public enum ALIGN {
+ CENTER,
+ TOP,
+ BOTTOM,
+ LEFT,
+ RIGHT
+ }
+
+ protected CustomDialog() {
+ super();
+ }
+
+ public static CustomDialog build() {
+ return new CustomDialog();
+ }
+
+ public CustomDialog(OnBindView onBindView) {
+ this.onBindView = onBindView;
+ }
+
+ public static CustomDialog show(OnBindView onBindView) {
+ CustomDialog customDialog = new CustomDialog(onBindView);
+ customDialog.show();
+ return customDialog;
+ }
+
+ public static CustomDialog show(OnBindView onBindView, ALIGN align) {
+ CustomDialog customDialog = new CustomDialog(onBindView);
+ customDialog.align = align;
+ customDialog.show();
+ return customDialog;
+ }
+
+ public void show() {
+ super.beforeShow();
+ dialogView = createView(R.layout.layout_dialogx_custom);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(dialogView);
+ }
+
+ public void show(Activity activity) {
+ super.beforeShow();
+ dialogView = createView(R.layout.layout_dialogx_custom);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(activity, dialogView);
+ }
+
+ public class DialogImpl implements DialogConvertViewInterface {
+
+ public DialogXBaseRelativeLayout boxRoot;
+ public RelativeLayout boxCustom;
+
+ public DialogImpl(View convertView) {
+ boxRoot = convertView.findViewById(R.id.box_root);
+ boxCustom = convertView.findViewById(R.id.box_custom);
+
+ init();
+ dialogImpl = this;
+ refreshView();
+ }
+
+ @Override
+ public void init() {
+ boxRoot.setParentDialog(me);
+ boxRoot.setOnLifecycleCallBack(new DialogXBaseRelativeLayout.OnLifecycleCallBack() {
+ @Override
+ public void onShow() {
+ isShow = true;
+ getDialogLifecycleCallback().onShow(me);
+ boxCustom.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void onDismiss() {
+ isShow = false;
+ getDialogLifecycleCallback().onDismiss(me);
+ }
+ });
+
+ boxRoot.setOnBackPressedListener(new OnBackPressedListener() {
+ @Override
+ public boolean onBackPressed() {
+ if (onBackPressedListener != null && onBackPressedListener.onBackPressed()) {
+ dismiss();
+ return false;
+ }
+ if (isCancelable()) {
+ dismiss();
+ }
+ return false;
+ }
+ });
+
+ boxRoot.post(new Runnable() {
+ @Override
+ public void run() {
+ Animation enterAnim;
+ if (enterAnimResId == R.anim.anim_dialogx_default_enter && exitAnimResId == R.anim.anim_dialogx_default_exit) {
+ switch (align) {
+ case TOP:
+ enterAnimResId = R.anim.anim_dialogx_top_enter;
+ exitAnimResId = R.anim.anim_dialogx_top_exit;
+ break;
+ case BOTTOM:
+ enterAnimResId = R.anim.anim_dialogx_bottom_enter;
+ exitAnimResId = R.anim.anim_dialogx_bottom_exit;
+ break;
+ case LEFT:
+ enterAnimResId = R.anim.anim_dialogx_left_enter;
+ exitAnimResId = R.anim.anim_dialogx_left_exit;
+ break;
+ case RIGHT:
+ enterAnimResId = R.anim.anim_dialogx_right_enter;
+ exitAnimResId = R.anim.anim_dialogx_right_exit;
+ break;
+ }
+ enterAnim = AnimationUtils.loadAnimation(getContext(), enterAnimResId);
+ enterAnim.setInterpolator(new DecelerateInterpolator(2f));
+ } else {
+ int enterAnimResIdTemp = R.anim.anim_dialogx_default_enter;
+ if (overrideEnterAnimRes != 0) {
+ enterAnimResIdTemp = overrideEnterAnimRes;
+ }
+ if (enterAnimResId != 0) {
+ enterAnimResIdTemp = enterAnimResId;
+ }
+ enterAnim = AnimationUtils.loadAnimation(getContext(), enterAnimResIdTemp);
+ }
+ long enterAnimDurationTemp = enterAnim.getDuration();
+ if (overrideEnterDuration >= 0) {
+ enterAnimDurationTemp = overrideEnterDuration;
+ }
+ if (enterAnimDuration >= 0) {
+ enterAnimDurationTemp = enterAnimDuration;
+ }
+ enterAnim.setDuration(enterAnimDurationTemp);
+ boxCustom.setVisibility(View.VISIBLE);
+ boxCustom.startAnimation(enterAnim);
+
+ boxRoot.setBackgroundColor(maskColor);
+ if (overrideMaskEnterAnimRes != 0) {
+ Animation maskEnterAnim = AnimationUtils.loadAnimation(getContext(), overrideMaskEnterAnimRes);
+ maskEnterAnim.setInterpolator(new DecelerateInterpolator(2f));
+ maskEnterAnim.setDuration(enterAnimDurationTemp);
+ boxRoot.startAnimation(maskEnterAnim);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void refreshView() {
+ RelativeLayout.LayoutParams rlp;
+ rlp = ((RelativeLayout.LayoutParams) boxCustom.getLayoutParams());
+ switch (align) {
+ case TOP:
+ rlp.removeRule(RelativeLayout.CENTER_IN_PARENT);
+ rlp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ break;
+ case BOTTOM:
+ rlp.removeRule(RelativeLayout.CENTER_IN_PARENT);
+ rlp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+ break;
+ case CENTER:
+ rlp.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
+ rlp.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+ rlp.addRule(RelativeLayout.CENTER_IN_PARENT);
+ break;
+ case LEFT:
+ rlp.removeRule(RelativeLayout.CENTER_IN_PARENT);
+ rlp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ rlp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
+ break;
+ case RIGHT:
+ rlp.removeRule(RelativeLayout.CENTER_IN_PARENT);
+ rlp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ rlp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+ break;
+ }
+ boxCustom.setLayoutParams(rlp);
+
+ boxRoot.setAutoUnsafePlacePadding(autoUnsafePlacePadding);
+ if (isCancelable()) {
+ boxRoot.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ doDismiss(v);
+ }
+ });
+ } else {
+ boxRoot.setOnClickListener(null);
+ }
+
+ if (onBindView != null && onBindView.getCustomView() != null) {
+ onBindView.bindParent(boxCustom, me);
+ }
+ }
+
+ @Override
+ public void doDismiss(View v) {
+ if (v != null) v.setEnabled(false);
+
+ int exitAnimResIdTemp = R.anim.anim_dialogx_default_exit;
+ if (overrideExitAnimRes != 0) {
+ exitAnimResIdTemp = overrideExitAnimRes;
+ }
+ if (exitAnimResId != 0) {
+ exitAnimResIdTemp = exitAnimResId;
+ }
+ Animation exitAnim = AnimationUtils.loadAnimation(getContext(), exitAnimResIdTemp);
+
+ long exitAnimDurationTemp = exitAnim.getDuration();
+ if (overrideExitDuration >= 0) {
+ exitAnimDurationTemp = overrideExitDuration;
+ }
+ if (exitAnimDuration >= 0) {
+ exitAnimDurationTemp = exitAnimDuration;
+ }
+ exitAnim.setDuration(exitAnimDurationTemp);
+ exitAnim.setAnimationListener(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationStart(Animation animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ dismiss(dialogView);
+ }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+
+ }
+ });
+ boxCustom.startAnimation(exitAnim);
+
+ if (overrideMaskExitAnimRes != 0) {
+ Animation maskExitAnim = AnimationUtils.loadAnimation(getContext(), overrideMaskExitAnimRes);
+ maskExitAnim.setDuration(exitAnimDurationTemp);
+ maskExitAnim.setInterpolator(new DecelerateInterpolator(2f));
+ boxRoot.startAnimation(maskExitAnim);
+ }
+ }
+ }
+
+ @Override
+ public String dialogKey() {
+ return getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")";
+ }
+
+ public void refreshUI() {
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ if (dialogImpl != null) dialogImpl.refreshView();
+ }
+ });
+ }
+
+ public void dismiss() {
+ if (dialogImpl == null) return;
+ dialogImpl.doDismiss(null);
+ }
+
+ public DialogLifecycleCallback getDialogLifecycleCallback() {
+ return dialogLifecycleCallback == null ? new DialogLifecycleCallback() {
+ } : dialogLifecycleCallback;
+ }
+
+ public CustomDialog setDialogLifecycleCallback(DialogLifecycleCallback dialogLifecycleCallback) {
+ this.dialogLifecycleCallback = dialogLifecycleCallback;
+ if (isShow) dialogLifecycleCallback.onShow(me);
+ return this;
+ }
+
+ public OnBackPressedListener getOnBackPressedListener() {
+ return onBackPressedListener;
+ }
+
+ public CustomDialog setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
+ this.onBackPressedListener = onBackPressedListener;
+ refreshUI();
+ return this;
+ }
+
+ public CustomDialog setStyle(DialogXStyle style) {
+ this.style = style;
+ return this;
+ }
+
+ public CustomDialog setTheme(DialogX.THEME theme) {
+ this.theme = theme;
+ return this;
+ }
+
+ public boolean isCancelable() {
+ if (privateCancelable != null) {
+ return privateCancelable == BOOLEAN.TRUE;
+ }
+ if (overrideCancelable != null) {
+ return overrideCancelable == BOOLEAN.TRUE;
+ }
+ return cancelable;
+ }
+
+ public CustomDialog setCancelable(boolean cancelable) {
+ this.privateCancelable = cancelable ? BOOLEAN.TRUE : BOOLEAN.FALSE;
+ refreshUI();
+ return this;
+ }
+
+ public CustomDialog.DialogImpl getDialogImpl() {
+ return dialogImpl;
+ }
+
+ public CustomDialog setCustomView(OnBindView onBindView) {
+ this.onBindView = onBindView;
+ refreshUI();
+ return this;
+ }
+
+ public View getCustomView() {
+ if (onBindView == null) return null;
+ return onBindView.getCustomView();
+ }
+
+ public CustomDialog removeCustomView() {
+ this.onBindView.clean();
+ refreshUI();
+ return this;
+ }
+
+ public int getEnterAnimResId() {
+ return enterAnimResId;
+ }
+
+ public CustomDialog setEnterAnimResId(int enterAnimResId) {
+ this.enterAnimResId = enterAnimResId;
+ return this;
+ }
+
+ public int getExitAnimResId() {
+ return exitAnimResId;
+ }
+
+ public CustomDialog setExitAnimResId(int exitAnimResId) {
+ this.exitAnimResId = exitAnimResId;
+ return this;
+ }
+
+ public CustomDialog setAnimResId(int enterAnimResId, int exitAnimResId) {
+ this.enterAnimResId = enterAnimResId;
+ this.exitAnimResId = exitAnimResId;
+ return this;
+ }
+
+ public ALIGN getAlign() {
+ return align;
+ }
+
+ public CustomDialog setAlign(ALIGN align) {
+ this.align = align;
+ return this;
+ }
+
+ public boolean isAutoUnsafePlacePadding() {
+ return autoUnsafePlacePadding;
+ }
+
+ public CustomDialog setAutoUnsafePlacePadding(boolean autoUnsafePlacePadding) {
+ this.autoUnsafePlacePadding = autoUnsafePlacePadding;
+ refreshUI();
+ return this;
+ }
+
+ public CustomDialog setFullScreen(boolean fullscreen) {
+ this.autoUnsafePlacePadding = !autoUnsafePlacePadding;
+ refreshUI();
+ return this;
+ }
+
+ public CustomDialog setMaskColor(@ColorInt int maskColor) {
+ this.maskColor = maskColor;
+ refreshUI();
+ return this;
+ }
+
+ public long getEnterAnimDuration() {
+ return enterAnimDuration;
+ }
+
+ public CustomDialog setEnterAnimDuration(long enterAnimDuration) {
+ this.enterAnimDuration = enterAnimDuration;
+ return this;
+ }
+
+ public long getExitAnimDuration() {
+ return exitAnimDuration;
+ }
+
+ public CustomDialog setExitAnimDuration(long exitAnimDuration) {
+ this.exitAnimDuration = exitAnimDuration;
+ return this;
+ }
+
+ @Override
+ public void onUIModeChange(Configuration newConfig) {
+ if (dialogView != null) {
+ dismiss(dialogView);
+ }
+ if (getDialogImpl().boxCustom != null) {
+ getDialogImpl().boxCustom.removeAllViews();
+ }
+
+ enterAnimDuration = 0;
+ dialogView = createView(R.layout.layout_dialogx_custom);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(dialogView);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/FullScreenDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/FullScreenDialog.java
new file mode 100644
index 0000000..2d83beb
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/FullScreenDialog.java
@@ -0,0 +1,407 @@
+package com.kongzue.dialogx.dialogs;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.RelativeLayout;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.ColorRes;
+
+import com.kongzue.dialogx.DialogX;
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.impl.AnimatorListenerEndCallBack;
+import com.kongzue.dialogx.interfaces.BaseDialog;
+import com.kongzue.dialogx.interfaces.DialogConvertViewInterface;
+import com.kongzue.dialogx.interfaces.DialogLifecycleCallback;
+import com.kongzue.dialogx.interfaces.DialogXStyle;
+import com.kongzue.dialogx.interfaces.OnBackPressedListener;
+import com.kongzue.dialogx.interfaces.OnBindView;
+import com.kongzue.dialogx.interfaces.OnSafeInsetsChangeListener;
+import com.kongzue.dialogx.util.FullScreenDialogTouchEventInterceptor;
+import com.kongzue.dialogx.util.views.ActivityScreenShotImageView;
+import com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout;
+import com.kongzue.dialogx.util.views.MaxRelativeLayout;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/6 15:17
+ */
+public class FullScreenDialog extends BaseDialog {
+
+ public static int overrideEnterDuration = -1;
+ public static int overrideExitDuration = -1;
+ public static BOOLEAN overrideCancelable;
+
+ protected OnBindView onBindView;
+ protected BOOLEAN privateCancelable;
+
+ protected DialogLifecycleCallback dialogLifecycleCallback;
+
+ protected FullScreenDialog me = this;
+
+ protected FullScreenDialog() {
+ super();
+ }
+
+ private View dialogView;
+
+ public static FullScreenDialog build() {
+ return new FullScreenDialog();
+ }
+
+ public FullScreenDialog(OnBindView onBindView) {
+ this.onBindView = onBindView;
+ }
+
+ public static FullScreenDialog show(OnBindView onBindView) {
+ FullScreenDialog fullScreenDialog = new FullScreenDialog(onBindView);
+ fullScreenDialog.show();
+ return fullScreenDialog;
+ }
+
+ public void show() {
+ super.beforeShow();
+ dialogView = createView(isLightTheme() ? R.layout.layout_dialogx_fullscreen : R.layout.layout_dialogx_fullscreen_dark);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(dialogView);
+ }
+
+ public void show(Activity activity) {
+ super.beforeShow();
+ dialogView = createView(isLightTheme() ? R.layout.layout_dialogx_fullscreen : R.layout.layout_dialogx_fullscreen_dark);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(activity, dialogView);
+ }
+
+ protected DialogImpl dialogImpl;
+
+ public class DialogImpl implements DialogConvertViewInterface {
+
+ private FullScreenDialogTouchEventInterceptor fullScreenDialogTouchEventInterceptor;
+
+ public ActivityScreenShotImageView imgZoomActivity;
+ public DialogXBaseRelativeLayout boxRoot;
+ public RelativeLayout boxBkg;
+ public MaxRelativeLayout bkg;
+ public RelativeLayout boxCustom;
+
+ public DialogImpl(View convertView) {
+ imgZoomActivity = convertView.findViewById(R.id.img_zoom_activity);
+ boxRoot = convertView.findViewById(R.id.box_root);
+ boxBkg = convertView.findViewById(R.id.box_bkg);
+ bkg = convertView.findViewById(R.id.bkg);
+ boxCustom = convertView.findViewById(R.id.box_custom);
+ init();
+ dialogImpl = this;
+ refreshView();
+ }
+
+ public float bkgEnterAimY = -1;
+ private long enterAnimDurationTemp = 300;
+
+ @Override
+ public void init() {
+ boxRoot.setParentDialog(me);
+ boxRoot.setOnLifecycleCallBack(new DialogXBaseRelativeLayout.OnLifecycleCallBack() {
+ @Override
+ public void onShow() {
+ isShow = true;
+ boxRoot.setAlpha(0f);
+
+ getDialogLifecycleCallback().onShow(me);
+ }
+
+ @Override
+ public void onDismiss() {
+ isShow = false;
+ getDialogLifecycleCallback().onDismiss(me);
+ }
+ });
+
+ boxRoot.setOnBackPressedListener(new OnBackPressedListener() {
+ @Override
+ public boolean onBackPressed() {
+ if (onBackPressedListener != null && onBackPressedListener.onBackPressed()) {
+ dismiss();
+ return false;
+ }
+ if (isCancelable()) {
+ dismiss();
+ }
+ return false;
+ }
+ });
+
+ fullScreenDialogTouchEventInterceptor = new FullScreenDialogTouchEventInterceptor(me, dialogImpl);
+
+ enterAnimDurationTemp = 300;
+ if (overrideEnterDuration >= 0) {
+ enterAnimDurationTemp = overrideEnterDuration;
+ }
+ if (enterAnimDuration >= 0) {
+ enterAnimDurationTemp = enterAnimDuration;
+ }
+
+ boxRoot.post(new Runnable() {
+ @Override
+ public void run() {
+ bkgEnterAimY = boxRoot.getSafeHeight() - boxCustom.getHeight();
+ if (bkgEnterAimY < 0) bkgEnterAimY = 0;
+ boxRoot.animate()
+ .setDuration(enterAnimDurationTemp)
+ .alpha(1f)
+ .setInterpolator(new DecelerateInterpolator())
+ .setListener(null);
+
+ ObjectAnimator exitAnim = ObjectAnimator.ofFloat(bkg, "y", boxRoot.getHeight(), bkgEnterAimY);
+ exitAnim.setDuration(enterAnimDurationTemp);
+ exitAnim.start();
+ }
+ });
+
+ bkg.setOnYChanged(new MaxRelativeLayout.OnYChanged() {
+ @Override
+ public void y(float y) {
+ float zoomScale = 1 - (boxRoot.getHeight() - y) * 0.00002f;
+ if (zoomScale > 1) zoomScale = 1;
+ imgZoomActivity.setScaleX(zoomScale);
+ imgZoomActivity.setScaleY(zoomScale);
+
+ imgZoomActivity.setRadius(dip2px(15) * ((boxRoot.getHeight() - y) / boxRoot.getHeight()));
+ }
+ });
+
+ boxRoot.setOnSafeInsetsChangeListener(new OnSafeInsetsChangeListener() {
+ @Override
+ public void onChange(Rect unsafeRect) {
+ if (unsafeRect.bottom > dip2px(100)) {
+ ObjectAnimator enterAnim = ObjectAnimator.ofFloat(bkg, "y", bkg.getY(), 0);
+ enterAnim.setDuration(enterAnimDurationTemp);
+ enterAnim.start();
+ }
+ }
+ });
+ }
+
+ @Override
+ public void refreshView() {
+ if (backgroundColor != -1) {
+ tintColor(bkg, backgroundColor);
+ }
+
+ if (isCancelable()) {
+ boxRoot.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ doDismiss(v);
+ }
+ });
+ } else {
+ boxRoot.setOnClickListener(null);
+ }
+
+ if (onBindView != null && onBindView.getCustomView() != null) {
+ onBindView.bindParent(boxCustom, me);
+ }
+
+ fullScreenDialogTouchEventInterceptor.refresh(me, this);
+ }
+
+ @Override
+ public void doDismiss(View v) {
+ if (v != null) v.setEnabled(false);
+
+ long exitAnimDurationTemp = 300;
+ if (overrideExitDuration >= 0) {
+ exitAnimDurationTemp = overrideExitDuration;
+ }
+ if (exitAnimDuration >= 0) {
+ exitAnimDurationTemp = exitAnimDuration;
+ }
+
+ ObjectAnimator exitAnim = ObjectAnimator.ofFloat(bkg, "y", bkg.getY(), boxBkg.getHeight());
+ exitAnim.setDuration(exitAnimDurationTemp);
+ exitAnim.start();
+
+ boxRoot.animate()
+ .alpha(0f)
+ .setInterpolator(new AccelerateInterpolator())
+ .setDuration(exitAnimDurationTemp);
+
+ new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ dismiss(dialogView);
+ }
+ },exitAnimDurationTemp);
+ }
+
+ public void preDismiss() {
+ if (isCancelable()) {
+ doDismiss(boxRoot);
+ } else {
+ long exitAnimDurationTemp = 300;
+ if (overrideExitDuration >= 0) {
+ exitAnimDurationTemp = overrideExitDuration;
+ }
+ if (exitAnimDuration >= 0) {
+ exitAnimDurationTemp = exitAnimDuration;
+ }
+
+ ObjectAnimator enterAnim = ObjectAnimator.ofFloat(bkg, "y", bkg.getY(), bkgEnterAimY);
+ enterAnim.setDuration(exitAnimDurationTemp);
+ enterAnim.start();
+ }
+ }
+ }
+
+ @Override
+ public String dialogKey() {
+ return getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")";
+ }
+
+ public void refreshUI() {
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ if (dialogImpl != null) dialogImpl.refreshView();
+ }
+ });
+ }
+
+ public void dismiss() {
+ if (dialogImpl == null) return;
+ dialogImpl.doDismiss(null);
+ }
+
+ public DialogLifecycleCallback getDialogLifecycleCallback() {
+ return dialogLifecycleCallback == null ? new DialogLifecycleCallback() {
+ } : dialogLifecycleCallback;
+ }
+
+ public FullScreenDialog setDialogLifecycleCallback(DialogLifecycleCallback dialogLifecycleCallback) {
+ this.dialogLifecycleCallback = dialogLifecycleCallback;
+ if (isShow) dialogLifecycleCallback.onShow(me);
+ return this;
+ }
+
+ public OnBackPressedListener getOnBackPressedListener() {
+ return onBackPressedListener;
+ }
+
+ public FullScreenDialog setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
+ this.onBackPressedListener = onBackPressedListener;
+ refreshUI();
+ return this;
+ }
+
+ public FullScreenDialog setStyle(DialogXStyle style) {
+ this.style = style;
+ return this;
+ }
+
+ public FullScreenDialog setTheme(DialogX.THEME theme) {
+ this.theme = theme;
+ return this;
+ }
+
+ public boolean isCancelable() {
+ if (privateCancelable != null) {
+ return privateCancelable == BOOLEAN.TRUE;
+ }
+ if (overrideCancelable != null) {
+ return overrideCancelable == BOOLEAN.TRUE;
+ }
+ return cancelable;
+ }
+
+ public FullScreenDialog setCancelable(boolean cancelable) {
+ this.privateCancelable = cancelable ? BOOLEAN.TRUE : BOOLEAN.FALSE;
+ refreshUI();
+ return this;
+ }
+
+ public DialogImpl getDialogImpl() {
+ return dialogImpl;
+ }
+
+ public FullScreenDialog setCustomView(OnBindView onBindView) {
+ this.onBindView = onBindView;
+ refreshUI();
+ return this;
+ }
+
+ public View getCustomView() {
+ if (onBindView == null) return null;
+ return onBindView.getCustomView();
+ }
+
+ public FullScreenDialog removeCustomView() {
+ this.onBindView.clean();
+ refreshUI();
+ return this;
+ }
+
+ public int getBackgroundColor() {
+ return backgroundColor;
+ }
+
+ public FullScreenDialog setBackgroundColor(@ColorInt int backgroundColor) {
+ this.backgroundColor = backgroundColor;
+ refreshUI();
+ return this;
+ }
+
+ public FullScreenDialog setBackgroundColorRes(@ColorRes int backgroundColorRes) {
+ this.backgroundColor = getColor(backgroundColorRes);
+ refreshUI();
+ return this;
+ }
+
+ public long getEnterAnimDuration() {
+ return enterAnimDuration;
+ }
+
+ public FullScreenDialog setEnterAnimDuration(long enterAnimDuration) {
+ this.enterAnimDuration = enterAnimDuration;
+ return this;
+ }
+
+ public long getExitAnimDuration() {
+ return exitAnimDuration;
+ }
+
+ public FullScreenDialog setExitAnimDuration(long exitAnimDuration) {
+ this.exitAnimDuration = exitAnimDuration;
+ return this;
+ }
+
+ @Override
+ public void onUIModeChange(Configuration newConfig) {
+ if (dialogView != null) {
+ dismiss(dialogView);
+ }
+ if (getDialogImpl().boxCustom != null) {
+ getDialogImpl().boxCustom.removeAllViews();
+ }
+ enterAnimDuration = 0;
+ dialogView = createView(isLightTheme() ? R.layout.layout_dialogx_fullscreen : R.layout.layout_dialogx_fullscreen_dark);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(dialogView);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/InputDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/InputDialog.java
new file mode 100644
index 0000000..5d2a5c4
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/InputDialog.java
@@ -0,0 +1,550 @@
+package com.kongzue.dialogx.dialogs;
+
+import android.content.res.Configuration;
+import android.view.View;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.ColorRes;
+
+import com.kongzue.dialogx.DialogX;
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.interfaces.OnBackPressedListener;
+import com.kongzue.dialogx.interfaces.OnBindView;
+import com.kongzue.dialogx.interfaces.OnInputDialogButtonClickListener;
+import com.kongzue.dialogx.interfaces.OnInputDialogButtonClickListener;
+import com.kongzue.dialogx.util.InputInfo;
+import com.kongzue.dialogx.util.TextInfo;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/9/24 13:53
+ */
+public class InputDialog extends MessageDialog {
+
+ protected InputDialog() {
+ super();
+ }
+
+ public static InputDialog build() {
+ return new InputDialog();
+ }
+
+ public InputDialog(CharSequence title, CharSequence message, CharSequence okText) {
+ cancelable = DialogX.cancelable;
+ this.title = title;
+ this.message = message;
+ this.okText = okText;
+ }
+
+ public InputDialog(int titleResId, int messageResId, int okTextResId) {
+ cancelable = DialogX.cancelable;
+ this.title = getString(titleResId);
+ this.message = getString(messageResId);
+ this.okText = getString(okTextResId);
+ }
+
+ public static InputDialog show(CharSequence title, CharSequence message, CharSequence okText) {
+ InputDialog inputDialog = new InputDialog(title, message, okText);
+ inputDialog.show();
+ return inputDialog;
+ }
+
+ public static InputDialog show(int titleResId, int messageResId, int okTextResId) {
+ InputDialog inputDialog = new InputDialog(titleResId, messageResId, okTextResId);
+ inputDialog.show();
+ return inputDialog;
+ }
+
+ public InputDialog(CharSequence title, CharSequence message, CharSequence okText, CharSequence cancelText) {
+ cancelable = DialogX.cancelable;
+ this.title = title;
+ this.message = message;
+ this.okText = okText;
+ this.cancelText = cancelText;
+ }
+
+ public InputDialog(int titleResId, int messageResId, int okTextResId, int cancelTextResId) {
+ cancelable = DialogX.cancelable;
+ this.title = getString(titleResId);
+ this.message = getString(messageResId);
+ this.okText = getString(okTextResId);
+ this.cancelText = getString(cancelTextResId);
+ }
+
+ public static InputDialog show(CharSequence title, CharSequence message, CharSequence okText, CharSequence cancelText) {
+ InputDialog inputDialog = new InputDialog(title, message, okText, cancelText);
+ inputDialog.show();
+ return inputDialog;
+ }
+
+ public static InputDialog show(int titleResId, int messageResId, int okTextResId, int cancelTextResId) {
+ InputDialog inputDialog = new InputDialog(titleResId, messageResId, okTextResId, cancelTextResId);
+ inputDialog.show();
+ return inputDialog;
+ }
+
+ public InputDialog(CharSequence title, CharSequence message, CharSequence okText, CharSequence cancelText, String inputText) {
+ cancelable = DialogX.cancelable;
+ this.title = title;
+ this.message = message;
+ this.okText = okText;
+ this.cancelText = cancelText;
+ this.inputText = inputText;
+ }
+
+ public static InputDialog show(CharSequence title, CharSequence message, CharSequence okText, CharSequence cancelText, String inputText) {
+ InputDialog inputDialog = new InputDialog(title, message, okText, cancelText, inputText);
+ inputDialog.show();
+ return inputDialog;
+ }
+
+ public InputDialog(CharSequence title, CharSequence message, CharSequence okText, CharSequence cancelText, CharSequence otherText) {
+ cancelable = DialogX.cancelable;
+ this.title = title;
+ this.message = message;
+ this.okText = okText;
+ this.cancelText = cancelText;
+ this.otherText = otherText;
+ }
+
+ public InputDialog(int titleResId, int messageResId, int okTextResId, int cancelTextResId, int otherTextResId) {
+ cancelable = DialogX.cancelable;
+ this.title = getString(titleResId);
+ this.message = getString(messageResId);
+ this.okText = getString(okTextResId);
+ this.cancelText = getString(cancelTextResId);
+ this.otherText = getString(otherTextResId);
+ }
+
+ public static InputDialog show(CharSequence title, CharSequence message, CharSequence okText, CharSequence cancelText, CharSequence otherText) {
+ InputDialog inputDialog = new InputDialog(title, message, okText, cancelText, otherText);
+ inputDialog.show();
+ return inputDialog;
+ }
+
+ public static InputDialog show(int titleResId, int messageResId, int okTextResId, int cancelTextResId, int otherTextResId) {
+ InputDialog inputDialog = new InputDialog(titleResId, messageResId, okTextResId, cancelTextResId, otherTextResId);
+ inputDialog.show();
+ return inputDialog;
+ }
+
+ public InputDialog(CharSequence title, CharSequence message, CharSequence okText, CharSequence cancelText, CharSequence otherText, String inputText) {
+ cancelable = DialogX.cancelable;
+ this.title = title;
+ this.message = message;
+ this.okText = okText;
+ this.cancelText = cancelText;
+ this.otherText = otherText;
+ this.inputText = inputText;
+ }
+
+ public InputDialog(int titleResId, int messageResId, int okTextResId, int cancelTextResId, int otherTextResId, int inputTextResId) {
+ cancelable = DialogX.cancelable;
+ this.title = getString(titleResId);
+ this.message = getString(messageResId);
+ this.okText = getString(okTextResId);
+ this.cancelText = getString(cancelTextResId);
+ this.otherText = getString(otherTextResId);
+ this.inputText = getString(inputTextResId);
+ }
+
+ public static InputDialog show(CharSequence title, CharSequence message, CharSequence okText, CharSequence cancelText, CharSequence otherText, String inputText) {
+ InputDialog inputDialog = new InputDialog(title, message, okText, cancelText, otherText, inputText);
+ inputDialog.show();
+ return inputDialog;
+ }
+
+ public static InputDialog show(int titleResId, int messageResId, int okTextResId, int cancelTextResId, int otherTextResId, int inputTextResId) {
+ InputDialog inputDialog = new InputDialog(titleResId, messageResId, okTextResId, cancelTextResId, otherTextResId, inputTextResId);
+ inputDialog.show();
+ return inputDialog;
+ }
+
+ @Override
+ public String dialogKey() {
+ return getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")";
+ }
+
+ public CharSequence getOkButton() {
+ return okText;
+ }
+
+ public InputDialog setOkButton(CharSequence okText) {
+ this.okText = okText;
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setOkButton(int okTextResId) {
+ this.okText = getString(okTextResId);
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setOkButton(OnInputDialogButtonClickListener okButtonClickListener) {
+ this.okButtonClickListener = okButtonClickListener;
+ return this;
+ }
+
+ public InputDialog setOkButton(CharSequence okText, OnInputDialogButtonClickListener okButtonClickListener) {
+ this.okText = okText;
+ this.okButtonClickListener = okButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setOkButton(int okTextResId, OnInputDialogButtonClickListener okButtonClickListener) {
+ this.okText = getString(okTextResId);
+ this.okButtonClickListener = okButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public CharSequence getCancelButton() {
+ return cancelText;
+ }
+
+ public InputDialog setCancelButton(CharSequence cancelText) {
+ this.cancelText = cancelText;
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setCancelButton(int cancelTextResId) {
+ this.cancelText = getString(cancelTextResId);
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setCancelButton(OnInputDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ return this;
+ }
+
+ public InputDialog setCancelButton(CharSequence cancelText, OnInputDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelText = cancelText;
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setCancelButton(int cancelTextResId, OnInputDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelText = getString(cancelTextResId);
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public CharSequence getOtherButton() {
+ return otherText;
+ }
+
+ public InputDialog setOtherButton(CharSequence otherText) {
+ this.otherText = otherText;
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setOtherButton(int otherTextResId) {
+ this.otherText = getString(otherTextResId);
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setOtherButton(OnInputDialogButtonClickListener otherButtonClickListener) {
+ this.otherButtonClickListener = otherButtonClickListener;
+ return this;
+ }
+
+ public InputDialog setOtherButton(CharSequence otherText, OnInputDialogButtonClickListener otherButtonClickListener) {
+ this.otherText = otherText;
+ this.otherButtonClickListener = otherButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setOtherButton(int otherTextResId, OnInputDialogButtonClickListener otherButtonClickListener) {
+ this.otherText = getString(otherTextResId);
+ this.otherButtonClickListener = otherButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public OnInputDialogButtonClickListener getInputOkButtonClickListener() {
+ return (OnInputDialogButtonClickListener) okButtonClickListener;
+ }
+
+ public InputDialog setOkButtonClickListener(OnInputDialogButtonClickListener okButtonClickListener) {
+ this.okButtonClickListener = okButtonClickListener;
+ return this;
+ }
+
+ public OnInputDialogButtonClickListener getInputCancelButtonClickListener() {
+ return (OnInputDialogButtonClickListener) cancelButtonClickListener;
+ }
+
+ public InputDialog setCancelButtonClickListener(OnInputDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ return this;
+ }
+
+ public OnInputDialogButtonClickListener getInputOtherButtonClickListener() {
+ return (OnInputDialogButtonClickListener) otherButtonClickListener;
+ }
+
+ public InputDialog setOtherButtonClickListener(OnInputDialogButtonClickListener otherButtonClickListener) {
+ this.otherButtonClickListener = otherButtonClickListener;
+ return this;
+ }
+
+ public CharSequence getTitle() {
+ return title;
+ }
+
+ public InputDialog setTitle(CharSequence title) {
+ this.title = title;
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setTitle(int titleResId) {
+ this.title = getString(titleResId);
+ refreshUI();
+ return this;
+ }
+
+ public CharSequence getMessage() {
+ return message;
+ }
+
+ public InputDialog setMessage(CharSequence message) {
+ this.message = message;
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setMessage(int messageResId) {
+ this.message = getString(messageResId);
+ refreshUI();
+ return this;
+ }
+
+ public String getInputText() {
+ if (getDialogImpl() != null && getDialogImpl().txtInput != null) {
+ return getDialogImpl().txtInput.getText().toString();
+ }
+ return inputText;
+ }
+
+ public InputDialog setInputText(String inputText) {
+ this.inputText = inputText;
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setInputText(int inputTextResId) {
+ this.inputText = getString(inputTextResId);
+ refreshUI();
+ return this;
+ }
+
+ public String getInputHintText() {
+ return inputHintText;
+ }
+
+ public InputDialog setInputHintText(String inputHintText) {
+ this.inputHintText = inputHintText;
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setInputHintText(int inputHintTextResId) {
+ this.inputHintText = getString(inputHintTextResId);
+ refreshUI();
+ return this;
+ }
+
+ public TextInfo getTitleTextInfo() {
+ return titleTextInfo;
+ }
+
+ public InputDialog setTitleTextInfo(TextInfo titleTextInfo) {
+ this.titleTextInfo = titleTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public TextInfo getMessageTextInfo() {
+ return messageTextInfo;
+ }
+
+ public InputDialog setMessageTextInfo(TextInfo messageTextInfo) {
+ this.messageTextInfo = messageTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public TextInfo getOkTextInfo() {
+ return okTextInfo;
+ }
+
+ public InputDialog setOkTextInfo(TextInfo okTextInfo) {
+ this.okTextInfo = okTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public TextInfo getCancelTextInfo() {
+ return cancelTextInfo;
+ }
+
+ public InputDialog setCancelTextInfo(TextInfo cancelTextInfo) {
+ this.cancelTextInfo = cancelTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public TextInfo getOtherTextInfo() {
+ return otherTextInfo;
+ }
+
+ public InputDialog setOtherTextInfo(TextInfo otherTextInfo) {
+ this.otherTextInfo = otherTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public InputInfo getInputInfo() {
+ return inputInfo;
+ }
+
+ public InputDialog setInputInfo(InputInfo inputInfo) {
+ this.inputInfo = inputInfo;
+ refreshUI();
+ return this;
+ }
+
+ public int getButtonOrientation() {
+ return buttonOrientation;
+ }
+
+ public InputDialog setButtonOrientation(int buttonOrientation) {
+ this.buttonOrientation = buttonOrientation;
+ refreshUI();
+ return this;
+ }
+
+ public boolean isCancelable() {
+ if (privateCancelable != null) {
+ return privateCancelable == BOOLEAN.TRUE;
+ }
+ if (overrideCancelable != null) {
+ return overrideCancelable == BOOLEAN.TRUE;
+ }
+ return cancelable;
+ }
+
+ public InputDialog setCancelable(boolean cancelable) {
+ this.privateCancelable = cancelable ? BOOLEAN.TRUE : BOOLEAN.FALSE;
+ refreshUI();
+ return this;
+ }
+
+ public OnBackPressedListener getOnBackPressedListener() {
+ return onBackPressedListener;
+ }
+
+ public InputDialog setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
+ this.onBackPressedListener = onBackPressedListener;
+ return this;
+ }
+
+ public boolean isAutoShowInputKeyboard() {
+ return autoShowInputKeyboard;
+ }
+
+ public InputDialog setAutoShowInputKeyboard(boolean autoShowInputKeyboard) {
+ this.autoShowInputKeyboard = autoShowInputKeyboard;
+ return this;
+ }
+
+ public InputDialog setCustomView(OnBindView onBindView) {
+ this.onBindView = onBindView;
+ refreshUI();
+ return this;
+ }
+
+ public View getCustomView() {
+ if (onBindView == null) return null;
+ return onBindView.getCustomView();
+ }
+
+ public InputDialog removeCustomView() {
+ this.onBindView.clean();
+ refreshUI();
+ return this;
+ }
+
+ public int getBackgroundColor() {
+ return backgroundColor;
+ }
+
+ public InputDialog setBackgroundColor(@ColorInt int backgroundColor) {
+ this.backgroundColor = backgroundColor;
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setBackgroundColorRes(@ColorRes int backgroundColorResId) {
+ this.backgroundColor = getColor(backgroundColorResId);
+ refreshUI();
+ return this;
+ }
+
+ public InputDialog setMaskColor(@ColorInt int maskColor) {
+ this.maskColor = maskColor;
+ refreshUI();
+ return this;
+ }
+
+ public long getEnterAnimDuration() {
+ return enterAnimDuration;
+ }
+
+ public InputDialog setEnterAnimDuration(long enterAnimDuration) {
+ this.enterAnimDuration = enterAnimDuration;
+ return this;
+ }
+
+ public long getExitAnimDuration() {
+ return exitAnimDuration;
+ }
+
+ public InputDialog setExitAnimDuration(long exitAnimDuration) {
+ this.exitAnimDuration = exitAnimDuration;
+ return this;
+ }
+
+ @Override
+ public void onUIModeChange(Configuration newConfig) {
+ if (dialogView != null) {
+ dismiss(dialogView);
+ }
+ if (getDialogImpl().boxCustom!=null){
+ getDialogImpl().boxCustom.removeAllViews();
+ }
+ int layoutId = style.layout(isLightTheme());
+ layoutId = layoutId == 0 ? (isLightTheme() ? R.layout.layout_dialogx_material : R.layout.layout_dialogx_material_dark) : layoutId;
+
+ String inputText = getInputText();
+ enterAnimDuration = 0;
+ dialogView = createView(layoutId);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(dialogView);
+ setInputText(inputText);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/MessageDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/MessageDialog.java
new file mode 100644
index 0000000..4807f07
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/MessageDialog.java
@@ -0,0 +1,1038 @@
+package com.kongzue.dialogx.dialogs;
+
+import android.animation.Animator;
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.Handler;
+import android.os.Looper;
+import android.text.InputFilter;
+import android.text.InputType;
+import android.text.method.LinkMovementMethod;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.Space;
+import android.widget.TextView;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.ColorRes;
+
+import com.kongzue.dialogx.DialogX;
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.impl.AnimatorListenerEndCallBack;
+import com.kongzue.dialogx.interfaces.BaseDialog;
+import com.kongzue.dialogx.interfaces.BaseOnDialogClickCallback;
+import com.kongzue.dialogx.interfaces.DialogConvertViewInterface;
+import com.kongzue.dialogx.interfaces.DialogLifecycleCallback;
+import com.kongzue.dialogx.interfaces.DialogXStyle;
+import com.kongzue.dialogx.interfaces.OnBackPressedListener;
+import com.kongzue.dialogx.interfaces.OnBindView;
+import com.kongzue.dialogx.interfaces.OnDialogButtonClickListener;
+import com.kongzue.dialogx.interfaces.OnInputDialogButtonClickListener;
+import com.kongzue.dialogx.style.MaterialStyle;
+import com.kongzue.dialogx.util.views.BlurView;
+import com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout;
+import com.kongzue.dialogx.util.InputInfo;
+import com.kongzue.dialogx.util.views.MaxRelativeLayout;
+import com.kongzue.dialogx.util.TextInfo;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/9/21 17:08
+ */
+public class MessageDialog extends BaseDialog {
+
+ public static int overrideEnterDuration = -1;
+ public static int overrideExitDuration = -1;
+ public static int overrideEnterAnimRes = 0;
+ public static int overrideExitAnimRes = 0;
+ public static BOOLEAN overrideCancelable;
+ protected OnBindView onBindView;
+ protected MessageDialog me = this;
+ protected BOOLEAN privateCancelable;
+
+ private DialogLifecycleCallback dialogLifecycleCallback;
+
+ protected MessageDialog() {
+ super();
+ }
+
+ protected View dialogView;
+
+ protected CharSequence title;
+ protected CharSequence message;
+ protected CharSequence okText;
+ protected CharSequence cancelText;
+ protected CharSequence otherText;
+ protected String inputText;
+ protected String inputHintText;
+ protected int maskColor = -1;
+
+ protected TextInfo titleTextInfo;
+ protected TextInfo messageTextInfo;
+ protected TextInfo okTextInfo;
+ protected TextInfo cancelTextInfo;
+ protected TextInfo otherTextInfo;
+ protected InputInfo inputInfo;
+
+ protected BaseOnDialogClickCallback okButtonClickListener;
+ protected BaseOnDialogClickCallback cancelButtonClickListener;
+ protected BaseOnDialogClickCallback otherButtonClickListener;
+
+ protected int buttonOrientation;
+
+ public static MessageDialog build() {
+ return new MessageDialog();
+ }
+
+ public MessageDialog(CharSequence title, CharSequence message) {
+ this.title = title;
+ this.message = message;
+ }
+
+ public MessageDialog(CharSequence title, CharSequence message, CharSequence okText) {
+ this.title = title;
+ this.message = message;
+ this.okText = okText;
+ }
+
+ public MessageDialog(int titleResId, int messageResId, int okTextResId) {
+ this.title = getString(titleResId);
+ this.message = getString(messageResId);
+ this.okText = getString(okTextResId);
+ }
+
+ public MessageDialog(int titleResId, int messageResId) {
+ this.title = getString(titleResId);
+ this.message = getString(messageResId);
+ }
+
+ public static MessageDialog show(CharSequence title, CharSequence message, CharSequence okText) {
+ MessageDialog messageDialog = new MessageDialog(title, message, okText);
+ messageDialog.show();
+ return messageDialog;
+ }
+
+ public static MessageDialog show(int titleResId, int messageResId, int okTextResId) {
+ MessageDialog messageDialog = new MessageDialog(titleResId, messageResId, okTextResId);
+ messageDialog.show();
+ return messageDialog;
+ }
+
+ public static MessageDialog show(CharSequence title, CharSequence message) {
+ MessageDialog messageDialog = new MessageDialog(title, message);
+ messageDialog.show();
+ return messageDialog;
+ }
+
+ public static MessageDialog show(int titleResId, int messageResId) {
+ MessageDialog messageDialog = new MessageDialog(titleResId, messageResId);
+ messageDialog.show();
+ return messageDialog;
+ }
+
+ public MessageDialog(CharSequence title, CharSequence message, CharSequence okText, CharSequence cancelText) {
+ this.title = title;
+ this.message = message;
+ this.okText = okText;
+ this.cancelText = cancelText;
+ }
+
+ public MessageDialog(int titleResId, int messageResId, int okTextResId, int cancelTextResId) {
+ this.title = getString(titleResId);
+ this.message = getString(messageResId);
+ this.okText = getString(okTextResId);
+ this.cancelText = getString(cancelTextResId);
+ }
+
+ public static MessageDialog show(CharSequence title, CharSequence message, CharSequence okText, CharSequence cancelText) {
+ MessageDialog messageDialog = new MessageDialog(title, message, okText, cancelText);
+ messageDialog.show();
+ return messageDialog;
+ }
+
+ public static MessageDialog show(int titleResId, int messageResId, int okTextResId, int cancelTextResId) {
+ MessageDialog messageDialog = new MessageDialog(titleResId, messageResId, okTextResId, cancelTextResId);
+ messageDialog.show();
+ return messageDialog;
+ }
+
+ public MessageDialog(CharSequence title, CharSequence message, CharSequence okText, CharSequence cancelText, CharSequence otherText) {
+ this.title = title;
+ this.message = message;
+ this.okText = okText;
+ this.cancelText = cancelText;
+ this.otherText = otherText;
+ }
+
+ public MessageDialog(int titleResId, int messageResId, int okTextResId, int cancelTextResId, int otherTextResId) {
+ this.title = getString(titleResId);
+ this.message = getString(messageResId);
+ this.okText = getString(okTextResId);
+ this.cancelText = getString(cancelTextResId);
+ this.otherText = getString(otherTextResId);
+ }
+
+ public static MessageDialog show(CharSequence title, CharSequence message, CharSequence okText, CharSequence cancelText, CharSequence otherText) {
+ MessageDialog messageDialog = new MessageDialog(title, message, okText, cancelText, otherText);
+ messageDialog.show();
+ return messageDialog;
+ }
+
+ public static MessageDialog show(int titleResId, int messageResId, int okTextResId, int cancelTextResId, int otherTextResId) {
+ MessageDialog messageDialog = new MessageDialog(titleResId, messageResId, okTextResId, cancelTextResId, otherTextResId);
+ messageDialog.show();
+ return messageDialog;
+ }
+
+ protected DialogImpl dialogImpl;
+
+ public void show() {
+ super.beforeShow();
+ int layoutId = style.layout(isLightTheme());
+ layoutId = layoutId == 0 ? (isLightTheme() ? R.layout.layout_dialogx_material : R.layout.layout_dialogx_material_dark) : layoutId;
+
+ dialogView = createView(layoutId);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(dialogView);
+ }
+
+ public void show(Activity activity) {
+ super.beforeShow();
+ int layoutId = style.layout(isLightTheme());
+ layoutId = layoutId == 0 ? (isLightTheme() ? R.layout.layout_dialogx_material : R.layout.layout_dialogx_material_dark) : layoutId;
+
+ dialogView = createView(layoutId);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(activity, dialogView);
+ }
+
+ public void refreshUI() {
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ if (dialogImpl != null) dialogImpl.refreshView();
+ }
+ });
+ }
+
+ public class DialogImpl implements DialogConvertViewInterface {
+ BlurView blurView;
+
+ public DialogXBaseRelativeLayout boxRoot;
+ public MaxRelativeLayout bkg;
+ public TextView txtDialogTitle;
+ public TextView txtDialogTip;
+ public RelativeLayout boxCustom;
+ public EditText txtInput;
+ public LinearLayout boxButton;
+ public TextView btnSelectOther;
+ public View spaceOtherButton;
+ public View splitHorizontal;
+ public TextView btnSelectNegative;
+ public TextView btnSelectPositive;
+
+ public DialogImpl(View convertView) {
+ boxRoot = convertView.findViewById(R.id.box_root);
+ bkg = convertView.findViewById(R.id.bkg);
+ txtDialogTitle = convertView.findViewById(R.id.txt_dialog_title);
+ txtDialogTip = convertView.findViewById(R.id.txt_dialog_tip);
+ boxCustom = convertView.findViewById(R.id.box_custom);
+ txtInput = convertView.findViewById(R.id.txt_input);
+ boxButton = convertView.findViewById(R.id.box_button);
+ btnSelectOther = convertView.findViewById(R.id.btn_selectOther);
+ spaceOtherButton = convertView.findViewById(R.id.space_other_button);
+ splitHorizontal = convertView.findViewWithTag("split");
+ btnSelectNegative = convertView.findViewById(R.id.btn_selectNegative);
+ btnSelectPositive = convertView.findViewById(R.id.btn_selectPositive);
+ init();
+ dialogImpl = this;
+ refreshView();
+ }
+
+ public void init() {
+ if (titleTextInfo == null) titleTextInfo = DialogX.titleTextInfo;
+ if (messageTextInfo == null) messageTextInfo = DialogX.messageTextInfo;
+ if (okTextInfo == null) okTextInfo = DialogX.okButtonTextInfo;
+ if (okTextInfo == null) okTextInfo = DialogX.buttonTextInfo;
+ if (cancelTextInfo == null) cancelTextInfo = DialogX.buttonTextInfo;
+ if (otherTextInfo == null) otherTextInfo = DialogX.buttonTextInfo;
+ if (inputInfo == null) inputInfo = DialogX.inputInfo;
+ if (backgroundColor == -1) backgroundColor = DialogX.backgroundColor;
+
+ txtDialogTitle.getPaint().setFakeBoldText(true);
+ btnSelectNegative.getPaint().setFakeBoldText(true);
+ btnSelectPositive.getPaint().setFakeBoldText(true);
+ btnSelectOther.getPaint().setFakeBoldText(true);
+
+ txtDialogTip.setMovementMethod(LinkMovementMethod.getInstance());
+
+ boxRoot.setParentDialog(me);
+ boxRoot.setOnLifecycleCallBack(new DialogXBaseRelativeLayout.OnLifecycleCallBack() {
+ @Override
+ public void onShow() {
+ isShow = true;
+ boxRoot.setAlpha(0f);
+ int enterAnimResId = style.enterAnimResId() == 0 ? R.anim.anim_dialogx_default_enter : style.enterAnimResId();
+ if (overrideEnterAnimRes != 0) {
+ enterAnimResId = overrideEnterAnimRes;
+ }
+ Animation enterAnim = AnimationUtils.loadAnimation(getContext(), enterAnimResId);
+ long enterAnimDurationTemp = enterAnim.getDuration();
+ if (overrideEnterDuration >= 0) {
+ enterAnimDurationTemp = overrideEnterDuration;
+ }
+ if (enterAnimDuration >= 0) {
+ enterAnimDurationTemp = enterAnimDuration;
+ }
+ enterAnim.setDuration(enterAnimDurationTemp);
+ enterAnim.setInterpolator(new DecelerateInterpolator());
+ bkg.startAnimation(enterAnim);
+
+ boxRoot.animate()
+ .setDuration(enterAnimDurationTemp)
+ .alpha(1f)
+ .setInterpolator(new DecelerateInterpolator())
+ .setListener(null);
+
+ getDialogLifecycleCallback().onShow(me);
+
+ if (style.messageDialogBlurSettings() != null && style.messageDialogBlurSettings().blurBackground()) {
+ bkg.post(new Runnable() {
+ @Override
+ public void run() {
+ int blurFrontColor = getResources().getColor(style.messageDialogBlurSettings().blurForwardColorRes(isLightTheme()));
+ blurView = new BlurView(bkg.getContext(), null);
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(bkg.getWidth(), bkg.getHeight());
+ params.addRule(RelativeLayout.CENTER_IN_PARENT);
+ blurView.setOverlayColor(backgroundColor == -1 ? blurFrontColor : backgroundColor);
+ blurView.setTag("blurView");
+ blurView.setRadiusPx(style.messageDialogBlurSettings().blurBackgroundRoundRadiusPx());
+ bkg.addView(blurView, 0, params);
+ }
+ });
+ }
+
+ if (autoShowInputKeyboard) {
+ txtInput.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (txtInput == null) return;
+ txtInput.requestFocus();
+ txtInput.setFocusableInTouchMode(true);
+ InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(txtInput, InputMethodManager.RESULT_UNCHANGED_SHOWN);
+ txtInput.setSelection(txtInput.getText().length());
+ if (inputInfo != null && inputInfo.isSelectAllText()) {
+ txtInput.selectAll();
+ }
+ }
+ }, 300);
+ } else {
+ if (inputInfo != null && inputInfo.isSelectAllText()) {
+ txtInput.clearFocus();
+ txtInput.requestFocus();
+ txtInput.selectAll();
+ }
+ }
+ }
+
+ @Override
+ public void onDismiss() {
+ isShow = false;
+ getDialogLifecycleCallback().onDismiss(me);
+ }
+ });
+
+ boxRoot.setOnBackPressedListener(new OnBackPressedListener() {
+ @Override
+ public boolean onBackPressed() {
+ if (onBackPressedListener != null && onBackPressedListener.onBackPressed()) {
+ dismiss();
+ return false;
+ }
+ if (isCancelable()) {
+ dismiss();
+ }
+ return false;
+ }
+ });
+ btnSelectPositive.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (txtInput != null) {
+ InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(txtInput.getWindowToken(), 0);
+ }
+ if (okButtonClickListener != null) {
+ if (okButtonClickListener instanceof OnInputDialogButtonClickListener) {
+ String s = txtInput == null ? "" : txtInput.getText().toString();
+ if (!((OnInputDialogButtonClickListener) okButtonClickListener).onClick(me, v, s)) {
+ doDismiss(v);
+ }
+ } else if (okButtonClickListener instanceof OnDialogButtonClickListener) {
+ if (!((OnDialogButtonClickListener) okButtonClickListener).onClick(me, v)) {
+ doDismiss(v);
+ }
+ }
+ } else {
+ doDismiss(v);
+ }
+ }
+ });
+ btnSelectNegative.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (txtInput != null) {
+ InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(txtInput.getWindowToken(), 0);
+ }
+ if (cancelButtonClickListener != null) {
+ if (cancelButtonClickListener instanceof OnInputDialogButtonClickListener) {
+ String s = txtInput == null ? "" : txtInput.getText().toString();
+ if (!((OnInputDialogButtonClickListener) cancelButtonClickListener).onClick(me, v, s)) {
+ doDismiss(v);
+ }
+ } else {
+ if (!((OnDialogButtonClickListener) cancelButtonClickListener).onClick(me, v)) {
+ doDismiss(v);
+ }
+ }
+ } else {
+ doDismiss(v);
+ }
+ }
+ });
+ btnSelectOther.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (txtInput != null) {
+ InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(txtInput.getWindowToken(), 0);
+ }
+ if (otherButtonClickListener != null) {
+ if (otherButtonClickListener instanceof OnInputDialogButtonClickListener) {
+ String s = txtInput == null ? "" : txtInput.getText().toString();
+ if (!((OnInputDialogButtonClickListener) otherButtonClickListener).onClick(me, v, s)) {
+ doDismiss(v);
+ }
+ } else {
+ if (!((OnDialogButtonClickListener) otherButtonClickListener).onClick(me, v)) {
+ doDismiss(v);
+ }
+ }
+ } else {
+ doDismiss(v);
+ }
+ }
+ });
+ }
+
+ public void refreshView() {
+ if (backgroundColor != -1) {
+ tintColor(bkg, backgroundColor);
+ if (style instanceof MaterialStyle) {
+ tintColor(btnSelectOther, backgroundColor);
+ tintColor(btnSelectNegative, backgroundColor);
+ tintColor(btnSelectPositive, backgroundColor);
+ }
+ }
+
+ bkg.setMaxWidth(DialogX.dialogMaxWidth);
+ if (me instanceof InputDialog) {
+ txtInput.setVisibility(View.VISIBLE);
+ } else {
+ txtInput.setVisibility(View.GONE);
+ }
+ boxRoot.setClickable(true);
+ if (maskColor != -1) boxRoot.setBackgroundColor(maskColor);
+
+ showText(txtDialogTitle, title);
+ showText(txtDialogTip, message);
+ showText(btnSelectPositive, okText);
+ showText(btnSelectNegative, cancelText);
+ showText(btnSelectOther, otherText);
+
+ txtInput.setText(inputText);
+ txtInput.setHint(inputHintText);
+ if (spaceOtherButton != null) {
+ if (otherText == null) {
+ spaceOtherButton.setVisibility(View.GONE);
+ } else {
+ spaceOtherButton.setVisibility(View.VISIBLE);
+ }
+ }
+
+ useTextInfo(txtDialogTitle, titleTextInfo);
+ useTextInfo(txtDialogTip, messageTextInfo);
+ useTextInfo(btnSelectPositive, okTextInfo);
+ useTextInfo(btnSelectNegative, cancelTextInfo);
+ useTextInfo(btnSelectOther, otherTextInfo);
+ if (inputInfo != null) {
+ if (inputInfo.getMAX_LENGTH() != -1)
+ txtInput.setFilters(new InputFilter[]{new InputFilter.LengthFilter(inputInfo.getMAX_LENGTH())});
+ int inputType = InputType.TYPE_CLASS_TEXT | inputInfo.getInputType();
+ if (inputInfo.isMultipleLines()) {
+ inputType = inputType | InputType.TYPE_TEXT_FLAG_MULTI_LINE;
+ }
+ txtInput.setInputType(inputType);
+ if (inputInfo.getTextInfo() != null) {
+ useTextInfo(txtInput, inputInfo.getTextInfo());
+ }
+ }
+
+ int visibleButtonCount = 0;
+ if (!isNull(okText)) {
+ visibleButtonCount = visibleButtonCount + 1;
+ }
+ if (!isNull(cancelText)) {
+ visibleButtonCount = visibleButtonCount + 1;
+ }
+ if (!isNull(otherText)) {
+ visibleButtonCount = visibleButtonCount + 1;
+ }
+
+ if (splitHorizontal != null) {
+ splitHorizontal.setBackgroundColor(getColor(style.splitColorRes(isLightTheme())));
+ }
+
+ boxButton.setOrientation(buttonOrientation);
+ if (buttonOrientation == LinearLayout.VERTICAL) {
+ //纵向
+ if (style.verticalButtonOrder() != null && style.verticalButtonOrder().length != 0) {
+ boxButton.removeAllViews();
+ for (int buttonType : style.verticalButtonOrder()) {
+ switch (buttonType) {
+ case DialogXStyle.BUTTON_OK:
+ boxButton.addView(btnSelectPositive);
+ if (style.overrideVerticalButtonRes() != null) {
+ btnSelectPositive.setBackgroundResource(
+ style.overrideVerticalButtonRes().overrideVerticalOkButtonBackgroundRes(visibleButtonCount, isLightTheme())
+ );
+ }
+ break;
+ case DialogXStyle.BUTTON_OTHER:
+ boxButton.addView(btnSelectOther);
+ if (style.overrideVerticalButtonRes() != null) {
+ btnSelectOther.setBackgroundResource(
+ style.overrideVerticalButtonRes().overrideVerticalOtherButtonBackgroundRes(visibleButtonCount, isLightTheme())
+ );
+ }
+ break;
+ case DialogXStyle.BUTTON_CANCEL:
+ boxButton.addView(btnSelectNegative);
+ if (style.overrideVerticalButtonRes() != null) {
+ btnSelectNegative.setBackgroundResource(
+ style.overrideVerticalButtonRes().overrideVerticalCancelButtonBackgroundRes(visibleButtonCount, isLightTheme())
+ );
+ }
+ break;
+ case DialogXStyle.SPACE:
+ Space space = new Space(getContext());
+ LinearLayout.LayoutParams spaceLp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ spaceLp.weight = 1;
+ boxButton.addView(space, spaceLp);
+ break;
+ case DialogXStyle.SPLIT:
+ View splitView = new View(getContext());
+ splitView.setBackgroundColor(getResources().getColor(style.splitColorRes(isLightTheme())));
+ LinearLayout.LayoutParams viewLp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, style.splitWidthPx());
+ boxButton.addView(splitView, viewLp);
+ break;
+ }
+ }
+ }
+ } else {
+ //横向
+ if (style.horizontalButtonOrder() != null && style.horizontalButtonOrder().length != 0) {
+ boxButton.removeAllViews();
+ for (int buttonType : style.horizontalButtonOrder()) {
+ switch (buttonType) {
+ case DialogXStyle.BUTTON_OK:
+ boxButton.addView(btnSelectPositive);
+ if (style.overrideHorizontalButtonRes() != null) {
+ btnSelectPositive.setBackgroundResource(
+ style.overrideHorizontalButtonRes().overrideHorizontalOkButtonBackgroundRes(visibleButtonCount, isLightTheme())
+ );
+ }
+ break;
+ case DialogXStyle.BUTTON_OTHER:
+ boxButton.addView(btnSelectOther);
+ if (style.overrideHorizontalButtonRes() != null) {
+ btnSelectOther.setBackgroundResource(
+ style.overrideHorizontalButtonRes().overrideHorizontalOtherButtonBackgroundRes(visibleButtonCount, isLightTheme())
+ );
+ }
+ break;
+ case DialogXStyle.BUTTON_CANCEL:
+ boxButton.addView(btnSelectNegative);
+ if (style.overrideHorizontalButtonRes() != null) {
+ btnSelectNegative.setBackgroundResource(
+ style.overrideHorizontalButtonRes().overrideHorizontalCancelButtonBackgroundRes(visibleButtonCount, isLightTheme())
+ );
+ }
+ break;
+ case DialogXStyle.SPACE:
+ if (boxButton.getChildCount() >= 1) {
+ if (boxButton.getChildAt(boxButton.getChildCount() - 1).getVisibility() == View.GONE) {
+ break;
+ }
+ } else {
+ break;
+ }
+ Space space = new Space(getContext());
+ LinearLayout.LayoutParams spaceLp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ spaceLp.weight = 1;
+ boxButton.addView(space, spaceLp);
+ break;
+ case DialogXStyle.SPLIT:
+ if (boxButton.getChildCount() >= 1) {
+ if (boxButton.getChildAt(boxButton.getChildCount() - 1).getVisibility() == View.GONE) {
+ break;
+ }
+ } else {
+ break;
+ }
+ View splitView = new View(getContext());
+ splitView.setBackgroundColor(getResources().getColor(style.splitColorRes(isLightTheme())));
+ LinearLayout.LayoutParams viewLp = new LinearLayout.LayoutParams(style.splitWidthPx(), ViewGroup.LayoutParams.MATCH_PARENT);
+ boxButton.addView(splitView, viewLp);
+ break;
+ }
+ }
+ }
+ }
+
+ //Events
+ if (isCancelable()) {
+ boxRoot.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ doDismiss(v);
+ }
+ });
+ } else {
+ boxRoot.setOnClickListener(null);
+ }
+
+ if (onBindView != null && onBindView.getCustomView() != null) {
+ onBindView.bindParent(boxCustom, me);
+ boxCustom.setVisibility(View.VISIBLE);
+ } else {
+ boxCustom.setVisibility(View.GONE);
+ }
+ }
+
+ public void doDismiss(View v) {
+ if (v != null) v.setEnabled(false);
+
+ int exitAnimResId = style.exitAnimResId() == 0 ? R.anim.anim_dialogx_default_exit : style.exitAnimResId();
+ if (overrideExitAnimRes != 0) {
+ exitAnimResId = overrideExitAnimRes;
+ }
+ Animation exitAnim = AnimationUtils.loadAnimation(getContext(), exitAnimResId);
+ long exitAnimDurationTemp = exitAnim.getDuration();
+ exitAnim.setInterpolator(new AccelerateInterpolator());
+ if (overrideExitDuration >= 0) {
+ exitAnimDurationTemp = overrideExitDuration;
+ }
+ if (exitAnimDuration >= 0) {
+ exitAnimDurationTemp = exitAnimDuration;
+ }
+ exitAnim.setDuration(exitAnimDurationTemp);
+ bkg.startAnimation(exitAnim);
+
+ boxRoot.animate()
+ .alpha(0f)
+ .setInterpolator(new AccelerateInterpolator())
+ .setDuration(exitAnimDuration == -1 ? exitAnim.getDuration() : exitAnimDuration);
+
+ new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ dismiss(dialogView);
+ }
+ },exitAnimDuration == -1 ? exitAnim.getDuration() : exitAnimDuration);
+ }
+ }
+
+ @Override
+ public String dialogKey() {
+ return getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")";
+ }
+
+ public void dismiss() {
+ if (dialogImpl == null) return;
+ dialogImpl.doDismiss(dialogImpl.bkg);
+ }
+
+ public DialogLifecycleCallback getDialogLifecycleCallback() {
+ return dialogLifecycleCallback == null ? new DialogLifecycleCallback() {
+ } : dialogLifecycleCallback;
+ }
+
+ public MessageDialog setDialogLifecycleCallback(DialogLifecycleCallback dialogLifecycleCallback) {
+ this.dialogLifecycleCallback = dialogLifecycleCallback;
+ if (isShow) dialogLifecycleCallback.onShow(me);
+ return this;
+ }
+
+ public MessageDialog setStyle(DialogXStyle style) {
+ this.style = style;
+ return this;
+ }
+
+ public MessageDialog setTheme(DialogX.THEME theme) {
+ this.theme = theme;
+ return this;
+ }
+
+ public CharSequence getOkButton() {
+ return okText;
+ }
+
+ public MessageDialog setOkButton(CharSequence okText) {
+ this.okText = okText;
+ refreshUI();
+ return this;
+ }
+
+ public MessageDialog setOkButton(int okTextRedId) {
+ this.okText = getString(okTextRedId);
+ refreshUI();
+ return this;
+ }
+
+ public MessageDialog setOkButton(OnDialogButtonClickListener okButtonClickListener) {
+ this.okButtonClickListener = okButtonClickListener;
+ return this;
+ }
+
+ public MessageDialog setOkButton(CharSequence okText, OnDialogButtonClickListener okButtonClickListener) {
+ this.okText = okText;
+ this.okButtonClickListener = okButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public MessageDialog setOkButton(int okTextRedId, OnDialogButtonClickListener okButtonClickListener) {
+ this.okText = getString(okTextRedId);
+ this.okButtonClickListener = okButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public CharSequence getCancelButton() {
+ return cancelText;
+ }
+
+ public MessageDialog setCancelButton(CharSequence cancelText) {
+ this.cancelText = cancelText;
+ refreshUI();
+ return this;
+ }
+
+ public MessageDialog setCancelButton(int cancelTextResId) {
+ this.cancelText = getString(cancelTextResId);
+ refreshUI();
+ return this;
+ }
+
+ public MessageDialog setCancelButton(OnDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ return this;
+ }
+
+ public MessageDialog setCancelButton(CharSequence cancelText, OnDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelText = cancelText;
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public MessageDialog setCancelButton(int cancelTextResId, OnDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelText = getString(cancelTextResId);
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public CharSequence getOtherButton() {
+ return otherText;
+ }
+
+ public MessageDialog setOtherButton(CharSequence otherText) {
+ this.otherText = otherText;
+ refreshUI();
+ return this;
+ }
+
+ public MessageDialog setOtherButton(int otherTextResId) {
+ this.otherText = getString(otherTextResId);
+ refreshUI();
+ return this;
+ }
+
+ public MessageDialog setOtherButton(OnDialogButtonClickListener otherButtonClickListener) {
+ this.otherButtonClickListener = otherButtonClickListener;
+ return this;
+ }
+
+ public MessageDialog setOtherButton(CharSequence otherText, OnDialogButtonClickListener otherButtonClickListener) {
+ this.otherText = otherText;
+ this.otherButtonClickListener = otherButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public MessageDialog setOtherButton(int otherTextResId, OnDialogButtonClickListener otherButtonClickListener) {
+ this.otherText = getString(otherTextResId);
+ this.otherButtonClickListener = otherButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public OnDialogButtonClickListener getOkButtonClickListener() {
+ return (OnDialogButtonClickListener) okButtonClickListener;
+ }
+
+ public MessageDialog setOkButtonClickListener(OnDialogButtonClickListener okButtonClickListener) {
+ this.okButtonClickListener = okButtonClickListener;
+ return this;
+ }
+
+ public OnDialogButtonClickListener getCancelButtonClickListener() {
+ return (OnDialogButtonClickListener) cancelButtonClickListener;
+ }
+
+ public MessageDialog setCancelButtonClickListener(OnDialogButtonClickListener cancelButtonClickListener) {
+ this.cancelButtonClickListener = cancelButtonClickListener;
+ return this;
+ }
+
+ public OnDialogButtonClickListener getOtherButtonClickListener() {
+ return (OnDialogButtonClickListener) otherButtonClickListener;
+ }
+
+ public MessageDialog setOtherButtonClickListener(OnDialogButtonClickListener otherButtonClickListener) {
+ this.otherButtonClickListener = otherButtonClickListener;
+ return this;
+ }
+
+ public CharSequence getTitle() {
+ return title;
+ }
+
+ public MessageDialog setTitle(CharSequence title) {
+ this.title = title;
+ refreshUI();
+ return this;
+ }
+
+ public MessageDialog setTitle(int titleResId) {
+ this.title = getString(titleResId);
+ refreshUI();
+ return this;
+ }
+
+ public CharSequence getMessage() {
+ return message;
+ }
+
+ public MessageDialog setMessage(CharSequence message) {
+ this.message = message;
+ refreshUI();
+ return this;
+ }
+
+ public MessageDialog setMessage(int messageResId) {
+ this.message = getString(messageResId);
+ refreshUI();
+ return this;
+ }
+
+ public TextInfo getTitleTextInfo() {
+ return titleTextInfo;
+ }
+
+ public MessageDialog setTitleTextInfo(TextInfo titleTextInfo) {
+ this.titleTextInfo = titleTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public TextInfo getMessageTextInfo() {
+ return messageTextInfo;
+ }
+
+ public MessageDialog setMessageTextInfo(TextInfo messageTextInfo) {
+ this.messageTextInfo = messageTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public TextInfo getOkTextInfo() {
+ return okTextInfo;
+ }
+
+ public MessageDialog setOkTextInfo(TextInfo okTextInfo) {
+ this.okTextInfo = okTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public TextInfo getCancelTextInfo() {
+ return cancelTextInfo;
+ }
+
+ public MessageDialog setCancelTextInfo(TextInfo cancelTextInfo) {
+ this.cancelTextInfo = cancelTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public TextInfo getOtherTextInfo() {
+ return otherTextInfo;
+ }
+
+ public MessageDialog setOtherTextInfo(TextInfo otherTextInfo) {
+ this.otherTextInfo = otherTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public int getButtonOrientation() {
+ return buttonOrientation;
+ }
+
+ public MessageDialog setButtonOrientation(int buttonOrientation) {
+ this.buttonOrientation = buttonOrientation;
+ refreshUI();
+ return this;
+ }
+
+ public boolean isCancelable() {
+ if (privateCancelable != null) {
+ return privateCancelable == BOOLEAN.TRUE;
+ }
+ if (overrideCancelable != null) {
+ return overrideCancelable == BOOLEAN.TRUE;
+ }
+ return cancelable;
+ }
+
+ public MessageDialog setCancelable(boolean cancelable) {
+ this.privateCancelable = cancelable ? BOOLEAN.TRUE : BOOLEAN.FALSE;
+ refreshUI();
+ return this;
+ }
+
+ public OnBackPressedListener getOnBackPressedListener() {
+ return onBackPressedListener;
+ }
+
+ public MessageDialog setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
+ this.onBackPressedListener = onBackPressedListener;
+ return this;
+ }
+
+ public DialogImpl getDialogImpl() {
+ return dialogImpl;
+ }
+
+ public MessageDialog setCustomView(OnBindView onBindView) {
+ this.onBindView = onBindView;
+ refreshUI();
+ return this;
+ }
+
+ public View getCustomView() {
+ if (onBindView == null) return null;
+ return onBindView.getCustomView();
+ }
+
+ public MessageDialog removeCustomView() {
+ this.onBindView.clean();
+ refreshUI();
+ return this;
+ }
+
+ public int getBackgroundColor() {
+ return backgroundColor;
+ }
+
+ public MessageDialog setBackgroundColor(@ColorInt int backgroundColor) {
+ this.backgroundColor = backgroundColor;
+ refreshUI();
+ return this;
+ }
+
+ public String getInputText() {
+ if (dialogImpl.txtInput != null) {
+ return dialogImpl.txtInput.getText().toString();
+ } else {
+ return "";
+ }
+ }
+
+ public MessageDialog setBackgroundColorRes(@ColorRes int backgroundColorResId) {
+ this.backgroundColor = getColor(backgroundColorResId);
+ refreshUI();
+ return this;
+ }
+
+ public MessageDialog setMaskColor(@ColorInt int maskColor) {
+ this.maskColor = maskColor;
+ refreshUI();
+ return this;
+ }
+
+ public long getEnterAnimDuration() {
+ return enterAnimDuration;
+ }
+
+ public MessageDialog setEnterAnimDuration(long enterAnimDuration) {
+ this.enterAnimDuration = enterAnimDuration;
+ return this;
+ }
+
+ public long getExitAnimDuration() {
+ return exitAnimDuration;
+ }
+
+ public MessageDialog setExitAnimDuration(long exitAnimDuration) {
+ this.exitAnimDuration = exitAnimDuration;
+ return this;
+ }
+
+ @Override
+ public void onUIModeChange(Configuration newConfig) {
+ if (dialogView != null) {
+ dismiss(dialogView);
+ }
+ if (getDialogImpl().boxCustom != null) {
+ getDialogImpl().boxCustom.removeAllViews();
+ }
+ int layoutId = style.layout(isLightTheme());
+ layoutId = layoutId == 0 ? (isLightTheme() ? R.layout.layout_dialogx_material : R.layout.layout_dialogx_material_dark) : layoutId;
+
+ enterAnimDuration = 0;
+ dialogView = createView(layoutId);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(dialogView);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopTip.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopTip.java
new file mode 100644
index 0000000..b65051b
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopTip.java
@@ -0,0 +1,851 @@
+package com.kongzue.dialogx.dialogs;
+
+import android.animation.Animator;
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.ColorRes;
+import androidx.annotation.IdRes;
+
+import com.kongzue.dialogx.DialogX;
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.impl.AnimatorListenerEndCallBack;
+import com.kongzue.dialogx.interfaces.BaseDialog;
+import com.kongzue.dialogx.interfaces.DialogConvertViewInterface;
+import com.kongzue.dialogx.interfaces.DialogLifecycleCallback;
+import com.kongzue.dialogx.interfaces.DialogXStyle;
+import com.kongzue.dialogx.interfaces.OnBackPressedListener;
+import com.kongzue.dialogx.interfaces.OnBindView;
+import com.kongzue.dialogx.interfaces.OnDialogButtonClickListener;
+import com.kongzue.dialogx.interfaces.OnSafeInsetsChangeListener;
+import com.kongzue.dialogx.style.MaterialStyle;
+import com.kongzue.dialogx.util.TextInfo;
+import com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/20 11:59
+ */
+public class PopTip extends BaseDialog {
+
+ public static final int TIME_NO_AUTO_DISMISS_DELAY = -1;
+ protected static List popTipList;
+
+ protected OnBindView onBindView;
+ protected DialogLifecycleCallback dialogLifecycleCallback;
+ protected PopTip me = this;
+ protected DialogImpl dialogImpl;
+ protected int enterAnimResId = R.anim.anim_dialogx_default_enter;
+ protected int exitAnimResId = R.anim.anim_dialogx_default_exit;
+ private View dialogView;
+ protected DialogXStyle.PopTipSettings.ALIGN align;
+ protected OnDialogButtonClickListener onButtonClickListener;
+ protected OnDialogButtonClickListener onPopTipClickListener;
+ protected boolean autoTintIconInLightOrDarkMode = true;
+
+ protected int iconResId;
+ protected CharSequence message;
+ protected CharSequence buttonText;
+
+ protected TextInfo messageTextInfo;
+ protected TextInfo buttonTextInfo = new TextInfo().setBold(true);
+
+ protected PopTip() {
+ super();
+ }
+
+ public static PopTip build() {
+ return new PopTip();
+ }
+
+ public PopTip(OnBindView onBindView) {
+ this.onBindView = onBindView;
+ }
+
+ public PopTip(CharSequence message) {
+ this.message = message;
+ }
+
+ public PopTip(int messageResId) {
+ this.message = getString(messageResId);
+ }
+
+ public PopTip(int iconResId, CharSequence message) {
+ this.iconResId = iconResId;
+ this.message = message;
+ }
+
+ public PopTip(int iconResId, CharSequence message, CharSequence buttonText) {
+ this.iconResId = iconResId;
+ this.message = message;
+ this.buttonText = buttonText;
+ }
+
+ public PopTip(int iconResId, int messageResId, int buttonTextResId) {
+ this.iconResId = iconResId;
+ this.message = getString(messageResId);
+ this.buttonText = getString(buttonTextResId);
+ }
+
+ public PopTip(CharSequence message, CharSequence buttonText) {
+ this.message = message;
+ this.buttonText = buttonText;
+ }
+
+ public PopTip(int messageResId, int buttonTextResId) {
+ this.message = getString(messageResId);
+ this.buttonText = getString(buttonTextResId);
+ }
+
+ public PopTip(CharSequence message, OnBindView onBindView) {
+ this.message = message;
+ this.onBindView = onBindView;
+ }
+
+ public PopTip(int messageResId, OnBindView onBindView) {
+ this.message = getString(messageResId);
+ this.onBindView = onBindView;
+ }
+
+ public PopTip(int iconResId, CharSequence message, OnBindView onBindView) {
+ this.iconResId = iconResId;
+ this.message = message;
+ this.onBindView = onBindView;
+ }
+
+ public PopTip(int iconResId, CharSequence message, CharSequence buttonText, OnBindView onBindView) {
+ this.iconResId = iconResId;
+ this.message = message;
+ this.buttonText = buttonText;
+ this.onBindView = onBindView;
+ }
+
+ public PopTip(int iconResId, int messageResId, int buttonTextResId, OnBindView onBindView) {
+ this.iconResId = iconResId;
+ this.message = getString(messageResId);
+ this.buttonText = getString(buttonTextResId);
+ this.onBindView = onBindView;
+ }
+
+ public PopTip(CharSequence message, CharSequence buttonText, OnBindView onBindView) {
+ this.message = message;
+ this.buttonText = buttonText;
+ this.onBindView = onBindView;
+ }
+
+ public PopTip(int messageResId, int buttonTextResId, OnBindView onBindView) {
+ this.message = getString(messageResId);
+ this.buttonText = getString(buttonTextResId);
+ this.onBindView = onBindView;
+ }
+
+ public static PopTip show(OnBindView onBindView) {
+ PopTip popTip = new PopTip(onBindView);
+ popTip.show();
+ return popTip;
+ }
+
+ public static PopTip show(CharSequence message) {
+ PopTip popTip = new PopTip(message);
+ popTip.show();
+ return popTip;
+ }
+
+ public static PopTip show(int messageResId) {
+ PopTip popTip = new PopTip(messageResId);
+ popTip.show();
+ return popTip;
+ }
+
+ public static PopTip show(CharSequence message, OnBindView onBindView) {
+ PopTip popTip = new PopTip(message, onBindView);
+ popTip.show();
+ return popTip;
+ }
+
+ public static PopTip show(int messageResId, OnBindView onBindView) {
+ PopTip popTip = new PopTip(messageResId, onBindView);
+ popTip.show();
+ return popTip;
+ }
+
+ public static PopTip show(CharSequence message, CharSequence buttonText) {
+ PopTip popTip = new PopTip(message, buttonText);
+ popTip.show();
+ return popTip;
+ }
+
+ public static PopTip show(int messageResId, int buttonTextResId) {
+ PopTip popTip = new PopTip(messageResId, buttonTextResId);
+ popTip.show();
+ return popTip;
+ }
+
+ public static PopTip show(int iconResId, CharSequence message, OnBindView onBindView) {
+ PopTip popTip = new PopTip(iconResId, message, onBindView);
+ popTip.show();
+ return popTip;
+ }
+
+ public static PopTip show(int iconResId, CharSequence message) {
+ PopTip popTip = new PopTip(iconResId, message);
+ popTip.show();
+ return popTip;
+ }
+
+ public static PopTip show(int iconResId, CharSequence message, CharSequence buttonText) {
+ PopTip popTip = new PopTip(iconResId, message, buttonText);
+ popTip.show();
+ return popTip;
+ }
+
+ public static PopTip show(int iconResId, CharSequence message, CharSequence buttonText, OnBindView onBindView) {
+ PopTip popTip = new PopTip(iconResId, message, buttonText, onBindView);
+ popTip.show();
+ return popTip;
+ }
+
+ public static PopTip show(int iconResId, int messageResId, int buttonTextResId, OnBindView onBindView) {
+ PopTip popTip = new PopTip(iconResId, messageResId, buttonTextResId, onBindView);
+ popTip.show();
+ return popTip;
+ }
+
+ public static PopTip show(CharSequence message, CharSequence buttonText, OnBindView onBindView) {
+ PopTip popTip = new PopTip(message, buttonText, onBindView);
+ popTip.show();
+ return popTip;
+ }
+
+ public static PopTip show(int messageResId, int buttonTextResId, OnBindView onBindView) {
+ PopTip popTip = new PopTip(messageResId, buttonTextResId, onBindView);
+ popTip.show();
+ return popTip;
+ }
+
+ public void show() {
+ super.beforeShow();
+ if (DialogX.onlyOnePopTip) {
+ PopTip oldInstance = null;
+ if (popTipList != null && !popTipList.isEmpty()) {
+ oldInstance = popTipList.get(popTipList.size() - 1);
+ }
+ if (oldInstance != null) {
+ oldInstance.dismiss();
+ }
+ } else {
+ if (popTipList != null) {
+ for (int i = 0; i < popTipList.size(); i++) {
+ PopTip popInstance = popTipList.get(i);
+ popInstance.moveUp();
+ }
+ }
+ }
+ if (popTipList == null) popTipList = new ArrayList<>();
+ popTipList.add(PopTip.this);
+ int layoutResId = isLightTheme() ? R.layout.layout_dialogx_poptip_material : R.layout.layout_dialogx_poptip_material_dark;
+ if (style.popTipSettings() != null) {
+ if (style.popTipSettings().layout(isLightTheme()) != 0) {
+ layoutResId = style.popTipSettings().layout(isLightTheme());
+ }
+ align = style.popTipSettings().align();
+ if (align == null) align = DialogXStyle.PopTipSettings.ALIGN.BOTTOM;
+ enterAnimResId = style.popTipSettings().enterAnimResId(isLightTheme()) != 0 ? style.popTipSettings().enterAnimResId(isLightTheme()) : R.anim.anim_dialogx_default_enter;
+ exitAnimResId = style.popTipSettings().exitAnimResId(isLightTheme()) != 0 ? style.popTipSettings().exitAnimResId(isLightTheme()) : R.anim.anim_dialogx_default_exit;
+ }
+ dialogView = createView(layoutResId);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(dialogView);
+ }
+
+ public void show(Activity activity) {
+ super.beforeShow();
+ if (DialogX.onlyOnePopTip) {
+ PopTip oldInstance = null;
+ if (popTipList != null && !popTipList.isEmpty()) {
+ oldInstance = popTipList.get(popTipList.size() - 1);
+ }
+ if (oldInstance != null) {
+ oldInstance.dismiss();
+ }
+ } else {
+ if (popTipList != null) {
+ for (int i = 0; i < popTipList.size(); i++) {
+ PopTip popInstance = popTipList.get(i);
+ popInstance.moveUp();
+ }
+ }
+ }
+ if (popTipList == null) popTipList = new ArrayList<>();
+ popTipList.add(PopTip.this);
+ int layoutResId = isLightTheme() ? R.layout.layout_dialogx_poptip_material : R.layout.layout_dialogx_poptip_material_dark;
+ if (style.popTipSettings() != null) {
+ if (style.popTipSettings().layout(isLightTheme()) != 0) {
+ layoutResId = style.popTipSettings().layout(isLightTheme());
+ }
+ align = style.popTipSettings().align();
+ if (align == null) align = DialogXStyle.PopTipSettings.ALIGN.BOTTOM;
+ enterAnimResId = style.popTipSettings().enterAnimResId(isLightTheme()) != 0 ? style.popTipSettings().enterAnimResId(isLightTheme()) : R.anim.anim_dialogx_default_enter;
+ exitAnimResId = style.popTipSettings().exitAnimResId(isLightTheme()) != 0 ? style.popTipSettings().exitAnimResId(isLightTheme()) : R.anim.anim_dialogx_default_exit;
+ }
+ dialogView = createView(layoutResId);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(activity, dialogView);
+ }
+
+ @Override
+ public String dialogKey() {
+ return getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")";
+ }
+
+ protected Timer autoDismissTimer;
+
+ public PopTip autoDismiss(long delay) {
+ if (autoDismissTimer != null) {
+ autoDismissTimer.cancel();
+ }
+ if (delay < 0) return this;
+ autoDismissTimer = new Timer();
+ autoDismissTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ dismiss();
+ }
+ }, delay);
+ return this;
+ }
+
+ public PopTip showShort() {
+ autoDismiss(2000);
+ return this;
+ }
+
+ public PopTip showLong() {
+ autoDismiss(3500);
+ return this;
+ }
+
+ public PopTip showAlways() {
+ return noAutoDismiss();
+ }
+
+ public PopTip noAutoDismiss() {
+ autoDismiss(TIME_NO_AUTO_DISMISS_DELAY);
+ return this;
+ }
+
+ public class DialogImpl implements DialogConvertViewInterface {
+
+ public DialogXBaseRelativeLayout boxRoot;
+ public LinearLayout boxBody;
+ public ImageView imgDialogxPopIcon;
+ public TextView txtDialogxPopText;
+ public RelativeLayout boxCustom;
+ public TextView txtDialogxButton;
+
+ public DialogImpl(View convertView) {
+ boxRoot = convertView.findViewById(R.id.box_root);
+ boxBody = convertView.findViewById(R.id.box_body);
+ imgDialogxPopIcon = convertView.findViewById(R.id.img_dialogx_pop_icon);
+ txtDialogxPopText = convertView.findViewById(R.id.txt_dialogx_pop_text);
+ boxCustom = convertView.findViewById(R.id.box_custom);
+ txtDialogxButton = convertView.findViewById(R.id.txt_dialogx_button);
+
+ init();
+ dialogImpl = this;
+ refreshView();
+ }
+
+ @Override
+ public void init() {
+ if (messageTextInfo == null) messageTextInfo = DialogX.popTextInfo;
+ if (buttonTextInfo == null) buttonTextInfo = DialogX.buttonTextInfo;
+ if (backgroundColor == -1) backgroundColor = DialogX.backgroundColor;
+
+ if (autoDismissTimer == null) {
+ showShort();
+ }
+
+ boxRoot.setParentDialog(me);
+ boxRoot.setAutoUnsafePlacePadding(false);
+ boxRoot.setOnLifecycleCallBack(new DialogXBaseRelativeLayout.OnLifecycleCallBack() {
+ @Override
+ public void onShow() {
+ isShow = true;
+ boxRoot.setAlpha(0f);
+
+ getDialogLifecycleCallback().onShow(me);
+ }
+
+ @Override
+ public void onDismiss() {
+ if (popTipList != null) popTipList.remove(PopTip.this);
+ isShow = false;
+ getDialogLifecycleCallback().onDismiss(me);
+ }
+ });
+
+ RelativeLayout.LayoutParams rlp;
+ rlp = ((RelativeLayout.LayoutParams) boxBody.getLayoutParams());
+ if (align == null) align = DialogXStyle.PopTipSettings.ALIGN.BOTTOM;
+ switch (align) {
+ case TOP:
+ rlp.removeRule(RelativeLayout.CENTER_IN_PARENT);
+ rlp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ break;
+ case BOTTOM:
+ rlp.removeRule(RelativeLayout.CENTER_IN_PARENT);
+ rlp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+ boxRoot.setAutoUnsafePlacePadding(true);
+ break;
+ case CENTER:
+ rlp.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
+ rlp.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+ rlp.addRule(RelativeLayout.CENTER_IN_PARENT);
+ break;
+ }
+ boxBody.setLayoutParams(rlp);
+
+ boxRoot.setOnSafeInsetsChangeListener(new OnSafeInsetsChangeListener() {
+ @Override
+ public void onChange(Rect unsafeRect) {
+ if (align == DialogXStyle.PopTipSettings.ALIGN.TOP) {
+ boxBody.setY(unsafeRect.top);
+ } else if (align == DialogXStyle.PopTipSettings.ALIGN.TOP_INSIDE) {
+ boxBody.setPadding(0, unsafeRect.top, 0, 0);
+ }
+ }
+ });
+
+ boxRoot.setOnBackPressedListener(new OnBackPressedListener() {
+ @Override
+ public boolean onBackPressed() {
+ return false;
+ }
+ });
+
+ boxRoot.post(new Runnable() {
+ @Override
+ public void run() {
+
+ Animation enterAnim = AnimationUtils.loadAnimation(getContext(), enterAnimResId);
+ enterAnim.setInterpolator(new DecelerateInterpolator(2f));
+ if (enterAnimDuration != -1) {
+ enterAnim.setDuration(enterAnimDuration);
+ }
+ boxBody.startAnimation(enterAnim);
+
+ boxRoot.animate()
+ .setDuration(enterAnimDuration == -1 ? enterAnim.getDuration() : enterAnimDuration)
+ .alpha(1f)
+ .setInterpolator(new DecelerateInterpolator())
+ .setListener(null);
+ }
+ });
+
+ txtDialogxButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (onButtonClickListener != null) {
+ if (!onButtonClickListener.onClick(me, v)) {
+ doDismiss(v);
+ }
+ } else {
+ doDismiss(v);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void refreshView() {
+ if (backgroundColor != -1) {
+ tintColor(boxBody, backgroundColor);
+ }
+
+ if (onBindView != null && onBindView.getCustomView() != null) {
+ onBindView.bindParent(boxCustom, me);
+ boxCustom.setVisibility(View.VISIBLE);
+ } else {
+ boxCustom.setVisibility(View.GONE);
+ }
+
+
+ showText(txtDialogxPopText, message);
+ showText(txtDialogxButton, buttonText);
+
+ useTextInfo(txtDialogxPopText, messageTextInfo);
+ useTextInfo(txtDialogxButton, buttonTextInfo);
+
+ if (iconResId != 0) {
+ imgDialogxPopIcon.setVisibility(View.VISIBLE);
+ imgDialogxPopIcon.setImageResource(iconResId);
+ if (autoTintIconInLightOrDarkMode) {
+ imgDialogxPopIcon.setImageTintList(txtDialogxPopText.getTextColors());
+ } else {
+ imgDialogxPopIcon.setImageTintList(null);
+ }
+ } else {
+ imgDialogxPopIcon.setVisibility(View.GONE);
+ }
+
+ if (onPopTipClickListener != null) {
+ boxBody.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (!onPopTipClickListener.onClick(me, v)) {
+ dismiss();
+ }
+ }
+ });
+ } else {
+ boxBody.setOnClickListener(null);
+ boxBody.setClickable(false);
+ }
+ }
+
+ @Override
+ public void doDismiss(final View v) {
+ boxRoot.post(new Runnable() {
+ @Override
+ public void run() {
+ if (v != null) v.setEnabled(false);
+
+ Animation exitAnim = AnimationUtils.loadAnimation(getContext(), exitAnimResId);
+ if (exitAnimDuration != -1) {
+ exitAnim.setDuration(exitAnimResId);
+ }
+ boxBody.startAnimation(exitAnim);
+
+ boxRoot.animate()
+ .alpha(0f)
+ .setInterpolator(new AccelerateInterpolator())
+ .setDuration(exitAnimDuration == -1 ? exitAnim.getDuration() : exitAnimDuration);
+
+ new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ dismiss(dialogView);
+ }
+ },exitAnimDuration == -1 ? exitAnim.getDuration() : exitAnimDuration);
+ }
+ });
+ }
+ }
+
+ private void moveUp() {
+ if (getDialogImpl() != null && getDialogImpl().boxBody != null) {
+ getDialogImpl().boxBody.post(new Runnable() {
+ @Override
+ public void run() {
+ if (style.popTipSettings() != null) align = style.popTipSettings().align();
+ if (align == null) align = DialogXStyle.PopTipSettings.ALIGN.BOTTOM;
+ switch (align) {
+ case TOP:
+ getDialogImpl().boxBody.animate()
+ .y(getDialogImpl().boxBody.getY() + getDialogImpl().boxBody.getHeight() * 1.3f)
+ .setDuration(enterAnimDuration == -1 ? 300 : enterAnimDuration)
+ .setInterpolator(new DecelerateInterpolator(2f))
+ ;
+ break;
+ case TOP_INSIDE:
+ getDialogImpl().boxBody.animate()
+ .y(getDialogImpl().boxBody.getY() + getDialogImpl().boxBody.getHeight() - getDialogImpl().boxBody.getPaddingTop())
+ .setDuration(enterAnimDuration == -1 ? 300 : enterAnimDuration)
+ .setInterpolator(new DecelerateInterpolator(2f))
+ ;
+ break;
+ case CENTER:
+ case BOTTOM:
+ case BOTTOM_INSIDE:
+ getDialogImpl().boxBody.animate()
+ .y(getDialogImpl().boxBody.getY() - getDialogImpl().boxBody.getHeight() * 1.3f)
+ .setDuration(enterAnimDuration == -1 ? 300 : enterAnimDuration)
+ .setInterpolator(new DecelerateInterpolator(2f))
+ ;
+ break;
+ }
+ }
+ });
+ }
+ }
+
+ public void refreshUI() {
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ if (dialogImpl != null) dialogImpl.refreshView();
+ }
+ });
+ }
+
+ public void dismiss() {
+ if (dialogImpl == null) return;
+ dialogImpl.doDismiss(null);
+ }
+
+ public DialogLifecycleCallback getDialogLifecycleCallback() {
+ return dialogLifecycleCallback == null ? new DialogLifecycleCallback() {
+ } : dialogLifecycleCallback;
+ }
+
+ public PopTip setDialogLifecycleCallback(DialogLifecycleCallback dialogLifecycleCallback) {
+ this.dialogLifecycleCallback = dialogLifecycleCallback;
+ if (isShow) dialogLifecycleCallback.onShow(me);
+ return this;
+ }
+
+ public PopTip setStyle(DialogXStyle style) {
+ this.style = style;
+ return this;
+ }
+
+ public PopTip setTheme(DialogX.THEME theme) {
+ this.theme = theme;
+ return this;
+ }
+
+ public PopTip.DialogImpl getDialogImpl() {
+ return dialogImpl;
+ }
+
+ public PopTip setCustomView(OnBindView onBindView) {
+ this.onBindView = onBindView;
+ refreshUI();
+ return this;
+ }
+
+ public View getCustomView() {
+ if (onBindView == null) return null;
+ return onBindView.getCustomView();
+ }
+
+ public PopTip removeCustomView() {
+ this.onBindView.clean();
+ refreshUI();
+ return this;
+ }
+
+ public DialogXStyle.PopTipSettings.ALIGN getAlign() {
+ return align;
+ }
+
+ public PopTip setAlign(DialogXStyle.PopTipSettings.ALIGN align) {
+ this.align = align;
+ return this;
+ }
+
+ public int getIconResId() {
+ return iconResId;
+ }
+
+ public PopTip setIconResId(int iconResId) {
+ this.iconResId = iconResId;
+ refreshUI();
+ return this;
+ }
+
+ public CharSequence getMessage() {
+ return message;
+ }
+
+ public PopTip setMessage(CharSequence message) {
+ this.message = message;
+ refreshUI();
+ return this;
+ }
+
+ public PopTip setMessage(int messageResId) {
+ this.message = getString(messageResId);
+ refreshUI();
+ return this;
+ }
+
+ public CharSequence getButtonText() {
+ return buttonText;
+ }
+
+ public PopTip setButton(CharSequence buttonText) {
+ this.buttonText = buttonText;
+ refreshUI();
+ return this;
+ }
+
+ public PopTip setButton(int buttonTextResId) {
+ this.buttonText = getString(buttonTextResId);
+ refreshUI();
+ return this;
+ }
+
+ public PopTip setButton(CharSequence buttonText, OnDialogButtonClickListener onButtonClickListener) {
+ this.buttonText = buttonText;
+ this.onButtonClickListener = onButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public PopTip setButton(int buttonTextResId, OnDialogButtonClickListener onButtonClickListener) {
+ this.buttonText = getString(buttonTextResId);
+ this.onButtonClickListener = onButtonClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public PopTip setButton(OnDialogButtonClickListener onButtonClickListener) {
+ this.onButtonClickListener = onButtonClickListener;
+ return this;
+ }
+
+ public TextInfo getMessageTextInfo() {
+ return messageTextInfo;
+ }
+
+ public PopTip setMessageTextInfo(TextInfo messageTextInfo) {
+ this.messageTextInfo = messageTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public TextInfo getButtonTextInfo() {
+ return buttonTextInfo;
+ }
+
+ public PopTip setButtonTextInfo(TextInfo buttonTextInfo) {
+ this.buttonTextInfo = buttonTextInfo;
+ refreshUI();
+ return this;
+ }
+
+ public OnDialogButtonClickListener getOnButtonClickListener() {
+ return onButtonClickListener;
+ }
+
+ public PopTip setOnButtonClickListener(OnDialogButtonClickListener onButtonClickListener) {
+ this.onButtonClickListener = onButtonClickListener;
+ return this;
+ }
+
+ public boolean isAutoTintIconInLightOrDarkMode() {
+ return autoTintIconInLightOrDarkMode;
+ }
+
+ public PopTip setAutoTintIconInLightOrDarkMode(boolean autoTintIconInLightOrDarkMode) {
+ this.autoTintIconInLightOrDarkMode = autoTintIconInLightOrDarkMode;
+ refreshUI();
+ return this;
+ }
+
+ public OnDialogButtonClickListener getOnPopTipClickListener() {
+ return onPopTipClickListener;
+ }
+
+ public PopTip setOnPopTipClickListener(OnDialogButtonClickListener onPopTipClickListener) {
+ this.onPopTipClickListener = onPopTipClickListener;
+ refreshUI();
+ return this;
+ }
+
+ public int getBackgroundColor() {
+ return backgroundColor;
+ }
+
+ public PopTip setBackgroundColor(@ColorInt int backgroundColor) {
+ this.backgroundColor = backgroundColor;
+ refreshUI();
+ return this;
+ }
+
+ public PopTip setBackgroundColorRes(@ColorRes int backgroundColorResId) {
+ this.backgroundColor = getColor(backgroundColorResId);
+ refreshUI();
+ return this;
+ }
+
+ public long getEnterAnimDuration() {
+ return enterAnimDuration;
+ }
+
+ public PopTip setEnterAnimDuration(long enterAnimDuration) {
+ this.enterAnimDuration = enterAnimDuration;
+ return this;
+ }
+
+ public long getExitAnimDuration() {
+ return exitAnimDuration;
+ }
+
+ public PopTip setExitAnimDuration(long exitAnimDuration) {
+ this.exitAnimDuration = exitAnimDuration;
+ return this;
+ }
+
+ @Override
+ public void onUIModeChange(Configuration newConfig) {
+ if (dialogView != null) {
+ dismiss(dialogView);
+ }
+ if (getDialogImpl().boxCustom != null) {
+ getDialogImpl().boxCustom.removeAllViews();
+ }
+
+ if (DialogX.onlyOnePopTip) {
+ PopTip oldInstance = null;
+ if (popTipList != null && !popTipList.isEmpty()) {
+ oldInstance = popTipList.get(popTipList.size() - 1);
+ }
+ if (oldInstance != null) {
+ oldInstance.dismiss();
+ }
+ } else {
+ if (popTipList != null) {
+ for (int i = 0; i < popTipList.size(); i++) {
+ PopTip popInstance = popTipList.get(i);
+ popInstance.moveUp();
+ }
+ }
+ }
+ if (popTipList == null) popTipList = new ArrayList<>();
+ popTipList.add(PopTip.this);
+
+ int layoutResId = isLightTheme() ? R.layout.layout_dialogx_poptip_material : R.layout.layout_dialogx_poptip_material_dark;
+ if (style.popTipSettings() != null) {
+ if (style.popTipSettings().layout(isLightTheme()) != 0) {
+ layoutResId = style.popTipSettings().layout(isLightTheme());
+ }
+ align = style.popTipSettings().align();
+ if (align == null) align = DialogXStyle.PopTipSettings.ALIGN.BOTTOM;
+ enterAnimResId = style.popTipSettings().enterAnimResId(isLightTheme()) != 0 ? style.popTipSettings().enterAnimResId(isLightTheme()) : R.anim.anim_dialogx_default_enter;
+ exitAnimResId = style.popTipSettings().exitAnimResId(isLightTheme()) != 0 ? style.popTipSettings().exitAnimResId(isLightTheme()) : R.anim.anim_dialogx_default_exit;
+ }
+ enterAnimDuration = 0;
+ dialogView = createView(layoutResId);
+ dialogImpl = new DialogImpl(dialogView);
+ dialogView.setTag(me);
+ show(dialogView);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/TipDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/TipDialog.java
new file mode 100644
index 0000000..8f94db5
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/TipDialog.java
@@ -0,0 +1,162 @@
+package com.kongzue.dialogx.dialogs;
+
+import android.app.Activity;
+
+import com.kongzue.dialogx.interfaces.DialogLifecycleCallback;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/9/28 23:53
+ */
+public class TipDialog extends WaitDialog {
+
+ protected TipDialog() {
+ super();
+ }
+
+ public static WaitDialog show(int messageResId) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(messageResId);
+ if (dialogImpl != null) {
+ dialogImpl.showTip(TYPE.WARNING);
+ } else {
+ me().showTip(messageResId, TYPE.WARNING);
+ }
+ return me();
+ }
+
+ public static WaitDialog show(Activity activity, int messageResId) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(messageResId);
+ if (dialogImpl != null && dialogImpl.bkg.getContext() == activity) {
+ dialogImpl.showTip(TYPE.WARNING);
+ } else {
+ me().showTip(activity, messageResId, TYPE.WARNING);
+ }
+ return me();
+ }
+
+ public static WaitDialog show(CharSequence message) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(message);
+ if (dialogImpl != null) {
+ dialogImpl.showTip(TYPE.WARNING);
+ } else {
+ me().showTip(message, TYPE.WARNING);
+ }
+ return me();
+ }
+
+ public static WaitDialog show(Activity activity, CharSequence message) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(message);
+ if (dialogImpl != null && dialogImpl.bkg.getContext() == activity) {
+ dialogImpl.showTip(TYPE.WARNING);
+ } else {
+ me().showTip(activity, message, TYPE.WARNING);
+ }
+ return me();
+ }
+
+ public static WaitDialog show(int messageResId, TYPE tip) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(messageResId);
+ if (dialogImpl != null) {
+ dialogImpl.showTip(tip);
+ } else {
+ me().showTip(messageResId, tip);
+ }
+ return me();
+ }
+
+ public static WaitDialog show(Activity activity, int messageResId, TYPE tip) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(messageResId);
+ if (dialogImpl != null && dialogImpl.bkg.getContext() == activity) {
+ dialogImpl.showTip(tip);
+ } else {
+ me().showTip(activity, messageResId, tip);
+ }
+ return me();
+ }
+
+ public static WaitDialog show(CharSequence message, TYPE tip) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(message);
+ if (dialogImpl != null) {
+ dialogImpl.showTip(tip);
+ } else {
+ me().showTip(message, tip);
+ }
+ return me();
+ }
+
+ public static WaitDialog show(Activity activity, CharSequence message, TYPE tip) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(message);
+ if (dialogImpl != null && dialogImpl.bkg.getContext() == activity) {
+ dialogImpl.showTip(tip);
+ } else {
+ me().showTip(activity, message, tip);
+ }
+ return me();
+ }
+
+ public static WaitDialog show(int messageResId, TYPE tip, long duration) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(messageResId);
+ me().tipShowDuration = duration;
+ if (dialogImpl != null) {
+ dialogImpl.showTip(tip);
+ } else {
+ me().showTip(messageResId, tip);
+ }
+ return me();
+ }
+
+ public static WaitDialog show(Activity activity, int messageResId, TYPE tip, long duration) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(messageResId);
+ me().tipShowDuration = duration;
+ if (dialogImpl != null && dialogImpl.bkg.getContext() == activity) {
+ dialogImpl.showTip(tip);
+ } else {
+ me().showTip(activity, messageResId, tip);
+ }
+ return me();
+ }
+
+ public static WaitDialog show(CharSequence message, TYPE tip, long duration) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(message);
+ me().tipShowDuration = duration;
+ if (dialogImpl != null) {
+ dialogImpl.showTip(tip);
+ } else {
+ me().showTip(message, tip);
+ }
+ return me();
+ }
+
+ public static WaitDialog show(Activity activity, CharSequence message, TYPE tip, long duration) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(message);
+ me().tipShowDuration = duration;
+ if (dialogImpl != null && dialogImpl.bkg.getContext() == activity) {
+ dialogImpl.showTip(tip);
+ } else {
+ me().showTip(activity, message, tip);
+ }
+ return me();
+ }
+
+ @Override
+ public String dialogKey() {
+ return getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")";
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/WaitDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/WaitDialog.java
new file mode 100644
index 0000000..a6317f9
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/WaitDialog.java
@@ -0,0 +1,750 @@
+package com.kongzue.dialogx.dialogs;
+
+import android.animation.Animator;
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.graphics.Color;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.ColorRes;
+
+import com.kongzue.dialogx.DialogX;
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.impl.AnimatorListenerEndCallBack;
+import com.kongzue.dialogx.interfaces.BaseDialog;
+import com.kongzue.dialogx.interfaces.DialogConvertViewInterface;
+import com.kongzue.dialogx.interfaces.DialogLifecycleCallback;
+import com.kongzue.dialogx.interfaces.OnBackPressedListener;
+import com.kongzue.dialogx.interfaces.OnBindView;
+import com.kongzue.dialogx.interfaces.ProgressViewInterface;
+import com.kongzue.dialogx.util.TextInfo;
+import com.kongzue.dialogx.util.views.BlurView;
+import com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout;
+import com.kongzue.dialogx.util.views.MaxRelativeLayout;
+import com.kongzue.dialogx.util.views.ProgressView;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/9/27 14:50
+ */
+public class WaitDialog extends BaseDialog {
+
+ public static int overrideEnterDuration = -1;
+ public static int overrideExitDuration = -1;
+ public static int overrideEnterAnimRes = 0;
+ public static int overrideExitAnimRes = 0;
+ public static BOOLEAN overrideCancelable;
+ protected OnBindView onBindView;
+
+ public enum TYPE {
+ NONE,
+ SUCCESS,
+ WARNING,
+ ERROR
+ }
+
+ protected static WeakReference me;
+ protected CharSequence message;
+ protected long tipShowDuration = 1500;
+ protected float waitProgress = -1;
+ protected int showType = -1; //-1:Waitdialog 状态标示符,其余为 TipDialog 状态标示
+ protected TextInfo messageTextInfo;
+ protected int maskColor = -1;
+ protected BOOLEAN privateCancelable;
+
+ private DialogLifecycleCallback dialogLifecycleCallback;
+
+ protected WaitDialog() {
+ super();
+ me = new WeakReference<>(this);
+ cancelable = DialogX.cancelableTipDialog;
+ }
+
+ public static WaitDialog show(CharSequence message) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().message = message;
+ me().showType = -1;
+ if (dialogImpl != null) {
+ dialogImpl.progressView.loading();
+ setMessage(message);
+ return me();
+ } else {
+ WaitDialog waitDialog = new WaitDialog();
+ waitDialog.message = message;
+ waitDialog.show();
+ return waitDialog;
+ }
+ }
+
+ public static WaitDialog show(Activity activity, CharSequence message) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().message = message;
+ me().showType = -1;
+ if (dialogImpl != null && dialogImpl.bkg.getContext() == activity) {
+ dialogImpl.progressView.loading();
+ setMessage(message);
+ return me();
+ } else {
+ WaitDialog waitDialog = new WaitDialog();
+ waitDialog.message = message;
+ waitDialog.show(activity);
+ return waitDialog;
+ }
+ }
+
+ public static WaitDialog show(int messageResId) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(messageResId);
+ me().showType = -1;
+ if (dialogImpl != null) {
+ dialogImpl.progressView.loading();
+ setMessage(messageResId);
+ return me();
+ } else {
+ WaitDialog waitDialog = new WaitDialog();
+ waitDialog.preMessage(messageResId);
+ waitDialog.show();
+ return waitDialog;
+ }
+ }
+
+ public static WaitDialog show(Activity activity, int messageResId) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().preMessage(messageResId);
+ me().showType = -1;
+ if (dialogImpl != null && dialogImpl.bkg.getContext() == activity) {
+ dialogImpl.progressView.loading();
+ setMessage(messageResId);
+ return me();
+ } else {
+ WaitDialog waitDialog = new WaitDialog();
+ waitDialog.preMessage(messageResId);
+ waitDialog.show(activity);
+ return waitDialog;
+ }
+ }
+
+ public static WaitDialog show(CharSequence message, float progress) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().showType = -1;
+ me().preMessage(message);
+ if (dialogImpl != null) {
+ setMessage(message);
+ me().setProgress(progress);
+ return me();
+ } else {
+ WaitDialog waitDialog = new WaitDialog();
+ waitDialog.preMessage(message);
+ waitDialog.show();
+ waitDialog.setProgress(progress);
+ return waitDialog;
+ }
+ }
+
+ public static WaitDialog show(Activity activity, CharSequence message, float progress) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().showType = -1;
+ me().preMessage(message);
+ if (dialogImpl != null && dialogImpl.bkg.getContext() == activity) {
+ setMessage(message);
+ me().setProgress(progress);
+ return me();
+ } else {
+ WaitDialog waitDialog = new WaitDialog();
+ waitDialog.preMessage(message);
+ waitDialog.show(activity);
+ waitDialog.setProgress(progress);
+ return waitDialog;
+ }
+ }
+
+ public static WaitDialog show(int messageResId, float progress) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().showType = -1;
+ me().preMessage(messageResId);
+ if (dialogImpl != null) {
+ setMessage(messageResId);
+ me().setProgress(progress);
+ return me();
+ } else {
+ WaitDialog waitDialog = new WaitDialog();
+ waitDialog.preMessage(messageResId);
+ waitDialog.show();
+ waitDialog.setProgress(progress);
+ return waitDialog;
+ }
+ }
+
+ public static WaitDialog show(Activity activity, int messageResId, float progress) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().showType = -1;
+ me().preMessage(messageResId);
+ if (dialogImpl != null && dialogImpl.bkg.getContext() == activity) {
+ setMessage(messageResId);
+ me().setProgress(progress);
+ return me();
+ } else {
+ WaitDialog waitDialog = new WaitDialog();
+ waitDialog.preMessage(messageResId);
+ waitDialog.show(activity);
+ waitDialog.setProgress(progress);
+ return waitDialog;
+ }
+ }
+
+ public static WaitDialog show(Activity activity, float progress) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().showType = -1;
+ if (dialogImpl != null && dialogImpl.bkg.getContext() == activity) {
+ me().setProgress(progress);
+ return me();
+ } else {
+ WaitDialog waitDialog = new WaitDialog();
+ waitDialog.show(activity);
+ waitDialog.setProgress(progress);
+ return waitDialog;
+ }
+ }
+
+ public static WaitDialog show(float progress) {
+ DialogImpl dialogImpl = me().dialogImpl;
+ me().showType = -1;
+ if (dialogImpl != null) {
+ me().setProgress(progress);
+ return me();
+ } else {
+ WaitDialog waitDialog = new WaitDialog();
+ waitDialog.show();
+ waitDialog.setProgress(progress);
+ return waitDialog;
+ }
+ }
+
+ public float getProgress() {
+ return waitProgress;
+ }
+
+ public WaitDialog setProgress(float waitProgress) {
+ this.waitProgress = waitProgress;
+ refreshUI();
+ return this;
+ }
+
+ private View dialogView;
+
+ public WaitDialog show() {
+ super.beforeShow();
+ int layoutResId = R.layout.layout_dialogx_wait;
+ if (style.overrideWaitTipRes() != null && style.overrideWaitTipRes().overrideWaitLayout(isLightTheme()) != 0) {
+ layoutResId = style.overrideWaitTipRes().overrideWaitLayout(isLightTheme());
+ }
+ dialogImpl = new DialogImpl(layoutResId);
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ dialogImpl.lazyCreate();
+ dialogView.setTag(me.get());
+ show(dialogView);
+ }
+ });
+ return this;
+ }
+
+ public WaitDialog show(final Activity activity) {
+ super.beforeShow();
+ int layoutResId = R.layout.layout_dialogx_wait;
+ if (style.overrideWaitTipRes() != null && style.overrideWaitTipRes().overrideWaitLayout(isLightTheme()) != 0) {
+ layoutResId = style.overrideWaitTipRes().overrideWaitLayout(isLightTheme());
+ }
+ dialogImpl = new DialogImpl(layoutResId);
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ dialogImpl.lazyCreate();
+ dialogView.setTag(me.get());
+ show(activity, dialogView);
+ }
+ });
+ return this;
+ }
+
+ protected DialogImpl dialogImpl;
+
+ public class DialogImpl implements DialogConvertViewInterface {
+ public DialogXBaseRelativeLayout boxRoot;
+ public MaxRelativeLayout bkg;
+ public BlurView blurView;
+ public RelativeLayout boxProgress;
+ public ProgressViewInterface progressView;
+ public RelativeLayout boxCustomView;
+ public TextView txtInfo;
+
+ private int layoutResId;
+
+ public DialogImpl(int layoutResId) {
+ this.layoutResId = layoutResId;
+ }
+
+ public void lazyCreate(){
+ dialogView = createView(layoutResId);
+ boxRoot = dialogView.findViewById(R.id.box_root);
+ bkg = dialogView.findViewById(R.id.bkg);
+ blurView = dialogView.findViewById(R.id.blurView);
+ boxProgress = dialogView.findViewById(R.id.box_progress);
+ View progressViewCache = (View) style.overrideWaitTipRes().overrideWaitView(getContext(), isLightTheme());
+ if (progressViewCache == null) {
+ progressViewCache = new ProgressView(getContext());
+ }
+ progressView = (ProgressViewInterface) progressViewCache;
+ boxProgress.addView(progressViewCache, new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ boxCustomView = dialogView.findViewById(R.id.box_customView);
+ txtInfo = dialogView.findViewById(R.id.txt_info);
+ init();
+ dialogImpl = this;
+ refreshView();
+ }
+
+ public DialogImpl(View convertView) {
+ boxRoot = convertView.findViewById(R.id.box_root);
+ bkg = convertView.findViewById(R.id.bkg);
+ blurView = convertView.findViewById(R.id.blurView);
+ boxProgress = convertView.findViewById(R.id.box_progress);
+ View progressViewCache = (View) style.overrideWaitTipRes().overrideWaitView(getContext(), isLightTheme());
+ if (progressViewCache == null) {
+ progressViewCache = new ProgressView(getContext());
+ }
+ progressView = (ProgressViewInterface) progressViewCache;
+ boxProgress.addView(progressViewCache, new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ boxCustomView = convertView.findViewById(R.id.box_customView);
+ txtInfo = convertView.findViewById(R.id.txt_info);
+ init();
+ dialogImpl = this;
+ refreshView();
+ }
+
+ public void init() {
+ if (messageTextInfo == null) messageTextInfo = DialogX.tipTextInfo;
+ if (backgroundColor == -1) backgroundColor = DialogX.tipBackgroundColor;
+
+ if (style.overrideWaitTipRes() == null) {
+ blurView.setRadiusPx(dip2px(15));
+ } else {
+ blurView.setRadiusPx(style.overrideWaitTipRes().overrideRadiusPx() < 0 ? dip2px(15) : style.overrideWaitTipRes().overrideRadiusPx());
+ }
+ boxRoot.setClickable(true);
+
+ boxRoot.setParentDialog(me.get());
+ boxRoot.setOnLifecycleCallBack(new DialogXBaseRelativeLayout.OnLifecycleCallBack() {
+ @Override
+ public void onShow() {
+ isShow = true;
+ boxRoot.setAlpha(0f);
+ bkg.post(new Runnable() {
+ @Override
+ public void run() {
+ int enterAnimResId = R.anim.anim_dialogx_default_enter;
+ if (overrideEnterAnimRes != 0) {
+ enterAnimResId = overrideEnterAnimRes;
+ }
+ Animation enterAnim = AnimationUtils.loadAnimation(getContext(), enterAnimResId);
+ long enterAnimDurationTemp = enterAnim.getDuration();
+ enterAnim.setInterpolator(new DecelerateInterpolator());
+ if (overrideEnterDuration >= 0) {
+ enterAnimDurationTemp = overrideEnterDuration;
+ }
+ if (enterAnimDuration >= 0) {
+ enterAnimDurationTemp = enterAnimDuration;
+ }
+ enterAnim.setDuration(enterAnimDurationTemp);
+ bkg.startAnimation(enterAnim);
+
+ boxRoot.animate()
+ .setDuration(enterAnimDurationTemp)
+ .alpha(1f)
+ .setInterpolator(new DecelerateInterpolator())
+ .setListener(null);
+
+ getDialogLifecycleCallback().onShow(me());
+ }
+ });
+ }
+
+ @Override
+ public void onDismiss() {
+ isShow = false;
+ dialogImpl = null;
+ getDialogLifecycleCallback().onDismiss(me());
+ me.clear();
+ }
+ });
+
+ if (readyTipType != null) {
+ progressView.noLoading();
+ ((View) progressView).postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ showTip(readyTipType);
+ }
+ }, 100);
+ }
+
+ boxRoot.setOnBackPressedListener(new OnBackPressedListener() {
+ @Override
+ public boolean onBackPressed() {
+ if (onBackPressedListener != null && onBackPressedListener.onBackPressed()) {
+ dismiss();
+ return false;
+ }
+ if (isCancelable()) {
+ dismiss();
+ }
+ return false;
+ }
+ });
+ }
+
+ private float oldProgress;
+
+ public void refreshView() {
+ if (style.overrideWaitTipRes() != null) {
+ int overrideBackgroundColorRes = style.overrideWaitTipRes().overrideBackgroundColorRes(isLightTheme());
+ if (overrideBackgroundColorRes == 0) {
+ overrideBackgroundColorRes = isLightTheme() ? R.color.dialogxWaitBkgDark : R.color.dialogxWaitBkgLight;
+ }
+ blurView.setOverlayColor(backgroundColor == -1 ? getResources().getColor(overrideBackgroundColorRes) : backgroundColor);
+ int overrideTextColorRes = style.overrideWaitTipRes().overrideTextColorRes(isLightTheme());
+ if (overrideTextColorRes == 0) {
+ overrideTextColorRes = isLightTheme() ? R.color.white : R.color.black;
+ }
+ txtInfo.setTextColor(getResources().getColor(overrideTextColorRes));
+ progressView.setColor(getResources().getColor(overrideTextColorRes));
+ blurView.setUseBlur(style.overrideWaitTipRes().blurBackground());
+ } else {
+ if (isLightTheme()) {
+ blurView.setOverlayColor(backgroundColor == -1 ? getResources().getColor(R.color.dialogxWaitBkgDark) : backgroundColor);
+ progressView.setColor(Color.WHITE);
+ txtInfo.setTextColor(Color.WHITE);
+ } else {
+ blurView.setOverlayColor(backgroundColor == -1 ? getResources().getColor(R.color.dialogxWaitBkgLight) : backgroundColor);
+ progressView.setColor(Color.BLACK);
+ txtInfo.setTextColor(Color.BLACK);
+ }
+ }
+ if (DialogX.tipProgressColor != -1) progressView.setColor(DialogX.tipProgressColor);
+
+ if (waitProgress >= 0 && waitProgress <= 1 && oldProgress != waitProgress) {
+ progressView.progress(waitProgress);
+ oldProgress = waitProgress;
+ }
+
+ showText(txtInfo, message);
+ useTextInfo(txtInfo, messageTextInfo);
+
+ if (maskColor != -1) boxRoot.setBackgroundColor(maskColor);
+
+ if (onBindView != null && onBindView.getCustomView() != null) {
+ onBindView.bindParent(boxCustomView, me.get());
+ boxCustomView.setVisibility(View.VISIBLE);
+ boxProgress.setVisibility(View.GONE);
+ } else {
+ boxCustomView.setVisibility(View.GONE);
+ boxProgress.setVisibility(View.VISIBLE);
+ }
+ }
+
+ public void doDismiss(final View v) {
+ boxRoot.post(new Runnable() {
+ @Override
+ public void run() {
+ if (v != null) v.setEnabled(false);
+
+ int exitAnimResId = R.anim.anim_dialogx_default_exit;
+ if (overrideExitAnimRes != 0) {
+ exitAnimResId = overrideExitAnimRes;
+ }
+ Animation exitAnim = AnimationUtils.loadAnimation(getContext(), exitAnimResId);
+ long exitAnimDurationTemp = exitAnim.getDuration();
+ if (overrideExitDuration >= 0) {
+ exitAnimDurationTemp = overrideExitDuration;
+ }
+ if (exitAnimDuration != -1) {
+ exitAnimDurationTemp = exitAnimDuration;
+ }
+ exitAnim.setDuration(exitAnimDurationTemp);
+ exitAnim.setInterpolator(new AccelerateInterpolator());
+ bkg.startAnimation(exitAnim);
+
+ boxRoot.animate()
+ .alpha(0f)
+ .setInterpolator(new AccelerateInterpolator())
+ .setDuration(exitAnimDurationTemp);
+
+ new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ dismiss(dialogView);
+ }
+ }, exitAnimDurationTemp);
+ }
+ });
+ }
+
+ public void showTip(final TYPE tip) {
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ showType = tip.ordinal();
+ if (progressView == null) return;
+ switch (tip) {
+ case NONE:
+ progressView.loading();
+ return;
+ case SUCCESS:
+ progressView.success();
+ break;
+ case WARNING:
+ progressView.warning();
+ break;
+ case ERROR:
+ progressView.error();
+ break;
+ }
+
+ //此事件是在完成衔接动画绘制后执行的逻辑
+ progressView.whenShowTick(new Runnable() {
+ @Override
+ public void run() {
+ getDialogLifecycleCallback().onShow(WaitDialog.this);
+ refreshView();
+ ((View) progressView).postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (showType > -1) {
+ doDismiss(null);
+ }
+ }
+ }, tipShowDuration);
+ }
+ });
+ }
+ });
+ }
+ }
+
+ @Override
+ public String dialogKey() {
+ return getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")";
+ }
+
+ @Override
+ public boolean isLightTheme() {
+ if (DialogX.tipTheme == null) {
+ return super.isLightTheme();
+ } else {
+ return DialogX.tipTheme == DialogX.THEME.LIGHT;
+ }
+ }
+
+ public void refreshUI() {
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ if (dialogImpl != null) dialogImpl.refreshView();
+ }
+ });
+ }
+
+ public void doDismiss() {
+ if (dialogImpl == null) return;
+ dialogImpl.doDismiss(null);
+ }
+
+ public static void dismiss() {
+ me().doDismiss();
+ }
+
+ protected static WaitDialog me() {
+ if (me == null || me.get() == null) me = new WeakReference<>(new WaitDialog());
+ return me.get();
+ }
+
+ protected TYPE readyTipType;
+
+ protected void showTip(CharSequence message, TYPE type) {
+ showType = type.ordinal();
+ this.message = message;
+ readyTipType = type;
+ show();
+ }
+
+ protected void showTip(Activity activity, CharSequence message, TYPE type) {
+ showType = type.ordinal();
+ this.message = message;
+ readyTipType = type;
+ show(activity);
+ }
+
+ protected void showTip(int messageResId, TYPE type) {
+ showType = type.ordinal();
+ this.message = getString(messageResId);
+ readyTipType = type;
+ show();
+ }
+
+ protected void showTip(Activity activity, int messageResId, TYPE type) {
+ showType = type.ordinal();
+ this.message = getString(messageResId);
+ readyTipType = type;
+ show(activity);
+ }
+
+ public static CharSequence getMessage() {
+ return me().message;
+ }
+
+ public static WaitDialog setMessage(CharSequence message) {
+ me().preMessage(message);
+ me().refreshUI();
+ return me();
+ }
+
+ public static WaitDialog setMessage(int messageResId) {
+ me().preMessage(messageResId);
+ me().refreshUI();
+ return me();
+ }
+
+ public boolean isCancelable() {
+ if (privateCancelable != null) {
+ return privateCancelable == BOOLEAN.TRUE;
+ }
+ if (overrideCancelable != null) {
+ return overrideCancelable == BOOLEAN.TRUE;
+ }
+ return cancelable;
+ }
+
+ public WaitDialog setCancelable(boolean cancelable) {
+ privateCancelable = cancelable ? BOOLEAN.TRUE : BOOLEAN.FALSE;
+ return this;
+ }
+
+ /**
+ * 用于从 WaitDialog 到 TipDialog 的消息设置
+ * 此方法不会立即执行,而是等到动画衔接完成后由事件设置
+ *
+ * @param message 消息
+ * @return me
+ */
+ protected WaitDialog preMessage(CharSequence message) {
+ me().message = message;
+ return me();
+ }
+
+ protected WaitDialog preMessage(int messageResId) {
+ me().message = getString(messageResId);
+ return me();
+ }
+
+ public DialogLifecycleCallback getDialogLifecycleCallback() {
+ return dialogLifecycleCallback == null ? new DialogLifecycleCallback() {
+ } : dialogLifecycleCallback;
+ }
+
+ public WaitDialog setDialogLifecycleCallback(DialogLifecycleCallback dialogLifecycleCallback) {
+ this.dialogLifecycleCallback = dialogLifecycleCallback;
+ if (isShow) dialogLifecycleCallback.onShow(me.get());
+ return this;
+ }
+
+ public DialogImpl getDialogImpl() {
+ return dialogImpl;
+ }
+
+ public WaitDialog setCustomView(OnBindView onBindView) {
+ this.onBindView = onBindView;
+ refreshUI();
+ return this;
+ }
+
+ public View getCustomView() {
+ if (onBindView == null) return null;
+ return onBindView.getCustomView();
+ }
+
+ public WaitDialog removeCustomView() {
+ this.onBindView.clean();
+ refreshUI();
+ return this;
+ }
+
+ public OnBackPressedListener getOnBackPressedListener() {
+ return onBackPressedListener;
+ }
+
+ public WaitDialog setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
+ this.onBackPressedListener = onBackPressedListener;
+ refreshUI();
+ return this;
+ }
+
+ public int getBackgroundColor() {
+ return backgroundColor;
+ }
+
+ public WaitDialog setBackgroundColor(@ColorInt int backgroundColor) {
+ this.backgroundColor = backgroundColor;
+ refreshUI();
+ return this;
+ }
+
+ public WaitDialog setBackgroundColorRes(@ColorRes int backgroundColorResId) {
+ this.backgroundColor = getColor(backgroundColorResId);
+ refreshUI();
+ return this;
+ }
+
+ public WaitDialog setMaskColor(@ColorInt int maskColor) {
+ this.maskColor = maskColor;
+ refreshUI();
+ return this;
+ }
+
+ public WaitDialog setEnterAnimDuration(long enterAnimDuration) {
+ this.enterAnimDuration = enterAnimDuration;
+ return this;
+ }
+
+ public long getExitAnimDuration() {
+ return exitAnimDuration;
+ }
+
+ public WaitDialog setExitAnimDuration(long exitAnimDuration) {
+ this.exitAnimDuration = exitAnimDuration;
+ return this;
+ }
+
+ @Override
+ public void onUIModeChange(Configuration newConfig) {
+ refreshUI();
+ }
+
+ public static WaitDialog getInstance() {
+ return me();
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/impl/ActivityLifecycleImpl.java b/DialogX/src/main/java/com/kongzue/dialogx/impl/ActivityLifecycleImpl.java
new file mode 100644
index 0000000..a898b8c
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/impl/ActivityLifecycleImpl.java
@@ -0,0 +1,87 @@
+package com.kongzue.dialogx.impl;
+
+import android.app.Activity;
+import android.app.Application;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Looper;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.kongzue.dialogx.interfaces.BaseDialog;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/9/22 11:31
+ */
+public class ActivityLifecycleImpl implements Application.ActivityLifecycleCallbacks {
+
+ private onActivityResumeCallBack onActivityResumeCallBack;
+
+ public ActivityLifecycleImpl(ActivityLifecycleImpl.onActivityResumeCallBack onActivityResumeCallBack) {
+ this.onActivityResumeCallBack = onActivityResumeCallBack;
+ }
+
+ public static void init(Context context, ActivityLifecycleImpl.onActivityResumeCallBack onActivityResumeCallBack) {
+ ((Application) context.getApplicationContext()).registerActivityLifecycleCallbacks(new ActivityLifecycleImpl(onActivityResumeCallBack));
+ }
+
+ @Override
+ public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
+ if (onActivityResumeCallBack != null) {
+ onActivityResumeCallBack.getActivity(activity);
+ }
+ }
+
+ @Override
+ public void onActivityStarted(@NonNull Activity activity) {
+
+ }
+
+ @Override
+ public void onActivityResumed(@NonNull Activity activity) {
+ if (activity.isDestroyed() || activity.isFinishing()) {
+ return;
+ }
+ if (onActivityResumeCallBack != null) {
+ onActivityResumeCallBack.getActivity(activity);
+ }
+ }
+
+ @Override
+ public void onActivityPaused(@NonNull Activity activity) {
+ }
+
+ @Override
+ public void onActivityStopped(@NonNull Activity activity) {
+ }
+
+ @Override
+ public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
+
+ }
+
+ @Override
+ public void onActivityDestroyed(@NonNull Activity activity) {
+ if (BaseDialog.getContext()==activity){
+ BaseDialog.cleanContext();
+ }
+ }
+
+ @Override
+ public void onActivityPreDestroyed(@NonNull final Activity activity) {
+ BaseDialog.recycleDialog(activity);
+ }
+
+ public interface onActivityResumeCallBack {
+ void getActivity(Activity activity);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/impl/AnimatorListenerEndCallBack.java b/DialogX/src/main/java/com/kongzue/dialogx/impl/AnimatorListenerEndCallBack.java
new file mode 100644
index 0000000..c0dc335
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/impl/AnimatorListenerEndCallBack.java
@@ -0,0 +1,30 @@
+package com.kongzue.dialogx.impl;
+
+import android.animation.Animator;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/9/22 14:37
+ */
+public abstract class AnimatorListenerEndCallBack implements Animator.AnimatorListener {
+ @Override
+ public void onAnimationStart(Animator animation) {
+
+ }
+
+ @Override
+ public abstract void onAnimationEnd(Animator animation);
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseDialog.java
new file mode 100644
index 0000000..fda8d9f
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseDialog.java
@@ -0,0 +1,365 @@
+package com.kongzue.dialogx.interfaces;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.Typeface;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.ColorRes;
+import androidx.appcompat.app.AppCompatDelegate;
+
+import com.kongzue.dialogx.DialogX;
+import com.kongzue.dialogx.dialogs.PopTip;
+import com.kongzue.dialogx.impl.ActivityLifecycleImpl;
+import com.kongzue.dialogx.util.TextInfo;
+import com.kongzue.dialogx.util.WindowUtil;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import static com.kongzue.dialogx.DialogX.DEBUGMODE;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/9/22 14:10
+ */
+public abstract class BaseDialog {
+
+ private static WeakReference rootFrameLayout;
+ private static WeakReference contextWeakReference;
+ protected WeakReference ownActivity;
+ private static List runningDialogList;
+ private WeakReference dialogView;
+
+ public static void init(Context context) {
+ if (context instanceof Activity) {
+ initActivityContext((Activity) context);
+ }
+ ActivityLifecycleImpl.init(context, new ActivityLifecycleImpl.onActivityResumeCallBack() {
+ @Override
+ public void getActivity(Activity activity) {
+ initActivityContext(activity);
+ }
+ });
+ }
+
+ private static void initActivityContext(Activity activity) {
+ try {
+ contextWeakReference = new WeakReference<>(activity);
+ rootFrameLayout = new WeakReference<>((FrameLayout) activity.getWindow().getDecorView());
+ } catch (Exception e) {
+ error("DialogX.init: 初始化异常,找不到Activity的根布局");
+ }
+ }
+
+ protected static void log(Object o) {
+ if (DEBUGMODE) Log.i(">>>", o.toString());
+ }
+
+ protected static void error(Object o) {
+ if (DEBUGMODE) Log.e(">>>", o.toString());
+ }
+
+ public abstract void onUIModeChange(Configuration newConfig);
+
+ protected static void show(final View view) {
+ if (view == null) return;
+ final BaseDialog baseDialog = (BaseDialog) view.getTag();
+ baseDialog.ownActivity = new WeakReference<>(contextWeakReference.get());
+ baseDialog.dialogView = new WeakReference<>(view);
+
+ log(baseDialog.dialogKey() + ".show");
+ addDialogToRunningList(baseDialog);
+ if (DialogX.implIMPLMode == DialogX.IMPL_MODE.VIEW) {
+ if (rootFrameLayout == null || rootFrameLayout.get() == null) return;
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ rootFrameLayout.get().addView(view);
+ }
+ });
+ } else {
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ WindowUtil.show(contextWeakReference.get(), view, !(baseDialog instanceof PopTip));
+ }
+ });
+ }
+ }
+
+ protected static void show(final Activity activity, final View view) {
+ if (activity == null || view == null) return;
+ if (activity.isDestroyed()) {
+ error(((BaseDialog) view.getTag()).dialogKey() + ".show ERROR: activity is Destroyed.");
+ return;
+ }
+ final BaseDialog baseDialog = (BaseDialog) view.getTag();
+ baseDialog.ownActivity = new WeakReference<>(activity);
+ baseDialog.dialogView = new WeakReference<>(view);
+
+ log(baseDialog + ".show");
+ addDialogToRunningList(baseDialog);
+ if (DialogX.implIMPLMode == DialogX.IMPL_MODE.VIEW) {
+ final FrameLayout activityRootView = (FrameLayout) activity.getWindow().getDecorView();
+ if (activityRootView == null) {
+ return;
+ }
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ activityRootView.addView(view);
+ }
+ });
+ } else {
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ WindowUtil.show(activity, view, !(baseDialog instanceof PopTip));
+ }
+ });
+ }
+ }
+
+ protected static void dismiss(final View dialogView) {
+ if (dialogView == null) return;
+ final BaseDialog baseDialog = (BaseDialog) dialogView.getTag();
+ log(baseDialog.dialogKey() + ".dismiss");
+ removeDialogToRunningList(baseDialog);
+ if (baseDialog.dialogView != null) baseDialog.dialogView.clear();
+ if (DialogX.implIMPLMode == DialogX.IMPL_MODE.VIEW) {
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ if (dialogView.getParent() == null || !(dialogView.getParent() instanceof ViewGroup)) {
+ if (rootFrameLayout == null) return;
+ rootFrameLayout.get().removeView(dialogView);
+ } else {
+ ((ViewGroup) dialogView.getParent()).removeView(dialogView);
+ }
+ }
+ });
+ } else {
+ runOnMain(new Runnable() {
+ @Override
+ public void run() {
+ WindowUtil.dismiss(dialogView);
+ }
+ });
+ }
+ }
+
+ private static void addDialogToRunningList(BaseDialog baseDialog) {
+ if (runningDialogList == null) runningDialogList = new ArrayList<>();
+ runningDialogList.add(baseDialog);
+ }
+
+ private static void removeDialogToRunningList(BaseDialog baseDialog) {
+ if (runningDialogList != null) runningDialogList.remove(baseDialog);
+ }
+
+ public static Context getContext() {
+ if (contextWeakReference == null) return null;
+ return contextWeakReference.get();
+ }
+
+ public static void cleanContext() {
+ contextWeakReference.clear();
+ contextWeakReference = null;
+ System.gc();
+ }
+
+ protected boolean cancelable = true;
+ protected OnBackPressedListener onBackPressedListener;
+ protected boolean isShow;
+ protected DialogXStyle style;
+ protected DialogX.THEME theme;
+ protected boolean autoShowInputKeyboard;
+ protected int backgroundColor = -1;
+ protected long enterAnimDuration = -1;
+ protected long exitAnimDuration = -1;
+
+ public BaseDialog() {
+ cancelable = DialogX.cancelable;
+ style = DialogX.globalStyle;
+ theme = DialogX.globalTheme;
+ enterAnimDuration = DialogX.enterAnimDuration;
+ exitAnimDuration = DialogX.exitAnimDuration;
+ autoShowInputKeyboard = DialogX.autoShowInputKeyboard;
+ }
+
+ public View createView(int layoutId) {
+ return LayoutInflater.from(getContext()).inflate(layoutId, null);
+ }
+
+ public boolean isShow() {
+ return isShow;
+ }
+
+ public DialogXStyle getStyle() {
+ return style;
+ }
+
+ public DialogX.THEME getTheme() {
+ return theme;
+ }
+
+ protected void useTextInfo(TextView textView, TextInfo textInfo) {
+ if (textInfo == null) return;
+ if (textView == null) return;
+ if (textInfo.getFontSize() > 0) {
+ textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textInfo.getFontSize());
+ }
+ if (textInfo.getFontColor() != 1) {
+ textView.setTextColor(textInfo.getFontColor());
+ }
+ if (textInfo.getGravity() != -1) {
+ textView.setGravity(textInfo.getGravity());
+ }
+ textView.getPaint().setFakeBoldText(textInfo.isBold());
+ }
+
+ protected void showText(TextView textView, CharSequence text) {
+ if (textView == null) return;
+ if (isNull(text)) {
+ textView.setVisibility(View.GONE);
+ textView.setText("");
+ } else {
+ textView.setVisibility(View.VISIBLE);
+ textView.setText(text);
+ }
+ }
+
+ protected View createHorizontalSplitView(int color) {
+ View splitView = new View(getContext());
+ splitView.setBackgroundColor(color);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1);
+ splitView.setLayoutParams(lp);
+ return splitView;
+ }
+
+ protected View createVerticalSplitView(int color, int height) {
+ View splitView = new View(getContext());
+ splitView.setBackgroundColor(color);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(1, dip2px(height));
+ splitView.setLayoutParams(lp);
+ return splitView;
+ }
+
+ public static boolean isNull(String s) {
+ if (s == null || s.trim().isEmpty() || "null".equals(s) || "(null)".equals(s)) {
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isNull(CharSequence c) {
+ String s = String.valueOf(c);
+ if (c == null || s.trim().isEmpty() || "null".equals(s) || "(null)".equals(s)) {
+ return true;
+ }
+ return false;
+ }
+
+ public Resources getResources() {
+ if (getContext() == null) return Resources.getSystem();
+ return getContext().getResources();
+ }
+
+ public int dip2px(float dpValue) {
+ final float scale = getContext().getResources().getDisplayMetrics().density;
+ return (int) (dpValue * scale + 0.5f);
+ }
+
+ public boolean isLightTheme() {
+ if (theme == DialogX.THEME.AUTO) {
+ return (getContext().getApplicationContext().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_NO;
+ }
+ return theme == DialogX.THEME.LIGHT;
+ }
+
+ public static FrameLayout getRootFrameLayout() {
+ if (rootFrameLayout == null) return null;
+ return rootFrameLayout.get();
+ }
+
+ public void tintColor(View view, int color) {
+ view.setBackgroundTintList(ColorStateList.valueOf(color));
+ }
+
+ protected void beforeShow() {
+ if (getContext() == null) {
+ error("DialogX 未初始化。\n请检查是否在启动对话框前进行初始化操作,使用以下代码进行初始化:\nDialogX.init(context);\n\n另外建议您前往查看 DialogX 的文档进行使用:https://github.com/kongzue/DialogX");
+ }
+ if (style.styleVer != DialogXStyle.styleVer) {
+ error("DialogX 所引用的 Style 不符合当前适用版本:" + DialogXStyle.styleVer + " 引入的 Style(" + style.getClass().getSimpleName() + ") 版本" + style.styleVer);
+ }
+ }
+
+ protected String getString(int titleResId) {
+ if (getContext() == null) {
+ error("DialogX 未初始化。\n请检查是否在启动对话框前进行初始化操作,使用以下代码进行初始化:\nDialogX.init(context);\n\n另外建议您前往查看 DialogX 的文档进行使用:https://github.com/kongzue/DialogX");
+ return null;
+ }
+ return getContext().getString(titleResId);
+ }
+
+ protected int getColor(int backgroundRes) {
+ if (getContext() == null) {
+ error("DialogX 未初始化。\n请检查是否在启动对话框前进行初始化操作,使用以下代码进行初始化:\nDialogX.init(context);\n\n另外建议您前往查看 DialogX 的文档进行使用:https://github.com/kongzue/DialogX");
+ return Color.BLACK;
+ }
+ return getResources().getColor(backgroundRes);
+ }
+
+ public enum BOOLEAN {
+ TRUE, FALSE
+ }
+
+ public abstract String dialogKey();
+
+ protected static void runOnMain(Runnable runnable) {
+ if (!DialogX.autoRunOnUIThread) runnable.run();
+ new Handler(Looper.getMainLooper()).post(runnable);
+ }
+
+ public Activity getActivity() {
+ return ownActivity == null ? null : ownActivity.get();
+ }
+
+ protected void cleanActivityContext() {
+ if (ownActivity != null) ownActivity.clear();
+ }
+
+ public static void recycleDialog(Activity activity) {
+ if (DialogX.implIMPLMode == DialogX.IMPL_MODE.WINDOW) {
+ if (runningDialogList != null) {
+ CopyOnWriteArrayList copyOnWriteList = new CopyOnWriteArrayList<>(runningDialogList);
+ for (BaseDialog baseDialog : copyOnWriteList) {
+ if (baseDialog.getActivity() == activity && baseDialog.dialogView != null) {
+ WindowUtil.dismiss(baseDialog.dialogView.get());
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseOnDialogClickCallback.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseOnDialogClickCallback.java
new file mode 100644
index 0000000..c39d368
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseOnDialogClickCallback.java
@@ -0,0 +1,11 @@
+package com.kongzue.dialogx.interfaces;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/22 15:07
+ */
+public interface BaseOnDialogClickCallback {
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BottomMenuListViewTouchEvent.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BottomMenuListViewTouchEvent.java
new file mode 100644
index 0000000..3471e29
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BottomMenuListViewTouchEvent.java
@@ -0,0 +1,17 @@
+package com.kongzue.dialogx.interfaces;
+
+import android.view.MotionEvent;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/11/18 15:01
+ */
+public abstract class BottomMenuListViewTouchEvent {
+
+ public void down(MotionEvent event){};
+ public void move(MotionEvent event){};
+ public void up(MotionEvent event){};
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogConvertViewInterface.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogConvertViewInterface.java
new file mode 100644
index 0000000..1ea5c70
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogConvertViewInterface.java
@@ -0,0 +1,19 @@
+package com.kongzue.dialogx.interfaces;
+
+import android.view.View;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/6 15:52
+ */
+public interface DialogConvertViewInterface {
+
+ void init();
+
+ void refreshView();
+
+ void doDismiss(View v);
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogLifecycleCallback.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogLifecycleCallback.java
new file mode 100644
index 0000000..eaec9e3
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogLifecycleCallback.java
@@ -0,0 +1,19 @@
+package com.kongzue.dialogx.interfaces;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/9/22 14:09
+ */
+public abstract class DialogLifecycleCallback {
+
+ public void onShow(T dialog){
+
+ }
+
+ public void onDismiss(T dialog){
+
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBackPressedListener.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBackPressedListener.java
new file mode 100644
index 0000000..997b615
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBackPressedListener.java
@@ -0,0 +1,12 @@
+package com.kongzue.dialogx.interfaces;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/9/25 15:48
+ */
+public interface OnBackPressedListener {
+ boolean onBackPressed();
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBindView.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBindView.java
new file mode 100644
index 0000000..fda1a74
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBindView.java
@@ -0,0 +1,93 @@
+package com.kongzue.dialogx.interfaces;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RelativeLayout;
+
+import com.kongzue.dialogx.DialogX;
+
+import static com.kongzue.dialogx.DialogX.ERROR_INIT_TIPS;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/8 17:00
+ */
+public abstract class OnBindView {
+ int layoutResId;
+ View customView;
+
+ public OnBindView(int layoutResId) {
+ if (BaseDialog.getContext() == null) {
+ DialogX.error(ERROR_INIT_TIPS);
+ return;
+ }
+ this.layoutResId = layoutResId;
+ customView = LayoutInflater.from(BaseDialog.getContext()).inflate(layoutResId, new RelativeLayout(BaseDialog.getContext()), false);
+ }
+
+ public OnBindView(View customView) {
+ this.customView = customView;
+ }
+
+ public abstract void onBind(D dialog, View v);
+
+ public int getLayoutResId() {
+ return layoutResId;
+ }
+
+ public OnBindView setLayoutResId(int layoutResId) {
+ this.layoutResId = layoutResId;
+ return this;
+ }
+
+ public View getCustomView() {
+ return customView;
+ }
+
+ public OnBindView setCustomView(View customView) {
+ this.customView = customView;
+ return this;
+ }
+
+ public void clean() {
+ layoutResId = 0;
+ customView = null;
+ }
+
+ public OnBindView bindParent(ViewGroup parentView) {
+ if (customView == null) return this;
+ if (customView.getParent() != null) {
+ if (customView.getParent()==parentView){
+ return this;
+ }
+ ((ViewGroup) customView.getParent()).removeView(customView);
+ }
+ ViewGroup.LayoutParams lp = parentView.getLayoutParams();
+ if (lp == null) {
+ lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+ parentView.addView(customView, lp);
+ return this;
+ }
+
+ public OnBindView bindParent(ViewGroup parentView, BaseDialog dialog) {
+ if (customView == null) return this;
+ if (customView.getParent() != null) {
+ if (customView.getParent()==parentView){
+ return this;
+ }
+ ((ViewGroup) customView.getParent()).removeView(customView);
+ }
+ ViewGroup.LayoutParams lp = customView.getLayoutParams();
+ if (lp == null) {
+ lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+ parentView.addView(customView, lp);
+ onBind((D) dialog, customView);
+ return this;
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnDialogButtonClickListener.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnDialogButtonClickListener.java
new file mode 100644
index 0000000..09896c9
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnDialogButtonClickListener.java
@@ -0,0 +1,16 @@
+package com.kongzue.dialogx.interfaces;
+
+import android.view.View;
+
+/**
+ * Author: @Kongzue
+ * Github: https://github.com/kongzue/
+ * Homepage: http://kongzue.com/
+ * Mail: myzcxhh@live.cn
+ * CreateTime: 2019/3/29 18:44
+ */
+public interface OnDialogButtonClickListener extends BaseOnDialogClickCallback{
+
+ boolean onClick(D baseDialog, View v);
+
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnIconChangeCallBack.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnIconChangeCallBack.java
new file mode 100644
index 0000000..6dfd630
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnIconChangeCallBack.java
@@ -0,0 +1,28 @@
+package com.kongzue.dialogx.interfaces;
+
+import com.kongzue.dialogx.dialogs.BottomMenu;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/9 14:54
+ */
+public abstract class OnIconChangeCallBack {
+
+ private boolean autoTintIconInLightOrDarkMode;
+
+ public OnIconChangeCallBack() {
+ }
+
+ public OnIconChangeCallBack(boolean autoTintIconInLightOrDarkMode) {
+ this.autoTintIconInLightOrDarkMode = autoTintIconInLightOrDarkMode;
+ }
+
+ public abstract int getIcon(BottomMenu bottomMenu, int index, String menuText);
+
+ public boolean isAutoTintIconInLightOrDarkMode() {
+ return autoTintIconInLightOrDarkMode;
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnInputDialogButtonClickListener.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnInputDialogButtonClickListener.java
new file mode 100644
index 0000000..5567dc0
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnInputDialogButtonClickListener.java
@@ -0,0 +1,17 @@
+package com.kongzue.dialogx.interfaces;
+
+import android.view.View;
+
+import com.kongzue.dialogx.dialogs.MessageDialog;
+
+/**
+ * Author: @Kongzue
+ * Github: https://github.com/kongzue/
+ * Homepage: http://kongzue.com/
+ * Mail: myzcxhh@live.cn
+ * CreateTime: 2019/4/8 21:09
+ */
+public interface OnInputDialogButtonClickListener extends BaseOnDialogClickCallback{
+
+ boolean onClick(D baseDialog, View v, String inputStr);
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemClickListener.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemClickListener.java
new file mode 100644
index 0000000..2edb4a8
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemClickListener.java
@@ -0,0 +1,12 @@
+package com.kongzue.dialogx.interfaces;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/10 6:26
+ */
+public interface OnMenuItemClickListener {
+ boolean onClick(D dialog, CharSequence text, int which);
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemSelectListener.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemSelectListener.java
new file mode 100644
index 0000000..855c1bf
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemSelectListener.java
@@ -0,0 +1,37 @@
+package com.kongzue.dialogx.interfaces;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2021/4/11 19:18
+ */
+public abstract class OnMenuItemSelectListener implements OnMenuItemClickListener {
+
+ /**
+ * 警告:不建议重写此方法!
+ * 如果选择使用 OnMenuItemSelectListener 作为 BottomMenu 的回调,那么点击 Item 后,菜单默认不应该关闭,
+ * 若选择自行处理菜单点击 onClick,那么请务必 return true 作为返回值,
+ * 否则不会处理 onOneItemSelect 或 onMultiItemSelect 事件。
+ *
+ * @param dialog BottomMenu实例
+ * @param text 菜单文本
+ * @param index 菜单索引值
+ * @return return true:拦截自动关闭对话框;return false:点击后关闭对话框
+ */
+ @Deprecated
+ @Override
+ public boolean onClick(D dialog, CharSequence text, int index) {
+ return true;
+ }
+
+ public void onOneItemSelect(D dialog, CharSequence text, int which) {
+
+ }
+
+ public void onMultiItemSelect(D dialog, CharSequence[] text, int[] indexArray) {
+
+ }
+
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnSafeInsetsChangeListener.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnSafeInsetsChangeListener.java
new file mode 100644
index 0000000..e0fda15
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnSafeInsetsChangeListener.java
@@ -0,0 +1,15 @@
+package com.kongzue.dialogx.interfaces;
+
+import android.graphics.Rect;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/19 16:06
+ */
+public interface OnSafeInsetsChangeListener {
+
+ void onChange(Rect unsafeRect);
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/style/MaterialStyle.java b/DialogX/src/main/java/com/kongzue/dialogx/style/MaterialStyle.java
new file mode 100644
index 0000000..f9aee1e
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/style/MaterialStyle.java
@@ -0,0 +1,225 @@
+package com.kongzue.dialogx.style;
+
+import android.content.Context;
+
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.interfaces.DialogXStyle;
+import com.kongzue.dialogx.interfaces.ProgressViewInterface;
+import com.kongzue.dialogx.util.views.ProgressView;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/9/26 13:09
+ */
+public class MaterialStyle implements DialogXStyle {
+
+ public static MaterialStyle style() {
+ return new MaterialStyle();
+ }
+
+ @Override
+ public int layout(boolean light) {
+ return light ? R.layout.layout_dialogx_material : R.layout.layout_dialogx_material_dark;
+ }
+
+ @Override
+ public int enterAnimResId() {
+ return R.anim.anim_dialogx_default_enter;
+ }
+
+ @Override
+ public int exitAnimResId() {
+ return R.anim.anim_dialogx_default_exit;
+ }
+
+ @Override
+ public int[] verticalButtonOrder() {
+ return new int[]{BUTTON_OK, BUTTON_OTHER, BUTTON_CANCEL};
+ }
+
+ @Override
+ public int[] horizontalButtonOrder() {
+ return new int[]{BUTTON_OTHER, SPACE, BUTTON_CANCEL, BUTTON_OK};
+ }
+
+ @Override
+ public int splitWidthPx() {
+ return 1;
+ }
+
+ @Override
+ public int splitColorRes(boolean light) {
+ return 0;
+ }
+
+ @Override
+ public BlurBackgroundSetting messageDialogBlurSettings() {
+ return null;
+ }
+
+ @Override
+ public HorizontalButtonRes overrideHorizontalButtonRes() {
+ return new HorizontalButtonRes() {
+ @Override
+ public int overrideHorizontalOkButtonBackgroundRes(int visibleButtonCount, boolean light) {
+ return light ? R.drawable.button_dialogx_material_light : R.drawable.button_dialogx_material_night;
+ }
+
+ @Override
+ public int overrideHorizontalCancelButtonBackgroundRes(int visibleButtonCount, boolean light) {
+ return light ? R.drawable.button_dialogx_material_light : R.drawable.button_dialogx_material_night;
+ }
+
+ @Override
+ public int overrideHorizontalOtherButtonBackgroundRes(int visibleButtonCount, boolean light) {
+ return light ? R.drawable.button_dialogx_material_light : R.drawable.button_dialogx_material_night;
+ }
+ };
+ }
+
+ @Override
+ public VerticalButtonRes overrideVerticalButtonRes() {
+ return new VerticalButtonRes() {
+ @Override
+ public int overrideVerticalOkButtonBackgroundRes(int visibleButtonCount, boolean light) {
+ return light ? R.drawable.button_dialogx_material_light : R.drawable.button_dialogx_material_night;
+ }
+
+ @Override
+ public int overrideVerticalCancelButtonBackgroundRes(int visibleButtonCount, boolean light) {
+ return light ? R.drawable.button_dialogx_material_light : R.drawable.button_dialogx_material_night;
+ }
+
+ @Override
+ public int overrideVerticalOtherButtonBackgroundRes(int visibleButtonCount, boolean light) {
+ return light ? R.drawable.button_dialogx_material_light : R.drawable.button_dialogx_material_night;
+ }
+ };
+ }
+
+ @Override
+ public WaitTipRes overrideWaitTipRes() {
+ return new WaitTipRes() {
+ @Override
+ public int overrideWaitLayout(boolean light) {
+ return R.layout.layout_dialogx_wait;
+ }
+
+ @Override
+ public int overrideRadiusPx() {
+ return -1;
+ }
+
+ @Override
+ public boolean blurBackground() {
+ return false;
+ }
+
+ @Override
+ public int overrideBackgroundColorRes(boolean light) {
+ return 0;
+ }
+
+ @Override
+ public int overrideTextColorRes(boolean light) {
+ return light ? R.color.white : R.color.black;
+ }
+
+ @Override
+ public ProgressViewInterface overrideWaitView(Context context, boolean light) {
+ return new ProgressView(context);
+ }
+ };
+ }
+
+ @Override
+ public BottomDialogRes overrideBottomDialogRes() {
+ return new BottomDialogRes() {
+
+ @Override
+ public boolean touchSlide() {
+ return true;
+ }
+
+ @Override
+ public int overrideDialogLayout(boolean light) {
+ return light ? R.layout.layout_dialogx_bottom_material : R.layout.layout_dialogx_bottom_material_dark;
+ }
+
+ @Override
+ public int overrideMenuDividerDrawableRes(boolean light) {
+ return light ? R.drawable.rect_dialogx_material_menu_split_divider : R.drawable.rect_dialogx_material_menu_split_divider_night;
+ }
+
+ @Override
+ public int overrideMenuDividerHeight(boolean light) {
+ return 1;
+ }
+
+ @Override
+ public int overrideMenuTextColor(boolean light) {
+ return light ? R.color.black90 : R.color.white90;
+ }
+
+ @Override
+ public float overrideBottomDialogMaxHeight() {
+ return 0.6f;
+ }
+
+ @Override
+ public int overrideMenuItemLayout(boolean light, int index, int count, boolean isContentVisibility) {
+ return 0;
+ }
+
+ @Override
+ public int overrideSelectionMenuBackgroundColor(boolean light) {
+ return 0;
+ }
+
+ @Override
+ public boolean selectionImageTint(boolean light) {
+ return false;
+ }
+
+ @Override
+ public int overrideSelectionImage(boolean light, boolean isSelected) {
+ return isSelected ? R.mipmap.img_dialogx_bottom_menu_material_item_selection : R.mipmap.img_dialogx_bottom_menu_material_item_non_select;
+ }
+
+ @Override
+ public int overrideMultiSelectionImage(boolean light, boolean isSelected) {
+ return isSelected ? R.mipmap.img_dialogx_bottom_menu_material_item_multi_selection : R.mipmap.img_dialogx_bottom_menu_material_item_non_multi_select;
+ }
+
+ };
+ }
+
+ @Override
+ public PopTipSettings popTipSettings() {
+ return new PopTipSettings() {
+ @Override
+ public int layout(boolean light) {
+ return light ? R.layout.layout_dialogx_poptip_material : R.layout.layout_dialogx_poptip_material_dark;
+ }
+
+ @Override
+ public ALIGN align() {
+ return ALIGN.BOTTOM;
+ }
+
+ @Override
+ public int enterAnimResId(boolean light) {
+ return R.anim.anim_dialogx_default_enter;
+ }
+
+ @Override
+ public int exitAnimResId(boolean light) {
+ return R.anim.anim_dialogx_default_exit;
+ }
+ };
+ }
+
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/BottomDialogTouchEventInterceptor.java b/DialogX/src/main/java/com/kongzue/dialogx/util/BottomDialogTouchEventInterceptor.java
new file mode 100644
index 0000000..1ce5f56
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/BottomDialogTouchEventInterceptor.java
@@ -0,0 +1,145 @@
+package com.kongzue.dialogx.util;
+
+import android.animation.ObjectAnimator;
+import android.content.res.Resources;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+
+import com.kongzue.dialogx.dialogs.BottomDialog;
+import com.kongzue.dialogx.interfaces.DialogConvertViewInterface;
+import com.kongzue.dialogx.util.views.BottomDialogScrollView;
+import com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/7 4:01
+ */
+public class BottomDialogTouchEventInterceptor {
+
+ /**
+ * 下边三个值用于判断触控过程,
+ * isBkgTouched:标记是否已按下
+ * bkgTouchDownY:记录起始触控位置
+ * scrolledY:记录 ScrollView 已滚动过的距离,下次触控事件将接着上次的位置继续滑动
+ * bkgOldY:记录按下时 bkg 的位置,用于区分松开手指时,bkg 移动的方向。
+ */
+ private boolean isBkgTouched = false;
+ private float bkgTouchDownY;
+ private float scrolledY;
+ private float bkgOldY;
+ /**
+ * 0:bkg接收触控事件,-1:scrollView进行滚动
+ * 此标记的意义在于,当从 [scrollView滚动] 与 [bkg接收触控事件] 状态切换时,
+ * 需要对bkgTouchDownY、scrolledY的值进行刷新,否则触控连续过程会出现闪跳。
+ */
+ private int oldMode;
+
+ public BottomDialogTouchEventInterceptor(BottomDialog me, BottomDialog.DialogImpl impl) {
+ refresh(me, impl);
+ }
+
+ public void refresh(final BottomDialog me, final BottomDialog.DialogImpl impl) {
+ if (me == null || impl == null || impl.bkg == null || impl.scrollView == null) {
+ return;
+ }
+ /**
+ * BottomDialog 触控事件说明:
+ * bkg 将拦截并接管所有触控操作。
+ * BottomDialog 的启动方式依据是内容布局高度是否大于可显示安全区域的高度。
+ * bkg 会在合适的时机,直接接管控制 ScrollView 的滚动。
+ * 因此,请确保内容布局的高度计算方式一定是按照内容高度计算,
+ * 即,请重写 onMeasure 方法:
+ * @Override
+ * protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ * int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
+ * super.onMeasure(widthMeasureSpec, expandSpec);
+ * }
+ */
+ if (me.isAllowInterceptTouch()) {
+ impl.bkg.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ //这里 return 什么实际上无关紧要,重点在于 MaxRelativeLayout.java(dispatchTouchEvent:184) 的事件分发会独立触发此处的额外滑动事件
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ bkgTouchDownY = event.getY();
+ isBkgTouched = true;
+ bkgOldY = impl.bkg.getY();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (isBkgTouched) {
+ float aimY = impl.bkg.getY() + event.getY() - bkgTouchDownY;
+ if (impl.bkg.isChildScrollViewCanScroll()) {
+ if (aimY > 0) {
+ if (impl.scrollView.getScrollY() == 0) {
+ if (impl.scrollView instanceof BottomDialogScrollView) {
+ ((BottomDialogScrollView) impl.scrollView).lockScroll(true);
+ }
+ impl.bkg.setY(aimY);
+ } else {
+ bkgTouchDownY = event.getY();
+ }
+ } else {
+ if (impl.scrollView instanceof BottomDialogScrollView) {
+ ((BottomDialogScrollView) impl.scrollView).lockScroll(false);
+ }
+ impl.bkg.setY(0);
+ }
+ } else {
+ if (aimY > impl.bkgEnterAimY) {
+ impl.bkg.setY(aimY);
+ } else {
+ impl.bkg.setY(impl.bkgEnterAimY);
+ }
+ }
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ scrolledY = impl.scrollView.getScrollY();
+ isBkgTouched = false;
+ if (bkgOldY == 0) {
+ if (impl.bkg.getY() < dip2px(35)) {
+ ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.bkg, "y", impl.bkg.getY(), 0);
+ enterAnim.setDuration(300);
+ enterAnim.start();
+ } else if (impl.bkg.getY() > impl.bkgEnterAimY + dip2px(35)) {
+ impl.preDismiss();
+ } else {
+ ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.bkg, "y", impl.bkg.getY(), impl.bkgEnterAimY);
+ enterAnim.setDuration(300);
+ enterAnim.start();
+ }
+ } else {
+ if (impl.bkg.getY() < bkgOldY - dip2px(35)) {
+ ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.bkg, "y", impl.bkg.getY(), 0);
+ enterAnim.setDuration(300);
+ enterAnim.start();
+ } else if (impl.bkg.getY() > bkgOldY + dip2px(35)) {
+ impl.preDismiss();
+ } else {
+ ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.bkg, "y", impl.bkg.getY(), impl.bkgEnterAimY);
+ enterAnim.setDuration(300);
+ enterAnim.start();
+ }
+ }
+ break;
+ }
+ return false;
+ }
+ });
+ } else {
+ impl.bkg.setOnTouchListener(null);
+ }
+ }
+
+ private int dip2px(float dpValue) {
+ final float scale = Resources.getSystem().getDisplayMetrics().density;
+ return (int) (dpValue * scale + 0.5f);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/FullScreenDialogTouchEventInterceptor.java b/DialogX/src/main/java/com/kongzue/dialogx/util/FullScreenDialogTouchEventInterceptor.java
new file mode 100644
index 0000000..0f982dd
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/FullScreenDialogTouchEventInterceptor.java
@@ -0,0 +1,96 @@
+package com.kongzue.dialogx.util;
+
+import android.animation.ObjectAnimator;
+import android.content.res.Resources;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.kongzue.dialogx.dialogs.FullScreenDialog;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/19 13:54
+ */
+public class FullScreenDialogTouchEventInterceptor {
+
+ /**
+ * 下边三个值用于判断触控过程,
+ * isBkgTouched:标记是否已按下
+ * bkgTouchDownY:记录起始触控位置
+ * scrolledY:记录 ScrollView 已滚动过的距离,下次触控事件将接着上次的位置继续滑动
+ * bkgOldY:记录按下时 bkg 的位置,用于区分松开手指时,bkg 移动的方向。
+ */
+ private boolean isBkgTouched = false;
+ private float bkgTouchDownY;
+ private float bkgOldY;
+
+ public FullScreenDialogTouchEventInterceptor(FullScreenDialog me, FullScreenDialog.DialogImpl impl) {
+ refresh(me, impl);
+ }
+
+ public void refresh(final FullScreenDialog me, final FullScreenDialog.DialogImpl impl) {
+ if (me == null || impl == null || impl.bkg == null) {
+ return;
+ }
+
+ impl.boxCustom.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ bkgTouchDownY = event.getY();
+ isBkgTouched = true;
+ bkgOldY = impl.bkg.getY();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (isBkgTouched) {
+ float aimY = impl.bkg.getY() + event.getY() - bkgTouchDownY;
+ if (aimY < 0) {
+ aimY = 0;
+ }
+ impl.bkg.setY(aimY);
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ isBkgTouched = false;
+ if (bkgOldY == 0) {
+ if (impl.bkg.getY() < dip2px(35)) {
+ ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.bkg, "y", impl.bkg.getY(), 0);
+ enterAnim.setDuration(300);
+ enterAnim.start();
+ } else if (impl.bkg.getY() > impl.bkgEnterAimY + dip2px(35)) {
+ impl.preDismiss();
+ } else {
+ ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.bkg, "y", impl.bkg.getY(), impl.bkgEnterAimY);
+ enterAnim.setDuration(300);
+ enterAnim.start();
+ }
+ } else {
+ if (impl.bkg.getY() < bkgOldY - dip2px(35)) {
+ ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.bkg, "y", impl.bkg.getY(), 0);
+ enterAnim.setDuration(300);
+ enterAnim.start();
+ } else if (impl.bkg.getY() > bkgOldY + dip2px(35)) {
+ impl.preDismiss();
+ } else {
+ ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.bkg, "y", impl.bkg.getY(), impl.bkgEnterAimY);
+ enterAnim.setDuration(300);
+ enterAnim.start();
+ }
+ }
+ break;
+ }
+ return true;
+ }
+ });
+ }
+
+ private int dip2px(float dpValue) {
+ final float scale = Resources.getSystem().getDisplayMetrics().density;
+ return (int) (dpValue * scale + 0.5f);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/IOSMenuArrayAdapter.java b/DialogX/src/main/java/com/kongzue/dialogx/util/IOSMenuArrayAdapter.java
new file mode 100644
index 0000000..1c38896
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/IOSMenuArrayAdapter.java
@@ -0,0 +1,19 @@
+package com.kongzue.dialogx.util;
+
+import android.content.Context;
+import android.widget.ArrayAdapter;
+
+import androidx.annotation.NonNull;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/10 19:56
+ */
+public class IOSMenuArrayAdapter extends ArrayAdapter {
+ public IOSMenuArrayAdapter(@NonNull Context context, int resource) {
+ super(context, resource);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/InputInfo.java b/DialogX/src/main/java/com/kongzue/dialogx/util/InputInfo.java
new file mode 100644
index 0000000..f2cd457
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/InputInfo.java
@@ -0,0 +1,62 @@
+package com.kongzue.dialogx.util;
+
+/**
+ * Author: @Kongzue
+ * Github: https://github.com/kongzue/
+ * Homepage: http://kongzue.com/
+ * Mail: myzcxhh@live.cn
+ * CreateTime: 2018/11/8 21:41
+ */
+public class InputInfo {
+
+ private int MAX_LENGTH = -1; //最大长度,-1不生效
+ private int inputType; //类型详见 android.text.InputType
+ private TextInfo textInfo; //默认字体样式
+ private boolean multipleLines; //支持多行
+ private boolean selectAllText; //默认选中所有文字(便于修改)
+
+ public int getMAX_LENGTH() {
+ return MAX_LENGTH;
+ }
+
+ public InputInfo setMAX_LENGTH(int MAX_LENGTH) {
+ this.MAX_LENGTH = MAX_LENGTH;
+ return this;
+ }
+
+ public int getInputType() {
+ return inputType;
+ }
+
+ public InputInfo setInputType(int inputType) {
+ this.inputType = inputType;
+ return this;
+ }
+
+ public TextInfo getTextInfo() {
+ return textInfo;
+ }
+
+ public InputInfo setTextInfo(TextInfo textInfo) {
+ this.textInfo = textInfo;
+ return this;
+ }
+
+ public boolean isMultipleLines() {
+ return multipleLines;
+ }
+
+ public InputInfo setMultipleLines(boolean multipleLines) {
+ this.multipleLines = multipleLines;
+ return this;
+ }
+
+ public boolean isSelectAllText() {
+ return selectAllText;
+ }
+
+ public InputInfo setSelectAllText(boolean selectAllText) {
+ this.selectAllText = selectAllText;
+ return this;
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/NormalMenuArrayAdapter.java b/DialogX/src/main/java/com/kongzue/dialogx/util/NormalMenuArrayAdapter.java
new file mode 100644
index 0000000..c7aa364
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/NormalMenuArrayAdapter.java
@@ -0,0 +1,213 @@
+package com.kongzue.dialogx.util;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Typeface;
+import android.graphics.drawable.StateListDrawable;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.SimpleAdapter;
+import android.widget.TextView;
+
+import com.kongzue.dialogx.DialogX;
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+
+import java.util.List;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/7 0:00
+ */
+public class NormalMenuArrayAdapter extends BaseAdapter {
+
+ private BottomMenu bottomMenu;
+ public List objects;
+ public Context context;
+
+ public NormalMenuArrayAdapter(BottomMenu bottomMenu, Context context, List objects) {
+ this.objects = objects;
+ this.context = context;
+ this.bottomMenu = bottomMenu;
+ }
+
+ class ViewHolder {
+ ImageView imgDialogxMenuIcon;
+ TextView txtDialogxMenuText;
+ ImageView imgDialogxMenuSelection;
+ }
+
+ @Override
+ public int getCount() {
+ return objects.size();
+ }
+
+ @Override
+ public CharSequence getItem(int position) {
+ return objects.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ViewHolder viewHolder = null;
+ if (convertView == null) {
+ viewHolder = new ViewHolder();
+ LayoutInflater mInflater = LayoutInflater.from(context);
+
+ int resourceId = R.layout.item_dialogx_material_bottom_menu_normal_text;
+ if (bottomMenu.getStyle().overrideBottomDialogRes() != null) {
+ resourceId = bottomMenu.getStyle().overrideBottomDialogRes().overrideMenuItemLayout(bottomMenu.isLightTheme(), position, getCount(), false);
+ if (resourceId == 0) {
+ resourceId = R.layout.item_dialogx_material_bottom_menu_normal_text;
+ } else {
+ if (bottomMenu.getDialogImpl().txtDialogTitle.getVisibility() == View.VISIBLE ||
+ bottomMenu.getDialogImpl().txtDialogTip.getVisibility() == View.VISIBLE ||
+ bottomMenu.getCustomView() != null) {
+ if (position == 0) {
+ resourceId = bottomMenu.getStyle().overrideBottomDialogRes().overrideMenuItemLayout(bottomMenu.isLightTheme(), position, getCount(), true);
+ }
+ }
+ }
+ }
+ convertView = mInflater.inflate(resourceId, null);
+
+ viewHolder.imgDialogxMenuIcon = convertView.findViewById(R.id.img_dialogx_menu_icon);
+ viewHolder.txtDialogxMenuText = convertView.findViewById(R.id.txt_dialogx_menu_text);
+ viewHolder.imgDialogxMenuSelection = convertView.findViewById(R.id.img_dialogx_menu_selection);
+
+ convertView.setTag(viewHolder);
+ } else {
+ viewHolder = (ViewHolder) convertView.getTag();
+ }
+ if (bottomMenu.getSelectMode() == BottomMenu.SELECT_MODE.SINGLE) {
+ if (viewHolder.imgDialogxMenuSelection != null) {
+ if (bottomMenu.getSelection() == position) {
+ viewHolder.imgDialogxMenuSelection.setVisibility(View.VISIBLE);
+ int overrideSelectionImageResId = bottomMenu.getStyle().overrideBottomDialogRes().overrideSelectionImage(bottomMenu.isLightTheme(), true);
+ if (overrideSelectionImageResId != 0) {
+ viewHolder.imgDialogxMenuSelection.setImageResource(overrideSelectionImageResId);
+ }
+ } else {
+ int overrideSelectionImageResId = bottomMenu.getStyle().overrideBottomDialogRes().overrideSelectionImage(bottomMenu.isLightTheme(), false);
+ if (overrideSelectionImageResId != 0) {
+ viewHolder.imgDialogxMenuSelection.setVisibility(View.VISIBLE);
+ viewHolder.imgDialogxMenuSelection.setImageResource(overrideSelectionImageResId);
+ } else {
+ viewHolder.imgDialogxMenuSelection.setVisibility(View.INVISIBLE);
+ }
+ }
+ }
+ } else if (bottomMenu.getSelectMode() == BottomMenu.SELECT_MODE.MULTIPLE) {
+ if (viewHolder.imgDialogxMenuSelection != null) {
+ if (bottomMenu.getSelectionList().contains(position)) {
+ viewHolder.imgDialogxMenuSelection.setVisibility(View.VISIBLE);
+ int overrideSelectionImageResId = bottomMenu.getStyle().overrideBottomDialogRes().overrideMultiSelectionImage(bottomMenu.isLightTheme(), true);
+ if (overrideSelectionImageResId != 0) {
+ viewHolder.imgDialogxMenuSelection.setImageResource(overrideSelectionImageResId);
+ }
+ } else {
+ int overrideSelectionImageResId = bottomMenu.getStyle().overrideBottomDialogRes().overrideMultiSelectionImage(bottomMenu.isLightTheme(), false);
+ if (overrideSelectionImageResId != 0) {
+ viewHolder.imgDialogxMenuSelection.setVisibility(View.VISIBLE);
+ viewHolder.imgDialogxMenuSelection.setImageResource(overrideSelectionImageResId);
+ } else {
+ viewHolder.imgDialogxMenuSelection.setVisibility(View.INVISIBLE);
+ }
+ }
+ }
+ } else {
+ viewHolder.imgDialogxMenuSelection.setVisibility(View.GONE);
+ }
+ int overrideSelectionBackgroundColorRes = 0;
+ if (bottomMenu.getStyle().overrideBottomDialogRes() != null) {
+ overrideSelectionBackgroundColorRes = bottomMenu.getStyle().overrideBottomDialogRes().overrideSelectionMenuBackgroundColor(bottomMenu.isLightTheme());
+ }
+ if (bottomMenu.getSelection() == position) {
+ if (overrideSelectionBackgroundColorRes != 0) {
+ convertView.setBackgroundTintList(ColorStateList.valueOf(context.getResources().getColor(overrideSelectionBackgroundColorRes)));
+ final View finalRootView = convertView;
+ convertView.post(new Runnable() {
+ @Override
+ public void run() {
+ finalRootView.setPressed(true);
+ }
+ });
+ }
+ } else {
+ convertView.setBackgroundTintList(null);
+ }
+ CharSequence text = objects.get(position);
+
+ int textColor = bottomMenu.isLightTheme() ? R.color.black90 : R.color.white90;
+ if (bottomMenu.getStyle().overrideBottomDialogRes() != null) {
+ if (bottomMenu.getStyle().overrideBottomDialogRes().overrideMenuTextColor(bottomMenu.isLightTheme()) != 0) {
+ textColor = bottomMenu.getStyle().overrideBottomDialogRes().overrideMenuTextColor(bottomMenu.isLightTheme());
+ }
+ }
+
+ if (null != text) {
+ viewHolder.txtDialogxMenuText.setText(text);
+ viewHolder.txtDialogxMenuText.setTextColor(context.getResources().getColor(textColor));
+ if (DialogX.menuTextInfo != null) {
+ useTextInfo(viewHolder.txtDialogxMenuText, DialogX.menuTextInfo);
+ }
+ if (viewHolder.imgDialogxMenuSelection != null) {
+ if (bottomMenu.getStyle().overrideBottomDialogRes() != null && bottomMenu.getStyle().overrideBottomDialogRes().selectionImageTint(bottomMenu.isLightTheme())) {
+ viewHolder.imgDialogxMenuSelection.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(textColor)));
+ } else {
+ viewHolder.imgDialogxMenuSelection.setImageTintList(null);
+ }
+ }
+
+ if (bottomMenu.getOnIconChangeCallBack() != null) {
+ int resId = bottomMenu.getOnIconChangeCallBack().getIcon(bottomMenu, position, text.toString());
+ boolean autoTintIconInLightOrDarkMode = bottomMenu.getOnIconChangeCallBack().isAutoTintIconInLightOrDarkMode();
+
+ if (resId != 0) {
+ viewHolder.imgDialogxMenuIcon.setVisibility(View.VISIBLE);
+ viewHolder.imgDialogxMenuIcon.setImageResource(resId);
+
+ if (autoTintIconInLightOrDarkMode) {
+ viewHolder.imgDialogxMenuIcon.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(textColor)));
+ }
+ } else {
+ viewHolder.imgDialogxMenuIcon.setVisibility(View.GONE);
+ }
+ } else {
+ viewHolder.imgDialogxMenuIcon.setVisibility(View.GONE);
+ }
+ }
+
+ return convertView;
+ }
+
+ protected void useTextInfo(TextView textView, TextInfo textInfo) {
+ if (textInfo == null) return;
+ if (textView == null) return;
+ if (textInfo.getFontSize() > 0) {
+ textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textInfo.getFontSize());
+ }
+ if (textInfo.getFontColor() != 1) {
+ textView.setTextColor(textInfo.getFontColor());
+ }
+ if (textInfo.getGravity() != -1) {
+ textView.setGravity(textInfo.getGravity());
+ }
+ Typeface font = Typeface.create(Typeface.SANS_SERIF, textInfo.isBold() ? Typeface.BOLD : Typeface.NORMAL);
+ textView.setTypeface(font);
+ }
+}
\ No newline at end of file
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/TextInfo.java b/DialogX/src/main/java/com/kongzue/dialogx/util/TextInfo.java
new file mode 100644
index 0000000..96cd131
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/TextInfo.java
@@ -0,0 +1,62 @@
+package com.kongzue.dialogx.util;
+
+/**
+ * Author: @Kongzue
+ * Github: https://github.com/kongzue/
+ * Homepage: http://kongzue.com/
+ * Mail: myzcxhh@live.cn
+ * CreateTime: 2018/11/10 22:01
+ */
+public class TextInfo {
+
+ private int fontSize = -1; //字号大小,值为-1时使用默认样式,单位:dp
+ private int gravity = -1; //对齐方式,值为-1时使用默认样式,取值可使用Gravity.CENTER等对齐方式
+ private int fontColor = 1; //文字颜色,值为1时使用默认样式,取值可以用Color.rgb(r,g,b)等方式获取
+ private boolean bold = false; //是否粗体
+
+ public int getFontSize() {
+ return fontSize;
+ }
+
+ public TextInfo setFontSize(int fontSize) {
+ this.fontSize = fontSize;
+ return this;
+ }
+
+ public int getGravity() {
+ return gravity;
+ }
+
+ public TextInfo setGravity(int gravity) {
+ this.gravity = gravity;
+ return this;
+ }
+
+ public int getFontColor() {
+ return fontColor;
+ }
+
+ public TextInfo setFontColor(int fontColor) {
+ this.fontColor = fontColor;
+ return this;
+ }
+
+ public boolean isBold() {
+ return bold;
+ }
+
+ public TextInfo setBold(boolean bold) {
+ this.bold = bold;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "TextInfo{" +
+ "fontSize=" + fontSize +
+ ", gravity=" + gravity +
+ ", fontColor=" + fontColor +
+ ", bold=" + bold +
+ '}';
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/WindowUtil.java b/DialogX/src/main/java/com/kongzue/dialogx/util/WindowUtil.java
new file mode 100644
index 0000000..24b8312
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/WindowUtil.java
@@ -0,0 +1,57 @@
+package com.kongzue.dialogx.util;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.os.Build;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.Toast;
+
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.interfaces.BaseDialog;
+
+import static android.view.WindowManager.LayoutParams.*;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2021/4/29 16:02
+ */
+public class WindowUtil {
+
+ public static void show(Activity activity, View dialogView, boolean touchEnable) {
+ WindowManager manager = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
+ WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
+
+ layoutParams.gravity = Gravity.CENTER_VERTICAL;
+ layoutParams.format = PixelFormat.TRANSPARENT;
+ layoutParams.type = TYPE_APPLICATION_ATTACHED_DIALOG;
+ layoutParams.flags = FLAG_FULLSCREEN |
+ FLAG_TRANSLUCENT_STATUS |
+ FLAG_TRANSLUCENT_NAVIGATION |
+ FLAG_LAYOUT_IN_SCREEN
+ ;
+ if (!touchEnable) {
+ layoutParams.flags = layoutParams.flags | FLAG_NOT_FOCUSABLE;
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ layoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+ }
+
+ manager.addView(dialogView, layoutParams);
+ }
+
+ public static void dismiss(View dialogView) {
+ BaseDialog baseDialog = (BaseDialog) dialogView.getTag();
+ if (baseDialog != null && baseDialog.getActivity() != null) {
+ WindowManager manager = (WindowManager) baseDialog.getActivity().getSystemService(Context.WINDOW_SERVICE);
+ manager.removeViewImmediate(dialogView);
+ }
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/ActivityScreenShotImageView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/ActivityScreenShotImageView.java
new file mode 100644
index 0000000..5b1f65d
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/ActivityScreenShotImageView.java
@@ -0,0 +1,124 @@
+package com.kongzue.dialogx.util.views;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+
+import androidx.appcompat.widget.AppCompatImageView;
+
+import com.kongzue.dialogx.interfaces.BaseDialog;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2019/11/17 23:53
+ */
+public class ActivityScreenShotImageView extends AppCompatImageView {
+
+ float width, height, mRadius;
+
+ public ActivityScreenShotImageView(Context context) {
+ super(context);
+ init(null);
+ }
+
+ public ActivityScreenShotImageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(attrs);
+ }
+
+ public ActivityScreenShotImageView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(attrs);
+ }
+
+ private void init(AttributeSet attrs) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ setLayerType(LAYER_TYPE_HARDWARE, null);
+ }
+ }
+
+ public void setRadius(float mRadius) {
+ this.mRadius = mRadius;
+ invalidate();
+ }
+
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ width = getWidth();
+ height = getHeight();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (width >= mRadius && height > mRadius) {
+ Path path = new Path();
+ path.moveTo(mRadius, 0);
+ path.lineTo(width - mRadius, 0);
+ path.quadTo(width, 0, width, mRadius);
+ path.lineTo(width, height - mRadius);
+ path.quadTo(width, height, width - mRadius, height);
+ path.lineTo(mRadius, height);
+ path.quadTo(0, height, 0, height - mRadius);
+ path.lineTo(0, mRadius);
+ path.quadTo(0, 0, mRadius, 0);
+
+ canvas.clipPath(path);
+ }
+ try {
+ super.onDraw(canvas);
+ } catch (Exception e) {
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ refreshImage();
+ }
+
+ private int screenWidth, screenHeight;
+
+ private void refreshImage() {
+ if (screenWidth != getMeasuredWidth() || screenHeight != getMeasuredHeight()) {
+ screenWidth = getMeasuredWidth();
+ screenHeight = getMeasuredHeight();
+ doScreenshotActivityAndZoom();
+ }
+ }
+
+ private void doScreenshotActivityAndZoom() {
+ if (BaseDialog.getRootFrameLayout() == null) return;
+ final View view = BaseDialog.getRootFrameLayout().getChildAt(0);
+ //先执行一次绘制,防止出现闪屏问题
+ drawViewImage(view);
+ view.post(new Runnable() {
+ @Override
+ public void run() {
+ //当view渲染完成后再次通知刷新一下界面(当旋转屏幕执行时,很可能出现渲染延迟的问题)
+ drawViewImage(view);
+ }
+ });
+ }
+
+ private void drawViewImage(View view) {
+ view.destroyDrawingCache();
+ view.setDrawingCacheEnabled(true);
+ view.buildDrawingCache();
+ Bitmap bmp = view.getDrawingCache();
+ setImageBitmap(bmp);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/BlurView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/BlurView.java
new file mode 100644
index 0000000..993fa13
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/BlurView.java
@@ -0,0 +1,455 @@
+package com.kongzue.dialogx.util.views;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.ViewTreeObserver;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.Nullable;
+import androidx.renderscript.Allocation;
+import androidx.renderscript.Element;
+import androidx.renderscript.RenderScript;
+import androidx.renderscript.ScriptIntrinsicBlur;
+
+import com.kongzue.dialogx.DialogX;
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.interfaces.BaseDialog;
+
+public class BlurView extends View {
+ private float mDownsampleFactor = 4;
+ private int mOverlayColor = Color.WHITE;
+ private float mBlurRadius = 35;
+
+ private float mRadius = 0;
+ private Path mBoundPath = null;
+
+ private boolean mDirty;
+ private Bitmap mBitmapToBlur, mBlurredBitmap;
+ private Canvas mBlurringCanvas;
+ private RenderScript mRenderScript;
+ private ScriptIntrinsicBlur mBlurScript;
+ private Allocation mBlurInput, mBlurOutput;
+ private boolean mIsRendering;
+ private final Rect mRectSrc = new Rect(), mRectDst = new Rect();
+ // mDecorView should be the root view of the activity (even if you are on a different window like a dialog)
+ private View mDecorView;
+ // If the view is on different root view (usually means we are on a PopupWindow),
+ // we need to manually call invalidate() in onPreDraw(), otherwise we will not be able to see the changes
+ private boolean mDifferentRoot;
+ private static int RENDERING_COUNT;
+
+ private Paint mPaint;
+ private RectF mRectF;
+
+ private Bitmap mRoundBitmap;
+ private Canvas mTmpCanvas;
+
+ public BlurView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ init(context, attrs);
+ }
+
+ public BlurView(Context context) {
+ super(context);
+
+ init(context, null);
+ }
+
+ public BlurView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ init(context, attrs);
+ }
+
+ public BlurView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ init(context, attrs);
+ }
+
+ private boolean isInit = false;
+
+ private void init(Context context, AttributeSet attrs) {
+ if (!isInit) {
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RealtimeBlurView);
+ mBlurRadius = a.getDimension(
+ R.styleable.RealtimeBlurView_realtimeBlurRadius,
+ TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 35, context.getResources().getDisplayMetrics())
+ );
+ mDownsampleFactor = a.getFloat(R.styleable.RealtimeBlurView_realtimeDownsampleFactor, 4);
+ mOverlayColor = a.getColor(R.styleable.RealtimeBlurView_realtimeOverlayColor, 0x00ffffff);
+
+ //ready rounded corner
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mRectF = new RectF();
+
+ mRadius = a.getDimension(R.styleable.RealtimeBlurView_radius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, context.getResources().getDisplayMetrics()));
+ a.recycle();
+
+ isInit = true;
+ }
+ }
+
+ public void setBlurRadius(float radius) {
+ if (mBlurRadius != radius) {
+ mBlurRadius = radius;
+ mDirty = true;
+ invalidate();
+ }
+ }
+
+ public void setRadiusPx(float r) {
+ if (mRadius != r) {
+ mRadius = r;
+ mDirty = true;
+ invalidate();
+ }
+ }
+
+ public void setDownsampleFactor(float factor) {
+ if (factor <= 0) {
+ throw new IllegalArgumentException("Downsample factor must be greater than 0.");
+ }
+
+ if (mDownsampleFactor != factor) {
+ mDownsampleFactor = factor;
+ mDirty = true; // may also change blur radius
+ releaseBitmap();
+ invalidate();
+ }
+ }
+
+ public void setOverlayColor(int color) {
+ if (mOverlayColor != color) {
+ mOverlayColor = color;
+ invalidate();
+ }
+ }
+
+ private void releaseBitmap() {
+ if (mBlurInput != null) {
+ mBlurInput.destroy();
+ mBlurInput = null;
+ }
+ if (mBlurOutput != null) {
+ mBlurOutput.destroy();
+ mBlurOutput = null;
+ }
+ if (mBitmapToBlur != null) {
+ mBitmapToBlur.recycle();
+ mBitmapToBlur = null;
+ }
+ if (mBlurredBitmap != null) {
+ mBlurredBitmap.recycle();
+ mBlurredBitmap = null;
+ }
+ }
+
+ private void releaseScript() {
+ if (mRenderScript != null) {
+ mRenderScript.destroy();
+ mRenderScript = null;
+ }
+ if (mBlurScript != null) {
+ mBlurScript.destroy();
+ mBlurScript = null;
+ }
+ }
+
+ protected void release() {
+ log("release");
+ releaseBitmap();
+ releaseScript();
+ }
+
+ protected boolean prepare() {
+ if (mBlurRadius == 0) {
+ release();
+ return false;
+ }
+
+ float downsampleFactor = mDownsampleFactor;
+
+ if (mDirty || mRenderScript == null) {
+ if (supportRenderScript && useBlur) {
+ if (mRenderScript == null) {
+ try {
+ mRenderScript = RenderScript.create(getContext());
+ mBlurScript = ScriptIntrinsicBlur.create(mRenderScript, Element.U8_4(mRenderScript));
+
+ } catch (Exception e) {
+ if (isDebug()) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ mDirty = false;
+ float radius = mBlurRadius / downsampleFactor;
+ if (radius > 25) {
+ downsampleFactor = downsampleFactor * radius / 25;
+ radius = 25;
+ }
+ if (mBlurScript != null) mBlurScript.setRadius(radius);
+ }
+ }
+
+ final int width = getWidth();
+ final int height = getHeight();
+
+ int scaledWidth = Math.max(1, (int) (width / downsampleFactor));
+ int scaledHeight = Math.max(1, (int) (height / downsampleFactor));
+
+ if (mBlurringCanvas == null || mBlurredBitmap == null || mBlurredBitmap.getWidth() != scaledWidth || mBlurredBitmap.getHeight() != scaledHeight) {
+ releaseBitmap();
+
+ boolean r = false;
+ try {
+ mBitmapToBlur = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888);
+ if (mBitmapToBlur == null) {
+ return false;
+ }
+ mBlurringCanvas = new Canvas(mBitmapToBlur);
+
+ if (!supportRenderScript || !useBlur) {
+ return true;
+ }
+
+ mBlurInput = Allocation.createFromBitmap(mRenderScript, mBitmapToBlur,
+ Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT
+ );
+ mBlurOutput = Allocation.createTyped(mRenderScript, mBlurInput.getType());
+
+ mBlurredBitmap = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888);
+ if (mBlurredBitmap == null) {
+ return false;
+ }
+
+ r = true;
+ } catch (Exception e) {
+ if (isDebug()) e.printStackTrace();
+ } finally {
+ if (!r) {
+ releaseBitmap();
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ protected void blur(Bitmap bitmapToBlur, Bitmap blurredBitmap) {
+ mBlurInput.copyFrom(bitmapToBlur);
+ mBlurScript.setInput(mBlurInput);
+ mBlurScript.forEach(mBlurOutput);
+ mBlurOutput.copyTo(blurredBitmap);
+ }
+
+ private final ViewTreeObserver.OnPreDrawListener preDrawListener = new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ final int[] locations = new int[2];
+ Bitmap oldBmp = mBlurredBitmap;
+ View decor = mDecorView;
+ if (decor != null && isShown() && prepare()) {
+ boolean redrawBitmap = mBlurredBitmap != oldBmp;
+ oldBmp = null;
+ decor.getLocationOnScreen(locations);
+ int x = -locations[0];
+ int y = -locations[1];
+
+ getLocationOnScreen(locations);
+ x += locations[0];
+ y += locations[1];
+
+ // just erase transparent
+ mBitmapToBlur.eraseColor(mOverlayColor & 0xffffff);
+
+ int rc = mBlurringCanvas.save();
+ mIsRendering = true;
+ RENDERING_COUNT++;
+ try {
+ mBlurringCanvas.scale(1.f * mBitmapToBlur.getWidth() / getWidth(), 1.f * mBitmapToBlur.getHeight() / getHeight());
+ mBlurringCanvas.translate(-x, -y);
+ if (decor.getBackground() != null) {
+ decor.getBackground().draw(mBlurringCanvas);
+ }
+ decor.draw(mBlurringCanvas);
+ } catch (Exception e) {
+ if (isDebug()) e.printStackTrace();
+ } finally {
+ mIsRendering = false;
+ RENDERING_COUNT--;
+ mBlurringCanvas.restoreToCount(rc);
+ }
+
+ blur(mBitmapToBlur, mBlurredBitmap);
+
+ if (redrawBitmap || mDifferentRoot) {
+ invalidate();
+ }
+ }
+
+ return true;
+ }
+ };
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ if (BaseDialog.getRootFrameLayout() != null && BaseDialog.getRootFrameLayout().getChildCount() >= 1) {
+ mDecorView = BaseDialog.getRootFrameLayout().getChildAt(0);
+ }
+ if (mDecorView != null) {
+ log("mDecorView is ok.");
+ mDecorView.getViewTreeObserver().addOnPreDrawListener(preDrawListener);
+ mDifferentRoot = mDecorView.getRootView() != getRootView();
+ if (mDifferentRoot) {
+ mDecorView.postInvalidate();
+ }
+ } else {
+ log("mDecorView is NULL.");
+ mDifferentRoot = false;
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ if (mDecorView != null) {
+ mDecorView.getViewTreeObserver().removeOnPreDrawListener(preDrawListener);
+ }
+ release();
+ super.onDetachedFromWindow();
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ if (!useBlur) {
+ Paint cutPaint = new Paint();
+ cutPaint.setAntiAlias(true);
+ cutPaint.setColor(mOverlayColor);
+ mRectF.right = getWidth();
+ mRectF.bottom = getHeight();
+ canvas.drawRoundRect(mRectF, mRadius, mRadius, cutPaint);
+ } else {
+ if (mIsRendering) {
+ // Quit here, don't draw views above me
+ //throw STOP_EXCEPTION;
+ } else if (RENDERING_COUNT > 0) {
+ // Doesn't support blurview overlap on another blurview
+ } else {
+ if (mRadius != 0) {
+ Rect rect = new Rect();
+ getLocalVisibleRect(rect);
+ rect.right = rect.left + getWidth();
+ rect.bottom = rect.top + getHeight();
+ mBoundPath = caculateRoundRectPath(rect);
+ canvas.clipPath(mBoundPath);
+ }
+ super.draw(canvas);
+ }
+ }
+ }
+
+ private Path caculateRoundRectPath(Rect r) {
+ Path path = new Path();
+ float radius = mRadius;
+ float elevation = 0;
+ path.addRoundRect(new RectF(r.left + elevation, r.top + elevation, r.right - elevation, r.bottom - elevation), radius, radius, Path.Direction.CW);
+ return path;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ drawBlurredBitmap(canvas, mBlurredBitmap, mOverlayColor);
+ }
+
+ /**
+ * Custom draw the blurred bitmap and color to define your own shape
+ *
+ * @param canvas
+ * @param blurredBitmap
+ * @param overlayColor
+ */
+ protected void drawBlurredBitmap(Canvas canvas, Bitmap blurredBitmap, int overlayColor) {
+ if (blurredBitmap != null) {
+ mRectSrc.right = blurredBitmap.getWidth();
+ mRectSrc.bottom = blurredBitmap.getHeight();
+ mRectDst.right = getWidth();
+ mRectDst.bottom = getHeight();
+ canvas.drawBitmap(blurredBitmap, mRectSrc, mRectDst, null);
+ }
+ canvas.drawColor((supportRenderScript && useBlur) ? overlayColor : removeAlphaColor(overlayColor));
+ }
+
+ private static boolean supportRenderScript = false;
+ private boolean useBlur = true;
+
+ public boolean isUseBlur() {
+ return useBlur;
+ }
+
+ public BlurView setUseBlur(boolean useBlur) {
+ this.useBlur = useBlur;
+ invalidate();
+ return this;
+ }
+
+ private static int removeAlphaColor(@ColorInt int color) {
+ int alpha = 255;
+ int red = Color.red(color);
+ int green = Color.green(color);
+ int blue = Color.blue(color);
+ return Color.argb(alpha, red, green, blue);
+ }
+
+ static {
+ /**
+ * 之所以需要启动一个新线程检测RenderScript是否可用的原因是不清楚Android什么时候对loadClass做了变更,
+ * 会直接抛出NoClassDefFoundError无法拦截,在主线程检测会导致程序直接闪退,因此改为异步检测。
+ * 检测后会给定(boolean)supportRenderScript用于判断时光支持
+ */
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ BlurView.class.getClassLoader().loadClass(RenderScript.class.getCanonicalName());
+ supportRenderScript = true;
+ } catch (Throwable e) {
+ if (isDebug()) {
+ e.printStackTrace();
+ }
+ supportRenderScript = false;
+ }
+ }
+ }.start();
+ }
+
+ public static boolean DEBUGMODE = false;
+
+ static boolean isDebug() {
+ return DEBUGMODE && DialogX.DEBUGMODE;
+ }
+
+ public static void log(Object o) {
+ if (isDebug()) Log.i(">>>", o.toString());
+ }
+
+ public static void error(Object o) {
+ if (isDebug()) Log.e(">>>", o.toString());
+ }
+}
\ No newline at end of file
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogListView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogListView.java
new file mode 100644
index 0000000..c4ce2a5
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogListView.java
@@ -0,0 +1,115 @@
+package com.kongzue.dialogx.util.views;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.ScrollView;
+
+import androidx.annotation.RequiresApi;
+
+import com.kongzue.dialogx.dialogs.BottomDialog;
+import com.kongzue.dialogx.interfaces.BottomMenuListViewTouchEvent;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/10/6 23:42
+ */
+public class BottomDialogListView extends ListView {
+
+ private BottomMenuListViewTouchEvent bottomMenuListViewTouchEvent;
+
+ public BottomDialogListView(Context context) {
+ super(context);
+ }
+
+ public BottomDialogListView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public BottomDialogListView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ private BottomDialog.DialogImpl dialogImpl;
+
+ public BottomDialogListView(BottomDialog.DialogImpl dialog, Context context) {
+ super(context);
+ dialogImpl = dialog;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
+ super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(dip2px(55)*size+size, MeasureSpec.EXACTLY));
+
+ //super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(expandSpec, MeasureSpec.AT_MOST));
+ }
+
+ private int dip2px(float dpValue) {
+ final float scale = Resources.getSystem().getDisplayMetrics().density;
+ return (int) (dpValue * scale + 0.5f);
+ }
+
+ private int mPosition;
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK;
+
+ if (actionMasked == MotionEvent.ACTION_DOWN) {
+ if (bottomMenuListViewTouchEvent != null) {
+ bottomMenuListViewTouchEvent.down(ev);
+ }
+ mPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
+ return super.dispatchTouchEvent(ev);
+ }
+
+ if (actionMasked == MotionEvent.ACTION_MOVE) {
+ if (bottomMenuListViewTouchEvent != null) {
+ bottomMenuListViewTouchEvent.move(ev);
+ }
+ return true;
+ }
+ if (actionMasked == MotionEvent.ACTION_UP || actionMasked == MotionEvent.ACTION_CANCEL) {
+ if (bottomMenuListViewTouchEvent != null) {
+ bottomMenuListViewTouchEvent.up(ev);
+ }
+ if (pointToPosition((int) ev.getX(), (int) ev.getY()) == mPosition) {
+ super.dispatchTouchEvent(ev);
+ } else {
+ setPressed(false);
+ invalidate();
+ }
+ }
+
+ return super.dispatchTouchEvent(ev);
+ }
+
+ public BottomMenuListViewTouchEvent getBottomMenuListViewTouchEvent() {
+ return bottomMenuListViewTouchEvent;
+ }
+
+ private int size =1;
+
+ @Override
+ public void setAdapter(ListAdapter adapter) {
+ size = adapter.getCount();
+ super.setAdapter(adapter);
+ }
+
+ public BottomDialogListView setBottomMenuListViewTouchEvent(BottomMenuListViewTouchEvent bottomMenuListViewTouchEvent) {
+ this.bottomMenuListViewTouchEvent = bottomMenuListViewTouchEvent;
+ return this;
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogScrollView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogScrollView.java
new file mode 100644
index 0000000..c684407
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogScrollView.java
@@ -0,0 +1,55 @@
+package com.kongzue.dialogx.util.views;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.widget.ScrollView;
+
+import com.kongzue.dialogx.dialogs.BottomDialog;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/11/17 15:29
+ */
+public class BottomDialogScrollView extends ScrollView {
+
+ public BottomDialogScrollView(Context context) {
+ super(context);
+ }
+
+ public BottomDialogScrollView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public BottomDialogScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public BottomDialogScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ boolean lockScroll;
+
+ public void lockScroll(boolean lockScroll) {
+ this.lockScroll = lockScroll;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (lockScroll) {
+ return false;
+ }
+ return super.onTouchEvent(ev);
+ }
+
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ return super.dispatchTouchEvent(ev);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/DialogXBaseRelativeLayout.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/DialogXBaseRelativeLayout.java
new file mode 100644
index 0000000..1be6476
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/DialogXBaseRelativeLayout.java
@@ -0,0 +1,244 @@
+package com.kongzue.dialogx.util.views;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewParent;
+import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.RelativeLayout;
+
+import androidx.core.view.ViewCompat;
+
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.interfaces.BaseDialog;
+import com.kongzue.dialogx.interfaces.OnBackPressedListener;
+import com.kongzue.dialogx.interfaces.OnSafeInsetsChangeListener;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/9/22 13:53
+ */
+public class DialogXBaseRelativeLayout extends RelativeLayout {
+
+ private OnSafeInsetsChangeListener onSafeInsetsChangeListener;
+ private BaseDialog parentDialog;
+ private boolean autoUnsafePlacePadding = true;
+ private boolean focusable = true;
+
+ private OnLifecycleCallBack onLifecycleCallBack;
+ private OnBackPressedListener onBackPressedListener;
+
+ public DialogXBaseRelativeLayout(Context context) {
+ super(context);
+ init(null);
+ }
+
+ public DialogXBaseRelativeLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(attrs);
+ }
+
+ public DialogXBaseRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(attrs);
+ }
+
+ public DialogXBaseRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init(attrs);
+ }
+
+ private boolean isInited = false;
+
+ private void init(AttributeSet attrs) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ setForceDarkAllowed(false);
+ }
+ if (!isInited ) {
+ if (attrs != null) {
+ TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DialogXBaseRelativeLayout);
+ focusable = a.getBoolean(R.styleable.DialogXBaseRelativeLayout_baseFocusable, true);
+ a.recycle();
+ }
+ if (focusable) {
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ requestFocus();
+ }
+ }
+ }
+
+ @Override
+ protected boolean fitSystemWindows(Rect insets) {
+ paddingView(insets.left, insets.top, insets.right, insets.bottom);
+ return super.fitSystemWindows(insets);
+ }
+
+ @Override
+ public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ paddingView(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
+ }
+ return super.dispatchApplyWindowInsets(insets);
+ }
+
+ public void paddingView(WindowInsets insets) {
+ if (insets == null) return;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ paddingView(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
+ }
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ if (isAttachedToWindow() && event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+ if (onBackPressedListener != null) {
+ onBackPressedListener.onBackPressed();
+ }
+ return true;
+ }
+ return super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+ return super.onTouchEvent(event);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ final ViewParent parent = getParent();
+
+ if (parent instanceof View)ViewCompat.setFitsSystemWindows(this, ViewCompat.getFitsSystemWindows((View) parent));
+ ViewCompat.requestApplyInsets(this);
+
+ if (BaseDialog.getContext() == null) return;
+ if (!isInEditMode()) {
+ ((Activity) BaseDialog.getContext()).getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(decorViewLayoutListener);
+ }
+
+ if (onLifecycleCallBack != null) {
+ onLifecycleCallBack.onShow();
+ }
+ }
+
+ private ViewTreeObserver.OnGlobalLayoutListener decorViewLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ paddingView(getRootWindowInsets());
+ } else {
+ if (BaseDialog.getContext() == null) return;
+ DisplayMetrics displayMetrics = new DisplayMetrics();
+ ((Activity) BaseDialog.getContext()).getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics);
+ Rect rect = new Rect();
+ ((Activity) BaseDialog.getContext()).getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
+ paddingView(rect.left, rect.top, displayMetrics.widthPixels - rect.right, displayMetrics.heightPixels - rect.bottom);
+ }
+ }
+ };
+
+ @Override
+ protected void onDetachedFromWindow() {
+ if (decorViewLayoutListener != null && ((Activity) BaseDialog.getContext()) != null) {
+ ((Activity) BaseDialog.getContext()).getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(decorViewLayoutListener);
+ }
+ if (onLifecycleCallBack != null) {
+ onLifecycleCallBack.onDismiss();
+ }
+ super.onDetachedFromWindow();
+ }
+
+ @Override
+ public boolean performClick() {
+ return super.performClick();
+ }
+
+ public DialogXBaseRelativeLayout setOnLifecycleCallBack(OnLifecycleCallBack onLifecycleCallBack) {
+ this.onLifecycleCallBack = onLifecycleCallBack;
+ return this;
+ }
+
+ public float getSafeHeight() {
+ return getMeasuredHeight() - unsafePlace.bottom - unsafePlace.top;
+ }
+
+ public abstract static class OnLifecycleCallBack {
+ public void onShow() {
+ }
+
+ public abstract void onDismiss();
+ }
+
+ protected Rect unsafePlace = new Rect();
+
+ private void paddingView(int left, int top, int right, int bottom) {
+ unsafePlace = new Rect(left, top, right, bottom);
+ if (onSafeInsetsChangeListener != null) onSafeInsetsChangeListener.onChange(unsafePlace);
+ MaxRelativeLayout bkgView = findViewById(R.id.bkg);
+ if (bkgView != null && bkgView.getLayoutParams() instanceof LayoutParams) {
+ LayoutParams bkgLp = (LayoutParams) bkgView.getLayoutParams();
+ if (bkgLp.getRules()[ALIGN_PARENT_BOTTOM] == RelativeLayout.TRUE && isAutoUnsafePlacePadding()) {
+ bkgView.setPadding(0, 0, 0, bottom);
+ setPadding(left, top, right, 0);
+ return;
+ }
+ }
+ if (isAutoUnsafePlacePadding()) setPadding(left, top, right, bottom);
+ }
+
+ public DialogXBaseRelativeLayout setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
+ this.onBackPressedListener = onBackPressedListener;
+ return this;
+ }
+
+ public OnSafeInsetsChangeListener getOnSafeInsetsChangeListener() {
+ return onSafeInsetsChangeListener;
+ }
+
+ public DialogXBaseRelativeLayout setOnSafeInsetsChangeListener(OnSafeInsetsChangeListener onSafeInsetsChangeListener) {
+ this.onSafeInsetsChangeListener = onSafeInsetsChangeListener;
+ return this;
+ }
+
+ public boolean isAutoUnsafePlacePadding() {
+ return autoUnsafePlacePadding;
+ }
+
+ public DialogXBaseRelativeLayout setAutoUnsafePlacePadding(boolean autoUnsafePlacePadding) {
+ this.autoUnsafePlacePadding = autoUnsafePlacePadding;
+ return this;
+ }
+
+ public BaseDialog getParentDialog() {
+ return parentDialog;
+ }
+
+ public DialogXBaseRelativeLayout setParentDialog(BaseDialog parentDialog) {
+ this.parentDialog = parentDialog;
+ return this;
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ getParentDialog().onUIModeChange(newConfig);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/MaxRelativeLayout.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/MaxRelativeLayout.java
new file mode 100644
index 0000000..ecefd1a
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/MaxRelativeLayout.java
@@ -0,0 +1,224 @@
+package com.kongzue.dialogx.util.views;
+
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewParent;
+import android.widget.RelativeLayout;
+import android.widget.ScrollView;
+
+import com.kongzue.dialogx.R;
+
+import static android.view.View.MeasureSpec.EXACTLY;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2019/9/24 17:34
+ */
+public class MaxRelativeLayout extends RelativeLayout {
+
+ private int maxWidth;
+ private int maxHeight;
+ private int minWidth;
+ private int minHeight;
+ private boolean lockWidth;
+ private boolean interceptTouch = true;
+
+ public MaxRelativeLayout(Context context) {
+ super(context);
+ init(context, null);
+ }
+
+ public MaxRelativeLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context, attrs);
+ }
+
+ public MaxRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(context, attrs);
+ }
+
+ private float startAnimValue = 0, endAnimValue = 0;
+
+ private void init(Context context, AttributeSet attrs) {
+ if (attrs != null) {
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaxRelativeLayout);
+ maxWidth = a.getDimensionPixelSize(R.styleable.MaxRelativeLayout_maxLayoutWidth, 0);
+ maxHeight = a.getDimensionPixelSize(R.styleable.MaxRelativeLayout_maxLayoutHeight, 0);
+ lockWidth = a.getBoolean(R.styleable.MaxRelativeLayout_lockWidth, false);
+ interceptTouch = a.getBoolean(R.styleable.MaxRelativeLayout_interceptTouch, true);
+
+ a.recycle();
+ }
+ minWidth = getMinimumWidth();
+ minHeight = getMinimumHeight();
+
+ if (!isInEditMode()) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ animate().setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float progress = (float) animation.getAnimatedValue();
+ long value = (long) (startAnimValue + (endAnimValue - startAnimValue) * progress);
+ if (onYChangedListener != null) onYChangedListener.y(value);
+ }
+ });
+ }
+ }
+ }
+
+ private ScrollView childScrollView;
+
+ public MaxRelativeLayout setMaxHeight(int maxHeight) {
+ this.maxHeight = maxHeight;
+ return this;
+ }
+
+ public MaxRelativeLayout setMaxWidth(int maxWidth) {
+ if (maxWidth > 0 && this.maxWidth != 0) this.maxWidth = maxWidth;
+ return this;
+ }
+
+ private int preWidth = -1;
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+
+ int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+ int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+
+ if (preWidth == -1 && widthSize != 0) {
+ preWidth = widthSize;
+ }
+ if (lockWidth) {
+ maxWidth = Math.min(widthSize, preWidth);
+ }
+ if (maxHeight > 0) {
+ heightSize = Math.min(heightSize, maxHeight);
+ }
+ if (maxWidth > 0) {
+ widthSize = Math.min(widthSize, maxWidth);
+ }
+ View blurView = findViewWithTag("blurView");
+ View contentView = findViewWithoutTag("blurView");
+ if (contentView != null) {
+ int widthTemp = contentView.getMeasuredWidth() == 0 ? getMeasuredWidth() : contentView.getMeasuredWidth();
+ int heightTemp = contentView.getMeasuredHeight() == 0 ? getMeasuredHeight() : contentView.getMeasuredHeight();
+ if (widthTemp < minWidth) widthTemp = minWidth;
+ if (heightTemp < minHeight) heightTemp = minHeight;
+ if (blurView != null) {
+ if (heightMode == EXACTLY){
+ heightTemp = heightSize;
+ }
+ if (widthMode == EXACTLY){
+ widthTemp = widthSize;
+ }
+ LayoutParams lp = (LayoutParams) blurView.getLayoutParams();
+ lp.width = widthTemp;
+ lp.height = heightTemp;
+ blurView.setLayoutParams(lp);
+ }
+ } else {
+ if (blurView != null) {
+ LayoutParams lp = (LayoutParams) blurView.getLayoutParams();
+ lp.width = getMeasuredWidth();
+ lp.height = getMeasuredHeight();
+ blurView.setLayoutParams(lp);
+ }
+ }
+
+ int maxHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
+ int maxWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
+ super.onMeasure(maxWidthMeasureSpec, maxHeightMeasureSpec);
+
+ childScrollView = findViewById(R.id.scrollView);
+ }
+
+ private View findViewWithoutTag(String tag) {
+ for (int i = 0; i < getChildCount(); i++) {
+ if (!tag.equals(getChildAt(i).getTag())) {
+ return getChildAt(i);
+ }
+ }
+ return null;
+ }
+
+ public boolean isChildScrollViewCanScroll() {
+ if (childScrollView == null) return false;
+ if (!childScrollView.isEnabled()) {
+ return false;
+ }
+ View child = childScrollView.getChildAt(0);
+ if (child != null) {
+ int childHeight = child.getHeight();
+ return childScrollView.getHeight() < childHeight;
+ }
+ return false;
+ }
+
+ public int dip2px(float dpValue) {
+ final float scale = getResources().getDisplayMetrics().density;
+ return (int) (dpValue * scale + 0.5f);
+ }
+
+ public boolean isLockWidth() {
+ return lockWidth;
+ }
+
+ public MaxRelativeLayout setLockWidth(boolean lockWidth) {
+ this.lockWidth = lockWidth;
+ return this;
+ }
+
+ private OnYChanged onYChangedListener;
+
+ public interface OnYChanged {
+ void y(float y);
+ }
+
+ @Override
+ public void setY(float y) {
+ super.setY(y);
+ }
+
+ public OnYChanged getOnYChanged() {
+ return onYChangedListener;
+ }
+
+ public MaxRelativeLayout setOnYChanged(OnYChanged onYChanged) {
+ this.onYChangedListener = onYChanged;
+ return this;
+ }
+
+ @Override
+ public void setTranslationY(float translationY) {
+ super.setTranslationY(translationY);
+ if (onYChangedListener != null) onYChangedListener.y(translationY);
+ }
+
+ private OnTouchListener onTouchListener;
+
+ @Override
+ public void setOnTouchListener(OnTouchListener l) {
+ onTouchListener = l;
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ if (onTouchListener != null) {
+ onTouchListener.onTouch(this, ev);
+ }
+ return super.dispatchTouchEvent(ev);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/NoArticulatedProgressView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/NoArticulatedProgressView.java
new file mode 100644
index 0000000..0f767f6
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/NoArticulatedProgressView.java
@@ -0,0 +1,452 @@
+package com.kongzue.dialogx.util.views;
+
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.HapticFeedbackConstants;
+import android.view.View;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
+
+import androidx.annotation.Nullable;
+
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.interfaces.ProgressViewInterface;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2021/3/14 20:58
+ */
+public class NoArticulatedProgressView extends View implements ProgressViewInterface {
+ public static final int STATUS_LOADING = 0;
+ public static final int STATUS_SUCCESS = 1;
+ public static final int STATUS_WARNING = 2;
+ public static final int STATUS_ERROR = 3;
+ public static final int STATUS_PROGRESSING = 4;
+
+ private int status = STATUS_LOADING;
+
+ private int width = dip2px(2);
+ private int color = Color.WHITE;
+
+ public NoArticulatedProgressView(Context context) {
+ super(context);
+ init(null);
+ }
+
+ public NoArticulatedProgressView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ init(attrs);
+ }
+
+ public NoArticulatedProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(attrs);
+ }
+
+ public NoArticulatedProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init(attrs);
+ }
+
+ private ValueAnimator rotateAnimator;
+ private ValueAnimator followAnimator;
+
+ private float currentRotateDegrees;
+ private float followRotateDegrees;
+
+ //跟随点度数做正弦值变化,halfSweepAMinValue为最低相较目标点度数差值,halfSweepAMaxValue为最大相较目标点度数差值
+ private float halfSweepAMaxValue = 180;
+ private float halfSweepAMinValue = 80;
+ //正弦函数的半径
+ private float halfSweepA;
+
+ Paint mPaint = new Paint();
+
+ private boolean isInited = false;
+
+ private void init(AttributeSet attrs) {
+ synchronized (NoArticulatedProgressView.class) {
+ if (isInited) {
+ return;
+ }
+ isInited = true;
+ if (attrs != null) {
+ TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ProgressView);
+ width = a.getDimensionPixelSize(R.styleable.ProgressView_progressStrokeWidth, dip2px(2));
+ color = a.getDimensionPixelSize(R.styleable.ProgressView_progressStrokeColor, color);
+
+ a.recycle();
+ }
+
+ mPaint.setAntiAlias(true);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setStrokeWidth(width);
+ mPaint.setStrokeCap(Paint.Cap.ROUND);
+ mPaint.setColor(color);
+
+ if (!isInEditMode()) {
+ halfSweepA = (halfSweepAMaxValue - halfSweepAMinValue) / 2;
+
+ rotateAnimator = ValueAnimator.ofFloat(0, 365);
+ rotateAnimator.setDuration(1000);
+ rotateAnimator.setInterpolator(new LinearInterpolator());
+ rotateAnimator.setRepeatCount(-1);
+ rotateAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ currentRotateDegrees = (float) animation.getAnimatedValue();
+ invalidate();
+ }
+ });
+
+ followAnimator = ValueAnimator.ofFloat(0, 365);
+ followAnimator.setDuration(1500);
+ followAnimator.setInterpolator(new LinearInterpolator());
+ followAnimator.setRepeatCount(-1);
+ followAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ followRotateDegrees = (float) animation.getAnimatedValue();
+ }
+ });
+
+ followAnimator.start();
+ rotateAnimator.start();
+ }
+ }
+ }
+
+ //旋转圆的中心坐标
+ private float mCenterX;
+ private float mCenterY;
+ //半径
+ private float mRadius = 100;
+ private RectF oval;
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ mCenterX = w * 1f / 2;
+ mCenterY = h * 1f / 2;
+ mRadius = Math.min(getWidth(), getHeight()) / 2 - width / 2;
+ oval = new RectF(mCenterX - mRadius, mCenterY - mRadius, mCenterX + mRadius, mCenterY + mRadius);
+ }
+
+ protected float oldAnimAngle;
+ private int successStep = 0;
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (isInEditMode()) {
+ canvas.drawArc(oval, 0, 365, false, mPaint);
+ return;
+ }
+ if (noShowLoading) {
+ canvas.drawArc(oval, 0, 365, false, mPaint);
+ successStep = 2;
+ drawDoneMark(status, canvas);
+ return;
+ }
+
+ float sweepAngle = (float) (halfSweepA * Math.sin(Math.toRadians(followRotateDegrees))) + halfSweepA + halfSweepAMinValue / 2;
+ switch (status) {
+ case STATUS_LOADING:
+ canvas.drawArc(oval, currentRotateDegrees, -sweepAngle, false, mPaint);
+ break;
+ case STATUS_SUCCESS:
+ case STATUS_WARNING:
+ case STATUS_ERROR:
+ canvas.drawArc(oval, 0, 360, false, mPaint);
+ drawDoneMark(status, canvas);
+ break;
+ case STATUS_PROGRESSING:
+ canvas.drawArc(oval, -90, currentRotateDegrees, false, mPaint);
+ if (waitProgressingRunnable != null) {
+ waitProgressingRunnable.run();
+ waitProgressingRunnable = null;
+ }
+ break;
+ }
+ }
+
+ private void drawDoneMark(int status, Canvas canvas) {
+ if (rotateAnimator.getInterpolator() != interpolator) {
+ rotateAnimator.setInterpolator(interpolator);
+ }
+ if (tickShowRunnable != null) {
+ tickShowRunnable.run();
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ tickShowRunnable = null;
+ }
+ switch (status) {
+ case STATUS_SUCCESS:
+ showSuccessTick(canvas);
+ break;
+ case STATUS_WARNING:
+ showWarningTick(canvas);
+ break;
+ case STATUS_ERROR:
+ showErrorTick(canvas);
+ break;
+ }
+ }
+
+ private int line1X = 0;
+ private int line1Y = 0;
+ private int line2X = 0;
+ private int line2Y = 0;
+
+ private int tickStep = 0;
+
+ //绘制对号
+ private void showSuccessTick(Canvas canvas) {
+ int tickLeftPoint = (int) (mCenterX - mRadius * 1 / 2);
+ int tickTurnLeftPoint = (int) (mCenterX - mRadius / 10);
+ int tickRightPoint = (int) (mRadius * 0.99f);
+ int speed = 2;
+ switch (tickStep) {
+ case 0:
+ if (tickLeftPoint + line1X < tickTurnLeftPoint) {
+ line1X = line1X + speed;
+ line1Y = line1Y + speed;
+ } else {
+ line2X = line1X;
+ line2Y = line1Y;
+ tickStep = 1;
+ }
+ break;
+ case 1:
+ if (line2X < tickRightPoint) {
+ line2X = line2X + 4;
+ line2Y = line2Y - 5;
+ }
+ break;
+ }
+ canvas.drawLine(tickLeftPoint, mCenterY, tickLeftPoint + line1X, mCenterY + line1Y, mPaint);
+ canvas.drawLine(tickLeftPoint + line1X, mCenterY + line1Y, tickLeftPoint + line2X, mCenterY + line2Y, mPaint);
+
+ postInvalidateDelayed(1);
+ }
+
+ //绘制感叹号
+ private void showWarningTick(Canvas canvas) {
+ int tickLeftPoint = (int) mCenterX;
+ int line1StartY = (int) (mCenterY - mRadius * 1 / 2);
+ int line1EndY = (int) (mCenterY + mRadius * 1 / 8);
+ int line2StartY = (int) (mCenterY + mRadius * 3 / 7);
+ int speed = 4;
+ switch (tickStep) {
+ case 0:
+ if (line1Y < line1EndY - line1StartY) {
+ line1Y = line1Y + speed;
+ } else {
+ line1Y = line1EndY - line1StartY;
+ tickStep = 1;
+ }
+ break;
+ case 1:
+ if (line2Y != line2StartY) {
+ canvas.drawLine(tickLeftPoint, line2StartY, tickLeftPoint, line2StartY + 1, mPaint);
+ }
+ break;
+ }
+ canvas.drawLine(tickLeftPoint, line1StartY, tickLeftPoint, line1StartY + line1Y, mPaint);
+ postInvalidateDelayed(tickStep == 1 ? 100 : 1);
+ }
+
+ //绘制错误符号
+ private void showErrorTick(Canvas canvas) {
+ int tickLeftPoint = (int) (mCenterX - mRadius * 4 / 10);
+ int tickRightPoint = (int) (mCenterX + mRadius * 4 / 10);
+ int tickTopPoint = (int) (mCenterY - mRadius * 4 / 10);
+ int speed = 4;
+
+ switch (tickStep) {
+ case 0:
+ if (tickRightPoint - line1X > tickLeftPoint) {
+ line1X = line1X + speed;
+ line1Y = line1Y + speed;
+ } else {
+ tickStep = 1;
+ canvas.drawLine(tickRightPoint, tickTopPoint, tickRightPoint - line1X, tickTopPoint + line1Y, mPaint);
+ postInvalidateDelayed(150);
+ return;
+ }
+ break;
+ case 1:
+ if (tickLeftPoint + line2X < tickRightPoint) {
+ line2X = line2X + speed;
+ line2Y = line2Y + speed;
+ }
+ canvas.drawLine(tickLeftPoint, tickTopPoint, tickLeftPoint + line2X, tickTopPoint + line2Y, mPaint);
+ break;
+ }
+ canvas.drawLine(tickRightPoint, tickTopPoint, tickRightPoint - line1X, tickTopPoint + line1Y, mPaint);
+ postInvalidateDelayed(1);
+ }
+
+ private TimeInterpolator interpolator;
+ private Runnable waitProgressingRunnable;
+
+ public void success() {
+ if (status == STATUS_PROGRESSING) {
+ progress(1f);
+ waitProgressingRunnable = new Runnable() {
+ @Override
+ public void run() {
+ tickStep = 0;
+ successStep = 2;
+ interpolator = new AccelerateDecelerateInterpolator();
+ status = STATUS_SUCCESS;
+ }
+ };
+ return;
+ }
+ tickStep = 0;
+ interpolator = new AccelerateDecelerateInterpolator();
+ status = STATUS_SUCCESS;
+ invalidate();
+ }
+
+ public void warning() {
+ if (status == STATUS_PROGRESSING) {
+ progress(1f);
+ waitProgressingRunnable = new Runnable() {
+ @Override
+ public void run() {
+ tickStep = 0;
+ successStep = 2;
+ interpolator = new DecelerateInterpolator(2);
+ status = STATUS_WARNING;
+ }
+ };
+ return;
+ }
+ tickStep = 0;
+ interpolator = new DecelerateInterpolator(2);
+ status = STATUS_WARNING;
+ invalidate();
+ }
+
+ public void error() {
+ if (status == STATUS_PROGRESSING) {
+ progress(1f);
+ waitProgressingRunnable = new Runnable() {
+ @Override
+ public void run() {
+ tickStep = 0;
+ successStep = 2;
+ interpolator = new DecelerateInterpolator(2);
+ status = STATUS_ERROR;
+ }
+ };
+ return;
+ }
+ tickStep = 0;
+ interpolator = new DecelerateInterpolator(2);
+ status = STATUS_ERROR;
+ invalidate();
+ }
+
+ public void progress(float progress) {
+ if (rotateAnimator != null) rotateAnimator.cancel();
+ if (followAnimator != null) followAnimator.cancel();
+ if (status != STATUS_PROGRESSING) {
+ currentRotateDegrees = 0;
+ }
+ rotateAnimator = ValueAnimator.ofFloat(currentRotateDegrees, 365 * progress);
+ rotateAnimator.setDuration(1000);
+ rotateAnimator.setInterpolator(new DecelerateInterpolator(2));
+ rotateAnimator.setRepeatCount(0);
+ rotateAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ currentRotateDegrees = (float) animation.getAnimatedValue();
+ invalidate();
+ }
+ });
+ rotateAnimator.start();
+ status = STATUS_PROGRESSING;
+ }
+
+ private Runnable tickShowRunnable;
+
+ public NoArticulatedProgressView whenShowTick(Runnable runnable) {
+ tickShowRunnable = runnable;
+ return this;
+ }
+
+ public void loading() {
+ noShowLoading = false;
+ oldAnimAngle = 0;
+ successStep = 0;
+ line1X = 0;
+ line1Y = 0;
+ line2X = 0;
+ line2Y = 0;
+ status = STATUS_LOADING;
+ if (rotateAnimator != null) rotateAnimator.cancel();
+ if (followAnimator != null) followAnimator.cancel();
+ isInited = false;
+ init(null);
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ if (rotateAnimator != null) {
+ rotateAnimator.cancel();
+ }
+ if (followAnimator != null) {
+ followAnimator.cancel();
+ }
+ super.onDetachedFromWindow();
+ }
+
+ public int getStrokeWidth() {
+ return width;
+ }
+
+ public NoArticulatedProgressView setStrokeWidth(int width) {
+ this.width = width;
+ if (mPaint != null) mPaint.setStrokeWidth(width);
+ return this;
+ }
+
+ public int getColor() {
+ return color;
+ }
+
+ public NoArticulatedProgressView setColor(int color) {
+ this.color = color;
+ if (mPaint != null) mPaint.setColor(color);
+ return this;
+ }
+
+ private boolean noShowLoading;
+
+ public void noLoading() {
+ noShowLoading = true;
+ }
+
+ private int dip2px(float dpValue) {
+ final float scale = Resources.getSystem().getDisplayMetrics().density;
+ return (int) (dpValue * scale + 0.5f);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/ProgressView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/ProgressView.java
new file mode 100644
index 0000000..5c88a0a
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/ProgressView.java
@@ -0,0 +1,475 @@
+package com.kongzue.dialogx.util.views;
+
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.HapticFeedbackConstants;
+import android.view.View;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
+
+import androidx.annotation.Nullable;
+
+import com.kongzue.dialogx.DialogX;
+import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.interfaces.ProgressViewInterface;
+
+/**
+ * @author: Kongzue
+ * @github: https://github.com/kongzue/
+ * @homepage: http://kongzue.com/
+ * @mail: myzcxhh@live.cn
+ * @createTime: 2020/9/27 16:16
+ * @license: Apache License 2.0
+ */
+public class ProgressView extends View implements ProgressViewInterface {
+
+ public static final int STATUS_LOADING = 0;
+ public static final int STATUS_SUCCESS = 1;
+ public static final int STATUS_WARNING = 2;
+ public static final int STATUS_ERROR = 3;
+ public static final int STATUS_PROGRESSING = 4;
+
+ private int status = STATUS_LOADING;
+
+ private int width = dip2px(2);
+ private int color = Color.WHITE;
+
+ public ProgressView(Context context) {
+ super(context);
+ init(null);
+ }
+
+ public ProgressView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ init(attrs);
+ }
+
+ public ProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(attrs);
+ }
+
+ public ProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init(attrs);
+ }
+
+ private ValueAnimator rotateAnimator;
+ private ValueAnimator followAnimator;
+
+ private float currentRotateDegrees;
+ private float followRotateDegrees;
+
+ //跟随点度数做正弦值变化,halfSweepAMinValue为最低相较目标点度数差值,halfSweepAMaxValue为最大相较目标点度数差值
+ private float halfSweepAMaxValue = 180;
+ private float halfSweepAMinValue = 80;
+ //正弦函数的半径
+ private float halfSweepA;
+
+ Paint mPaint = new Paint();
+
+ private boolean isInited = false;
+
+ private void init(AttributeSet attrs) {
+ synchronized (ProgressView.class) {
+ if (isInited) {
+ return;
+ }
+ isInited = true;
+ if (attrs != null) {
+ TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ProgressView);
+ width = a.getDimensionPixelSize(R.styleable.ProgressView_progressStrokeWidth, dip2px(2));
+ color = a.getDimensionPixelSize(R.styleable.ProgressView_progressStrokeColor, color);
+
+ a.recycle();
+ }
+
+ mPaint.setAntiAlias(true);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setStrokeWidth(width);
+ mPaint.setStrokeCap(Paint.Cap.ROUND);
+ mPaint.setColor(color);
+
+ if (!isInEditMode()) {
+ halfSweepA = (halfSweepAMaxValue - halfSweepAMinValue) / 2;
+
+ rotateAnimator = ValueAnimator.ofFloat(0, 365);
+ rotateAnimator.setDuration(1000);
+ rotateAnimator.setInterpolator(new LinearInterpolator());
+ rotateAnimator.setRepeatCount(-1);
+ rotateAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ currentRotateDegrees = (float) animation.getAnimatedValue();
+ invalidate();
+ }
+ });
+
+ followAnimator = ValueAnimator.ofFloat(0, 365);
+ followAnimator.setDuration(1500);
+ followAnimator.setInterpolator(new LinearInterpolator());
+ followAnimator.setRepeatCount(-1);
+ followAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ followRotateDegrees = (float) animation.getAnimatedValue();
+ }
+ });
+
+ followAnimator.start();
+ rotateAnimator.start();
+ }
+ }
+ }
+
+ //旋转圆的中心坐标
+ private float mCenterX;
+ private float mCenterY;
+ //半径
+ private float mRadius = 100;
+ private RectF oval;
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ mCenterX = w * 1f / 2;
+ mCenterY = h * 1f / 2;
+ mRadius = Math.min(getWidth(), getHeight()) / 2 - width / 2;
+ oval = new RectF(mCenterX - mRadius, mCenterY - mRadius, mCenterX + mRadius, mCenterY + mRadius);
+ }
+
+ protected float oldAnimAngle;
+ private int successStep = 0;
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (isInEditMode()) {
+ canvas.drawArc(oval, 0, 365, false, mPaint);
+ return;
+ }
+ if (noShowLoading) {
+ canvas.drawArc(oval, 0, 365, false, mPaint);
+ successStep = 2;
+ drawDoneMark(status, canvas);
+ return;
+ }
+
+ float sweepAngle = (float) (halfSweepA * Math.sin(Math.toRadians(followRotateDegrees))) + halfSweepA + halfSweepAMinValue / 2;
+ switch (status) {
+ case STATUS_LOADING:
+ canvas.drawArc(oval, currentRotateDegrees, -sweepAngle, false, mPaint);
+ break;
+ case STATUS_SUCCESS:
+ case STATUS_WARNING:
+ case STATUS_ERROR:
+ switch (successStep) {
+ case 0:
+ canvas.drawArc(oval, currentRotateDegrees, -sweepAngle, false, mPaint);
+ if ((currentRotateDegrees - sweepAngle) > 270) {
+ successStep = 1;
+ }
+ break;
+ case 1:
+ float aimAngle = currentRotateDegrees > 270 ? currentRotateDegrees - 270 : 90 + currentRotateDegrees;
+ canvas.drawArc(oval, 270, aimAngle, false, mPaint);
+ if (oldAnimAngle > aimAngle && oldAnimAngle > 300) {
+ successStep = 2;
+ canvas.drawArc(oval, 0, 360, false, mPaint);
+ break;
+ }
+ oldAnimAngle = aimAngle;
+ break;
+ case 2:
+ canvas.drawArc(oval, 0, 360, false, mPaint);
+ drawDoneMark(status, canvas);
+ break;
+ }
+ break;
+ case STATUS_PROGRESSING:
+ canvas.drawArc(oval, -90, currentRotateDegrees, false, mPaint);
+ if (currentRotateDegrees == 365 && waitProgressingRunnable != null) {
+ waitProgressingRunnable.run();
+ waitProgressingRunnable = null;
+ }
+ break;
+ }
+ }
+
+ private void drawDoneMark(int status, Canvas canvas) {
+ if (rotateAnimator.getInterpolator() != interpolator) {
+ rotateAnimator.setInterpolator(interpolator);
+ }
+ if (tickShowRunnable != null) {
+ tickShowRunnable.run();
+ if (DialogX.useHaptic) performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ tickShowRunnable = null;
+ }
+ switch (status) {
+ case STATUS_SUCCESS:
+ showSuccessTick(canvas);
+ break;
+ case STATUS_WARNING:
+ showWarningTick(canvas);
+ break;
+ case STATUS_ERROR:
+ showErrorTick(canvas);
+ break;
+ }
+ }
+
+ private int line1X = 0;
+ private int line1Y = 0;
+ private int line2X = 0;
+ private int line2Y = 0;
+
+ private int tickStep = 0;
+
+ //绘制对号
+ private void showSuccessTick(Canvas canvas) {
+ int tickLeftPoint = (int) (mCenterX - mRadius * 1 / 2);
+ int tickTurnLeftPoint = (int) (mCenterX - mRadius / 10);
+ int tickRightPoint = (int) (mRadius * 0.99f);
+ int speed = 2;
+ switch (tickStep) {
+ case 0:
+ if (tickLeftPoint + line1X < tickTurnLeftPoint) {
+ line1X = line1X + speed;
+ line1Y = line1Y + speed;
+ } else {
+ line2X = line1X;
+ line2Y = line1Y;
+ tickStep = 1;
+ }
+ break;
+ case 1:
+ if (line2X < tickRightPoint) {
+ line2X = line2X + 4;
+ line2Y = line2Y - 5;
+ }
+ break;
+ }
+ canvas.drawLine(tickLeftPoint, mCenterY, tickLeftPoint + line1X, mCenterY + line1Y, mPaint);
+ canvas.drawLine(tickLeftPoint + line1X, mCenterY + line1Y, tickLeftPoint + line2X, mCenterY + line2Y, mPaint);
+
+ postInvalidateDelayed(1);
+ }
+
+ //绘制感叹号
+ private void showWarningTick(Canvas canvas) {
+ int tickLeftPoint = (int) mCenterX;
+ int line1StartY = (int) (mCenterY - mRadius * 1 / 2);
+ int line1EndY = (int) (mCenterY + mRadius * 1 / 8);
+ int line2StartY = (int) (mCenterY + mRadius * 3 / 7);
+ int speed = 4;
+ switch (tickStep) {
+ case 0:
+ if (line1Y < line1EndY - line1StartY) {
+ line1Y = line1Y + speed;
+ } else {
+ line1Y = line1EndY - line1StartY;
+ tickStep = 1;
+ }
+ break;
+ case 1:
+ if (line2Y != line2StartY) {
+ canvas.drawLine(tickLeftPoint, line2StartY, tickLeftPoint, line2StartY + 1, mPaint);
+ }
+ break;
+ }
+ canvas.drawLine(tickLeftPoint, line1StartY, tickLeftPoint, line1StartY + line1Y, mPaint);
+ postInvalidateDelayed(tickStep == 1 ? 100 : 1);
+ }
+
+ //绘制错误符号
+ private void showErrorTick(Canvas canvas) {
+ int tickLeftPoint = (int) (mCenterX - mRadius * 4 / 10);
+ int tickRightPoint = (int) (mCenterX + mRadius * 4 / 10);
+ int tickTopPoint = (int) (mCenterY - mRadius * 4 / 10);
+ int speed = 4;
+
+ switch (tickStep) {
+ case 0:
+ if (tickRightPoint - line1X > tickLeftPoint) {
+ line1X = line1X + speed;
+ line1Y = line1Y + speed;
+ } else {
+ tickStep = 1;
+ canvas.drawLine(tickRightPoint, tickTopPoint, tickRightPoint - line1X, tickTopPoint + line1Y, mPaint);
+ postInvalidateDelayed(150);
+ return;
+ }
+ break;
+ case 1:
+ if (tickLeftPoint + line2X < tickRightPoint) {
+ line2X = line2X + speed;
+ line2Y = line2Y + speed;
+ }
+ canvas.drawLine(tickLeftPoint, tickTopPoint, tickLeftPoint + line2X, tickTopPoint + line2Y, mPaint);
+ break;
+ }
+ canvas.drawLine(tickRightPoint, tickTopPoint, tickRightPoint - line1X, tickTopPoint + line1Y, mPaint);
+ postInvalidateDelayed(1);
+ }
+
+ private TimeInterpolator interpolator;
+ private Runnable waitProgressingRunnable;
+
+ public void success() {
+ if (status == STATUS_PROGRESSING) {
+ progress(1f);
+ waitProgressingRunnable = new Runnable() {
+ @Override
+ public void run() {
+ tickStep = 0;
+ successStep = 2;
+ interpolator = new AccelerateDecelerateInterpolator();
+ status = STATUS_SUCCESS;
+ }
+ };
+ return;
+ }
+ tickStep = 0;
+ interpolator = new AccelerateDecelerateInterpolator();
+ status = STATUS_SUCCESS;
+ invalidate();
+ }
+
+ public void warning() {
+ if (status == STATUS_PROGRESSING) {
+ progress(1f);
+ waitProgressingRunnable = new Runnable() {
+ @Override
+ public void run() {
+ tickStep = 0;
+ successStep = 2;
+ interpolator = new DecelerateInterpolator(2);
+ status = STATUS_WARNING;
+ }
+ };
+ return;
+ }
+ tickStep = 0;
+ interpolator = new DecelerateInterpolator(2);
+ status = STATUS_WARNING;
+ invalidate();
+ }
+
+ public void error() {
+ if (status == STATUS_PROGRESSING) {
+ progress(1f);
+ waitProgressingRunnable = new Runnable() {
+ @Override
+ public void run() {
+ tickStep = 0;
+ successStep = 2;
+ interpolator = new DecelerateInterpolator(2);
+ status = STATUS_ERROR;
+ }
+ };
+ return;
+ }
+ tickStep = 0;
+ interpolator = new DecelerateInterpolator(2);
+ status = STATUS_ERROR;
+ invalidate();
+ }
+
+ public void progress(float progress) {
+ if (rotateAnimator != null) rotateAnimator.cancel();
+ if (followAnimator != null) followAnimator.cancel();
+ if (status != STATUS_PROGRESSING) {
+ currentRotateDegrees = 0;
+ }
+ rotateAnimator = ValueAnimator.ofFloat(currentRotateDegrees, 365 * progress);
+ rotateAnimator.setDuration(1000);
+ rotateAnimator.setInterpolator(new DecelerateInterpolator(2));
+ rotateAnimator.setRepeatCount(0);
+ rotateAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ currentRotateDegrees = (float) animation.getAnimatedValue();
+ invalidate();
+ }
+ });
+ rotateAnimator.start();
+ status = STATUS_PROGRESSING;
+ }
+
+ private Runnable tickShowRunnable;
+
+ public ProgressView whenShowTick(Runnable runnable) {
+ tickShowRunnable = runnable;
+ return this;
+ }
+
+ public void loading() {
+ noShowLoading = false;
+ oldAnimAngle = 0;
+ successStep = 0;
+ line1X = 0;
+ line1Y = 0;
+ line2X = 0;
+ line2Y = 0;
+ status = STATUS_LOADING;
+ if (rotateAnimator != null) rotateAnimator.cancel();
+ if (followAnimator != null) followAnimator.cancel();
+ isInited = false;
+ init(null);
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ if (rotateAnimator != null) {
+ rotateAnimator.cancel();
+ }
+ if (followAnimator != null) {
+ followAnimator.cancel();
+ }
+ super.onDetachedFromWindow();
+ }
+
+ public int getStrokeWidth() {
+ return width;
+ }
+
+ public ProgressView setStrokeWidth(int width) {
+ this.width = width;
+ if (mPaint != null) mPaint.setStrokeWidth(width);
+ return this;
+ }
+
+ public int getColor() {
+ return color;
+ }
+
+ public ProgressView setColor(int color) {
+ this.color = color;
+ if (mPaint != null) mPaint.setColor(color);
+ return this;
+ }
+
+ private boolean noShowLoading;
+
+ public void noLoading() {
+ noShowLoading = true;
+ }
+
+ private int dip2px(float dpValue) {
+ final float scale = Resources.getSystem().getDisplayMetrics().density;
+ return (int) (dpValue * scale + 0.5f);
+ }
+}
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/RoundView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/RoundView.java
new file mode 100644
index 0000000..c457993
--- /dev/null
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/RoundView.java
@@ -0,0 +1,56 @@
+package com.kongzue.dialogx.util.views;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.widget.RelativeLayout;
+
+public class RoundView extends RelativeLayout {
+
+ private float mRadius = 0;
+ private Path mBoundPath = null;
+
+ public RoundView(Context context) {
+ this(context, null);
+ }
+
+ public RoundView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public RoundView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setWillNotDraw(false);
+ mRadius = 50;
+ }
+
+ public void setRadius(float radius) {
+ if (mRadius == radius)
+ return;
+ this.mRadius = radius;
+ postInvalidate();
+ }
+
+ public float getRadius() {
+ return mRadius;
+ }
+
+ public void draw(Canvas canvas) {
+ Rect rect = new Rect();
+ getLocalVisibleRect(rect);
+ mBoundPath = caculateRoundRectPath(rect);
+ canvas.clipPath(mBoundPath);
+ super.draw(canvas);
+ }
+
+ private Path caculateRoundRectPath(Rect r) {
+ Path path = new Path();
+ float radius = getRadius();
+ float elevation = 0;
+ path.addRoundRect(new RectF(r.left + elevation, r.top + elevation, r.right - elevation, r.bottom - elevation), radius, radius, Path.Direction.CW);
+ return path;
+ }
+}
\ No newline at end of file
diff --git a/DialogX/src/main/res/anim/anim_dialogx_bottom_enter.xml b/DialogX/src/main/res/anim/anim_dialogx_bottom_enter.xml
new file mode 100644
index 0000000..815d566
--- /dev/null
+++ b/DialogX/src/main/res/anim/anim_dialogx_bottom_enter.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/anim/anim_dialogx_bottom_exit.xml b/DialogX/src/main/res/anim/anim_dialogx_bottom_exit.xml
new file mode 100644
index 0000000..d60af3f
--- /dev/null
+++ b/DialogX/src/main/res/anim/anim_dialogx_bottom_exit.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/anim/anim_dialogx_default_alpha_enter.xml b/DialogX/src/main/res/anim/anim_dialogx_default_alpha_enter.xml
new file mode 100644
index 0000000..f42dab9
--- /dev/null
+++ b/DialogX/src/main/res/anim/anim_dialogx_default_alpha_enter.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/anim/anim_dialogx_default_enter.xml b/DialogX/src/main/res/anim/anim_dialogx_default_enter.xml
new file mode 100644
index 0000000..2fb1104
--- /dev/null
+++ b/DialogX/src/main/res/anim/anim_dialogx_default_enter.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/anim/anim_dialogx_default_exit.xml b/DialogX/src/main/res/anim/anim_dialogx_default_exit.xml
new file mode 100644
index 0000000..1709be3
--- /dev/null
+++ b/DialogX/src/main/res/anim/anim_dialogx_default_exit.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/anim/anim_dialogx_left_enter.xml b/DialogX/src/main/res/anim/anim_dialogx_left_enter.xml
new file mode 100644
index 0000000..d3b1c6a
--- /dev/null
+++ b/DialogX/src/main/res/anim/anim_dialogx_left_enter.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/anim/anim_dialogx_left_exit.xml b/DialogX/src/main/res/anim/anim_dialogx_left_exit.xml
new file mode 100644
index 0000000..60fe2ab
--- /dev/null
+++ b/DialogX/src/main/res/anim/anim_dialogx_left_exit.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/anim/anim_dialogx_right_enter.xml b/DialogX/src/main/res/anim/anim_dialogx_right_enter.xml
new file mode 100644
index 0000000..3746a76
--- /dev/null
+++ b/DialogX/src/main/res/anim/anim_dialogx_right_enter.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/anim/anim_dialogx_right_exit.xml b/DialogX/src/main/res/anim/anim_dialogx_right_exit.xml
new file mode 100644
index 0000000..be93c12
--- /dev/null
+++ b/DialogX/src/main/res/anim/anim_dialogx_right_exit.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/anim/anim_dialogx_top_enter.xml b/DialogX/src/main/res/anim/anim_dialogx_top_enter.xml
new file mode 100644
index 0000000..95efebb
--- /dev/null
+++ b/DialogX/src/main/res/anim/anim_dialogx_top_enter.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/anim/anim_dialogx_top_exit.xml b/DialogX/src/main/res/anim/anim_dialogx_top_exit.xml
new file mode 100644
index 0000000..771dbfa
--- /dev/null
+++ b/DialogX/src/main/res/anim/anim_dialogx_top_exit.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/drawable/button_dialogx_material_light.xml b/DialogX/src/main/res/drawable/button_dialogx_material_light.xml
new file mode 100644
index 0000000..65e5908
--- /dev/null
+++ b/DialogX/src/main/res/drawable/button_dialogx_material_light.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/drawable/button_dialogx_material_night.xml b/DialogX/src/main/res/drawable/button_dialogx_material_night.xml
new file mode 100644
index 0000000..e2f8fb7
--- /dev/null
+++ b/DialogX/src/main/res/drawable/button_dialogx_material_night.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_light.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_light.xml
new file mode 100644
index 0000000..505db92
--- /dev/null
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_light.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_night.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_night.xml
new file mode 100644
index 0000000..a90496c
--- /dev/null
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_night.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_light.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_light.xml
new file mode 100644
index 0000000..e500950
--- /dev/null
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_light.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_night.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_night.xml
new file mode 100644
index 0000000..edc0eaf
--- /dev/null
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_night.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_button_light_forword.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_button_light_forword.xml
new file mode 100644
index 0000000..261c420
--- /dev/null
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_button_light_forword.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_button_night_forword.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_button_night_forword.xml
new file mode 100644
index 0000000..518437f
--- /dev/null
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_button_night_forword.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap.xml
new file mode 100644
index 0000000..07c0254
--- /dev/null
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap_night.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap_night.xml
new file mode 100644
index 0000000..d41f3a9
--- /dev/null
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap_night.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_menu_split_divider.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_menu_split_divider.xml
new file mode 100644
index 0000000..aa97988
--- /dev/null
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_menu_split_divider.xml
@@ -0,0 +1,12 @@
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_menu_split_divider_night.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_menu_split_divider_night.xml
new file mode 100644
index 0000000..29b7e21
--- /dev/null
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_menu_split_divider_night.xml
@@ -0,0 +1,12 @@
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_poptip_bkg.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_poptip_bkg.xml
new file mode 100644
index 0000000..db95930
--- /dev/null
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_poptip_bkg.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_poptip_bkg_night.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_poptip_bkg_night.xml
new file mode 100644
index 0000000..e367970
--- /dev/null
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_poptip_bkg_night.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/DialogX/src/main/res/layout/item_dialogx_material_bottom_menu_normal_text.xml b/DialogX/src/main/res/layout/item_dialogx_material_bottom_menu_normal_text.xml
new file mode 100644
index 0000000..70a7bb9
--- /dev/null
+++ b/DialogX/src/main/res/layout/item_dialogx_material_bottom_menu_normal_text.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/layout/layout_dialogx_bottom_material.xml b/DialogX/src/main/res/layout/layout_dialogx_bottom_material.xml
new file mode 100644
index 0000000..3649d43
--- /dev/null
+++ b/DialogX/src/main/res/layout/layout_dialogx_bottom_material.xml
@@ -0,0 +1,161 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/layout/layout_dialogx_bottom_material_dark.xml b/DialogX/src/main/res/layout/layout_dialogx_bottom_material_dark.xml
new file mode 100644
index 0000000..59311e6
--- /dev/null
+++ b/DialogX/src/main/res/layout/layout_dialogx_bottom_material_dark.xml
@@ -0,0 +1,161 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/layout/layout_dialogx_custom.xml b/DialogX/src/main/res/layout/layout_dialogx_custom.xml
new file mode 100644
index 0000000..1ab3f6b
--- /dev/null
+++ b/DialogX/src/main/res/layout/layout_dialogx_custom.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/layout/layout_dialogx_fullscreen.xml b/DialogX/src/main/res/layout/layout_dialogx_fullscreen.xml
new file mode 100644
index 0000000..02ed5f4
--- /dev/null
+++ b/DialogX/src/main/res/layout/layout_dialogx_fullscreen.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DialogX/src/main/res/layout/layout_dialogx_fullscreen_dark.xml b/DialogX/src/main/res/layout/layout_dialogx_fullscreen_dark.xml
new file mode 100644
index 0000000..4632192
--- /dev/null
+++ b/DialogX/src/main/res/layout/layout_dialogx_fullscreen_dark.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DialogX/src/main/res/layout/layout_dialogx_material.xml b/DialogX/src/main/res/layout/layout_dialogx_material.xml
new file mode 100644
index 0000000..941364b
--- /dev/null
+++ b/DialogX/src/main/res/layout/layout_dialogx_material.xml
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/layout/layout_dialogx_material_dark.xml b/DialogX/src/main/res/layout/layout_dialogx_material_dark.xml
new file mode 100644
index 0000000..f3674c7
--- /dev/null
+++ b/DialogX/src/main/res/layout/layout_dialogx_material_dark.xml
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/layout/layout_dialogx_poptip_material.xml b/DialogX/src/main/res/layout/layout_dialogx_poptip_material.xml
new file mode 100644
index 0000000..42fcdab
--- /dev/null
+++ b/DialogX/src/main/res/layout/layout_dialogx_poptip_material.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/layout/layout_dialogx_poptip_material_dark.xml b/DialogX/src/main/res/layout/layout_dialogx_poptip_material_dark.xml
new file mode 100644
index 0000000..d2619a8
--- /dev/null
+++ b/DialogX/src/main/res/layout/layout_dialogx_poptip_material_dark.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/layout/layout_dialogx_wait.xml b/DialogX/src/main/res/layout/layout_dialogx_wait.xml
new file mode 100644
index 0000000..7b4319d
--- /dev/null
+++ b/DialogX/src/main/res/layout/layout_dialogx_wait.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/mipmap-xxhdpi/img_dialogx_bottom_menu_material_item_multi_selection.png b/DialogX/src/main/res/mipmap-xxhdpi/img_dialogx_bottom_menu_material_item_multi_selection.png
new file mode 100644
index 0000000..feebea1
Binary files /dev/null and b/DialogX/src/main/res/mipmap-xxhdpi/img_dialogx_bottom_menu_material_item_multi_selection.png differ
diff --git a/DialogX/src/main/res/mipmap-xxhdpi/img_dialogx_bottom_menu_material_item_non_multi_select.png b/DialogX/src/main/res/mipmap-xxhdpi/img_dialogx_bottom_menu_material_item_non_multi_select.png
new file mode 100644
index 0000000..2b23ee6
Binary files /dev/null and b/DialogX/src/main/res/mipmap-xxhdpi/img_dialogx_bottom_menu_material_item_non_multi_select.png differ
diff --git a/DialogX/src/main/res/mipmap-xxhdpi/img_dialogx_bottom_menu_material_item_non_select.png b/DialogX/src/main/res/mipmap-xxhdpi/img_dialogx_bottom_menu_material_item_non_select.png
new file mode 100644
index 0000000..005c878
Binary files /dev/null and b/DialogX/src/main/res/mipmap-xxhdpi/img_dialogx_bottom_menu_material_item_non_select.png differ
diff --git a/DialogX/src/main/res/mipmap-xxhdpi/img_dialogx_bottom_menu_material_item_selection.png b/DialogX/src/main/res/mipmap-xxhdpi/img_dialogx_bottom_menu_material_item_selection.png
new file mode 100644
index 0000000..fd1d9d6
Binary files /dev/null and b/DialogX/src/main/res/mipmap-xxhdpi/img_dialogx_bottom_menu_material_item_selection.png differ
diff --git a/DialogX/src/main/res/values/attrs.xml b/DialogX/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..f5aa743
--- /dev/null
+++ b/DialogX/src/main/res/values/attrs.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/values/colors.xml b/DialogX/src/main/res/values/colors.xml
new file mode 100644
index 0000000..dd3c440
--- /dev/null
+++ b/DialogX/src/main/res/values/colors.xml
@@ -0,0 +1,40 @@
+
+
+ #2196F3
+
+ #353535
+ #000
+ #E6000000
+ #CC000000
+ #BF000000
+ #B3000000
+ #99000000
+ #80000000
+ #66000000
+ #4D000000
+ #40000000
+ #33000000
+ #1A000000
+ #00000000
+
+ #fff
+ #E6ffffff
+ #CCffffff
+ #BFffffff
+ #B3ffffff
+ #99ffffff
+ #80ffffff
+ #66ffffff
+ #4Dffffff
+ #40ffffff
+ #33ffffff
+ #1Affffff
+
+ #2196F3
+
+ #343434
+ #F5F6F7
+ #232323
+
+ #86B3D6
+
\ No newline at end of file
diff --git a/DialogX/src/main/res/values/styles.xml b/DialogX/src/main/res/values/styles.xml
new file mode 100644
index 0000000..a70d270
--- /dev/null
+++ b/DialogX/src/main/res/values/styles.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index fefb304..e38170f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -99,7 +99,11 @@ android {
}
productFlavors {
}
-
+ packagingOptions {
+ // pickFirsts:当出现重复文件,会使用第一个匹配的文件打包进入apk
+ pickFirst 'lib/*/libRSSupport.so'
+ pickFirst 'lib/*/librsjni.so'
+ }
}
@@ -112,6 +116,7 @@ repositories {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation fileTree(include: ['*.jar'], dir: 'libs')
+ implementation project(path: ':DialogX')
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
diff --git a/app/src/main/java/xyz/fycz/myreader/application/App.java b/app/src/main/java/xyz/fycz/myreader/application/App.java
index 39ddf12..6a78c00 100644
--- a/app/src/main/java/xyz/fycz/myreader/application/App.java
+++ b/app/src/main/java/xyz/fycz/myreader/application/App.java
@@ -25,6 +25,7 @@ import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
+import com.kongzue.dialogx.DialogX;
import com.liulishuo.filedownloader.FileDownloader;
import com.liulishuo.filedownloader.connection.FileDownloadUrlConnection;
@@ -97,8 +98,10 @@ public class App extends Application {
mFixedThreadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());//初始化线程池
initNightTheme();
// LLog.init(APPCONST.LOG_DIR);
+ initDialogX();
}
+
private void firstInit() {
SharedPreUtils sru = SharedPreUtils.getInstance();
if (!sru.getBoolean("firstInit")) {
@@ -107,14 +110,22 @@ public class App extends Application {
}
}
+ private void initDialogX() {
+ DialogX.init(this);
+ DialogX.DEBUGMODE = debug;
+ }
+
public void initNightTheme() {
if (isNightFS()) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
+ DialogX.globalTheme = DialogX.THEME.AUTO;
} else {
if (isNightTheme()) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
+ DialogX.globalTheme = DialogX.THEME.DARK;
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
+ DialogX.globalTheme = DialogX.THEME.LIGHT;
}
}
}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/storage/WebDavHelp.kt b/app/src/main/java/xyz/fycz/myreader/model/storage/WebDavHelp.kt
index e8fb03a..4c25536 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/storage/WebDavHelp.kt
+++ b/app/src/main/java/xyz/fycz/myreader/model/storage/WebDavHelp.kt
@@ -3,11 +3,14 @@ package xyz.fycz.myreader.model.storage
import android.content.Context
import android.os.Handler
import android.os.Looper
+import com.kongzue.dialogx.dialogs.BottomMenu
+import com.kongzue.dialogx.interfaces.OnMenuItemClickListener
import io.reactivex.Single
import io.reactivex.SingleOnSubscribe
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import org.jetbrains.anko.selector
+import xyz.fycz.myreader.R
import xyz.fycz.myreader.base.observer.MySingleObserver
import xyz.fycz.myreader.common.APPCONST
import xyz.fycz.myreader.util.SharedPreUtils
@@ -68,11 +71,21 @@ object WebDavHelp {
fun showRestoreDialog(context: Context, names: ArrayList, callBack: Restore.CallBack?): Boolean {
return if (names.isNotEmpty()) {
- context.selector(title = "选择恢复文件", items = names) { _, index ->
+ /*context.selector(title = "选择恢复文件", items = names) { _, index ->
if (index in 0 until 30.coerceAtLeast(names.size)) {
restoreWebDav(names[index], callBack)
}
- }
+ }*/
+ BottomMenu.build().setTitle("选择恢复文件")
+ .setMenuStringList(names)
+ .setOnMenuItemClickListener { dialog, text, which ->
+ if (which in 0 until 30.coerceAtLeast(names.size)) {
+ restoreWebDav(names[which], callBack)
+ }
+ false
+ }
+ .setCancelButton(R.string.cancel)
+ .show()
true
} else {
false
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/AdSettingActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/AdSettingActivity.java
index b96a176..cc6b1c3 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/AdSettingActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/AdSettingActivity.java
@@ -5,6 +5,8 @@ import android.view.View;
import androidx.appcompat.widget.Toolbar;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import xyz.fycz.myreader.R;
@@ -116,14 +118,22 @@ public class AdSettingActivity extends BaseActivity {
checked = i;
}
}
- MyAlertDialog.build(AdSettingActivity.this)
+ /*MyAlertDialog.build(AdSettingActivity.this)
.setTitle(getString(R.string.splash_ad_times))
.setSingleChoiceItems(adTimes, checked, (dialog, which) -> {
curAdTimes = ints[which];
spu.putInt("curAdTimes", curAdTimes);
binding.tvSplashCurAdTimes.setText(getString(R.string.splash_cur_ad_times, adTimes[which], curAdCount + "次"));
dialog.dismiss();
- }).setNegativeButton("取消", null).show();
+ }).setNegativeButton("取消", null).show();*/
+ BottomMenu.show(getString(R.string.splash_ad_times), adTimes)
+ .setSelection(checked)
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ curAdTimes = ints[which];
+ spu.putInt("curAdTimes", curAdTimes);
+ binding.tvSplashCurAdTimes.setText(getString(R.string.splash_cur_ad_times, adTimes[which], curAdCount + "次"));
+ return false;
+ }).setCancelButton(R.string.cancel);
}
@Override
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/MoreSettingActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/MoreSettingActivity.java
index dcec558..f509ce3 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/MoreSettingActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/MoreSettingActivity.java
@@ -17,6 +17,8 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.FragmentTransaction;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
@@ -280,7 +282,7 @@ public class MoreSettingActivity extends BaseActivity {
);
binding.llBookSort.setOnClickListener(v -> {
- MyAlertDialog.build(this)
+ /*MyAlertDialog.build(this)
.setTitle(getString(R.string.book_sort))
.setSingleChoiceItems(R.array.book_sort, sortStyle, (dialog, which) -> {
sortStyle = which;
@@ -298,7 +300,26 @@ public class MoreSettingActivity extends BaseActivity {
binding.tvBookSort.setText(getString(R.string.book_name_sort));
}
dialog.dismiss();
- }).setNegativeButton("取消", null).show();
+ }).setNegativeButton("取消", null).show();*/
+ BottomMenu.show(getString(R.string.book_sort), getResources().getStringArray(R.array.book_sort))
+ .setSelection(sortStyle)
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ sortStyle = which;
+ mSetting.setSortStyle(sortStyle);
+ SysManager.saveSetting(mSetting);
+ if (sortStyle == 0) {
+ binding.tvBookSort.setText(getString(R.string.manual_sort));
+ if (!SharedPreUtils.getInstance().getBoolean("manualSortTip")) {
+ DialogCreator.createTipDialog(this, "可在书架编辑状态下长按移动书籍进行排序!");
+ SharedPreUtils.getInstance().putBoolean("manualSortTip", true);
+ }
+ } else if (sortStyle == 1) {
+ binding.tvBookSort.setText(getString(R.string.time_sort));
+ } else if (sortStyle == 2) {
+ binding.tvBookSort.setText(getString(R.string.book_name_sort));
+ }
+ return false;
+ }).setCancelButton(R.string.cancel);
});
binding.rlPrivateBookcase.setOnClickListener(v -> {
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
index 36d7731..1b49512 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
@@ -39,6 +39,10 @@ import androidx.core.content.ContextCompat;
import com.gyf.immersionbar.ImmersionBar;
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener;
+import com.kongzue.dialogx.dialogs.BottomDialog;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+import com.kongzue.dialogx.interfaces.OnDialogButtonClickListener;
+import com.kongzue.dialogx.interfaces.OnMenuItemSelectListener;
import org.jetbrains.annotations.NotNull;
@@ -1555,7 +1559,7 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
return;
}
App.runOnUiThread(() -> {
- MyAlertDialog.build(this)
+ /*MyAlertDialog.build(this)
.setTitle("缓存书籍")
.setSingleChoiceItems(getResources().getStringArray(R.array.download), selectedIndex,
(dialog, which) -> selectedIndex = which).setNegativeButton("取消", ((dialog, which) -> dialog.dismiss())).setPositiveButton("确定",
@@ -1574,7 +1578,31 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
addDownload(0, mChapters.size());
break;
}
- }).show();
+ }).show();*/
+ BottomMenu.show("缓存书籍", getResources().getStringArray(R.array.download))
+ .setSelection(selectedIndex)
+ .setOnMenuItemClickListener(new OnMenuItemSelectListener() {
+ @Override
+ public void onOneItemSelect(BottomMenu dialog, CharSequence text, int which) {
+ selectedIndex = which;
+ }
+ }).setOkButton("确定", (baseDialog, v) -> {
+ switch (selectedIndex) {
+ case 0:
+ addDownload(mPageLoader.getChapterPos(), mPageLoader.getChapterPos() + 50);
+ break;
+ case 1:
+ addDownload(mPageLoader.getChapterPos() - 50, mPageLoader.getChapterPos() + 50);
+ break;
+ case 2:
+ addDownload(mPageLoader.getChapterPos(), mChapters.size());
+ break;
+ case 3:
+ addDownload(0, mChapters.size());
+ break;
+ }
+ return false;
+ }).setCancelButton(R.string.cancel);
});
}
@@ -1952,7 +1980,7 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
break;
case 3:
selectString = StringUtils.deleteWhitespace(binding.readPvContent.getSelectStr());
- MyAlertDialog.build(ReadActivity.this)
+ /*MyAlertDialog.build(ReadActivity.this)
.setTitle(R.string.search)
.setItems(R.array.search_way, (dialog, which) -> {
String url = "";
@@ -1978,7 +2006,33 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
ToastUtils.showError(e.getLocalizedMessage());
}
}).setNegativeButton("取消", null)
- .show();
+ .show();*/
+ BottomMenu.show(R.string.search, getResources().getStringArray(R.array.search_way))
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ String url = "";
+ switch (which) {
+ case 0:
+ url = URLCONST.BAI_DU_SEARCH;
+ break;
+ case 1:
+ url = URLCONST.GOOGLE_SEARCH;
+ break;
+ case 2:
+ url = URLCONST.YOU_DAO_SEARCH;
+ break;
+ }
+ url = url.replace("{key}", selectString);
+ Log.d("SEARCH_URL", url);
+ try {
+ Uri uri = Uri.parse(url);
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ startActivity(intent);
+ } catch (Exception e) {
+ e.printStackTrace();
+ ToastUtils.showError(e.getLocalizedMessage());
+ }
+ return false;
+ }).setCancelButton(R.string.cancel);
clearSelect();
break;
case 4:
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReplaceRuleActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReplaceRuleActivity.java
index 22e633c..9548af7 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReplaceRuleActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReplaceRuleActivity.java
@@ -17,6 +17,8 @@ import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -187,7 +189,7 @@ public class ReplaceRuleActivity extends BaseActivity {
});
replaceDialog.show(getSupportFragmentManager(), "replaceRule");
} else if (itemId == R.id.action_import) {
- MyAlertDialog.build(this)
+ /*MyAlertDialog.build(this)
.setTitle("导入规则")
.setItems(R.array.import_rule, (dialog, which) -> {
if (which == 0) {
@@ -211,7 +213,32 @@ public class ReplaceRuleActivity extends BaseActivity {
(dialog1, which1) -> importDataS(url[0]));
}
- }).show();
+ }).show();*/
+ BottomMenu.show("导入规则", getResources().getStringArray(R.array.import_rule))
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ if (which == 0) {
+ String pasteText = ClipBoardUtil.paste(this);
+ if (!isEmpty(pasteText)) {
+ importDataS(pasteText);
+ } else {
+ ToastUtils.showError("剪切板内容为空,导入失败");
+ }
+ } else if (which == 1) {
+ ToastUtils.showInfo("请选择内容替换规则JSON文件");
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("application/json");
+ startActivityForResult(intent, APPCONST.REQUEST_IMPORT_REPLACE_RULE);
+ } else {
+ String[] url = new String[1];
+ MyAlertDialog.createInputDia(this, "网络导入",
+ "请输入网址", "", true, 200,
+ text0 -> url[0] = text0,
+ (dialog1, which1) -> importDataS(url[0]));
+
+ }
+ return false;
+ }).setCancelButton(R.string.cancel);
} else if (itemId == R.id.action_export) {
if (mReplaceRules == null || mReplaceRules.size() == 0) {
ToastUtils.showWarring("当前没有任何规则,无法导出!");
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java
index ffd88e4..7bd89b5 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java
@@ -1,8 +1,14 @@
package xyz.fycz.myreader.ui.adapter;
import android.content.Context;
+import android.view.View;
import android.widget.*;
+import com.kongzue.dialogx.dialogs.BottomDialog;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+import com.kongzue.dialogx.interfaces.OnDialogButtonClickListener;
+import com.kongzue.dialogx.interfaces.OnMenuItemSelectListener;
+
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
@@ -274,7 +280,7 @@ public abstract class BookcaseAdapter extends DragAdapter {
}
final int[] begin = new int[1];
final int[] end = new int[1];
- MyAlertDialog.build(mContext)
+ /*MyAlertDialog.build(mContext)
.setTitle("缓存书籍")
.setSingleChoiceItems(mContext.getResources().getStringArray(R.array.download), selectedIndex,
(dialog, which) -> selectedIndex = which).setNegativeButton("取消", ((dialog, which) -> dialog.dismiss())).setPositiveButton("确定",
@@ -302,7 +308,40 @@ public abstract class BookcaseAdapter extends DragAdapter {
mBookcasePresenter.addDownload(book, chapters, begin[0], end[0], false);
});
mBookcasePresenter.getEs().submit(downloadThread);
- }).show();
+ }).show();*/
+ BottomMenu.show("缓存书籍", mContext.getResources().getStringArray(R.array.download))
+ .setSelection(selectedIndex)
+ .setOnMenuItemClickListener(new OnMenuItemSelectListener() {
+ @Override
+ public void onOneItemSelect(BottomMenu dialog, CharSequence text, int which) {
+ selectedIndex = which;
+ }
+ }).setOkButton("确定", (baseDialog, v) -> {
+ switch (selectedIndex) {
+ case 0:
+ begin[0] = book.getHisttoryChapterNum();
+ end[0] = book.getHisttoryChapterNum() + 50;
+ break;
+ case 1:
+ begin[0] = book.getHisttoryChapterNum() - 50;
+ end[0] = book.getHisttoryChapterNum() + 50;
+ break;
+ case 2:
+ begin[0] = book.getHisttoryChapterNum();
+ end[0] = 99999;
+ break;
+ case 3:
+ begin[0] = 0;
+ end[0] = 99999;
+ break;
+ }
+ Thread downloadThread = new Thread(() -> {
+ ArrayList chapters = (ArrayList) mChapterService.findBookAllChapterByBookId(book.getId());
+ mBookcasePresenter.addDownload(book, chapters, begin[0], end[0], false);
+ });
+ mBookcasePresenter.getEs().submit(downloadThread);
+ return false;
+ }).setCancelButton(R.string.cancel);
}
static class ViewHolder {
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java
index 19dcb99..9345cdc 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java
@@ -10,6 +10,8 @@ import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+
import java.io.IOException;
import java.util.ArrayList;
@@ -140,7 +142,7 @@ public class BookcaseDetailedAdapter extends BookcaseAdapter {
});
viewHolder.llBookRead.setOnLongClickListener(v -> {
if (!ismEditState()) {
- AlertDialog bookDialog = MyAlertDialog.build(mContext)
+ /*AlertDialog bookDialog = MyAlertDialog.build(mContext)
.setTitle(book.getName())
.setItems(menu, (dialog, which) -> {
switch (which) {
@@ -183,7 +185,47 @@ public class BookcaseDetailedAdapter extends BookcaseAdapter {
.setNegativeButton(null, null)
.setPositiveButton(null, null)
.create();
- bookDialog.show();
+ bookDialog.show();*/
+ BottomMenu.show(book.getName(), menu)
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ switch (which) {
+ case 0:
+ if (!isGroup) {
+ book.setSortCode(0);
+ }else {
+ book.setGroupSort(0);
+ }
+ mBookService.updateEntity(book);
+ mBookcasePresenter.init();
+ ToastUtils.showSuccess("书籍《" + book.getName() + "》移至顶部成功!");
+ break;
+ case 1:
+ downloadBook(book);
+ break;
+ case 2:
+ App.getApplication().newThread(() -> {
+ try {
+ if (unionChapterCathe(book)) {
+ DialogCreator.createTipDialog(mContext,
+ "缓存导出成功,导出目录:"
+ + APPCONST.TXT_BOOK_DIR);
+ } else {
+ DialogCreator.createTipDialog(mContext,
+ "章节目录为空或未找到缓存文件,缓存导出失败!");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ DialogCreator.createTipDialog(mContext,
+ "章节目录为空或未找到缓存文件,缓存导出失败!");
+ }
+ });
+ break;
+ case 3:
+ showDeleteBookDialog(book);
+ break;
+ }
+ return false;
+ });
return true;
}
return false;
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java
index a80f7d2..e2a52fe 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java
@@ -8,6 +8,8 @@ import android.view.ViewGroup;
import androidx.appcompat.app.AlertDialog;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+
import java.io.IOException;
import java.util.ArrayList;
@@ -117,7 +119,7 @@ public class BookcaseDragAdapter extends BookcaseAdapter {
});
viewHolder.ivBookImg.setOnLongClickListener(v -> {
if (!ismEditState()) {
- AlertDialog bookDialog = MyAlertDialog.build(mContext)
+ /*AlertDialog bookDialog = MyAlertDialog.build(mContext)
.setTitle(book.getName())
.setItems(menu, (dialog, which) -> {
switch (which) {
@@ -168,7 +170,55 @@ public class BookcaseDragAdapter extends BookcaseAdapter {
.setNegativeButton(null, null)
.setPositiveButton(null, null)
.create();
- bookDialog.show();
+ bookDialog.show();*/
+ BottomMenu.show(book.getName(), menu)
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ switch (which) {
+ case 0:
+ Intent intent = new Intent(mContext, BookDetailedActivity.class);
+ BitIntentDataManager.getInstance().putData(intent, book);
+ mContext.startActivity(intent);
+ break;
+ case 1:
+ if (!isGroup) {
+ book.setSortCode(0);
+ }else {
+ book.setGroupSort(0);
+ }
+ mBookService.updateEntity(book);
+ mBookcasePresenter.init();
+ ToastUtils.showSuccess("书籍《" + book.getName() + "》移至顶部成功!");
+ break;
+ case 2:
+ downloadBook(book);
+ break;
+ case 3:
+ App.getApplication().newThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (unionChapterCathe(book)) {
+ DialogCreator.createTipDialog(mContext,
+ "缓存导出成功,导出目录:"
+ + APPCONST.TXT_BOOK_DIR);
+ } else {
+ DialogCreator.createTipDialog(mContext,
+ "章节目录为空或未找到缓存文件,缓存导出失败!");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ DialogCreator.createTipDialog(mContext,
+ "章节目录为空或未找到缓存文件,缓存导出失败!");
+ }
+ }
+ });
+ break;
+ case 4:
+ showDeleteBookDialog(book);
+ break;
+ }
+ return false;
+ });
return true;
}
return false;
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/dialog/BookGroupDialog.java b/app/src/main/java/xyz/fycz/myreader/ui/dialog/BookGroupDialog.java
index 447318d..e773076 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/dialog/BookGroupDialog.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/dialog/BookGroupDialog.java
@@ -14,6 +14,9 @@ import android.widget.EditText;
import androidx.appcompat.app.AlertDialog;
import com.google.android.material.textfield.TextInputLayout;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+import com.kongzue.dialogx.interfaces.BaseDialog;
+import com.kongzue.dialogx.interfaces.OnDialogButtonClickListener;
import java.util.ArrayList;
import java.util.List;
@@ -74,9 +77,10 @@ public class BookGroupDialog {
/**
* 加入分组
+ *
* @param book
*/
- public void addGroup(Book book, OnGroup onGroup){
+ public void addGroup(Book book, OnGroup onGroup) {
List books = new ArrayList<>();
books.add(book);
addGroup(books, onGroup);
@@ -84,10 +88,11 @@ public class BookGroupDialog {
/**
* 加入批量分组
+ *
* @param mSelectBooks
* @param onGroup
*/
- public void addGroup(List mSelectBooks, OnGroup onGroup){
+ public void addGroup(List mSelectBooks, OnGroup onGroup) {
initBookGroups(true);
showSelectGroupDia((dialog, which) -> {
if (which < mBookGroups.size()) {
@@ -108,10 +113,11 @@ public class BookGroupDialog {
}
});
}
+
/**
* 添加/重命名分组对话框
*/
- public void showAddOrRenameGroupDia(boolean isRename, boolean isAddGroup, int groupNum, OnGroup onGroup){
+ public void showAddOrRenameGroupDia(boolean isRename, boolean isAddGroup, int groupNum, OnGroup onGroup) {
View view = LayoutInflater.from(mContext).inflate(R.layout.edit_dialog, null);
TextInputLayout textInputLayout = view.findViewById(R.id.text_input_lay);
int maxLen = 20;
@@ -125,7 +131,7 @@ public class BookGroupDialog {
}
editText.requestFocus();
InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
- mHandler.postDelayed(() ->{
+ mHandler.postDelayed(() -> {
imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);
}, 220);
AlertDialog newGroupDia = MyAlertDialog.build(mContext)
@@ -139,8 +145,8 @@ public class BookGroupDialog {
posBtn.setEnabled(false);
posBtn.setOnClickListener(v1 -> {
CharSequence newGroupName = editText.getText().toString();
- for (CharSequence oldGroupName : mGroupNames){
- if (oldGroupName.equals(newGroupName)){
+ for (CharSequence oldGroupName : mGroupNames) {
+ if (oldGroupName.equals(newGroupName)) {
ToastUtils.showWarring("分组[" + newGroupName + "]已存在,无法" + (!isRename ? "添加!" : "重命名!"));
return;
}
@@ -148,10 +154,10 @@ public class BookGroupDialog {
bookGroup.setName(newGroupName.toString());
if (!isRename) {
mBookGroupService.addBookGroup(bookGroup);
- }else {
+ } else {
mBookGroupService.updateEntity(bookGroup);
SharedPreUtils spu = SharedPreUtils.getInstance();
- if (spu.getString(mContext.getString(R.string.curBookGroupName), "").equals(oldName)){
+ if (spu.getString(mContext.getString(R.string.curBookGroupName), "").equals(oldName)) {
spu.putString(mContext.getString(R.string.curBookGroupName), newGroupName.toString());
if (onGroup != null) onGroup.change();
}
@@ -161,7 +167,7 @@ public class BookGroupDialog {
+ bookGroup.getName() + "]");
imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);
newGroupDia.dismiss();
- if (isAddGroup){
+ if (isAddGroup) {
if (onGroup != null) onGroup.addGroup();
}
});
@@ -202,11 +208,11 @@ public class BookGroupDialog {
sb.append(mBookGroups.get(i).getName()).append("、");
}
}
- if (sb.length() > 0){
+ if (sb.length() > 0) {
sb.deleteCharAt(sb.lastIndexOf("、"));
}
SharedPreUtils spu = SharedPreUtils.getInstance();
- if (mBookGroupService.getGroupById(spu.getString(mContext.getString(R.string.curBookGroupId), "")) == null){
+ if (mBookGroupService.getGroupById(spu.getString(mContext.getString(R.string.curBookGroupId), "")) == null) {
spu.putString(mContext.getString(R.string.curBookGroupId), "");
spu.putString(mContext.getString(R.string.curBookGroupName), "");
onGroup.change();
@@ -214,17 +220,23 @@ public class BookGroupDialog {
ToastUtils.showSuccess("分组[" + sb.toString() + "]删除成功!");
}, null, null);
}
+
//显示选择书籍对话框
- public void showSelectGroupDia(DialogInterface.OnClickListener onClickListener){
- MyAlertDialog.build(mContext)
+ public void showSelectGroupDia(DialogInterface.OnClickListener onClickListener) {
+ /*MyAlertDialog.build(mContext)
.setTitle("选择分组")
.setItems(mGroupNames, onClickListener)
.setCancelable(false)
.setPositiveButton("取消", null)
- .show();
+ .show();*/
+ BottomMenu.show("选择分组", mGroupNames)
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ onClickListener.onClick(null, which);
+ return false;
+ }).setCancelButton(R.string.cancel);
}
- public abstract static class OnGroup{
+ public abstract static class OnGroup {
public abstract void change();
public void addGroup() {
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/dialog/MultiChoiceDialog.java b/app/src/main/java/xyz/fycz/myreader/ui/dialog/MultiChoiceDialog.java
index 140334b..69ae119 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/dialog/MultiChoiceDialog.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/dialog/MultiChoiceDialog.java
@@ -6,6 +6,8 @@ import android.widget.Button;
import android.widget.ListView;
import androidx.appcompat.app.AlertDialog;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+
/**
* @author fengyue
* @date 2020/8/29 21:08
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/DIYSourceFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/DIYSourceFragment.java
index 2268172..4aee230 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/fragment/DIYSourceFragment.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/DIYSourceFragment.java
@@ -16,6 +16,8 @@ import androidx.annotation.Nullable;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@@ -139,7 +141,7 @@ public class DIYSourceFragment extends BaseFragment {
startActivityForResult(new Intent(getContext(), SourceEditActivity.class),
APPCONST.REQUEST_EDIT_BOOK_SOURCE));
binding.tvImportSource.setOnClickListener(v -> {
- MyAlertDialog.build(getContext())
+ /*MyAlertDialog.build(getContext())
.setTitle("导入书源")
.setItems(R.array.import_rule, (dialog, which) -> {
if (which == 0) {
@@ -163,7 +165,32 @@ public class DIYSourceFragment extends BaseFragment {
(dialog1, which1) -> importDataS(url[0]));
}
- }).show();
+ }).show();*/
+ BottomMenu.show("导入书源", getResources().getStringArray(R.array.import_rule))
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ if (which == 0) {
+ String pasteText = ClipBoardUtil.paste(getContext());
+ if (!isEmpty(pasteText)) {
+ importDataS(pasteText);
+ } else {
+ ToastUtils.showError("剪切板内容为空,导入失败");
+ }
+ } else if (which == 1) {
+ ToastUtils.showInfo("请选择书源JSON文件");
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("application/json");
+ startActivityForResult(intent, APPCONST.REQUEST_IMPORT_BOOK_SOURCE);
+ } else {
+ String[] url = new String[1];
+ MyAlertDialog.createInputDia(getContext(), "网络导入",
+ "请输入网址", "", true, 200,
+ text0 -> url[0] = text0,
+ (dialog1, which1) -> importDataS(url[0]));
+
+ }
+ return false;
+ }).setCancelButton(R.string.cancel);
});
binding.tvSourceTip.setOnClickListener(v -> {
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java
index 8521fe8..61d4ed7 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java
@@ -14,6 +14,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+
import org.jetbrains.annotations.NotNull;
import java.text.SimpleDateFormat;
@@ -65,9 +67,9 @@ public class MineFragment extends BaseFragment {
//private boolean isLogin;
private Setting mSetting;
- private String[] webSynMenu;
+// private String[] webSynMenu;
private String[] backupMenu;
- private AlertDialog themeModeDia;
+// private AlertDialog themeModeDia;
private int themeMode;
private String[] themeModeArr;
@SuppressLint("HandlerLeak")
@@ -102,11 +104,11 @@ public class MineFragment extends BaseFragment {
super.initData(savedInstanceState);
//isLogin = UserService.isLogin();
mSetting = SysManager.getSetting();
- webSynMenu = new String[]{
+ /*webSynMenu = new String[]{
App.getmContext().getString(R.string.menu_backup_webBackup),
App.getmContext().getString(R.string.menu_backup_webRestore),
App.getmContext().getString(R.string.menu_backup_autoSyn)
- };
+ };*/
backupMenu = new String[]{
App.getmContext().getResources().getString(R.string.menu_backup_backup),
App.getmContext().getResources().getString(R.string.menu_backup_restore),
@@ -196,7 +198,7 @@ public class MineFragment extends BaseFragment {
});
binding.mineRlBackup.setOnClickListener(v -> {
- AlertDialog bookDialog = MyAlertDialog.build(getContext())
+ /*AlertDialog bookDialog = MyAlertDialog.build(getContext())
.setTitle(getContext().getResources().getString(R.string.menu_bookcase_backup))
.setItems(backupMenu, (dialog, which) -> {
switch (which) {
@@ -211,7 +213,19 @@ public class MineFragment extends BaseFragment {
.setNegativeButton(null, null)
.setPositiveButton(null, null)
.create();
- bookDialog.show();
+ bookDialog.show();*/
+ BottomMenu.show(getContext().getResources().getString(R.string.menu_bookcase_backup), backupMenu)
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ switch (which) {
+ case 0:
+ mHandler.sendMessage(mHandler.obtainMessage(2));
+ break;
+ case 1:
+ mHandler.sendMessage(mHandler.obtainMessage(3));
+ break;
+ }
+ return false;
+ }).setCancelButton(R.string.cancel);
});
/*binding.mineRlSyn.setOnClickListener(v -> {
if (!UserService.isLogin()) {
@@ -258,7 +272,7 @@ public class MineFragment extends BaseFragment {
startActivity(settingIntent);
});
binding.mineRlThemeMode.setOnClickListener(v -> {
- if (themeModeDia != null) {
+ /*if (themeModeDia != null) {
themeModeDia.show();
return;
}
@@ -292,8 +306,34 @@ public class MineFragment extends BaseFragment {
})
.setNegativeButton("取消", null)
.create();
- themeModeDia.show();
-
+ themeModeDia.show();*/
+ BottomMenu.show("主题模式", themeModeArr)
+ .setSelection(themeMode)
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ if (themeMode == which) {
+ return false;
+ }
+ themeMode = which;
+ switch (which) {
+ case 0:
+ SharedPreUtils.getInstance().putBoolean(getString(R.string.isNightFS), true);
+ break;
+ case 1:
+ SharedPreUtils.getInstance().putBoolean(getString(R.string.isNightFS), false);
+ mSetting.setDayStyle(true);
+ SysManager.saveSetting(mSetting);
+ break;
+ case 2:
+ SharedPreUtils.getInstance().putBoolean(getString(R.string.isNightFS), false);
+ mSetting.setDayStyle(false);
+ SysManager.saveSetting(mSetting);
+ break;
+ }
+ dialog.dismiss();
+ binding.tvThemeModeSelect.setText(themeModeArr[themeMode]);
+ App.getApplication().initNightTheme();
+ return false;
+ }).setCancelButton(R.string.cancel);
});
binding.mineRlAdSetting.setOnClickListener(v -> startActivity(new Intent(getActivity(), AdSettingActivity.class)));
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/popmenu/CustomizeLayoutMenu.java b/app/src/main/java/xyz/fycz/myreader/ui/popmenu/CustomizeLayoutMenu.java
index 0aaa65e..f7aa30e 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/popmenu/CustomizeLayoutMenu.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/popmenu/CustomizeLayoutMenu.java
@@ -23,6 +23,7 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import com.jaredrummler.android.colorpicker.ColorPickerDialog;
+import com.kongzue.dialogx.dialogs.BottomMenu;
import java.io.IOException;
import java.util.ArrayList;
@@ -156,7 +157,7 @@ public class CustomizeLayoutMenu extends FrameLayout {
}
items[i] = "布局" + (i + 1);
}
- MyAlertDialog.build(context)
+ /*MyAlertDialog.build(context)
.setTitle("选择布局保存的位置")
.setItems(items, (dialog, which) -> {
if (which == 5) which = 6;
@@ -164,7 +165,16 @@ public class CustomizeLayoutMenu extends FrameLayout {
SysManager.saveSetting(setting);
callback.upStyle();
ToastUtils.showSuccess("布局保存成功");
- }).show();
+ }).show();*/
+ BottomMenu.show("选择布局保存的位置", items)
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ if (which == 5) which = 6;
+ setting.saveLayout(which);
+ SysManager.saveSetting(setting);
+ callback.upStyle();
+ ToastUtils.showSuccess("布局保存成功");
+ return false;
+ });
});
binding.tvImportLayout.setOnClickListener(v -> importLayout());
binding.tvExportLayout.setOnClickListener(v -> exportLayout());
@@ -217,14 +227,22 @@ public class CustomizeLayoutMenu extends FrameLayout {
for (int i = 0; i < items.length; i++) {
items[i] = "布局" + (i + 1);
}
- MyAlertDialog.build(context)
+ /*MyAlertDialog.build(context)
.setTitle("选择需要导出的布局")
.setItems(items, (dialog, which) -> {
if (setting.exportLayout(which)){
DialogCreator.createTipDialog(context,
"布局配置导出成功,导出位置:" + APPCONST.FILE_DIR + "readConfig.zip");
}
- }).show();
+ }).show();*/
+ BottomMenu.show("选择需要导出的布局", items)
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ if (setting.exportLayout(which)){
+ DialogCreator.createTipDialog(context,
+ "布局配置导出成功,导出位置:" + APPCONST.FILE_DIR + "readConfig.zip");
+ }
+ return false;
+ });
}
public void zip2Layout(String zipPath) {
@@ -240,7 +258,7 @@ public class CustomizeLayoutMenu extends FrameLayout {
for (int i = 0; i < items.length; i++) {
items[i] = "布局" + (i + 1);
}
- MyAlertDialog.build(context)
+ /*MyAlertDialog.build(context)
.setTitle("选择要覆盖的布局")
.setItems(items, (dialog, which) -> {
setting.importLayout(which, readStyle);
@@ -252,7 +270,20 @@ public class CustomizeLayoutMenu extends FrameLayout {
FileUtils.deleteFile(APPCONST.TEM_FILE_DIR + "bg.fyl");
ToastUtils.showSuccess("配置导入成功");
callback.upStyle();
- }).show();
+ }).show();*/
+ BottomMenu.show("选择要覆盖的布局", items)
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ setting.importLayout(which, readStyle);
+ if (!readStyle.bgIsColor() && !readStyle.bgIsAssert()){
+ FileUtils.copy(APPCONST.TEM_FILE_DIR + "bg.fyl",APPCONST.BG_FILE_DIR + "bg" + which + ".fyl");
+ readStyle.setBgPath(APPCONST.BG_FILE_DIR + "bg" + which + ".fyl");
+ }
+ FileUtils.deleteFile(APPCONST.TEM_FILE_DIR + "readConfig.fyl");
+ FileUtils.deleteFile(APPCONST.TEM_FILE_DIR + "bg.fyl");
+ ToastUtils.showSuccess("配置导入成功");
+ callback.upStyle();
+ return false;
+ });
} catch (IOException e) {
e.printStackTrace();
ToastUtils.showError("配置导入失败" + e.getLocalizedMessage());
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/popmenu/ReadSettingMenu.java b/app/src/main/java/xyz/fycz/myreader/ui/popmenu/ReadSettingMenu.java
index 9794c8e..476ad28 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/popmenu/ReadSettingMenu.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/popmenu/ReadSettingMenu.java
@@ -11,6 +11,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.databinding.MenuReadSettingBinding;
@@ -116,7 +118,7 @@ public class ReadSettingMenu extends FrameLayout {
binding.tvLineSpacing0.setOnClickListener(v -> ((ReadActivity) context).showCustomizeMenu());
//缩进
binding.tvIntent.setOnClickListener(v -> {
- AlertDialog dialog = new AlertDialog.Builder(context, R.style.alertDialogTheme)
+ /*AlertDialog dialog = new AlertDialog.Builder(context, R.style.alertDialogTheme)
.setTitle("缩进")
.setSingleChoiceItems(context.getResources().getStringArray(R.array.indent),
setting.getIntent(),
@@ -127,7 +129,15 @@ public class ReadSettingMenu extends FrameLayout {
dialogInterface.dismiss();
})
.create();
- dialog.show();
+ dialog.show();*/
+ BottomMenu.show("缩进", getResources().getStringArray(R.array.indent))
+ .setSelection(setting.getIntent())
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ setting.setIntent(which);
+ SysManager.saveSetting(setting);
+ callback.onRefreshUI();
+ return false;
+ }).setCancelButton(R.string.cancel);
});
//样式选择
binding.ivCommonStyle.setOnClickListener(v -> selectedStyle(0));
@@ -170,7 +180,7 @@ public class ReadSettingMenu extends FrameLayout {
default:
checkedItem = 0;
}
- MyAlertDialog.build(context)
+ /*MyAlertDialog.build(context)
.setTitle("翻页模式")
.setSingleChoiceItems(R.array.page_mode, checkedItem, (dialog, which) -> {
switch (which) {
@@ -196,7 +206,35 @@ public class ReadSettingMenu extends FrameLayout {
dialog.dismiss();
SysManager.saveSetting(setting);
callback.onPageModeChange();
- }).show();
+ }).show();*/
+ BottomMenu.show("翻页模式", getResources().getStringArray(R.array.page_mode))
+ .setSelection(checkedItem)
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ switch (which) {
+ case 0:
+ setting.setPageMode(PageMode.COVER);
+ break;
+ case 1:
+ setting.setPageMode(PageMode.SIMULATION);
+ break;
+ case 2:
+ setting.setPageMode(PageMode.SLIDE);
+ break;
+ case 3:
+ setting.setPageMode(PageMode.VERTICAL_COVER);
+ break;
+ case 4:
+ setting.setPageMode(PageMode.SCROLL);
+ break;
+ case 5:
+ setting.setPageMode(PageMode.NONE);
+ break;
+ }
+ dialog.dismiss();
+ SysManager.saveSetting(setting);
+ callback.onPageModeChange();
+ return false;
+ }).setCancelButton(R.string.cancel);
});
//横屏竖屏切换
binding.readTvHvScreen.setOnClickListener(v -> {
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java
index 6e3c185..7fdb952 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java
@@ -17,6 +17,8 @@ import android.widget.PopupMenu;
import androidx.core.app.ActivityCompat;
+import com.kongzue.dialogx.dialogs.BottomMenu;
+
import org.jetbrains.annotations.NotNull;
import java.text.Collator;
@@ -586,7 +588,7 @@ public class BookcasePresenter implements BasePresenter {
* 分组管理对话框
*/
private void showGroupManDia() {
- MyAlertDialog.build(mMainActivity)
+ /*MyAlertDialog.build(mMainActivity)
.setTitle("分组管理")
.setItems(mMainActivity.getResources().getStringArray(R.array.group_man)
, (dialog, which) -> {
@@ -630,7 +632,51 @@ public class BookcasePresenter implements BasePresenter {
});
break;
}
- }).show();
+ }).show();*/
+ BottomMenu.show("分组管理", mMainActivity.getResources().getStringArray(R.array.group_man))
+ .setOnMenuItemClickListener((dialog, text, which) -> {
+ mBookGroupDia.initBookGroups(false);
+ switch (which) {
+ case 0:
+ mBookGroupDia.showAddOrRenameGroupDia(false, false, 0, new BookGroupDialog.OnGroup() {
+ @Override
+ public void change() {
+ ogcl.onChange();
+ }
+
+ @Override
+ public void addGroup() {
+ mBookcaseFragment.getmBtnAddGroup().performClick();
+ }
+ });
+ break;
+ case 1:
+ mBookGroupDia.showSelectGroupDia((dialog1, which1) -> {
+ mBookGroupDia.showAddOrRenameGroupDia(true, false, which1, new BookGroupDialog.OnGroup() {
+ @Override
+ public void change() {
+ ogcl.onChange();
+ }
+
+ @Override
+ public void addGroup() {
+ mBookcaseFragment.getmBtnAddGroup().performClick();
+ }
+ });
+ });
+ break;
+ case 2:
+ mBookGroupDia.showDeleteGroupDia(new BookGroupDialog.OnGroup() {
+ @Override
+ public void change() {
+ ogcl.onChange();
+ init();
+ }
+ });
+ break;
+ }
+ return false;
+ }).setCancelButton(R.string.cancel);
}
//分组切换监听器
diff --git a/app/src/main/java/xyz/fycz/myreader/util/utils/AdUtils.java b/app/src/main/java/xyz/fycz/myreader/util/utils/AdUtils.java
index 427b4f8..456713e 100644
--- a/app/src/main/java/xyz/fycz/myreader/util/utils/AdUtils.java
+++ b/app/src/main/java/xyz/fycz/myreader/util/utils/AdUtils.java
@@ -123,9 +123,9 @@ public class AdUtils {
public static void initAd() {
if (!hasInitAd) {
hasInitAd = true;
- DdSdkHelper.init("", "", "",
- "", "",
- "", "",
+ DdSdkHelper.init("1234", "216", "51716a16fbdf50905704b6575b1b3b60",
+ "142364", "35ce0efe5f3cc960b116db227498e238",
+ "8167", "85bd159309c3da1b",
App.getApplication(), App.isDebug());
}
}
diff --git a/settings.gradle b/settings.gradle
index e7b4def..9fdc043 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1,2 @@
include ':app'
+include ':DialogX'