浏览代码

add custom view impl.
build bottom dialog and bottom menu.

kongzue 4 年之前
父节点
当前提交
1cbc80df6c

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

@@ -4,6 +4,7 @@ import android.animation.Animator;
 import android.animation.ObjectAnimator;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
@@ -21,6 +22,7 @@ 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.BottomDialogTouchEventInterceptor;
 import com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout;
 import com.kongzue.dialogx.util.views.MaxRelativeLayout;
@@ -34,16 +36,45 @@ import com.kongzue.dialogx.util.views.MaxRelativeLayout;
  */
 public class BottomDialog extends BaseDialog {
     
+    protected OnBindView<BottomDialog> onBindView;
+    protected CharSequence title;
+    protected CharSequence message;
+    protected CharSequence cancelText;
+    
     private DialogLifecycleCallback<BottomDialog> dialogLifecycleCallback;
     
     protected BottomDialog me;
     
-    public BottomDialog() {
+    protected BottomDialog() {
         me = this;
     }
     
     private View dialogView;
     
+    public static BottomDialog build() {
+        return new BottomDialog();
+    }
+    
+    public BottomDialog(CharSequence title, CharSequence message) {
+        this.title = title;
+        this.message = message;
+    }
+    
+    public BottomDialog(CharSequence title, CharSequence message, OnBindView<BottomDialog> onBindView) {
+        this.title = title;
+        this.message = message;
+        this.onBindView = onBindView;
+    }
+    
+    public BottomDialog(CharSequence title, OnBindView<BottomDialog> onBindView) {
+        this.title = title;
+        this.onBindView = onBindView;
+    }
+    
+    public BottomDialog(OnBindView<BottomDialog> onBindView) {
+        this.onBindView = onBindView;
+    }
+    
     public void show() {
         int layoutId = R.layout.layout_dialogx_bottom_material;
         
@@ -106,6 +137,8 @@ public class BottomDialog extends BaseDialog {
                     getDialogLifecycleCallback().onShow(me);
                     
                     onDialogInit(dialogImpl);
+    
+                    if (onBindView!=null)onBindView.onBind(me, onBindView.getCustomView());
                 }
                 
                 @Override
@@ -114,6 +147,20 @@ public class BottomDialog extends BaseDialog {
                     getDialogLifecycleCallback().onDismiss(me);
                 }
             });
+            
+            boxRoot.setOnBackPressedListener(new OnBackPressedListener() {
+                @Override
+                public boolean onBackPressed() {
+                    if (onBackPressedListener != null && onBackPressedListener.onBackPressed()) {
+                        dismiss();
+                        return false;
+                    }
+                    if (cancelable) {
+                        dismiss();
+                    }
+                    return false;
+                }
+            });
         }
         
         private ViewTreeObserver.OnGlobalLayoutListener onContentViewLayoutChangeListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@@ -136,6 +183,10 @@ public class BottomDialog extends BaseDialog {
         @Override
         public void refreshView() {
             txtDialogTitle.getPaint().setFakeBoldText(true);
+            
+            showText(txtDialogTitle, title);
+            showText(txtDialogTip, message);
+            
             if (cancelable) {
                 boxRoot.setOnClickListener(new View.OnClickListener() {
                     @Override
@@ -146,15 +197,19 @@ public class BottomDialog extends BaseDialog {
             } else {
                 boxRoot.setOnClickListener(null);
             }
-            boxRoot.setOnBackPressedListener(new OnBackPressedListener() {
-                @Override
-                public boolean onBackPressed() {
-                    if (cancelable) {
-                        dismiss();
+            
+            if (onBindView != null) {
+                if (onBindView.getCustomView() != null) {
+                    if (onBindView.getCustomView().isAttachedToWindow()) {
+                        boxCustom.removeView(onBindView.getCustomView());
                     }
-                    return false;
+                    ViewGroup.LayoutParams lp = boxCustom.getLayoutParams();
+                    if (lp == null) {
+                        lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+                    }
+                    boxCustom.addView(onBindView.getCustomView(), lp);
                 }
-            });
+            }
         }
         
         @Override
@@ -175,6 +230,16 @@ public class BottomDialog extends BaseDialog {
                 }
             });
         }
+        
+        public void preDismiss() {
+            if (cancelable) {
+                doDismiss(boxRoot);
+            } else {
+                ObjectAnimator enterAnim = ObjectAnimator.ofFloat(bkg, "y", bkg.getY(), bkgEnterAimY);
+                enterAnim.setDuration(300);
+                enterAnim.start();
+            }
+        }
     }
     
     protected void onDialogInit(DialogImpl dialog) {
@@ -223,4 +288,61 @@ public class BottomDialog extends BaseDialog {
     public DialogImpl getDialogImpl() {
         return dialogImpl;
     }
+    
+    public CharSequence getTitle() {
+        return title;
+    }
+    
+    public BottomDialog setTitle(CharSequence title) {
+        this.title = title;
+        refreshUI();
+        return this;
+    }
+    
+    public CharSequence getMessage() {
+        return message;
+    }
+    
+    public BottomDialog setMessage(CharSequence message) {
+        this.message = message;
+        refreshUI();
+        return this;
+    }
+    
+    public CharSequence getCancelText() {
+        return cancelText;
+    }
+    
+    public BottomDialog setCancelText(CharSequence cancelText) {
+        this.cancelText = cancelText;
+        refreshUI();
+        return this;
+    }
+    
+    public BottomDialog setCustomView(OnBindView<BottomDialog> 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 OnBackPressedListener getOnBackPressedListener() {
+        return onBackPressedListener;
+    }
+    
+    public BottomDialog setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
+        this.onBackPressedListener = onBackPressedListener;
+        refreshUI();
+        return this;
+    }
 }

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

@@ -8,6 +8,7 @@ import android.widget.RelativeLayout;
 import android.widget.Toast;
 
 import com.kongzue.dialogx.R;
+import com.kongzue.dialogx.interfaces.OnBackPressedListener;
 import com.kongzue.dialogx.util.NormalMenuArrayAdapter;
 import com.kongzue.dialogx.util.views.BottomDialogListView;
 
@@ -25,6 +26,14 @@ import static android.view.View.OVER_SCROLL_NEVER;
  */
 public class BottomMenu extends BottomDialog {
     
+    protected BottomMenu() {
+        me = this;
+    }
+    
+    public static BottomMenu build() {
+        return new BottomMenu();
+    }
+    
     private OnIconChangeCallBack onIconChangeCallBack;
     private BottomDialogListView listView;
     private BaseAdapter menuArrayAdapter;
@@ -94,4 +103,14 @@ public class BottomMenu extends BottomDialog {
     public interface OnIconChangeCallBack {
         int getIcon(int index, String menuText);
     }
+    
+    public OnBackPressedListener getOnBackPressedListener() {
+        return onBackPressedListener;
+    }
+    
+    public BottomMenu setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
+        this.onBackPressedListener = onBackPressedListener;
+        refreshUI();
+        return this;
+    }
 }

+ 21 - 1
DialogX/src/main/java/com/kongzue/dialogx/dialogs/InputDialog.java

@@ -1,6 +1,9 @@
 package com.kongzue.dialogx.dialogs;
 
+import android.view.View;
+
 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;
@@ -15,7 +18,7 @@ import com.kongzue.dialogx.util.TextInfo;
  */
 public class InputDialog extends MessageDialog {
     
-    public InputDialog() {
+    protected InputDialog() {
         me = this;
     }
     
@@ -326,4 +329,21 @@ public class InputDialog extends MessageDialog {
         this.autoShowInputKeyboard = autoShowInputKeyboard;
         return this;
     }
+    
+    public InputDialog setCustomView(OnBindView<MessageDialog> 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;
+    }
 }

+ 108 - 69
DialogX/src/main/java/com/kongzue/dialogx/dialogs/MessageDialog.java

@@ -25,6 +25,7 @@ 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.util.views.BlurView;
@@ -42,11 +43,12 @@ import com.kongzue.dialogx.util.TextInfo;
  */
 public class MessageDialog extends BaseDialog {
     
+    protected OnBindView<MessageDialog> onBindView;
     protected MessageDialog me;
     
     private DialogLifecycleCallback<MessageDialog> dialogLifecycleCallback;
     
-    public MessageDialog() {
+    protected MessageDialog() {
         me = this;
     }
     
@@ -168,7 +170,7 @@ public class MessageDialog extends BaseDialog {
             init();
             refreshView();
         }
-    
+        
         public void init() {
             txtDialogTitle.getPaint().setFakeBoldText(true);
             btnSelectNegative.getPaint().setFakeBoldText(true);
@@ -217,6 +219,8 @@ public class MessageDialog extends BaseDialog {
                             }
                         }, 300);
                     }
+    
+                    if (onBindView!=null)onBindView.onBind(me, onBindView.getCustomView());
                 }
                 
                 @Override
@@ -225,8 +229,79 @@ public class MessageDialog extends BaseDialog {
                     getDialogLifecycleCallback().onDismiss(me);
                 }
             });
+            
+            boxRoot.setOnBackPressedListener(new OnBackPressedListener() {
+                @Override
+                public boolean onBackPressed() {
+                    if (onBackPressedListener != null && onBackPressedListener.onBackPressed()) {
+                        dismiss();
+                        return false;
+                    }
+                    if (cancelable) {
+                        dismiss();
+                    }
+                    return false;
+                }
+            });
+            btnSelectPositive.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    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.onClick(me, v)) {
+                                doDismiss(v);
+                            }
+                        }
+                    } else {
+                        doDismiss(v);
+                    }
+                }
+            });
+            btnSelectNegative.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    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 (!cancelButtonClickListener.onClick(me, v)) {
+                                doDismiss(v);
+                            }
+                        }
+                    } else {
+                        doDismiss(v);
+                    }
+                }
+            });
+            btnSelectOther.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    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 (!otherButtonClickListener.onClick(me, v)) {
+                                doDismiss(v);
+                            }
+                        }
+                    } else {
+                        doDismiss(v);
+                    }
+                }
+            });
         }
-    
+        
         public void refreshView() {
             bkg.setMaxWidth(DialogX.dialogMaxWidth);
             if (me instanceof InputDialog) {
@@ -405,75 +480,22 @@ public class MessageDialog extends BaseDialog {
             } else {
                 boxRoot.setOnClickListener(null);
             }
-            boxRoot.setOnBackPressedListener(new OnBackPressedListener() {
-                @Override
-                public boolean onBackPressed() {
-                    if (cancelable) {
-                        dismiss();
-                    }
-                    return false;
-                }
-            });
-            btnSelectPositive.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    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.onClick(me, v)) {
-                                doDismiss(v);
-                            }
-                        }
-                    } else {
-                        doDismiss(v);
-                    }
-                }
-            });
-            btnSelectNegative.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    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 (!cancelButtonClickListener.onClick(me, v)) {
-                                doDismiss(v);
-                            }
-                        }
-                    } else {
-                        doDismiss(v);
-                    }
+            
+            if (onBindView != null && onBindView.getCustomView() != null) {
+                if (onBindView.getCustomView().isAttachedToWindow()) {
+                    boxCustom.removeView(onBindView.getCustomView());
                 }
-            });
-            btnSelectOther.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    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 (!otherButtonClickListener.onClick(me, v)) {
-                                doDismiss(v);
-                            }
-                        }
-                    } else {
-                        doDismiss(v);
-                    }
+                ViewGroup.LayoutParams lp = boxCustom.getLayoutParams();
+                if (lp == null) {
+                    lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                 }
-            });
-            
+                boxCustom.setVisibility(View.VISIBLE);
+                boxCustom.addView(onBindView.getCustomView(), lp);
+            } else {
+                boxCustom.setVisibility(View.GONE);
+            }
         }
-    
+        
         public void doDismiss(View v) {
             if (v != null) v.setEnabled(false);
             
@@ -718,4 +740,21 @@ public class MessageDialog extends BaseDialog {
     public DialogImpl getDialogImpl() {
         return dialogImpl;
     }
+    
+    public MessageDialog setCustomView(OnBindView<MessageDialog> 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;
+    }
 }

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

@@ -18,7 +18,7 @@ public class TipDialog extends WaitDialog {
         return tipDialog;
     }
     
-    private TipDialog() {
+    protected TipDialog() {
         super();
     }
     

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

@@ -3,6 +3,7 @@ package com.kongzue.dialogx.dialogs;
 import android.animation.Animator;
 import android.graphics.Color;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
@@ -15,6 +16,8 @@ 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.util.views.BlurView;
 import com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout;
 import com.kongzue.dialogx.util.views.MaxRelativeLayout;
@@ -31,6 +34,8 @@ import java.lang.ref.WeakReference;
  */
 public class WaitDialog extends BaseDialog {
     
+    protected OnBindView<WaitDialog> onBindView;
+    
     public enum TYPE {
         NONE,
         SUCCESS,
@@ -47,6 +52,7 @@ public class WaitDialog extends BaseDialog {
     
     protected WaitDialog() {
         me = new WeakReference<>(this);
+        cancelable = false;
     }
     
     public static WaitDialog show(CharSequence message) {
@@ -63,7 +69,7 @@ public class WaitDialog extends BaseDialog {
         }
     }
     
-    public static WaitDialog show(CharSequence message,float progress) {
+    public static WaitDialog show(CharSequence message, float progress) {
         DialogImpl dialogImpl = me().dialogImpl;
         me().message = message;
         if (dialogImpl != null) {
@@ -133,7 +139,7 @@ public class WaitDialog extends BaseDialog {
             init();
             refreshView();
         }
-    
+        
         public void init() {
             blurView.setRadiusPx(dip2px(15));
             boxRoot.setClickable(true);
@@ -157,6 +163,8 @@ public class WaitDialog extends BaseDialog {
                             getDialogLifecycleCallback().onShow(me());
                         }
                     });
+                    
+                    if (onBindView != null) onBindView.onBind(me.get(), onBindView.getCustomView());
                 }
                 
                 @Override
@@ -177,10 +185,24 @@ public class WaitDialog extends BaseDialog {
                     }
                 }, 100);
             }
+            
+            boxRoot.setOnBackPressedListener(new OnBackPressedListener() {
+                @Override
+                public boolean onBackPressed() {
+                    if (onBackPressedListener != null && onBackPressedListener.onBackPressed()) {
+                        dismiss();
+                        return false;
+                    }
+                    if (cancelable) {
+                        dismiss();
+                    }
+                    return false;
+                }
+            });
         }
         
         private float oldProgress;
-    
+        
         public void refreshView() {
             if (style.overrideWaitTipRes() != null) {
                 int overrideBackgroundColorRes = style.overrideWaitTipRes().overrideBackgroundColorRes(isLightTheme());
@@ -213,6 +235,22 @@ public class WaitDialog extends BaseDialog {
             }
             
             showText(txtInfo, message);
+            
+            if (onBindView != null && onBindView.getCustomView() != null) {
+                if (onBindView.getCustomView().isAttachedToWindow()) {
+                    boxCustomView.removeView(onBindView.getCustomView());
+                }
+                ViewGroup.LayoutParams lp = boxCustomView.getLayoutParams();
+                if (lp == null) {
+                    lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+                }
+                boxCustomView.setVisibility(View.VISIBLE);
+                boxProgress.setVisibility(View.GONE);
+                boxCustomView.addView(onBindView.getCustomView(), lp);
+            } else {
+                boxCustomView.setVisibility(View.GONE);
+                boxProgress.setVisibility(View.VISIBLE);
+            }
         }
         
         public void doDismiss(View v) {
@@ -312,4 +350,31 @@ public class WaitDialog extends BaseDialog {
     public DialogImpl getDialogImpl() {
         return dialogImpl;
     }
+    
+    public WaitDialog setCustomView(OnBindView<WaitDialog> 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;
+    }
 }

+ 50 - 0
DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBindView.java

@@ -0,0 +1,50 @@
+package com.kongzue.dialogx.interfaces;
+
+import android.view.LayoutInflater;
+import android.view.View;
+
+/**
+ * @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<D> {
+    int layoutResId;
+    View customView;
+    
+    public OnBindView(int layoutResId) {
+        this.layoutResId = layoutResId;
+        customView = LayoutInflater.from(BaseDialog.getContext()).inflate(layoutResId, null);
+    }
+    
+    public OnBindView(View customView) {
+        this.customView = customView;
+    }
+    
+    public abstract void onBind(D dialog, View v);
+    
+    public int getLayoutResId() {
+        return layoutResId;
+    }
+    
+    public OnBindView<D> setLayoutResId(int layoutResId) {
+        this.layoutResId = layoutResId;
+        return this;
+    }
+    
+    public View getCustomView() {
+        return customView;
+    }
+    
+    public OnBindView<D> setCustomView(View customView) {
+        this.customView = customView;
+        return this;
+    }
+    
+    public void clean() {
+        layoutResId = 0;
+        customView = null;
+    }
+}

+ 24 - 4
DialogX/src/main/java/com/kongzue/dialogx/util/BottomDialogTouchEventInterceptor.java

@@ -2,6 +2,7 @@ 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;
@@ -23,11 +24,13 @@ public class BottomDialogTouchEventInterceptor {
      * 下边三个值用于判断触控过程,
      * isBkgTouched:标记是否已按下
      * bkgTouchDownY:记录起始触控位置
-     * scrolledY:记录 ScrollView 已滚动过的距离,下次触控事件将接着上次的位置继续滑动。
+     * scrolledY:记录 ScrollView 已滚动过的距离,下次触控事件将接着上次的位置继续滑动
+     * bkgOldY:记录按下时 bkg 的位置,用于区分松开手指时,bkg 移动的方向。
      */
     private boolean isBkgTouched = false;
     private float bkgTouchDownY;
     private float scrolledY;
+    private float bkgOldY;
     /**
      * 0:bkg接收触控事件,-1:scrollView进行滚动
      * 此标记的意义在于,当从 [scrollView滚动] 与 [bkg接收触控事件] 状态切换时,
@@ -57,6 +60,7 @@ public class BottomDialogTouchEventInterceptor {
                     case MotionEvent.ACTION_DOWN:
                         bkgTouchDownY = event.getY();
                         isBkgTouched = true;
+                        bkgOldY = impl.bkg.getY();
                         break;
                     case MotionEvent.ACTION_MOVE:
                         if (isBkgTouched) {
@@ -95,13 +99,29 @@ public class BottomDialogTouchEventInterceptor {
                     case MotionEvent.ACTION_CANCEL:
                         scrolledY = impl.scrollView.getScrollY();
                         isBkgTouched = false;
-                        if (impl.bkg.getY() > 0) {
-                            if (impl.bkg.getY() < impl.bkgEnterAimY + dip2px(35)) {
+                        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 {
-                                impl.doDismiss(impl.boxRoot);
+                                ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.bkg, "y", impl.bkg.getY(), impl.bkgEnterAimY);
+                                enterAnim.setDuration(300);
+                                enterAnim.start();
                             }
                         }
                         break;

+ 2 - 3
DialogX/src/main/res/layout/layout_dialogx_bottom_material.xml

@@ -65,7 +65,7 @@
                             android:layout_width="match_parent"
                             android:layout_height="wrap_content"
                             android:layout_marginHorizontal="20dp"
-                            android:paddingBottom="15dp"
+                            android:paddingBottom="5dp"
                             android:text="This is content text."
                             android:textColor="@color/black70"
                             android:textSize="16dp" />
@@ -73,8 +73,7 @@
                         <RelativeLayout
                             android:id="@+id/box_custom"
                             android:layout_width="match_parent"
-                            android:layout_height="wrap_content"
-                            android:layout_marginTop="-10dp"/>
+                            android:layout_height="wrap_content"/>
 
                     </LinearLayout>
 

+ 2 - 2
README.md

@@ -7,7 +7,7 @@ DialogX 采用分离设计,默认自带 Material 主题,可选引入 IOS、K
 
 更低的耦合度,无论对话框是否正在显示,请肆意执行的 Activity 关闭逻辑,而无需担心引发 WindowLeaked 错误。
 
-目前开发进度:55% [=========== · · · · · · · · · ]
+目前开发进度:60% [●●●●●●●●●●●●○○○○○○○○]
 
 ## 开发计划
 
@@ -18,7 +18,7 @@ DialogX开发计划
     WaitDialog                              √
     TipDialog(extends WaitDialog)           √
     BottomDialog                            -
-    BottomMenu                              ×
+    BottomMenu                              -
     FullScreenDialog                        ×
     CustomDialog                            ×
     PopTip                                  ×

+ 0 - 1
app/build.gradle

@@ -28,7 +28,6 @@ repositories{
 }
 dependencies {
     implementation fileTree(dir: "libs", include: ["*.jar"])
-    implementation 'androidx.appcompat:appcompat:1.2.0'
     implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
     implementation 'com.kongzue.baseframeworkx:baseframework:6.7.6'
     implementation project(':DialogX')

+ 93 - 21
app/src/main/java/com/kongzue/dialogxdemo/MainActivity.java

@@ -2,6 +2,7 @@ package com.kongzue.dialogxdemo;
 
 import android.graphics.Color;
 import android.view.View;
+import android.widget.EditText;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.RadioButton;
@@ -23,6 +24,10 @@ import com.kongzue.dialogx.dialogs.InputDialog;
 import com.kongzue.dialogx.dialogs.MessageDialog;
 import com.kongzue.dialogx.dialogs.TipDialog;
 import com.kongzue.dialogx.dialogs.WaitDialog;
+import com.kongzue.dialogx.interfaces.BaseDialog;
+import com.kongzue.dialogx.interfaces.OnBackPressedListener;
+import com.kongzue.dialogx.interfaces.OnBindView;
+import com.kongzue.dialogx.interfaces.OnDialogButtonClickListener;
 import com.kongzue.dialogx.style.IOSStyle;
 import com.kongzue.dialogx.style.KongzueStyle;
 import com.kongzue.dialogx.style.MIUIStyle;
@@ -57,9 +62,9 @@ public class MainActivity extends BaseActivity {
     private TextView btnTipWarning;
     private TextView btnTipError;
     private TextView btnTipProgress;
-    private TextView btnShowBreak;
     private TextView btnBottomDialog;
     private TextView btnBottomMenu;
+    private TextView btnBottomReply;
     private TextView btnCustomMessageDialog;
     private TextView btnCustomInputDialog;
     private TextView btnCustomBottomMenu;
@@ -67,6 +72,7 @@ public class MainActivity extends BaseActivity {
     private TextView btnCustomDialog;
     private TextView btnFullScreenDialogWebPage;
     private TextView btnFullScreenDialogLogin;
+    private TextView btnShowBreak;
     
     @Override
     public void initViews() {
@@ -92,9 +98,9 @@ public class MainActivity extends BaseActivity {
         btnTipWarning = findViewById(R.id.btn_tipWarning);
         btnTipError = findViewById(R.id.btn_tipError);
         btnTipProgress = findViewById(R.id.btn_tipProgress);
-        btnShowBreak = findViewById(R.id.btn_showBreak);
         btnBottomDialog = findViewById(R.id.btn_bottom_dialog);
         btnBottomMenu = findViewById(R.id.btn_bottom_menu);
+        btnBottomReply = findViewById(R.id.btn_bottom_reply);
         btnCustomMessageDialog = findViewById(R.id.btn_customMessageDialog);
         btnCustomInputDialog = findViewById(R.id.btn_customInputDialog);
         btnCustomBottomMenu = findViewById(R.id.btn_customBottomMenu);
@@ -102,6 +108,7 @@ public class MainActivity extends BaseActivity {
         btnCustomDialog = findViewById(R.id.btn_customDialog);
         btnFullScreenDialogWebPage = findViewById(R.id.btn_fullScreenDialog_webPage);
         btnFullScreenDialogLogin = findViewById(R.id.btn_fullScreenDialog_login);
+        btnShowBreak = findViewById(R.id.btn_showBreak);
     }
     
     @Override
@@ -112,6 +119,10 @@ public class MainActivity extends BaseActivity {
     //用于模拟进度提示
     private CycleRunner cycleRunner;
     private float progress = 0;
+    private int waitId;
+    
+    private TextView btnReplyCommit;
+    private EditText editReplyCommit;
     
     @Override
     public void setEvents() {
@@ -223,17 +234,39 @@ public class MainActivity extends BaseActivity {
         btnTipProgress.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
+                waitId = 0;
                 progress = 0;
-                WaitDialog.show("连接服务器...");
+                WaitDialog.show("假装连接...").setOnBackPressedListener(new OnBackPressedListener() {
+                    @Override
+                    public boolean onBackPressed() {
+                        toast("点击返回");
+                        MessageDialog.show("正在进行", "是否取消?", "是", "否").setOkButton(new OnDialogButtonClickListener() {
+                            @Override
+                            public boolean onClick(BaseDialog baseDialog, View v) {
+                                waitId = -1;
+                                WaitDialog.dismiss();
+                                return false;
+                            }
+                        });
+                        return false;
+                    }
+                });
                 runOnMainDelayed(new Runnable() {
                     @Override
                     public void run() {
+                        if (waitId != 0) {
+                            return;
+                        }
                         cycleRunner = runOnMainCycle(new Runnable() {
                             @Override
                             public void run() {
+                                if (waitId != 0) {
+                                    cycleRunner.cancel();
+                                    return;
+                                }
                                 progress = progress + 0.1f;
                                 if (progress < 1f) {
-                                    WaitDialog.show("正在加载" + ((int) (progress * 100)) + "%", progress);
+                                    WaitDialog.show("假装加载" + ((int) (progress * 100)) + "%", progress);
                                 } else {
                                     TipDialog.show("加载完成", WaitDialog.TYPE.SUCCESS);
                                     cycleRunner.cancel();
@@ -244,40 +277,79 @@ public class MainActivity extends BaseActivity {
                 }, 3000);
             }
         });
-    
+        
         btnBottomDialog.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                new BottomDialog().show();
+                new BottomDialog("标题", "这里是对话框内容。\n你可以向下滑动来关闭这个对话框。\n底部对话框也支持自定义布局扩展使用方式。",
+                        new OnBindView<BottomDialog>(R.layout.layout_custom_view) {
+                            @Override
+                            public void onBind(BottomDialog dialog, View v) {
+                            
+                            }
+                        }).show();
             }
         });
         
         btnBottomMenu.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                new BottomMenu().setOnIconChangeCallBack(new BottomMenu.OnIconChangeCallBack() {
+                BottomMenu.build().setOnIconChangeCallBack(new BottomMenu.OnIconChangeCallBack() {
                     @Override
                     public int getIcon(int index, String menuText) {
-                        switch (menuText){
-                            case "添加":      return R.mipmap.img_dialogx_demo_add;
-                            case "查看":      return R.mipmap.img_dialogx_demo_view;
-                            case "编辑":      return R.mipmap.img_dialogx_demo_edit;
-                            case "删除":      return R.mipmap.img_dialogx_demo_delete;
-                            case "分享":      return R.mipmap.img_dialogx_demo_share;
-                            case "评论":      return R.mipmap.img_dialogx_demo_comment;
-                            case "下载":      return R.mipmap.img_dialogx_demo_download;
-                            case "收藏":      return R.mipmap.img_dialogx_demo_favorite;
-                            case "赞!":      return R.mipmap.img_dialogx_demo_link;
-                            case "不喜欢":     return R.mipmap.img_dialogx_demo_dislike;
-                            case "所属专辑":    return R.mipmap.img_dialogx_demo_album;
-                            case "复制链接":    return R.mipmap.img_dialogx_demo_link;
-                            case "类似推荐":    return R.mipmap.img_dialogx_demo_recommend;
+                        switch (menuText) {
+                            case "添加":
+                                return R.mipmap.img_dialogx_demo_add;
+                            case "查看":
+                                return R.mipmap.img_dialogx_demo_view;
+                            case "编辑":
+                                return R.mipmap.img_dialogx_demo_edit;
+                            case "删除":
+                                return R.mipmap.img_dialogx_demo_delete;
+                            case "分享":
+                                return R.mipmap.img_dialogx_demo_share;
+                            case "评论":
+                                return R.mipmap.img_dialogx_demo_comment;
+                            case "下载":
+                                return R.mipmap.img_dialogx_demo_download;
+                            case "收藏":
+                                return R.mipmap.img_dialogx_demo_favorite;
+                            case "赞!":
+                                return R.mipmap.img_dialogx_demo_link;
+                            case "不喜欢":
+                                return R.mipmap.img_dialogx_demo_dislike;
+                            case "所属专辑":
+                                return R.mipmap.img_dialogx_demo_album;
+                            case "复制链接":
+                                return R.mipmap.img_dialogx_demo_link;
+                            case "类似推荐":
+                                return R.mipmap.img_dialogx_demo_recommend;
                         }
                         return 0;
                     }
                 }).show();
             }
         });
+        
+        btnBottomReply.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                BottomDialog.build().setCustomView(new OnBindView<BottomDialog>(R.layout.layout_custom_reply) {
+                    @Override
+                    public void onBind(BottomDialog dialog, View v) {
+                        btnReplyCommit = v.findViewById(R.id.btn_reply_commit);
+                        editReplyCommit = v.findViewById(R.id.edit_reply_commit);
+    
+                        btnReplyCommit.setOnClickListener(new View.OnClickListener() {
+                            @Override
+                            public void onClick(View v) {
+                                toast("提交内容:\n"+editReplyCommit.getText().toString());
+                            }
+                        });
+                    }
+                }).show();
+            }
+        });
     }
     
     @Override

+ 55 - 0
app/src/main/res/layout/layout_custom_reply.xml

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center_vertical"
+        android:orientation="horizontal">
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="35dp"
+            android:layout_weight="1"
+            android:gravity="center_vertical"
+            android:paddingHorizontal="15dp"
+            android:text="回复"
+            android:textColor="@color/black90"
+            android:textSize="16dp" />
+
+        <TextView
+            android:id="@+id/btn_reply_commit"
+            android:layout_width="wrap_content"
+            android:layout_height="35dp"
+            android:gravity="center_vertical"
+            android:paddingHorizontal="15dp"
+            android:text="发布"
+            android:textColor="@color/dialogxColorBlue"
+            android:textSize="16dp" />
+
+    </LinearLayout>
+
+    <EditText
+        android:id="@+id/edit_reply_commit"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@color/empty"
+        android:gravity="left|top"
+        android:hint="请输入内容..."
+        android:inputType="textMultiLine"
+        android:minHeight="100dp"
+        android:paddingHorizontal="15dp"
+        android:paddingVertical="5dp"
+        android:textSize="16dp" />
+
+    <CheckBox
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="10dp"
+        android:layout_marginBottom="10dp"
+        android:text="回复并转发" />
+
+</LinearLayout>

+ 29 - 0
app/src/main/res/layout/layout_custom_view.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center_horizontal"
+        android:orientation="vertical"
+        android:paddingBottom="15dp"
+        android:paddingTop="15dp">
+
+        <ImageView
+            android:id="@+id/img_ico"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@mipmap/ico_wechat" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="10dp"
+            android:text="这里是自定义Layout测试"
+            android:textSize="12dp" />
+
+    </LinearLayout>
+
+</RelativeLayout>

二进制
app/src/main/res/mipmap-xxhdpi/ico_wechat.png