kongzue %!s(int64=2) %!d(string=hai) anos
pai
achega
5e8c6af807

+ 6 - 6
DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomDialog.java

@@ -315,7 +315,7 @@ public class BottomDialog extends BaseDialog {
                     
                     getDialogLifecycleCallback().onShow(me);
                     
-                    onDialogInit(dialogImpl);
+                    onDialogShow();
                     
                     boxRoot.post(new Runnable() {
                         @Override
@@ -466,6 +466,8 @@ public class BottomDialog extends BaseDialog {
                     bkgAlpha.start();
                 }
             });
+            
+            onDialogInit();
         }
         
         @Override
@@ -493,7 +495,7 @@ public class BottomDialog extends BaseDialog {
             useTextInfo(btnCancel, cancelTextInfo);
             useTextInfo(btnSelectOther, otherTextInfo);
             useTextInfo(btnSelectPositive, okTextInfo);
-    
+            
             if (titleIcon != null) {
                 int size = (int) txtDialogTitle.getTextSize();
                 titleIcon.setBounds(0, 0, size, size);
@@ -541,7 +543,6 @@ public class BottomDialog extends BaseDialog {
             
             if (maskColor != -1) {
                 boxRoot.setBackgroundColor(maskColor);
-                boxRoot.setBkgAlpha(0f);
             }
             
             if (onBindView != null && onBindView.getCustomView() != null) {
@@ -591,6 +592,8 @@ public class BottomDialog extends BaseDialog {
             showText(btnSelectPositive, okText);
             showText(btnCancel, cancelText);
             showText(btnSelectOther, otherText);
+            
+            onDialogRefreshUI();
         }
         
         @Override
@@ -654,9 +657,6 @@ public class BottomDialog extends BaseDialog {
         }
     }
     
-    protected void onDialogInit(DialogImpl dialog) {
-    }
-    
     public void refreshUI() {
         if (getDialogImpl() == null) return;
         runOnMain(new Runnable() {

+ 9 - 9
DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomMenu.java

@@ -476,12 +476,12 @@ public class BottomMenu extends BottomDialog {
     private long lastClickTime = 0;
     
     @Override
-    protected void onDialogInit(final DialogImpl dialog) {
-        if (dialog != null) {
-            dialog.boxList.setVisibility(View.VISIBLE);
+    protected void onDialogShow() {
+        if (getDialogImpl() != null) {
+            getDialogImpl().boxList.setVisibility(View.VISIBLE);
             
             if (!isAllowInterceptTouch()) {
-                dialog.bkg.setMaxHeight((int) bottomDialogMaxHeight);
+                getDialogImpl().bkg.setMaxHeight((int) bottomDialogMaxHeight);
                 if (bottomDialogMaxHeight != 0) {
                     dialogImpl.scrollView.lockScroll(true);
                 }
@@ -499,9 +499,9 @@ public class BottomMenu extends BottomDialog {
             
             
             if (!isLightTheme()) {
-                listView = new BottomDialogListView(dialog, getTopActivity(), R.style.DialogXCompatThemeDark);
+                listView = new BottomDialogListView(getDialogImpl(), getTopActivity(), R.style.DialogXCompatThemeDark);
             } else {
-                listView = new BottomDialogListView(dialog, getTopActivity());
+                listView = new BottomDialogListView(getDialogImpl(), getTopActivity());
             }
             listView.setOverScrollMode(OVER_SCROLL_NEVER);
             listView.setDivider(getResources().getDrawable(dividerDrawableResId));
@@ -510,7 +510,7 @@ public class BottomMenu extends BottomDialog {
             listView.setBottomMenuListViewTouchEvent(new BottomMenuListViewTouchEvent() {
                 @Override
                 public void down(MotionEvent event) {
-                    touchDownY = dialog.bkg.getY();
+                    touchDownY = getDialogImpl().bkg.getY();
                 }
             });
             
@@ -520,7 +520,7 @@ public class BottomMenu extends BottomDialog {
                     long currentTime = System.currentTimeMillis();
                     if (currentTime - lastClickTime > ITEM_CLICK_DELAY) {
                         lastClickTime = currentTime;
-                        float deltaY = Math.abs(touchDownY - dialog.bkg.getY());
+                        float deltaY = Math.abs(touchDownY - getDialogImpl().bkg.getY());
                         if (deltaY > dip2px(15)) {
                             return;
                         }
@@ -595,7 +595,7 @@ public class BottomMenu extends BottomDialog {
             }
             
             RelativeLayout.LayoutParams listViewLp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-            dialog.boxList.addView(listView, listViewLp);
+            getDialogImpl().boxList.addView(listView, listViewLp);
             
             refreshUI();
             

+ 19 - 1
DialogX/src/main/java/com/kongzue/dialogx/dialogs/CustomDialog.java

@@ -151,12 +151,19 @@ public class CustomDialog extends BaseDialog {
         
         @Override
         public void init() {
+            if (baseViewLoc == null && baseView != null) {
+                baseViewLoc = new int[4];
+                baseView.getLocationOnScreen(baseViewLoc);
+            }
             boxRoot.setParentDialog(me);
             boxRoot.setOnLifecycleCallBack(new DialogXBaseRelativeLayout.OnLifecycleCallBack() {
                 @Override
                 public void onShow() {
                     isShow = true;
                     preShow = false;
+                    
+                    onDialogShow();
+                    
                     getDialogLifecycleCallback().onShow(me);
                     boxCustom.setVisibility(View.GONE);
                 }
@@ -267,6 +274,8 @@ public class CustomDialog extends BaseDialog {
                     bkgAlpha.start();
                 }
             });
+            
+            onDialogInit();
         }
         
         boolean initSetCustomViewLayoutListener = false;
@@ -313,9 +322,13 @@ public class CustomDialog extends BaseDialog {
                                 if (isAlignBaseViewGravity(Gravity.BOTTOM)) {
                                     calY = baseViewTop + baseView.getHeight() + marginRelativeBaseView[1];
                                 }
+                                baseViewLoc[2] = baseView.getWidth();
+                                baseViewLoc[3] = baseView.getHeight();
                                 
                                 if (calX != 0) boxCustom.setX(calX);
                                 if (calY != 0) boxCustom.setY(calY);
+                                
+                                onGetBaseViewLoc(baseViewLoc);
                             }
                         }
                     };
@@ -423,6 +436,8 @@ public class CustomDialog extends BaseDialog {
                 boxCustom.setMaxHeight(height);
                 boxCustom.setMinimumHeight(height);
             }
+            
+            onDialogRefreshUI();
         }
         
         @Override
@@ -495,6 +510,9 @@ public class CustomDialog extends BaseDialog {
         }
     }
     
+    protected void onGetBaseViewLoc(int[] baseViewLoc) {
+    }
+    
     @Override
     public String dialogKey() {
         return getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")";
@@ -720,7 +738,7 @@ public class CustomDialog extends BaseDialog {
     public CustomDialog setAlignBaseViewGravity(View baseView, int alignGravity) {
         this.baseView = baseView;
         this.alignViewGravity = alignGravity;
-        baseViewLoc = new int[2];
+        baseViewLoc = new int[4];
         baseView.getLocationOnScreen(baseViewLoc);
         setFullScreen(true);
         return this;

+ 6 - 0
DialogX/src/main/java/com/kongzue/dialogx/dialogs/FullScreenDialog.java

@@ -151,6 +151,8 @@ public class FullScreenDialog extends BaseDialog {
                     isShow = true;
                     preShow = false;
                     
+                    onDialogShow();
+                    
                     getDialogLifecycleCallback().onShow(me);
                 }
                 
@@ -231,6 +233,8 @@ public class FullScreenDialog extends BaseDialog {
                     }
                 }
             });
+            
+            onDialogInit();
         }
         
         private void showEnterAnim(int customViewHeight) {
@@ -315,6 +319,8 @@ public class FullScreenDialog extends BaseDialog {
             }
             
             fullScreenDialogTouchEventInterceptor.refresh(me, this);
+            
+            onDialogRefreshUI();
         }
         
         @Override

+ 441 - 5
DialogX/src/main/java/com/kongzue/dialogx/dialogs/GuideDialog.java

@@ -1,16 +1,33 @@
 package com.kongzue.dialogx.dialogs;
 
 import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.view.Gravity;
 import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
 
 import androidx.annotation.ColorInt;
 
 import com.kongzue.dialogx.DialogX;
+import com.kongzue.dialogx.R;
 import com.kongzue.dialogx.interfaces.DialogLifecycleCallback;
 import com.kongzue.dialogx.interfaces.DialogXStyle;
 import com.kongzue.dialogx.interfaces.OnBackPressedListener;
 import com.kongzue.dialogx.interfaces.OnBackgroundMaskClickListener;
 import com.kongzue.dialogx.interfaces.OnBindView;
+import com.kongzue.dialogx.interfaces.OnDialogButtonClickListener;
+import com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout;
 
 /**
  * @author: Kongzue
@@ -21,22 +38,174 @@ import com.kongzue.dialogx.interfaces.OnBindView;
  */
 public class GuideDialog extends CustomDialog {
     
+    public enum STAGE_LIGHT_TYPE {
+        RECTANGLE,      //矩形
+        SQUARE_OUTSIDE, //方形(外围)
+        SQUARE_INSIDE,  //方形(内围)
+        CIRCLE_OUTSIDE, //圆形(外围)
+        CIRCLE_INSIDE,  //圆形(内围)
+    }
+    
+    protected STAGE_LIGHT_TYPE stageLightType = STAGE_LIGHT_TYPE.CIRCLE_OUTSIDE;
+    protected Drawable tipImage;
+    protected float stageLightFilletRadius;     //舞台灯光部分的圆角
+    protected int maskColor = -1;
+    protected OnDialogButtonClickListener<GuideDialog> onStageLightPathClickListener;
+    
     protected GuideDialog() {
         super();
+        enterAnimResId = R.anim.anim_dialogx_alpha_enter;
+        exitAnimResId = R.anim.anim_dialogx_default_exit;
+        this.alignViewGravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
     }
     
     public static GuideDialog build() {
         return new GuideDialog();
     }
     
-    public static GuideDialog build(OnBindView<CustomDialog> onBindView) {
-        return new GuideDialog(onBindView);
+    public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType) {
+        this();
+        this.baseView = baseView;
+        this.stageLightType = stageLightType;
+    }
+    
+    public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, OnBindView<CustomDialog> onBindView, int alignBaseViewGravity) {
+        this();
+        this.baseView = baseView;
+        this.stageLightType = stageLightType;
+        this.onBindView = onBindView;
+        this.alignViewGravity = alignBaseViewGravity;
+    }
+    
+    public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, int tipImageResId, int alignBaseViewGravity) {
+        this();
+        this.baseView = baseView;
+        this.tipImage = getResources().getDrawable(tipImageResId);
+        this.stageLightType = stageLightType;
+        this.alignViewGravity = alignBaseViewGravity;
+    }
+    
+    public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, Bitmap tipImage, int alignBaseViewGravity) {
+        this();
+        this.baseView = baseView;
+        this.tipImage = new BitmapDrawable(getResources(), tipImage);
+        this.stageLightType = stageLightType;
+        this.alignViewGravity = alignBaseViewGravity;
+    }
+    
+    public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, Drawable tipImage, int alignBaseViewGravity) {
+        this();
+        this.baseView = baseView;
+        this.tipImage = tipImage;
+        this.stageLightType = stageLightType;
+        this.alignViewGravity = alignBaseViewGravity;
+    }
+    
+    public GuideDialog(int tipImageResId) {
+        this();
+        this.tipImage = getResources().getDrawable(tipImageResId);
+    }
+    
+    public GuideDialog(Bitmap tipImage) {
+        this();
+        this.tipImage = new BitmapDrawable(getResources(), tipImage);
+    }
+    
+    public GuideDialog(Drawable tipImage) {
+        this();
+        this.tipImage = tipImage;
+    }
+    
+    public GuideDialog(int tipImageResId, ALIGN align) {
+        this();
+        this.tipImage = getResources().getDrawable(tipImageResId);
+        this.align = align;
+    }
+    
+    public GuideDialog(Bitmap tipImage, ALIGN align) {
+        this();
+        this.tipImage = new BitmapDrawable(getResources(), tipImage);
+        this.align = align;
+    }
+    
+    public GuideDialog(Drawable tipImage, ALIGN align) {
+        this();
+        this.tipImage = tipImage;
+        this.align = align;
     }
     
     public GuideDialog(OnBindView<CustomDialog> onBindView) {
+        this();
+        this.onBindView = onBindView;
+    }
+    
+    public GuideDialog(OnBindView<CustomDialog> onBindView, ALIGN align) {
+        this();
         this.onBindView = onBindView;
+        this.align = align;
+    }
+    
+    public GuideDialog(View baseView, int tipImageResId) {
+        this();
+        this.baseView = baseView;
+        this.tipImage = getResources().getDrawable(tipImageResId);
+    }
+    
+    public GuideDialog(View baseView, Bitmap tipImage) {
+        this();
+        this.baseView = baseView;
+        this.tipImage = new BitmapDrawable(getResources(), tipImage);
+    }
+    
+    public GuideDialog(View baseView, Drawable tipImage) {
+        this();
+        this.baseView = baseView;
+        this.tipImage = tipImage;
+    }
+    
+    public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, int tipImageResId) {
+        this();
+        this.baseView = baseView;
+        this.stageLightType = stageLightType;
+        this.tipImage = getResources().getDrawable(tipImageResId);
+    }
+    
+    public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, Bitmap tipImage) {
+        this();
+        this.baseView = baseView;
+        this.stageLightType = stageLightType;
+        this.tipImage = new BitmapDrawable(getResources(), tipImage);
+    }
+    
+    public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, Drawable tipImage) {
+        this();
+        this.baseView = baseView;
+        this.stageLightType = stageLightType;
+        this.tipImage = tipImage;
+    }
+    
+    public GuideDialog(View baseView, int tipImageResId, int alignBaseViewGravity) {
+        this();
+        this.baseView = baseView;
+        this.alignViewGravity = alignBaseViewGravity;
+        this.tipImage = getResources().getDrawable(tipImageResId);
+    }
+    
+    public GuideDialog(View baseView, Bitmap tipImage, int alignBaseViewGravity) {
+        this();
+        this.baseView = baseView;
+        this.alignViewGravity = alignBaseViewGravity;
+        this.tipImage = new BitmapDrawable(getResources(), tipImage);
     }
     
+    public GuideDialog(View baseView, Drawable tipImage, int alignBaseViewGravity) {
+        this();
+        this.baseView = baseView;
+        this.alignViewGravity = alignBaseViewGravity;
+        this.tipImage = tipImage;
+    }
+    
+    //静态方法
     public static GuideDialog show(OnBindView<CustomDialog> onBindView) {
         GuideDialog guideDialog = new GuideDialog(onBindView);
         guideDialog.show();
@@ -50,6 +219,91 @@ public class GuideDialog extends CustomDialog {
         return guideDialog;
     }
     
+    public static GuideDialog show(int tipImageResId) {
+        return new GuideDialog(tipImageResId).show();
+    }
+    
+    public static GuideDialog show(Bitmap tipImage) {
+        return new GuideDialog(tipImage).show();
+    }
+    
+    public static GuideDialog show(Drawable tipImage) {
+        return new GuideDialog(tipImage).show();
+    }
+    
+    public static GuideDialog show(int tipImageResId, ALIGN align) {
+        GuideDialog guideDialog = new GuideDialog(tipImageResId, align);
+        guideDialog.align = align;
+        return guideDialog.show();
+    }
+    
+    public static GuideDialog show(Bitmap tipImage, ALIGN align) {
+        GuideDialog guideDialog = new GuideDialog(tipImage, align);
+        guideDialog.align = align;
+        return guideDialog.show();
+    }
+    
+    public static GuideDialog show(Drawable tipImage, ALIGN align) {
+        return new GuideDialog(tipImage, align).show();
+    }
+    
+    public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType) {
+        return new GuideDialog(baseView, stageLightType).show();
+    }
+    
+    public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, OnBindView<CustomDialog> onBindView, int alignBaseViewGravity) {
+        return new GuideDialog(baseView, stageLightType, onBindView, alignBaseViewGravity).show();
+    }
+    
+    public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, int tipImageResId, int alignBaseViewGravity) {
+        return new GuideDialog(baseView, stageLightType, tipImageResId, alignBaseViewGravity).show();
+    }
+    
+    public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, Bitmap tipImage, int alignBaseViewGravity) {
+        return new GuideDialog(baseView, stageLightType, tipImage, alignBaseViewGravity).show();
+    }
+    
+    public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, Drawable tipImage, int alignBaseViewGravity) {
+        return new GuideDialog(baseView, stageLightType, tipImage, alignBaseViewGravity).show();
+    }
+    
+    public static GuideDialog show(View baseView, int tipImageResId) {
+        return new GuideDialog(baseView, tipImageResId).show();
+    }
+    
+    public static GuideDialog show(View baseView, Bitmap tipImage) {
+        return new GuideDialog(baseView, tipImage).show();
+    }
+    
+    public static GuideDialog show(View baseView, Drawable tipImage) {
+        return new GuideDialog(baseView, tipImage).show();
+    }
+    
+    public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, int tipImageResId) {
+        return new GuideDialog(baseView, stageLightType, tipImageResId).show();
+    }
+    
+    public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, Bitmap tipImage) {
+        return new GuideDialog(baseView, stageLightType, tipImage).show();
+    }
+    
+    public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, Drawable tipImage) {
+        return new GuideDialog(baseView, stageLightType, tipImage).show();
+    }
+    
+    public static GuideDialog show(View baseView, int tipImageResId, int alignBaseViewGravity) {
+        return new GuideDialog(baseView, tipImageResId, alignBaseViewGravity).show();
+    }
+    
+    public static GuideDialog show(View baseView, Bitmap tipImage, int alignBaseViewGravity) {
+        return new GuideDialog(baseView, tipImage, alignBaseViewGravity).show();
+    }
+    
+    public static GuideDialog show(View baseView, Drawable tipImage, int alignBaseViewGravity) {
+        return new GuideDialog(baseView, tipImage, alignBaseViewGravity).show();
+    }
+    
+    //执行方法
     public GuideDialog show() {
         super.show();
         return this;
@@ -86,6 +340,7 @@ public class GuideDialog extends CustomDialog {
         this.theme = theme;
         return this;
     }
+    
     public GuideDialog setCancelable(boolean cancelable) {
         this.privateCancelable = cancelable ? BOOLEAN.TRUE : BOOLEAN.FALSE;
         refreshUI();
@@ -101,15 +356,18 @@ public class GuideDialog extends CustomDialog {
         refreshUI();
         return this;
     }
+    
     public GuideDialog removeCustomView() {
         this.onBindView.clean();
         refreshUI();
         return this;
     }
+    
     public GuideDialog setEnterAnimResId(int enterAnimResId) {
         this.enterAnimResId = enterAnimResId;
         return this;
     }
+    
     public GuideDialog setExitAnimResId(int exitAnimResId) {
         this.exitAnimResId = exitAnimResId;
         return this;
@@ -120,6 +378,7 @@ public class GuideDialog extends CustomDialog {
         this.exitAnimResId = exitAnimResId;
         return this;
     }
+    
     public GuideDialog setAlign(ALIGN align) {
         this.align = align;
         return this;
@@ -152,14 +411,17 @@ public class GuideDialog extends CustomDialog {
         this.exitAnimDuration = exitAnimDuration;
         return this;
     }
+    
     public GuideDialog setDialogImplMode(DialogX.IMPL_MODE dialogImplMode) {
         this.dialogImplMode = dialogImplMode;
         return this;
     }
+    
     public GuideDialog setBkgInterceptTouch(boolean bkgInterceptTouch) {
         this.bkgInterceptTouch = bkgInterceptTouch;
         return this;
     }
+    
     public GuideDialog setAlignBaseViewGravity(View baseView, int alignGravity) {
         this.baseView = baseView;
         this.alignViewGravity = alignGravity;
@@ -170,7 +432,7 @@ public class GuideDialog extends CustomDialog {
     }
     
     public GuideDialog setAlignBaseViewGravity(View baseView, int alignGravity, int marginLeft,
-                                                int marginTop, int marginRight, int marginBottom) {
+                                               int marginTop, int marginRight, int marginBottom) {
         this.marginRelativeBaseView = new int[]{marginLeft, marginTop, marginRight, marginBottom};
         return setAlignBaseViewGravity(baseView, alignGravity);
     }
@@ -181,7 +443,7 @@ public class GuideDialog extends CustomDialog {
     }
     
     public GuideDialog setBaseViewMargin(int marginLeft, int marginTop,
-                                          int marginRight, int marginBottom) {
+                                         int marginRight, int marginBottom) {
         this.marginRelativeBaseView = new int[]{marginLeft, marginTop, marginRight, marginBottom};
         return this;
     }
@@ -217,6 +479,7 @@ public class GuideDialog extends CustomDialog {
         refreshUI();
         return this;
     }
+    
     /**
      * 设置对话框 UI 高度(单位:像素)
      *
@@ -229,9 +492,182 @@ public class GuideDialog extends CustomDialog {
         return this;
     }
     
-    
     public GuideDialog setOnBackgroundMaskClickListener(OnBackgroundMaskClickListener<CustomDialog> onBackgroundMaskClickListener) {
         this.onBackgroundMaskClickListener = onBackgroundMaskClickListener;
         return this;
     }
+    
+    @Override
+    protected void onDialogShow() {
+        super.onDialogShow();
+        if (baseView == null) {
+            super.setMaskColor(maskColor == -1 ? getColor(R.color.black50) : maskColor);
+        }
+    }
+    
+    View stageLightPathStub;
+    
+    @Override
+    protected void onDialogRefreshUI() {
+        super.onDialogRefreshUI();
+        if (onBindView == null && tipImage != null) {
+            getDialogImpl().boxCustom.setFocusable(false);
+            getDialogImpl().boxCustom.setFocusableInTouchMode(false);
+            getDialogImpl().boxCustom.setOnClickListener(null);
+            getDialogImpl().boxCustom.setClickable(false);
+            
+            ImageView imageView = new ImageView(getContext());
+            imageView.setImageDrawable(tipImage);
+            imageView.setAdjustViewBounds(true);
+            imageView.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+            onBindView = new OnBindView<CustomDialog>(imageView) {
+                @Override
+                public void onBind(CustomDialog dialog, View v) {
+                
+                }
+            };
+            onBindView.bindParent(getDialogImpl().boxCustom, me);
+        }
+        if (getOnStageLightPathClickListener() != null && baseView != null) {
+            stageLightPathStub = new View(getContext());
+            stageLightPathStub.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    if (!getOnStageLightPathClickListener().onClick(GuideDialog.this, v)) {
+                        dismiss();
+                    }
+                }
+            });
+            getDialogImpl().boxRoot.addView(stageLightPathStub);
+        } else {
+            if (stageLightPathStub != null && stageLightPathStub.getParent() instanceof ViewGroup) {
+                ((ViewGroup) stageLightPathStub.getParent()).removeView(stageLightPathStub);
+            }
+        }
+    }
+    
+    @Override
+    protected void onGetBaseViewLoc(int[] baseViewLoc) {
+        super.onGetBaseViewLoc(baseViewLoc);
+        if (getDialogImpl() == null) {
+            return;
+        }
+        Bitmap bkg = Bitmap.createBitmap(getDialogImpl().boxRoot.getWidth(), getDialogImpl().boxRoot.getHeight(), Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bkg);
+        
+        int x = baseViewLoc[0];
+        int y = baseViewLoc[1];
+        int w = baseViewLoc[2];
+        int h = baseViewLoc[3];
+        int hW = w / 2;
+        int hH = h / 2;
+        
+        if (stageLightPathStub != null && (stageLightPathStub.getX() != x || stageLightPathStub.getY() != y)) {
+            RelativeLayout.LayoutParams rLp = (RelativeLayout.LayoutParams) stageLightPathStub.getLayoutParams();
+            if (rLp == null) {
+                rLp = new RelativeLayout.LayoutParams(w, h);
+            } else {
+                rLp.width = w;
+                rLp.height = h;
+            }
+            stageLightPathStub.setLayoutParams(rLp);
+            stageLightPathStub.setX(x);
+            stageLightPathStub.setY(y);
+        }
+        
+        switch (stageLightType) {
+            case CIRCLE_OUTSIDE: {
+                int r = (int) Math.sqrt(hW * hW + hH * hH);
+                canvas.drawCircle(x + hW, y + hH, r, getStageLightPaint());
+            }
+            break;
+            case CIRCLE_INSIDE: {
+                int r = Math.min(w, h) / 2;
+                canvas.drawCircle(x + hW, y + hH, r, getStageLightPaint());
+            }
+            break;
+            case RECTANGLE: {
+                canvas.drawRoundRect(new RectF(x, y, x + w, y + h), stageLightFilletRadius, stageLightFilletRadius, getStageLightPaint());
+            }
+            break;
+            case SQUARE_INSIDE: {
+                int r = Math.min(w, h);
+                canvas.drawRoundRect(new RectF(x + hW - r / 2, y + hH - r / 2, x + hW - r / 2 + r, y + hH - r / 2 + r), stageLightFilletRadius, stageLightFilletRadius, getStageLightPaint());
+            }
+            break;
+            case SQUARE_OUTSIDE: {
+                int r = Math.max(w, h);
+                canvas.drawRoundRect(new RectF(x + hW - r / 2, y + hH - r / 2, x + hW - r / 2 + r, y + hH - r / 2 + r), stageLightFilletRadius, stageLightFilletRadius, getStageLightPaint());
+            }
+            break;
+        }
+        stageLightPaint.setXfermode(null);
+        canvas.drawColor(maskColor == -1 ? getColor(R.color.black50) : maskColor, PorterDuff.Mode.SRC_OUT);
+        BitmapDrawable bkgDrawable = new BitmapDrawable(getResources(), bkg);
+        getDialogImpl().boxRoot.setBackground(bkgDrawable);
+    }
+    
+    Paint stageLightPaint;
+    
+    private Paint getStageLightPaint() {
+        if (stageLightPaint == null) {
+            stageLightPaint = new Paint();
+            stageLightPaint.setColor(Color.RED);
+            stageLightPaint.setStyle(Paint.Style.FILL);
+            stageLightPaint.setAntiAlias(true);
+        }
+        return stageLightPaint;
+    }
+    
+    public STAGE_LIGHT_TYPE getStageLightType() {
+        return stageLightType;
+    }
+    
+    public GuideDialog setStageLightType(STAGE_LIGHT_TYPE stageLightType) {
+        this.stageLightType = stageLightType;
+        refreshUI();
+        return this;
+    }
+    
+    public Drawable getTipImage() {
+        return tipImage;
+    }
+    
+    public GuideDialog setTipImage(int tipImageResId) {
+        this.tipImage = getResources().getDrawable(tipImageResId);
+        refreshUI();
+        return this;
+    }
+    
+    public GuideDialog setTipImage(Bitmap tipImage) {
+        this.tipImage = new BitmapDrawable(getResources(), tipImage);
+        refreshUI();
+        return this;
+    }
+    
+    public GuideDialog setTipImage(Drawable tipImage) {
+        this.tipImage = tipImage;
+        refreshUI();
+        return this;
+    }
+    
+    public float getStageLightFilletRadius() {
+        return stageLightFilletRadius;
+    }
+    
+    public GuideDialog setStageLightFilletRadius(float stageLightFilletRadius) {
+        this.stageLightFilletRadius = stageLightFilletRadius;
+        refreshUI();
+        return this;
+    }
+    
+    public OnDialogButtonClickListener<GuideDialog> getOnStageLightPathClickListener() {
+        return onStageLightPathClickListener;
+    }
+    
+    public GuideDialog setOnStageLightPathClickListener(OnDialogButtonClickListener<GuideDialog> onStageLightPathClickListener) {
+        this.onStageLightPathClickListener = onStageLightPathClickListener;
+        refreshUI();
+        return this;
+    }
 }

+ 4 - 1
DialogX/src/main/java/com/kongzue/dialogx/dialogs/MessageDialog.java

@@ -342,6 +342,7 @@ public class MessageDialog extends BaseDialog {
                     });
                     bkgAlpha.start();
                     
+                    onDialogShow();
                     getDialogLifecycleCallback().onShow(me);
                     
                     if (style.messageDialogBlurSettings() != null && style.messageDialogBlurSettings().blurBackground()) {
@@ -474,6 +475,8 @@ public class MessageDialog extends BaseDialog {
                     }
                 }
             });
+            
+            onDialogInit();
         }
         
         public void refreshView() {
@@ -500,7 +503,6 @@ public class MessageDialog extends BaseDialog {
             boxRoot.setClickable(true);
             if (maskColor != -1) {
                 boxRoot.setBackgroundColor(maskColor);
-                boxRoot.setBkgAlpha(0f);
             }
             if (backgroundRadius > -1) {
                 GradientDrawable gradientDrawable = (GradientDrawable) bkg.getBackground();
@@ -704,6 +706,7 @@ public class MessageDialog extends BaseDialog {
             } else {
                 boxCustom.setVisibility(View.GONE);
             }
+            onDialogRefreshUI();
         }
         
         public void doDismiss(View v) {

+ 3 - 0
DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopMenu.java

@@ -276,6 +276,7 @@ public class PopMenu extends BaseDialog {
                 public void onShow() {
                     isShow = true;
                     preShow = false;
+                    onDialogShow();
                     getDialogLifecycleCallback().onShow(me);
                     refreshUI();
                 }
@@ -562,6 +563,7 @@ public class PopMenu extends BaseDialog {
                     }
                 }
             });
+            onDialogInit();
         }
         
         @Override
@@ -627,6 +629,7 @@ public class PopMenu extends BaseDialog {
                 boxBody.setMaxHeight(height);
                 boxBody.setMinimumHeight(height);
             }
+            onDialogRefreshUI();
         }
         
         @Override

+ 3 - 1
DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopNotification.java

@@ -526,7 +526,7 @@ public class PopNotification extends BaseDialog implements NoTouchInterface {
                     isShow = true;
                     preShow = false;
                     boxRoot.setAlpha(0f);
-                    
+                    onDialogShow();
                     getDialogLifecycleCallback().onShow(me);
                 }
                 
@@ -636,6 +636,7 @@ public class PopNotification extends BaseDialog implements NoTouchInterface {
                     }
                 }
             });
+            onDialogInit();
         }
         
         @Override
@@ -729,6 +730,7 @@ public class PopNotification extends BaseDialog implements NoTouchInterface {
             if (bodyMargin[2] != -1) rlp.rightMargin = bodyMargin[2];
             if (bodyMargin[3] != -1) rlp.bottomMargin = bodyMargin[3];
             boxBody.setLayoutParams(rlp);
+            onDialogRefreshUI();
         }
         
         @Override

+ 3 - 1
DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopTip.java

@@ -462,7 +462,7 @@ public class PopTip extends BaseDialog implements NoTouchInterface {
                     isShow = true;
                     preShow = false;
                     boxRoot.setAlpha(0f);
-                    
+                    onDialogShow();
                     getDialogLifecycleCallback().onShow(me);
                 }
                 
@@ -546,6 +546,7 @@ public class PopTip extends BaseDialog implements NoTouchInterface {
                     }
                 }
             });
+            onDialogInit();
         }
         
         @Override
@@ -618,6 +619,7 @@ public class PopTip extends BaseDialog implements NoTouchInterface {
             if (bodyMargin[2] != -1) rlp.rightMargin = bodyMargin[2];
             if (bodyMargin[3] != -1) rlp.bottomMargin = bodyMargin[3];
             boxBody.setLayoutParams(rlp);
+            onDialogRefreshUI();
         }
         
         @Override

+ 3 - 2
DialogX/src/main/java/com/kongzue/dialogx/dialogs/WaitDialog.java

@@ -368,7 +368,7 @@ public class WaitDialog extends BaseDialog {
                                     .alpha(1f)
                                     .setInterpolator(new DecelerateInterpolator())
                                     .setListener(null);
-                            
+                            onDialogShow();
                             getDialogLifecycleCallback().onShow(me());
                         }
                     });
@@ -414,6 +414,7 @@ public class WaitDialog extends BaseDialog {
                     return false;
                 }
             });
+            onDialogInit();
         }
         
         private float oldProgress;
@@ -479,7 +480,6 @@ public class WaitDialog extends BaseDialog {
             
             if (maskColor != -1) {
                 boxRoot.setBackgroundColor(maskColor);
-                boxRoot.setBkgAlpha(0f);
             }
             
             if (onBindView != null && onBindView.getCustomView() != null) {
@@ -507,6 +507,7 @@ public class WaitDialog extends BaseDialog {
             } else {
                 boxRoot.setClickable(false);
             }
+            onDialogRefreshUI();
         }
         
         public void doDismiss(final View v) {

+ 10 - 0
DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseDialog.java

@@ -30,6 +30,7 @@ import androidx.lifecycle.LifecycleOwner;
 
 import com.kongzue.dialogx.DialogX;
 import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.dialogs.BottomDialog;
 import com.kongzue.dialogx.impl.ActivityLifecycleImpl;
 import com.kongzue.dialogx.impl.DialogFragmentImpl;
 import com.kongzue.dialogx.util.ActivityRunnable;
@@ -835,4 +836,13 @@ public abstract class BaseDialog {
     }
     
     public abstract <D extends BaseDialog> D show();
+    
+    protected void onDialogShow() {
+    }
+    
+    protected void onDialogInit() {
+    }
+    
+    protected void onDialogRefreshUI() {
+    }
 }

+ 11 - 0
DialogX/src/main/java/com/kongzue/dialogx/util/views/DialogXBaseRelativeLayout.java

@@ -4,7 +4,9 @@ import android.app.Activity;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
+import android.graphics.Canvas;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
@@ -302,11 +304,20 @@ public class DialogXBaseRelativeLayout extends RelativeLayout {
         }
     }
     
+    float nowBkgAlphaValue;
+    
     public DialogXBaseRelativeLayout setBkgAlpha(float alpha) {
+        nowBkgAlphaValue = alpha;
         if (getBackground() != null) getBackground().mutate().setAlpha((int) (alpha * 255));
         return this;
     }
     
+    @Override
+    public void setBackground(Drawable background) {
+        background.setAlpha((int) (nowBkgAlphaValue * 255));
+        super.setBackground(background);
+    }
+    
     public boolean isBaseFocusable() {
         return focusable;
     }

+ 9 - 0
DialogX/src/main/res/anim/anim_dialogx_alpha_enter.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+
+    <alpha
+        android:duration="300"
+        android:fromAlpha="0.0"
+        android:toAlpha="1.0" />
+</set>

+ 44 - 3
app/src/main/java/com/kongzue/dialogxdemo/activity/MainActivity.java

@@ -48,6 +48,7 @@ import com.kongzue.dialogx.dialogs.BottomDialog;
 import com.kongzue.dialogx.dialogs.BottomMenu;
 import com.kongzue.dialogx.dialogs.CustomDialog;
 import com.kongzue.dialogx.dialogs.FullScreenDialog;
+import com.kongzue.dialogx.dialogs.GuideDialog;
 import com.kongzue.dialogx.dialogs.InputDialog;
 import com.kongzue.dialogx.dialogs.MessageDialog;
 import com.kongzue.dialogx.dialogs.PopMenu;
@@ -141,6 +142,9 @@ public class MainActivity extends BaseActivity {
     private MaterialButton btnFullScreenDialogFragment;
     private MaterialButton btnContextMenu;
     private TextView btnSelectMenu;
+    private MaterialButton btnShowGuide;
+    private MaterialButton btnShowGuideBaseView;
+    private MaterialButton btnShowGuideBaseViewRectangle;
     private MaterialButton btnShowBreak;
     private MaterialButton btnListDialog;
     private TextView txtVer;
@@ -200,6 +204,9 @@ public class MainActivity extends BaseActivity {
         btnFullScreenDialogFragment = findViewById(R.id.btn_fullScreenDialog_fragment);
         btnContextMenu = findViewById(R.id.btn_contextMenu);
         btnSelectMenu = findViewById(R.id.btn_selectMenu);
+        btnShowGuide = findViewById(R.id.btn_showGuide);
+        btnShowGuideBaseView = findViewById(R.id.btn_showGuideBaseView);
+        btnShowGuideBaseViewRectangle = findViewById(R.id.btn_showGuideBaseViewRectangle);
         btnShowBreak = findViewById(R.id.btn_showBreak);
         btnListDialog = findViewById(R.id.btn_listDialog);
         txtVer = findViewById(R.id.txt_ver);
@@ -322,7 +329,7 @@ public class MainActivity extends BaseActivity {
                 }
             }
         });
-    
+        
         grpStyle.addOnButtonCheckedListener(new MaterialButtonToggleGroup.OnButtonCheckedListener() {
             @Override
             public void onButtonChecked(MaterialButtonToggleGroup group, int checkedId, boolean isChecked) {
@@ -749,13 +756,47 @@ public class MainActivity extends BaseActivity {
             }
         });
         
+        btnShowGuide.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                GuideDialog.show(R.mipmap.img_guide_tip);
+            }
+        });
+        
+        btnShowGuideBaseView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                GuideDialog.show(btnFullScreenDialogLogin, R.mipmap.img_tip_login)
+                        .setBaseViewMarginTop(-dip2px(30));
+            }
+        });
+        
+        btnShowGuideBaseViewRectangle.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                GuideDialog.show(btnCustomDialogAlign,
+                                GuideDialog.STAGE_LIGHT_TYPE.RECTANGLE,
+                                R.mipmap.img_tip_login_clicktest)
+                        .setStageLightFilletRadius(dip2px(5))
+                        .setBaseViewMarginTop(-dip2px(30))
+                        .setOnStageLightPathClickListener(new OnDialogButtonClickListener<GuideDialog>() {
+                            @Override
+                            public boolean onClick(GuideDialog dialog, View v) {
+                                toast("点击了原按钮");
+                                btnCustomDialogAlign.callOnClick();
+                                return false;
+                            }
+                        });
+            }
+        });
+        
         btnShowBreak.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 jump(MainActivity.class, new JumpParameter().put("showBreak", true).put("fromActivity", getInstanceKey()));
             }
         });
-    
+        
         btnListDialog.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -911,7 +952,7 @@ public class MainActivity extends BaseActivity {
                         .setMaskColor(getResources().getColor(R.color.black30))
                         .setEnterAnimResId(R.anim.anim_custom_pop_enter)
                         .setExitAnimResId(R.anim.anim_custom_pop_exit)
-                        .setAlignBaseViewGravity(btnCustomDialogAlign, Gravity.TOP|Gravity.CENTER_HORIZONTAL)
+                        .setAlignBaseViewGravity(btnCustomDialogAlign, Gravity.TOP | Gravity.CENTER_HORIZONTAL)
                         .setBaseViewMarginBottom(-dip2px(45))
                         .show();
             }

+ 64 - 0
app/src/main/res/layout/activity_main.xml

@@ -926,6 +926,70 @@
 
             </LinearLayout>
 
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="15dp"
+                android:text="引导提示"
+                android:textColor="#dc000000"
+                android:textSize="14dp"
+                android:textStyle="bold" />
+
+            <com.kongzue.stacklabelview.StackLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal">
+
+                <com.google.android.material.button.MaterialButton
+                    android:id="@+id/btn_showGuide"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_margin="5dp"
+                    android:paddingLeft="15dp"
+                    android:paddingTop="10dp"
+                    android:paddingRight="15dp"
+                    android:paddingBottom="10dp"
+                    android:text="普通引导"
+                    android:textAllCaps="false"
+                    android:textColor="@color/white"
+                    android:textSize="13dp"
+                    android:textStyle="bold"
+                    app:cornerRadius="99dp" />
+
+                <com.google.android.material.button.MaterialButton
+                    android:id="@+id/btn_showGuideBaseView"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_margin="5dp"
+                    android:paddingLeft="15dp"
+                    android:paddingTop="10dp"
+                    android:paddingRight="15dp"
+                    android:paddingBottom="10dp"
+                    android:text="指定引导"
+                    android:textAllCaps="false"
+                    android:textColor="@color/white"
+                    android:textSize="13dp"
+                    android:textStyle="bold"
+                    app:cornerRadius="99dp" />
+
+                <com.google.android.material.button.MaterialButton
+                    android:id="@+id/btn_showGuideBaseViewRectangle"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_margin="5dp"
+                    android:paddingLeft="15dp"
+                    android:paddingTop="10dp"
+                    android:paddingRight="15dp"
+                    android:paddingBottom="10dp"
+                    android:text="指定引导(矩形)"
+                    android:textAllCaps="false"
+                    android:textColor="@color/white"
+                    android:textSize="13dp"
+                    android:textStyle="bold"
+                    app:cornerRadius="99dp" />
+
+            </com.kongzue.stacklabelview.StackLayout>
+
             <TextView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"

BIN=BIN
app/src/main/res/mipmap-xxhdpi/img_guide_tip.png


BIN=BIN
app/src/main/res/mipmap-xxhdpi/img_tip_login.png


BIN=BIN
app/src/main/res/mipmap-xxhdpi/img_tip_login_clicktest.png