parent
							
								
									1a32d43d1c
								
							
						
					
					
						commit
						5b11f21f85
					
				| @ -0,0 +1 @@ | ||||
| /build | ||||
| @ -0,0 +1,90 @@ | ||||
| apply plugin: 'com.android.library' | ||||
| apply plugin: 'android-maven' | ||||
| 
 | ||||
| def siteUrl = 'https://github.com/kongzue/DialogX' //项目在github主页地址 | ||||
| def gitUrl = 'https://github.com/kongzue/DialogX.git'   //Git仓库的地址 | ||||
| 
 | ||||
| group = "com.kongzue.dialogx" | ||||
| 
 | ||||
| android { | ||||
|     compileSdkVersion 30 | ||||
| 
 | ||||
|     defaultConfig { | ||||
|         minSdkVersion 21 | ||||
|         targetSdkVersion 30 | ||||
|         versionCode 10 | ||||
|         versionName "1.0" | ||||
| 
 | ||||
|         consumerProguardFiles "consumer-rules.pro" | ||||
| 
 | ||||
|         renderscriptTargetApi 21 | ||||
|         renderscriptSupportModeEnabled true    // Enable RS support | ||||
|     } | ||||
| 
 | ||||
|     buildTypes { | ||||
|         release { | ||||
|             minifyEnabled false | ||||
|             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| //install { | ||||
| //    repositories.mavenInstaller { | ||||
| //        // This generates POM.xml with proper parameters | ||||
| //        pom { | ||||
| //            project { | ||||
| //                packaging 'aar' | ||||
| //                name 'dialogx' | ||||
| //                url siteUrl | ||||
| //                licenses { | ||||
| //                    license { | ||||
| //                        name 'The Apache Software License, Version 2.0' | ||||
| //                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt' | ||||
| //                    } | ||||
| //                } | ||||
| //                developers { | ||||
| //                    developer { | ||||
| //                        id 'myzchh'//设置自己ID | ||||
| //                        name 'myzchh'//设置自己名字 | ||||
| //                        email 'myzcxhh@live.cn'//设置自己邮箱 | ||||
| //                    } | ||||
| //                } | ||||
| //                scm { | ||||
| //                    connection gitUrl | ||||
| //                    developerConnection gitUrl | ||||
| //                    url siteUrl | ||||
| //                } | ||||
| //            } | ||||
| //        } | ||||
| //    } | ||||
| //} | ||||
| task sourcesJar(type: Jar) { | ||||
|     from android.sourceSets.main.java.srcDirs | ||||
|     classifier = 'sources' | ||||
| } | ||||
| 
 | ||||
| artifacts { | ||||
|     archives sourcesJar | ||||
| } | ||||
| 
 | ||||
| //Properties properties = new Properties() | ||||
| //properties.load(project.rootProject.file('local.properties').newDataInputStream()) | ||||
| //bintray { | ||||
| //    user = properties.getProperty("bintray.user") | ||||
| //    key = properties.getProperty("bintray.apikey") | ||||
| //    configurations = ['archives'] | ||||
| //    pkg { | ||||
| //        repo = "maven" | ||||
| //        name = "dialogX" //项目在JCenter的名字 | ||||
| //        websiteUrl = siteUrl | ||||
| //        vcsUrl = gitUrl | ||||
| //        licenses = ["Apache-2.0"] | ||||
| //        publish = true | ||||
| //    } | ||||
| //} | ||||
| dependencies { | ||||
|     implementation fileTree(dir: "libs", include: ["*.jar"]) | ||||
|     implementation 'androidx.appcompat:appcompat:1.2.0+' | ||||
|     api files('libs\\DialogXInterface.jar') | ||||
| } | ||||
| @ -0,0 +1,21 @@ | ||||
| # Add project specific ProGuard rules here. | ||||
| # You can control the set of applied configuration files using the | ||||
| # proguardFiles setting in build.gradle. | ||||
| # | ||||
| # For more details, see | ||||
| #   http://developer.android.com/guide/developing/tools/proguard.html | ||||
| 
 | ||||
| # If your project uses WebView with JS, uncomment the following | ||||
| # and specify the fully qualified class name to the JavaScript interface | ||||
| # class: | ||||
| #-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||||
| #   public *; | ||||
| #} | ||||
| 
 | ||||
| # Uncomment this to preserve the line number information for | ||||
| # debugging stack traces. | ||||
| #-keepattributes SourceFile,LineNumberTable | ||||
| 
 | ||||
| # If you keep the line number information, uncomment this to | ||||
| # hide the original source file name. | ||||
| #-renamesourcefileattribute SourceFile | ||||
| @ -0,0 +1,4 @@ | ||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     package="com.kongzue.dialogx"> | ||||
| 
 | ||||
| </manifest> | ||||
| @ -0,0 +1,131 @@ | ||||
| package com.kongzue.dialogx; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.util.Log; | ||||
| 
 | ||||
| import com.kongzue.dialogx.interfaces.BaseDialog; | ||||
| import com.kongzue.dialogx.interfaces.DialogLifecycleCallback; | ||||
| import com.kongzue.dialogx.interfaces.DialogXStyle; | ||||
| import com.kongzue.dialogx.style.MaterialStyle; | ||||
| 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/21 17:07 | ||||
|  */ | ||||
| public class DialogX { | ||||
|      | ||||
|     public static final String ERROR_INIT_TIPS = "DialogX.init: 初始化异常,context 为 null 或未初始化,详情请查看 https://github.com/kongzue/DialogX/wiki"; | ||||
|      | ||||
|     //开启日志
 | ||||
|     public static boolean DEBUGMODE = true; | ||||
|      | ||||
|     //全局主题风格
 | ||||
|     public static DialogXStyle globalStyle = MaterialStyle.style(); | ||||
|      | ||||
|     //全局对话框明暗风格
 | ||||
|     public static DialogX.THEME globalTheme = DialogX.THEME.LIGHT; | ||||
|      | ||||
|     //TipDialog 和 WaitDialog 明暗风格,不设置则默认根据 globalTheme 定义
 | ||||
|     public static DialogX.THEME tipTheme; | ||||
|      | ||||
|     //DialogX 实现模式(实验性功能)
 | ||||
|     public static IMPL_MODE implIMPLMode = IMPL_MODE.VIEW; | ||||
|      | ||||
|     //对话框最大宽度(像素)
 | ||||
|     public static int dialogMaxWidth; | ||||
|      | ||||
|     //是否允许 InputDialog 自动弹出键盘
 | ||||
|     public static boolean autoShowInputKeyboard = true; | ||||
|      | ||||
|     //同时只显示一个 PopTip
 | ||||
|     public static boolean onlyOnePopTip = false; | ||||
|      | ||||
|     //默认按钮文字样式
 | ||||
|     public static TextInfo buttonTextInfo; | ||||
|      | ||||
|     //默认确定按钮文字样式
 | ||||
|     public static TextInfo okButtonTextInfo; | ||||
|      | ||||
|     //默认标题文字样式
 | ||||
|     public static TextInfo titleTextInfo; | ||||
|      | ||||
|     //默认内容文字样式
 | ||||
|     public static TextInfo messageTextInfo; | ||||
|      | ||||
|     //默认 WaitDialog 和 TipDialog 文字样式
 | ||||
|     public static TextInfo tipTextInfo; | ||||
|      | ||||
|     //默认输入框文字样式
 | ||||
|     public static InputInfo inputInfo; | ||||
|      | ||||
|     //默认底部菜单、对话框的标题文字样式
 | ||||
|     public static TextInfo menuTitleInfo; | ||||
|      | ||||
|     //默认底部菜单文本样式
 | ||||
|     public static TextInfo menuTextInfo; | ||||
|      | ||||
|     //默认对话框背景颜色(值为 ColorInt,为-1不生效)
 | ||||
|     public static int backgroundColor = -1; | ||||
|      | ||||
|     //默认 TipDialog 和 WaitDialog 背景颜色(值为 ColorInt,为-1不生效)
 | ||||
|     public static int tipBackgroundColor = -1; | ||||
|      | ||||
|     /** | ||||
|      * 重写 TipDialog 和 WaitDialog 进度动画颜色, | ||||
|      * 注意此属性为覆盖性质,即设置此值将替换提示框原本的进度动画的颜色,包括亮暗色切换的颜色变化也将被替代 | ||||
|      * (值为 ColorInt,为-1不生效) | ||||
|      */ | ||||
|     public static int tipProgressColor = -1; | ||||
|      | ||||
|     //默认对话框默认是否可以点击外围遮罩区域或返回键关闭,此开关不影响提示框(TipDialog)以及等待框(TipDialog)
 | ||||
|     public static boolean cancelable = true; | ||||
|      | ||||
|     //默认提示框及等待框(WaitDialog、TipDialog)默认是否可以关闭
 | ||||
|     public static boolean cancelableTipDialog = false; | ||||
|      | ||||
|     //默认取消按钮文本文字,影响 BottomDialog
 | ||||
|     public static String cancelButtonText; | ||||
|      | ||||
|     //默认 PopTip 文本样式
 | ||||
|     public static TextInfo popTextInfo; | ||||
|      | ||||
|     //默认启动对话框动画时长
 | ||||
|     public static long enterAnimDuration = -1; | ||||
|      | ||||
|     //默认关闭对话框动画时长
 | ||||
|     public static long exitAnimDuration = -1; | ||||
|      | ||||
|     //全局 Dialog 生命周期监听器
 | ||||
|     public static DialogLifecycleCallback<BaseDialog> dialogLifeCycleListener; | ||||
|      | ||||
|     //是否自动在主线程执行
 | ||||
|     public static boolean autoRunOnUIThread = true; | ||||
|      | ||||
|     //使用振动反馈
 | ||||
|     public static boolean useHaptic = true; | ||||
|      | ||||
|     public enum THEME { | ||||
|         LIGHT, DARK, AUTO | ||||
|     } | ||||
|      | ||||
|     public enum IMPL_MODE { | ||||
|         VIEW, WINDOW | ||||
|     } | ||||
|      | ||||
|     public static void init(Context context) { | ||||
|         if (context == null) { | ||||
|             error(ERROR_INIT_TIPS); | ||||
|             return; | ||||
|         } | ||||
|         BaseDialog.init(context); | ||||
|     } | ||||
|      | ||||
|     public static void error(Object o) { | ||||
|         if (DEBUGMODE) Log.e(">>>", o.toString()); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,952 @@ | ||||
| package com.kongzue.dialogx.dialogs; | ||||
| 
 | ||||
| import android.animation.Animator; | ||||
| import android.animation.ObjectAnimator; | ||||
| import android.app.Activity; | ||||
| import android.content.res.Configuration; | ||||
| import android.os.Handler; | ||||
| import android.os.Looper; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
| import android.view.ViewTreeObserver; | ||||
| 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.ScrollView; | ||||
| import android.widget.TextView; | ||||
| 
 | ||||
| import androidx.annotation.ColorInt; | ||||
| import androidx.annotation.ColorRes; | ||||
| import androidx.core.view.ViewCompat; | ||||
| 
 | ||||
| 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.util.BottomDialogTouchEventInterceptor; | ||||
| 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 static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK; | ||||
| 
 | ||||
| /** | ||||
|  * @author: Kongzue | ||||
|  * @github: https://github.com/kongzue/
 | ||||
|  * @homepage: http://kongzue.com/
 | ||||
|  * @mail: myzcxhh@live.cn | ||||
|  * @createTime: 2020/10/6 15:17 | ||||
|  */ | ||||
| public class BottomDialog extends BaseDialog { | ||||
|      | ||||
|     public static int overrideEnterDuration = -1; | ||||
|     public static int overrideExitDuration = -1; | ||||
|     public static BOOLEAN overrideCancelable; | ||||
|     protected OnBindView<BottomDialog> onBindView; | ||||
|     protected CharSequence title; | ||||
|     protected CharSequence message; | ||||
|     protected CharSequence cancelText; | ||||
|     protected CharSequence okText; | ||||
|     protected CharSequence otherText; | ||||
|     protected boolean allowInterceptTouch = true; | ||||
|     protected int maskColor = -1; | ||||
|     protected OnDialogButtonClickListener<BottomDialog> cancelButtonClickListener; | ||||
|     protected OnDialogButtonClickListener<BottomDialog> okButtonClickListener; | ||||
|     protected OnDialogButtonClickListener<BottomDialog> otherButtonClickListener; | ||||
|     protected BOOLEAN privateCancelable; | ||||
|      | ||||
|     protected TextInfo titleTextInfo; | ||||
|     protected TextInfo messageTextInfo; | ||||
|     protected TextInfo cancelTextInfo = new TextInfo().setBold(true); | ||||
|     protected TextInfo okTextInfo = new TextInfo().setBold(true); | ||||
|     protected TextInfo otherTextInfo = new TextInfo().setBold(true); | ||||
|      | ||||
|     /** | ||||
|      * 此值用于,当禁用滑动时(style.overrideBottomDialogRes.touchSlide = false时)的最大显示高度。 | ||||
|      * 0:不限制,最大显示到屏幕可用高度。 | ||||
|      */ | ||||
|     protected float bottomDialogMaxHeight = 0.6f; | ||||
|      | ||||
|     protected DialogLifecycleCallback<BottomDialog> dialogLifecycleCallback; | ||||
|      | ||||
|     protected BottomDialog me = this; | ||||
|      | ||||
|     protected BottomDialog() { | ||||
|         super(); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String dialogKey() { | ||||
|         return getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")"; | ||||
|     } | ||||
|      | ||||
|     private View dialogView; | ||||
|      | ||||
|     public static BottomDialog build() { | ||||
|         return new BottomDialog(); | ||||
|     } | ||||
|      | ||||
|     public BottomDialog(CharSequence title, CharSequence message) { | ||||
|         this.title = title; | ||||
|         this.message = message; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog(int titleResId, int messageResId) { | ||||
|         this.title = getString(titleResId); | ||||
|         this.message = getString(messageResId); | ||||
|     } | ||||
|      | ||||
|     public static BottomDialog show(CharSequence title, CharSequence message) { | ||||
|         BottomDialog bottomDialog = new BottomDialog(title, message); | ||||
|         bottomDialog.show(); | ||||
|         return bottomDialog; | ||||
|     } | ||||
|      | ||||
|     public static BottomDialog show(int titleResId, int messageResId) { | ||||
|         BottomDialog bottomDialog = new BottomDialog(titleResId, messageResId); | ||||
|         bottomDialog.show(); | ||||
|         return bottomDialog; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog(CharSequence title, CharSequence message, OnBindView<BottomDialog> onBindView) { | ||||
|         this.title = title; | ||||
|         this.message = message; | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog(int titleResId, int messageResId, OnBindView<BottomDialog> onBindView) { | ||||
|         this.title = getString(titleResId); | ||||
|         this.message = getString(messageResId); | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public static BottomDialog show(CharSequence title, CharSequence message, OnBindView<BottomDialog> onBindView) { | ||||
|         BottomDialog bottomDialog = new BottomDialog(title, message, onBindView); | ||||
|         bottomDialog.show(); | ||||
|         return bottomDialog; | ||||
|     } | ||||
|      | ||||
|     public static BottomDialog show(int titleResId, int messageResId, OnBindView<BottomDialog> onBindView) { | ||||
|         BottomDialog bottomDialog = new BottomDialog(titleResId, messageResId, onBindView); | ||||
|         bottomDialog.show(); | ||||
|         return bottomDialog; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog(CharSequence title, OnBindView<BottomDialog> onBindView) { | ||||
|         this.title = title; | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog(int titleResId, OnBindView<BottomDialog> onBindView) { | ||||
|         this.title = getString(titleResId); | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public static BottomDialog show(CharSequence title, OnBindView<BottomDialog> onBindView) { | ||||
|         BottomDialog bottomDialog = new BottomDialog(title, onBindView); | ||||
|         bottomDialog.show(); | ||||
|         return bottomDialog; | ||||
|     } | ||||
|      | ||||
|     public static BottomDialog show(int titleResId, OnBindView<BottomDialog> onBindView) { | ||||
|         BottomDialog bottomDialog = new BottomDialog(titleResId, onBindView); | ||||
|         bottomDialog.show(); | ||||
|         return bottomDialog; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog(OnBindView<BottomDialog> onBindView) { | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public static BottomDialog show(OnBindView<BottomDialog> 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会以内容高度启动。 | ||||
|          * <p> | ||||
|          * 记录这个值的目的是,当用户向下滑动时,判断情况该回到这个位置还是关闭对话框, | ||||
|          * 并阻止当内容高度已经完全显示时的继续向上滑动操作。 | ||||
|          */ | ||||
|         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<BottomDialog> getDialogLifecycleCallback() { | ||||
|         return dialogLifecycleCallback == null ? new DialogLifecycleCallback<BottomDialog>() { | ||||
|         } : dialogLifecycleCallback; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog setDialogLifecycleCallback(DialogLifecycleCallback<BottomDialog> 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<BottomDialog> cancelButtonClickListener) { | ||||
|         this.cancelButtonClickListener = cancelButtonClickListener; | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog setCancelButton(CharSequence cancelText, OnDialogButtonClickListener<BottomDialog> cancelButtonClickListener) { | ||||
|         this.cancelText = cancelText; | ||||
|         this.cancelButtonClickListener = cancelButtonClickListener; | ||||
|         refreshUI(); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog setCancelButton(int cancelTextResId, OnDialogButtonClickListener<BottomDialog> cancelButtonClickListener) { | ||||
|         this.cancelText = getString(cancelTextResId); | ||||
|         this.cancelButtonClickListener = cancelButtonClickListener; | ||||
|         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 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<BottomDialog> getCancelButtonClickListener() { | ||||
|         return cancelButtonClickListener; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog setCancelButtonClickListener(OnDialogButtonClickListener<BottomDialog> 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<BottomDialog> OkButtonClickListener) { | ||||
|         this.okButtonClickListener = OkButtonClickListener; | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog setOkButton(CharSequence OkText, OnDialogButtonClickListener<BottomDialog> OkButtonClickListener) { | ||||
|         this.okText = OkText; | ||||
|         this.okButtonClickListener = OkButtonClickListener; | ||||
|         refreshUI(); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog setOkButton(int OkTextResId, OnDialogButtonClickListener<BottomDialog> 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<BottomDialog> OtherButtonClickListener) { | ||||
|         this.otherButtonClickListener = OtherButtonClickListener; | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog setOtherButton(CharSequence OtherText, OnDialogButtonClickListener<BottomDialog> OtherButtonClickListener) { | ||||
|         this.otherText = OtherText; | ||||
|         this.otherButtonClickListener = OtherButtonClickListener; | ||||
|         refreshUI(); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public BottomDialog setOtherButton(int OtherTextResId, OnDialogButtonClickListener<BottomDialog> 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); | ||||
|     } | ||||
| } | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -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<CustomDialog> onBindView; | ||||
|     protected DialogLifecycleCallback<CustomDialog> 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<CustomDialog> onBindView) { | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public static CustomDialog show(OnBindView<CustomDialog> onBindView) { | ||||
|         CustomDialog customDialog = new CustomDialog(onBindView); | ||||
|         customDialog.show(); | ||||
|         return customDialog; | ||||
|     } | ||||
|      | ||||
|     public static CustomDialog show(OnBindView<CustomDialog> 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<CustomDialog> getDialogLifecycleCallback() { | ||||
|         return dialogLifecycleCallback == null ? new DialogLifecycleCallback<CustomDialog>() { | ||||
|         } : dialogLifecycleCallback; | ||||
|     } | ||||
|      | ||||
|     public CustomDialog setDialogLifecycleCallback(DialogLifecycleCallback<CustomDialog> 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<CustomDialog> 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); | ||||
|     } | ||||
| } | ||||
| @ -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<FullScreenDialog> onBindView; | ||||
|     protected BOOLEAN privateCancelable; | ||||
|      | ||||
|     protected DialogLifecycleCallback<FullScreenDialog> dialogLifecycleCallback; | ||||
|      | ||||
|     protected FullScreenDialog me = this; | ||||
|      | ||||
|     protected FullScreenDialog() { | ||||
|         super(); | ||||
|     } | ||||
|      | ||||
|     private View dialogView; | ||||
|      | ||||
|     public static FullScreenDialog build() { | ||||
|         return new FullScreenDialog(); | ||||
|     } | ||||
|      | ||||
|     public FullScreenDialog(OnBindView<FullScreenDialog> onBindView) { | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public static FullScreenDialog show(OnBindView<FullScreenDialog> 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<FullScreenDialog> getDialogLifecycleCallback() { | ||||
|         return dialogLifecycleCallback == null ? new DialogLifecycleCallback<FullScreenDialog>() { | ||||
|         } : dialogLifecycleCallback; | ||||
|     } | ||||
|      | ||||
|     public FullScreenDialog setDialogLifecycleCallback(DialogLifecycleCallback<FullScreenDialog> 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<FullScreenDialog> 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); | ||||
|     } | ||||
| } | ||||
| @ -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<InputDialog> okButtonClickListener) { | ||||
|         this.okButtonClickListener = okButtonClickListener; | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public InputDialog setOkButton(CharSequence okText, OnInputDialogButtonClickListener<InputDialog> okButtonClickListener) { | ||||
|         this.okText = okText; | ||||
|         this.okButtonClickListener = okButtonClickListener; | ||||
|         refreshUI(); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public InputDialog setOkButton(int okTextResId, OnInputDialogButtonClickListener<InputDialog> 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<InputDialog> cancelButtonClickListener) { | ||||
|         this.cancelButtonClickListener = cancelButtonClickListener; | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public InputDialog setCancelButton(CharSequence cancelText, OnInputDialogButtonClickListener<InputDialog> cancelButtonClickListener) { | ||||
|         this.cancelText = cancelText; | ||||
|         this.cancelButtonClickListener = cancelButtonClickListener; | ||||
|         refreshUI(); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public InputDialog setCancelButton(int cancelTextResId, OnInputDialogButtonClickListener<InputDialog> 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<InputDialog> otherButtonClickListener) { | ||||
|         this.otherButtonClickListener = otherButtonClickListener; | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public InputDialog setOtherButton(CharSequence otherText, OnInputDialogButtonClickListener<InputDialog> otherButtonClickListener) { | ||||
|         this.otherText = otherText; | ||||
|         this.otherButtonClickListener = otherButtonClickListener; | ||||
|         refreshUI(); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public InputDialog setOtherButton(int otherTextResId, OnInputDialogButtonClickListener<InputDialog> otherButtonClickListener) { | ||||
|         this.otherText = getString(otherTextResId); | ||||
|         this.otherButtonClickListener = otherButtonClickListener; | ||||
|         refreshUI(); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public OnInputDialogButtonClickListener<InputDialog> getInputOkButtonClickListener() { | ||||
|         return (OnInputDialogButtonClickListener<InputDialog>) okButtonClickListener; | ||||
|     } | ||||
|      | ||||
|     public InputDialog setOkButtonClickListener(OnInputDialogButtonClickListener<InputDialog> okButtonClickListener) { | ||||
|         this.okButtonClickListener = okButtonClickListener; | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public OnInputDialogButtonClickListener getInputCancelButtonClickListener() { | ||||
|         return (OnInputDialogButtonClickListener<InputDialog>) cancelButtonClickListener; | ||||
|     } | ||||
|      | ||||
|     public InputDialog setCancelButtonClickListener(OnInputDialogButtonClickListener<InputDialog> cancelButtonClickListener) { | ||||
|         this.cancelButtonClickListener = cancelButtonClickListener; | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public OnInputDialogButtonClickListener getInputOtherButtonClickListener() { | ||||
|         return (OnInputDialogButtonClickListener<InputDialog>) otherButtonClickListener; | ||||
|     } | ||||
|      | ||||
|     public InputDialog setOtherButtonClickListener(OnInputDialogButtonClickListener<InputDialog> 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<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; | ||||
|     } | ||||
|      | ||||
|     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); | ||||
|     } | ||||
| } | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -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<PopTip> popTipList; | ||||
|      | ||||
|     protected OnBindView<PopTip> onBindView; | ||||
|     protected DialogLifecycleCallback<PopTip> 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<PopTip> onButtonClickListener; | ||||
|     protected OnDialogButtonClickListener<PopTip> 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<PopTip> 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<PopTip> onBindView) { | ||||
|         this.message = message; | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public PopTip(int messageResId, OnBindView<PopTip> onBindView) { | ||||
|         this.message = getString(messageResId); | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public PopTip(int iconResId, CharSequence message, OnBindView<PopTip> onBindView) { | ||||
|         this.iconResId = iconResId; | ||||
|         this.message = message; | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public PopTip(int iconResId, CharSequence message, CharSequence buttonText, OnBindView<PopTip> onBindView) { | ||||
|         this.iconResId = iconResId; | ||||
|         this.message = message; | ||||
|         this.buttonText = buttonText; | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public PopTip(int iconResId, int messageResId, int buttonTextResId, OnBindView<PopTip> onBindView) { | ||||
|         this.iconResId = iconResId; | ||||
|         this.message = getString(messageResId); | ||||
|         this.buttonText = getString(buttonTextResId); | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public PopTip(CharSequence message, CharSequence buttonText, OnBindView<PopTip> onBindView) { | ||||
|         this.message = message; | ||||
|         this.buttonText = buttonText; | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public PopTip(int messageResId, int buttonTextResId, OnBindView<PopTip> onBindView) { | ||||
|         this.message = getString(messageResId); | ||||
|         this.buttonText = getString(buttonTextResId); | ||||
|         this.onBindView = onBindView; | ||||
|     } | ||||
|      | ||||
|     public static PopTip show(OnBindView<PopTip> 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<PopTip> onBindView) { | ||||
|         PopTip popTip = new PopTip(message, onBindView); | ||||
|         popTip.show(); | ||||
|         return popTip; | ||||
|     } | ||||
|      | ||||
|     public static PopTip show(int messageResId, OnBindView<PopTip> 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<PopTip> 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<PopTip> onBindView) { | ||||
|         PopTip popTip = new PopTip(iconResId, message, buttonText, onBindView); | ||||
|         popTip.show(); | ||||
|         return popTip; | ||||
|     } | ||||
|      | ||||
|     public static PopTip show(int iconResId, int messageResId, int buttonTextResId, OnBindView<PopTip> onBindView) { | ||||
|         PopTip popTip = new PopTip(iconResId, messageResId, buttonTextResId, onBindView); | ||||
|         popTip.show(); | ||||
|         return popTip; | ||||
|     } | ||||
|      | ||||
|     public static PopTip show(CharSequence message, CharSequence buttonText, OnBindView<PopTip> onBindView) { | ||||
|         PopTip popTip = new PopTip(message, buttonText, onBindView); | ||||
|         popTip.show(); | ||||
|         return popTip; | ||||
|     } | ||||
|      | ||||
|     public static PopTip show(int messageResId, int buttonTextResId, OnBindView<PopTip> 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<PopTip> getDialogLifecycleCallback() { | ||||
|         return dialogLifecycleCallback == null ? new DialogLifecycleCallback<PopTip>() { | ||||
|         } : dialogLifecycleCallback; | ||||
|     } | ||||
|      | ||||
|     public PopTip setDialogLifecycleCallback(DialogLifecycleCallback<PopTip> 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<PopTip> 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<PopTip> onButtonClickListener) { | ||||
|         this.buttonText = buttonText; | ||||
|         this.onButtonClickListener = onButtonClickListener; | ||||
|         refreshUI(); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public PopTip setButton(int buttonTextResId, OnDialogButtonClickListener<PopTip> onButtonClickListener) { | ||||
|         this.buttonText = getString(buttonTextResId); | ||||
|         this.onButtonClickListener = onButtonClickListener; | ||||
|         refreshUI(); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public PopTip setButton(OnDialogButtonClickListener<PopTip> 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<PopTip> getOnButtonClickListener() { | ||||
|         return onButtonClickListener; | ||||
|     } | ||||
|      | ||||
|     public PopTip setOnButtonClickListener(OnDialogButtonClickListener<PopTip> onButtonClickListener) { | ||||
|         this.onButtonClickListener = onButtonClickListener; | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public boolean isAutoTintIconInLightOrDarkMode() { | ||||
|         return autoTintIconInLightOrDarkMode; | ||||
|     } | ||||
|      | ||||
|     public PopTip setAutoTintIconInLightOrDarkMode(boolean autoTintIconInLightOrDarkMode) { | ||||
|         this.autoTintIconInLightOrDarkMode = autoTintIconInLightOrDarkMode; | ||||
|         refreshUI(); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public OnDialogButtonClickListener<PopTip> getOnPopTipClickListener() { | ||||
|         return onPopTipClickListener; | ||||
|     } | ||||
|      | ||||
|     public PopTip setOnPopTipClickListener(OnDialogButtonClickListener<PopTip> 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); | ||||
|     } | ||||
| } | ||||
| @ -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()) + ")"; | ||||
|     } | ||||
| } | ||||
| @ -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<WaitDialog> onBindView; | ||||
|      | ||||
|     public enum TYPE { | ||||
|         NONE, | ||||
|         SUCCESS, | ||||
|         WARNING, | ||||
|         ERROR | ||||
|     } | ||||
|      | ||||
|     protected static WeakReference<WaitDialog> 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<WaitDialog> 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<WaitDialog> getDialogLifecycleCallback() { | ||||
|         return dialogLifecycleCallback == null ? new DialogLifecycleCallback<WaitDialog>() { | ||||
|         } : dialogLifecycleCallback; | ||||
|     } | ||||
|      | ||||
|     public WaitDialog setDialogLifecycleCallback(DialogLifecycleCallback<WaitDialog> dialogLifecycleCallback) { | ||||
|         this.dialogLifecycleCallback = dialogLifecycleCallback; | ||||
|         if (isShow) dialogLifecycleCallback.onShow(me.get()); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     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; | ||||
|     } | ||||
|      | ||||
|     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(); | ||||
|     } | ||||
| } | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
| @ -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) { | ||||
|      | ||||
|     } | ||||
| } | ||||
| @ -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<FrameLayout> rootFrameLayout; | ||||
|     private static WeakReference<Activity> contextWeakReference; | ||||
|     protected WeakReference<Activity> ownActivity; | ||||
|     private static List<BaseDialog> runningDialogList; | ||||
|     private WeakReference<View> 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<BaseDialog> copyOnWriteList = new CopyOnWriteArrayList<>(runningDialogList); | ||||
|                 for (BaseDialog baseDialog : copyOnWriteList) { | ||||
|                     if (baseDialog.getActivity() == activity && baseDialog.dialogView != null) { | ||||
|                         WindowUtil.dismiss(baseDialog.dialogView.get()); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -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 { | ||||
| } | ||||
| @ -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){}; | ||||
| } | ||||
| @ -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); | ||||
| } | ||||
| @ -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<T extends BaseDialog> { | ||||
|      | ||||
|     public void onShow(T dialog){ | ||||
|      | ||||
|     } | ||||
|      | ||||
|     public void onDismiss(T dialog){ | ||||
|      | ||||
|     } | ||||
| } | ||||
| @ -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(); | ||||
| } | ||||
| @ -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<D> { | ||||
|     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<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; | ||||
|     } | ||||
|      | ||||
|     public OnBindView<D> 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<D> 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; | ||||
|     } | ||||
| } | ||||
| @ -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<D extends BaseDialog> extends BaseOnDialogClickCallback{ | ||||
|      | ||||
|     boolean onClick(D baseDialog, View v); | ||||
|      | ||||
| } | ||||
| @ -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; | ||||
|     } | ||||
| } | ||||
| @ -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<D extends BaseDialog> extends BaseOnDialogClickCallback{ | ||||
|      | ||||
|     boolean onClick(D baseDialog, View v, String inputStr); | ||||
| } | ||||
| @ -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<D> { | ||||
|     boolean onClick(D dialog, CharSequence text, int which); | ||||
| } | ||||
| @ -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<D> implements OnMenuItemClickListener<D> { | ||||
|      | ||||
|     /** | ||||
|      * 警告:不建议重写此方法! | ||||
|      * 如果选择使用 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) { | ||||
|      | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -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); | ||||
| } | ||||
| @ -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; | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
| @ -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<CharSequence> { | ||||
|     public IOSMenuArrayAdapter(@NonNull Context context, int resource) { | ||||
|         super(context, resource); | ||||
|     } | ||||
| } | ||||
| @ -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; | ||||
|     } | ||||
| } | ||||
| @ -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<CharSequence> objects; | ||||
|     public Context context; | ||||
| 
 | ||||
|     public NormalMenuArrayAdapter(BottomMenu bottomMenu, Context context, List<CharSequence> 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); | ||||
|     } | ||||
| } | ||||
| @ -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 + | ||||
|                 '}'; | ||||
|     } | ||||
| } | ||||
| @ -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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
| @ -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()); | ||||
|     } | ||||
| } | ||||
| @ -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; | ||||
|     } | ||||
| } | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
| @ -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; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,11 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <translate | ||||
|         android:duration="300" | ||||
|         android:fromYDelta="100%p" | ||||
|         android:toYDelta="0" /> | ||||
|     <alpha | ||||
|         android:duration="300" | ||||
|         android:fromAlpha="0.0" | ||||
|         android:toAlpha="1.0" /> | ||||
| </set> | ||||
| @ -0,0 +1,11 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <translate | ||||
|         android:duration="300" | ||||
|         android:fromYDelta="0" | ||||
|         android:toYDelta="100%p"/> | ||||
|     <alpha | ||||
|         android:duration="300" | ||||
|         android:fromAlpha="1.0" | ||||
|         android:toAlpha="0.0"/> | ||||
| </set> | ||||
| @ -0,0 +1,8 @@ | ||||
| <?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> | ||||
| @ -0,0 +1,17 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
| 
 | ||||
|     <scale | ||||
|         android:duration="300" | ||||
|         android:fromXScale="0.9" | ||||
|         android:fromYScale="0.9" | ||||
|         android:pivotX="50%" | ||||
|         android:pivotY="60%" | ||||
|         android:toXScale="1.0" | ||||
|         android:toYScale="1.0" /> | ||||
| 
 | ||||
|     <alpha | ||||
|         android:duration="300" | ||||
|         android:fromAlpha="0.0" | ||||
|         android:toAlpha="1.0" /> | ||||
| </set> | ||||
| @ -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="1.0" | ||||
|         android:toAlpha="0.0" /> | ||||
| 
 | ||||
| </set> | ||||
| @ -0,0 +1,11 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <translate | ||||
|         android:duration="300" | ||||
|         android:fromXDelta="-100%p" | ||||
|         android:toXDelta="0" /> | ||||
|     <alpha | ||||
|         android:duration="300" | ||||
|         android:fromAlpha="0.0" | ||||
|         android:toAlpha="1.0" /> | ||||
| </set> | ||||
| @ -0,0 +1,11 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <translate | ||||
|         android:duration="300" | ||||
|         android:fromXDelta="0" | ||||
|         android:toXDelta="-100%p"/> | ||||
|     <alpha | ||||
|         android:duration="300" | ||||
|         android:fromAlpha="1.0" | ||||
|         android:toAlpha="0.0"/> | ||||
| </set> | ||||
| @ -0,0 +1,11 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <translate | ||||
|         android:duration="300" | ||||
|         android:fromXDelta="100%p" | ||||
|         android:toXDelta="0" /> | ||||
|     <alpha | ||||
|         android:duration="300" | ||||
|         android:fromAlpha="0.0" | ||||
|         android:toAlpha="1.0" /> | ||||
| </set> | ||||
| @ -0,0 +1,11 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <translate | ||||
|         android:duration="300" | ||||
|         android:fromXDelta="0" | ||||
|         android:toXDelta="100%p"/> | ||||
|     <alpha | ||||
|         android:duration="300" | ||||
|         android:fromAlpha="1.0" | ||||
|         android:toAlpha="0.0"/> | ||||
| </set> | ||||
| @ -0,0 +1,11 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <translate | ||||
|         android:duration="300" | ||||
|         android:fromYDelta="-100%p" | ||||
|         android:toYDelta="0" /> | ||||
|     <alpha | ||||
|         android:duration="300" | ||||
|         android:fromAlpha="0.0" | ||||
|         android:toAlpha="1.0" /> | ||||
| </set> | ||||
| @ -0,0 +1,11 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <translate | ||||
|         android:duration="300" | ||||
|         android:fromYDelta="0" | ||||
|         android:toYDelta="-100%p"/> | ||||
|     <alpha | ||||
|         android:duration="300" | ||||
|         android:fromAlpha="1.0" | ||||
|         android:toAlpha="0.0"/> | ||||
| </set> | ||||
| @ -0,0 +1,7 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <ripple xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:color="@color/black10"> | ||||
| 
 | ||||
|     <item android:drawable="@drawable/rect_dialogx_material_button_light_forword"/> | ||||
| </ripple> | ||||
| @ -0,0 +1,7 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <ripple xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:color="@color/white10"> | ||||
| 
 | ||||
|     <item android:drawable="@drawable/rect_dialogx_material_button_night_forword"/> | ||||
| </ripple> | ||||
| @ -0,0 +1,6 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:shape="rectangle"> | ||||
|     <solid android:color="@color/white"/> | ||||
|     <corners android:radius="10dp" /> | ||||
| </shape> | ||||
| @ -0,0 +1,6 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:shape="rectangle"> | ||||
|     <solid android:color="@color/dialogxMaterialDarkDialogBkgColor"/> | ||||
|     <corners android:radius="10dp" /> | ||||
| </shape> | ||||
| @ -0,0 +1,11 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:shape="rectangle"> | ||||
|     <!--left to right--> | ||||
|     <solid | ||||
|         android:color="@color/white"/> | ||||
| 
 | ||||
|     <corners | ||||
|         android:topRightRadius="10dp" | ||||
|         android:topLeftRadius="10dp"/> | ||||
| </shape> | ||||
| @ -0,0 +1,11 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:shape="rectangle"> | ||||
|     <!--left to right--> | ||||
|     <solid | ||||
|         android:color="@color/dialogxMaterialDarkDialogBkgColor"/> | ||||
| 
 | ||||
|     <corners | ||||
|         android:topRightRadius="10dp" | ||||
|         android:topLeftRadius="10dp"/> | ||||
| </shape> | ||||
| @ -0,0 +1,6 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:shape="rectangle"> | ||||
|     <solid android:color="@color/white"/> | ||||
|     <corners android:radius="3dp" /> | ||||
| </shape> | ||||
| @ -0,0 +1,6 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:shape="rectangle"> | ||||
|     <solid android:color="@color/dialogxMaterialDarkDialogBkgColor"/> | ||||
|     <corners android:radius="3dp" /> | ||||
| </shape> | ||||
| @ -0,0 +1,6 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:shape="rectangle"> | ||||
|     <solid android:color="@color/black10"/> | ||||
|     <corners android:radius="99dp" /> | ||||
| </shape> | ||||
| @ -0,0 +1,6 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:shape="rectangle"> | ||||
|     <solid android:color="@color/white10"/> | ||||
|     <corners android:radius="99dp" /> | ||||
| </shape> | ||||
| @ -0,0 +1,12 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > | ||||
| 
 | ||||
|     <item | ||||
|         android:left="15dp" | ||||
|         android:right="15dp"> | ||||
|         <shape android:shape="rectangle" > | ||||
|             <solid android:color="@color/black10" /> | ||||
|         </shape> | ||||
|     </item> | ||||
| 
 | ||||
| </layer-list> | ||||
| @ -0,0 +1,12 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > | ||||
| 
 | ||||
|     <item | ||||
|         android:left="25dp" | ||||
|         android:right="25dp"> | ||||
|         <shape android:shape="rectangle" > | ||||
|             <solid android:color="@color/white10" /> | ||||
|         </shape> | ||||
|     </item> | ||||
| 
 | ||||
| </layer-list> | ||||
| @ -0,0 +1,10 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:shape="rectangle"> | ||||
|     <!--left to right--> | ||||
|     <solid | ||||
|         android:color="@color/white"/> | ||||
| 
 | ||||
|     <corners | ||||
|         android:radius="5dp"/> | ||||
| </shape> | ||||
| @ -0,0 +1,10 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:shape="rectangle"> | ||||
|     <!--left to right--> | ||||
|     <solid | ||||
|         android:color="@color/dialogxMaterialDarkDialogBkgColor"/> | ||||
| 
 | ||||
|     <corners | ||||
|         android:radius="5dp"/> | ||||
| </shape> | ||||
| @ -0,0 +1,43 @@ | ||||
| <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="wrap_content"> | ||||
| 
 | ||||
|     <LinearLayout | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="55dp" | ||||
|         android:gravity="center_vertical" | ||||
|         android:paddingLeft="20dp" | ||||
|         android:paddingRight="20dp"> | ||||
| 
 | ||||
|         <ImageView | ||||
|             android:id="@+id/img_dialogx_menu_icon" | ||||
|             android:layout_width="35dp" | ||||
|             android:layout_height="35dp" | ||||
|             android:layout_marginLeft="-5dp" | ||||
|             android:layout_marginRight="10dp" | ||||
|             android:padding="5dp" /> | ||||
| 
 | ||||
|         <ImageView | ||||
|             android:id="@+id/img_dialogx_menu_selection" | ||||
|             android:layout_width="35dp" | ||||
|             android:layout_height="35dp" | ||||
|             android:layout_centerVertical="true" | ||||
|             android:layout_marginLeft="-5dp" | ||||
|             android:layout_marginRight="10dp" | ||||
|             android:padding="5dp" | ||||
|             android:src="@mipmap/img_dialogx_bottom_menu_material_item_selection" /> | ||||
| 
 | ||||
|         <TextView | ||||
|             android:id="@+id/txt_dialogx_menu_text" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_weight="1" | ||||
|             android:gravity="left|center_vertical" | ||||
|             android:maxLines="1" | ||||
|             android:text="" | ||||
|             android:textColor="@color/black90" | ||||
|             android:textSize="16dp" /> | ||||
| 
 | ||||
|     </LinearLayout> | ||||
| 
 | ||||
| </RelativeLayout> | ||||
| @ -0,0 +1,161 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:id="@+id/box_root" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:background="@color/black20" | ||||
|     android:orientation="vertical"> | ||||
| 
 | ||||
|     <RelativeLayout | ||||
|         android:id="@+id/box_bkg" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent"> | ||||
| 
 | ||||
|         <com.kongzue.dialogx.util.views.MaxRelativeLayout | ||||
|             android:id="@+id/bkg" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_alignParentBottom="true" | ||||
|             android:background="@drawable/rect_dialogx_material_bottom_bkg_light" | ||||
|             android:clickable="true" | ||||
|             android:focusableInTouchMode="true"> | ||||
| 
 | ||||
|             <ImageView | ||||
|                 android:id="@+id/img_tab" | ||||
|                 android:layout_width="30dp" | ||||
|                 android:layout_height="4dp" | ||||
|                 android:layout_centerHorizontal="true" | ||||
|                 android:layout_marginTop="10dp" | ||||
|                 android:src="@drawable/rect_dialogx_material_dialogtap" /> | ||||
| 
 | ||||
|             <LinearLayout | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:orientation="vertical" | ||||
|                 android:paddingTop="15dp"> | ||||
| 
 | ||||
|                 <TextView | ||||
|                     android:id="@+id/txt_dialog_title" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_gravity="center_horizontal" | ||||
|                     android:gravity="center_vertical" | ||||
|                     android:paddingLeft="20dp" | ||||
|                     android:paddingRight="20dp" | ||||
|                     android:paddingBottom="10dp" | ||||
|                     android:text="Title" | ||||
|                     android:textColor="@color/black" | ||||
|                     android:textSize="21dp" /> | ||||
| 
 | ||||
|                 <com.kongzue.dialogx.util.views.BottomDialogScrollView | ||||
|                     android:id="@+id/scrollView" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_weight="1" | ||||
|                     android:overScrollMode="never" | ||||
|                     android:scrollbarSize="7dp" | ||||
|                     android:scrollbars="vertical"> | ||||
| 
 | ||||
|                     <LinearLayout | ||||
|                         android:id="@+id/box_content" | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:orientation="vertical"> | ||||
| 
 | ||||
|                         <TextView | ||||
|                             android:id="@+id/txt_dialog_tip" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:layout_marginLeft="20dp" | ||||
|                             android:layout_marginRight="20dp" | ||||
|                             android:layout_marginBottom="5dp" | ||||
|                             android:paddingBottom="5dp" | ||||
|                             android:text="This is content text." | ||||
|                             android:textColor="@color/black70" | ||||
|                             android:textSize="16dp" /> | ||||
| 
 | ||||
|                         <RelativeLayout | ||||
|                             android:id="@+id/box_custom" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" /> | ||||
| 
 | ||||
|                         <RelativeLayout | ||||
|                             android:id="@+id/box_list" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" /> | ||||
| 
 | ||||
|                     </LinearLayout> | ||||
| 
 | ||||
|                 </com.kongzue.dialogx.util.views.BottomDialogScrollView> | ||||
| 
 | ||||
|                 <LinearLayout | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_gravity="center_horizontal" | ||||
|                     android:gravity="right|center_vertical" | ||||
|                     android:orientation="horizontal" | ||||
|                     android:paddingLeft="10dp" | ||||
|                     android:paddingRight="10dp"> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:id="@+id/btn_selectOther" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="36dp" | ||||
|                         android:layout_marginTop="10dp" | ||||
|                         android:layout_marginBottom="10dp" | ||||
|                         android:background="@drawable/button_dialogx_material_light" | ||||
|                         android:clickable="true" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingLeft="15dp" | ||||
|                         android:paddingRight="15dp" | ||||
|                         android:text="Other" | ||||
|                         android:textColor="@color/colorAccent" | ||||
|                         android:textSize="15dp" | ||||
|                         android:visibility="gone" /> | ||||
| 
 | ||||
|                     <Space | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:layout_weight="1" /> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:id="@+id/btn_selectNegative" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="36dp" | ||||
|                         android:layout_marginTop="10dp" | ||||
|                         android:layout_marginBottom="10dp" | ||||
|                         android:background="@drawable/button_dialogx_material_light" | ||||
|                         android:clickable="true" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingLeft="15dp" | ||||
|                         android:paddingRight="15dp" | ||||
|                         android:tag="cancel" | ||||
|                         android:text="Cancel" | ||||
|                         android:textColor="@color/colorAccent" | ||||
|                         android:textSize="15dp" /> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:id="@+id/btn_selectPositive" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="36dp" | ||||
|                         android:layout_marginTop="10dp" | ||||
|                         android:layout_marginBottom="10dp" | ||||
|                         android:background="@drawable/button_dialogx_material_light" | ||||
|                         android:clickable="true" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingLeft="15dp" | ||||
|                         android:paddingRight="15dp" | ||||
|                         android:text="OK" | ||||
|                         android:textColor="@color/colorAccent" | ||||
|                         android:textSize="15dp" /> | ||||
| 
 | ||||
|                 </LinearLayout> | ||||
| 
 | ||||
|             </LinearLayout> | ||||
| 
 | ||||
|         </com.kongzue.dialogx.util.views.MaxRelativeLayout> | ||||
| 
 | ||||
|     </RelativeLayout> | ||||
| 
 | ||||
| </com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout> | ||||
| @ -0,0 +1,161 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:id="@+id/box_root" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:background="@color/black40" | ||||
|     android:orientation="vertical"> | ||||
| 
 | ||||
|     <RelativeLayout | ||||
|         android:id="@+id/box_bkg" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent"> | ||||
| 
 | ||||
|         <com.kongzue.dialogx.util.views.MaxRelativeLayout | ||||
|             android:id="@+id/bkg" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_alignParentBottom="true" | ||||
|             android:background="@drawable/rect_dialogx_material_bottom_bkg_night" | ||||
|             android:clickable="true" | ||||
|             android:focusableInTouchMode="true"> | ||||
| 
 | ||||
|             <ImageView | ||||
|                 android:id="@+id/img_tab" | ||||
|                 android:layout_width="30dp" | ||||
|                 android:layout_height="4dp" | ||||
|                 android:layout_centerHorizontal="true" | ||||
|                 android:layout_marginTop="10dp" | ||||
|                 android:layout_marginBottom="1dp" | ||||
|                 android:src="@drawable/rect_dialogx_material_dialogtap_night" /> | ||||
| 
 | ||||
|             <LinearLayout | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:orientation="vertical" | ||||
|                 android:paddingTop="15dp"> | ||||
| 
 | ||||
|                 <TextView | ||||
|                     android:id="@+id/txt_dialog_title" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_gravity="center_horizontal" | ||||
|                     android:gravity="center_vertical" | ||||
|                     android:paddingLeft="20dp" | ||||
|                     android:paddingRight="20dp" | ||||
|                     android:paddingBottom="10dp" | ||||
|                     android:text="Title" | ||||
|                     android:textColor="@color/white" | ||||
|                     android:textSize="21dp" /> | ||||
| 
 | ||||
|                 <com.kongzue.dialogx.util.views.BottomDialogScrollView | ||||
|                     android:id="@+id/scrollView" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_weight="1" | ||||
|                     android:overScrollMode="never" | ||||
|                     android:scrollbarSize="7dp" | ||||
|                     android:scrollbars="vertical"> | ||||
| 
 | ||||
|                     <LinearLayout | ||||
|                         android:id="@+id/box_content" | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:orientation="vertical"> | ||||
| 
 | ||||
|                         <TextView | ||||
|                             android:id="@+id/txt_dialog_tip" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:layout_marginLeft="20dp" | ||||
|                             android:layout_marginRight="20dp" | ||||
|                             android:layout_marginBottom="5dp" | ||||
|                             android:paddingBottom="5dp" | ||||
|                             android:text="This is content text." | ||||
|                             android:textColor="@color/white60" | ||||
|                             android:textSize="16dp" /> | ||||
| 
 | ||||
|                         <RelativeLayout | ||||
|                             android:id="@+id/box_custom" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" /> | ||||
| 
 | ||||
|                         <RelativeLayout | ||||
|                             android:id="@+id/box_list" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" /> | ||||
| 
 | ||||
|                     </LinearLayout> | ||||
| 
 | ||||
|                 </com.kongzue.dialogx.util.views.BottomDialogScrollView> | ||||
| 
 | ||||
|                 <LinearLayout | ||||
|                     android:id="@+id/box_button" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_gravity="center_horizontal" | ||||
|                     android:gravity="right|center_vertical" | ||||
|                     android:orientation="horizontal" | ||||
|                     android:paddingLeft="10dp" | ||||
|                     android:paddingRight="10dp"> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="36dp" | ||||
|                         android:layout_marginTop="10dp" | ||||
|                         android:layout_marginBottom="10dp" | ||||
|                         android:background="@drawable/button_dialogx_material_night" | ||||
|                         android:clickable="true" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingLeft="15dp" | ||||
|                         android:paddingRight="15dp" | ||||
|                         android:text="Other" | ||||
|                         android:textColor="@color/colorAccent" | ||||
|                         android:textSize="15dp" | ||||
|                         android:visibility="gone" /> | ||||
| 
 | ||||
|                     <Space | ||||
|                         android:id="@+id/space_other_button" | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:layout_weight="1" /> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="36dp" | ||||
|                         android:layout_marginTop="10dp" | ||||
|                         android:layout_marginBottom="10dp" | ||||
|                         android:background="@drawable/button_dialogx_material_night" | ||||
|                         android:clickable="true" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingLeft="15dp" | ||||
|                         android:paddingRight="15dp" | ||||
|                         android:tag="cancel" | ||||
|                         android:text="Cancel" | ||||
|                         android:textColor="@color/colorAccent" | ||||
|                         android:textSize="15dp" /> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:id="@+id/btn_selectPositive" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="36dp" | ||||
|                         android:layout_marginTop="10dp" | ||||
|                         android:layout_marginBottom="10dp" | ||||
|                         android:background="@drawable/button_dialogx_material_night" | ||||
|                         android:clickable="true" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingLeft="15dp" | ||||
|                         android:paddingRight="15dp" | ||||
|                         android:text="OK" | ||||
|                         android:textColor="@color/colorAccent" | ||||
|                         android:textSize="15dp" /> | ||||
| 
 | ||||
|                 </LinearLayout> | ||||
| 
 | ||||
|             </LinearLayout> | ||||
| 
 | ||||
|         </com.kongzue.dialogx.util.views.MaxRelativeLayout> | ||||
| 
 | ||||
|     </RelativeLayout> | ||||
| 
 | ||||
| </com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout> | ||||
| @ -0,0 +1,17 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:id="@+id/box_root" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:orientation="vertical"> | ||||
| 
 | ||||
|     <RelativeLayout | ||||
|         android:id="@+id/box_custom" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_centerInParent="true" | ||||
|         android:clickable="true"> | ||||
| 
 | ||||
|     </RelativeLayout> | ||||
| 
 | ||||
| </com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout> | ||||
| @ -0,0 +1,47 @@ | ||||
| <?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" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:background="@color/black"> | ||||
| 
 | ||||
|     <com.kongzue.dialogx.util.views.ActivityScreenShotImageView | ||||
|         android:id="@+id/img_zoom_activity" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         android:layout_centerInParent="true" /> | ||||
| 
 | ||||
|     <com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout | ||||
|         android:id="@+id/box_root" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         android:background="@color/black20" | ||||
|         android:orientation="vertical"> | ||||
| 
 | ||||
|         <RelativeLayout | ||||
|             android:id="@+id/box_bkg" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent"> | ||||
| 
 | ||||
|             <com.kongzue.dialogx.util.views.MaxRelativeLayout | ||||
|                 android:id="@+id/bkg" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="match_parent" | ||||
|                 android:layout_alignParentBottom="true" | ||||
|                 android:background="@drawable/rect_dialogx_material_bottom_bkg_light" | ||||
|                 android:focusableInTouchMode="true"> | ||||
| 
 | ||||
|                 <RelativeLayout | ||||
|                     android:id="@+id/box_custom" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:clickable="true" | ||||
|                     android:orientation="vertical"/> | ||||
| 
 | ||||
|             </com.kongzue.dialogx.util.views.MaxRelativeLayout> | ||||
| 
 | ||||
|         </RelativeLayout> | ||||
| 
 | ||||
|     </com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout> | ||||
| 
 | ||||
| </RelativeLayout> | ||||
| @ -0,0 +1,47 @@ | ||||
| <?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" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:background="@color/black"> | ||||
| 
 | ||||
|     <com.kongzue.dialogx.util.views.ActivityScreenShotImageView | ||||
|         android:id="@+id/img_zoom_activity" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         android:layout_centerInParent="true" /> | ||||
| 
 | ||||
|     <com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout | ||||
|         android:id="@+id/box_root" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         android:background="@color/black20" | ||||
|         android:orientation="vertical"> | ||||
| 
 | ||||
|         <RelativeLayout | ||||
|             android:id="@+id/box_bkg" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent"> | ||||
| 
 | ||||
|             <com.kongzue.dialogx.util.views.MaxRelativeLayout | ||||
|                 android:id="@+id/bkg" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="match_parent" | ||||
|                 android:layout_alignParentBottom="true" | ||||
|                 android:background="@drawable/rect_dialogx_material_bottom_bkg_night" | ||||
|                 android:focusableInTouchMode="true"> | ||||
| 
 | ||||
|                 <RelativeLayout | ||||
|                     android:id="@+id/box_custom" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:clickable="true" | ||||
|                     android:orientation="vertical"/> | ||||
| 
 | ||||
|             </com.kongzue.dialogx.util.views.MaxRelativeLayout> | ||||
| 
 | ||||
|         </RelativeLayout> | ||||
| 
 | ||||
|     </com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout> | ||||
| 
 | ||||
| </RelativeLayout> | ||||
| @ -0,0 +1,160 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:id="@+id/box_root" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:background="@color/black20" | ||||
|     android:orientation="vertical"> | ||||
| 
 | ||||
|     <RelativeLayout | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent"> | ||||
| 
 | ||||
|         <com.kongzue.dialogx.util.views.MaxRelativeLayout | ||||
|             android:id="@+id/bkg" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_centerInParent="true" | ||||
|             android:layout_marginLeft="35dp" | ||||
|             android:layout_marginRight="35dp" | ||||
|             android:background="@drawable/rect_dialogx_material_bkg_light" | ||||
|             android:elevation="27dp"> | ||||
| 
 | ||||
|             <LinearLayout | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:clickable="true" | ||||
|                 android:orientation="vertical"> | ||||
| 
 | ||||
|                 <TextView | ||||
|                     android:id="@+id/txt_dialog_title" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_gravity="center_horizontal" | ||||
|                     android:gravity="center_vertical" | ||||
|                     android:paddingLeft="20dp" | ||||
|                     android:paddingTop="15dp" | ||||
|                     android:paddingRight="20dp" | ||||
|                     android:paddingBottom="15dp" | ||||
|                     android:text="Title" | ||||
|                     android:textColor="@color/black" | ||||
|                     android:textSize="21dp" /> | ||||
| 
 | ||||
|                 <ScrollView | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_weight="1" | ||||
|                     android:overScrollMode="never"> | ||||
| 
 | ||||
|                     <LinearLayout | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:orientation="vertical"> | ||||
| 
 | ||||
|                         <TextView | ||||
|                             android:id="@+id/txt_dialog_tip" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:layout_gravity="center_horizontal" | ||||
|                             android:layout_marginLeft="20dp" | ||||
|                             android:layout_marginRight="20dp" | ||||
|                             android:text="This is content text." | ||||
|                             android:textColor="@color/black70" | ||||
|                             android:textSize="16dp" /> | ||||
| 
 | ||||
|                         <RelativeLayout | ||||
|                             android:id="@+id/box_custom" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:visibility="gone" /> | ||||
| 
 | ||||
|                         <EditText | ||||
|                             android:id="@+id/txt_input" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:layout_gravity="center_horizontal" | ||||
|                             android:layout_marginLeft="20dp" | ||||
|                             android:layout_marginTop="10dp" | ||||
|                             android:layout_marginRight="20dp" | ||||
|                             android:inputType="text" | ||||
|                             android:maxLines="1" | ||||
|                             android:paddingTop="10dp" | ||||
|                             android:paddingBottom="10dp" | ||||
|                             android:scrollbars="vertical" | ||||
|                             android:text="" | ||||
|                             android:textColor="@color/black90" | ||||
|                             android:textSize="18dp" | ||||
|                             android:theme="@style/DialogXCompatThemeLight" /> | ||||
| 
 | ||||
|                     </LinearLayout> | ||||
| 
 | ||||
|                 </ScrollView> | ||||
| 
 | ||||
|                 <LinearLayout | ||||
|                     android:id="@+id/box_button" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_gravity="center_horizontal" | ||||
|                     android:layout_marginTop="5dp" | ||||
|                     android:gravity="right|center_vertical" | ||||
|                     android:orientation="horizontal" | ||||
|                     android:paddingLeft="10dp" | ||||
|                     android:paddingTop="10dp" | ||||
|                     android:paddingRight="10dp" | ||||
|                     android:paddingBottom="10dp"> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:id="@+id/btn_selectOther" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="36dp" | ||||
|                         android:background="@drawable/button_dialogx_material_light" | ||||
|                         android:clickable="true" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingLeft="15dp" | ||||
|                         android:paddingRight="15dp" | ||||
|                         android:text="Other" | ||||
|                         android:textColor="@color/colorAccent" | ||||
|                         android:textSize="15dp" | ||||
|                         android:visibility="gone" /> | ||||
| 
 | ||||
|                     <Space | ||||
|                         android:id="@+id/space_other_button" | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:layout_weight="1" /> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:id="@+id/btn_selectNegative" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="36dp" | ||||
|                         android:background="@drawable/button_dialogx_material_light" | ||||
|                         android:clickable="true" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingLeft="15dp" | ||||
|                         android:paddingRight="15dp" | ||||
|                         android:text="Cancel" | ||||
|                         android:textColor="@color/colorAccent" | ||||
|                         android:textSize="15dp" /> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:id="@+id/btn_selectPositive" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="36dp" | ||||
|                         android:background="@drawable/button_dialogx_material_light" | ||||
|                         android:clickable="true" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingLeft="15dp" | ||||
|                         android:paddingRight="15dp" | ||||
|                         android:text="OK" | ||||
|                         android:textColor="@color/colorAccent" | ||||
|                         android:textSize="15dp" /> | ||||
| 
 | ||||
|                 </LinearLayout> | ||||
| 
 | ||||
|             </LinearLayout> | ||||
| 
 | ||||
|         </com.kongzue.dialogx.util.views.MaxRelativeLayout> | ||||
| 
 | ||||
|     </RelativeLayout> | ||||
| 
 | ||||
| </com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout> | ||||
| @ -0,0 +1,160 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:id="@+id/box_root" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:background="@color/black40" | ||||
|     android:orientation="vertical"> | ||||
| 
 | ||||
|     <RelativeLayout | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent"> | ||||
| 
 | ||||
|         <com.kongzue.dialogx.util.views.MaxRelativeLayout | ||||
|             android:id="@+id/bkg" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_centerInParent="true" | ||||
|             android:layout_marginLeft="35dp" | ||||
|             android:layout_marginRight="35dp" | ||||
|             android:background="@drawable/rect_dialogx_material_bkg_night" | ||||
|             android:elevation="27dp"> | ||||
| 
 | ||||
|             <LinearLayout | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:clickable="true" | ||||
|                 android:orientation="vertical"> | ||||
| 
 | ||||
|                 <TextView | ||||
|                     android:id="@+id/txt_dialog_title" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_gravity="center_horizontal" | ||||
|                     android:gravity="center_vertical" | ||||
|                     android:paddingLeft="20dp" | ||||
|                     android:paddingTop="15dp" | ||||
|                     android:paddingRight="20dp" | ||||
|                     android:paddingBottom="15dp" | ||||
|                     android:text="Title" | ||||
|                     android:textColor="@color/white" | ||||
|                     android:textSize="21dp" /> | ||||
| 
 | ||||
|                 <ScrollView | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_weight="1" | ||||
|                     android:overScrollMode="never"> | ||||
| 
 | ||||
|                     <LinearLayout | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:orientation="vertical"> | ||||
| 
 | ||||
|                         <TextView | ||||
|                             android:id="@+id/txt_dialog_tip" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:layout_gravity="center_horizontal" | ||||
|                             android:layout_marginLeft="20dp" | ||||
|                             android:layout_marginRight="20dp" | ||||
|                             android:text="This is content text." | ||||
|                             android:textColor="@color/white60" | ||||
|                             android:textSize="16dp" /> | ||||
| 
 | ||||
|                         <RelativeLayout | ||||
|                             android:id="@+id/box_custom" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:visibility="gone" /> | ||||
| 
 | ||||
|                         <EditText | ||||
|                             android:id="@+id/txt_input" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:layout_gravity="center_horizontal" | ||||
|                             android:layout_marginLeft="20dp" | ||||
|                             android:layout_marginTop="10dp" | ||||
|                             android:layout_marginRight="20dp" | ||||
|                             android:inputType="text" | ||||
|                             android:maxLines="1" | ||||
|                             android:paddingTop="10dp" | ||||
|                             android:paddingBottom="10dp" | ||||
|                             android:scrollbars="vertical" | ||||
|                             android:text="" | ||||
|                             android:textColor="@color/white" | ||||
|                             android:textSize="18dp" | ||||
|                             android:theme="@style/DialogXCompatThemeDark" /> | ||||
| 
 | ||||
|                     </LinearLayout> | ||||
| 
 | ||||
|                 </ScrollView> | ||||
| 
 | ||||
|                 <LinearLayout | ||||
|                     android:id="@+id/box_button" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_gravity="center_horizontal" | ||||
|                     android:layout_marginTop="5dp" | ||||
|                     android:gravity="right|center_vertical" | ||||
|                     android:orientation="horizontal" | ||||
|                     android:paddingLeft="10dp" | ||||
|                     android:paddingTop="10dp" | ||||
|                     android:paddingRight="10dp" | ||||
|                     android:paddingBottom="10dp"> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:id="@+id/btn_selectOther" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="36dp" | ||||
|                         android:background="@drawable/button_dialogx_material_night" | ||||
|                         android:clickable="true" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingLeft="15dp" | ||||
|                         android:paddingRight="15dp" | ||||
|                         android:text="Other" | ||||
|                         android:textColor="@color/colorAccent" | ||||
|                         android:textSize="15dp" | ||||
|                         android:visibility="gone" /> | ||||
| 
 | ||||
|                     <Space | ||||
|                         android:id="@+id/space_other_button" | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:layout_weight="1" /> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:id="@+id/btn_selectNegative" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="36dp" | ||||
|                         android:background="@drawable/button_dialogx_material_night" | ||||
|                         android:clickable="true" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingLeft="15dp" | ||||
|                         android:paddingRight="15dp" | ||||
|                         android:text="Cancel" | ||||
|                         android:textColor="@color/colorAccent" | ||||
|                         android:textSize="15dp" /> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:id="@+id/btn_selectPositive" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="36dp" | ||||
|                         android:background="@drawable/button_dialogx_material_night" | ||||
|                         android:clickable="true" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingLeft="15dp" | ||||
|                         android:paddingRight="15dp" | ||||
|                         android:text="OK" | ||||
|                         android:textColor="@color/colorAccent" | ||||
|                         android:textSize="15dp" /> | ||||
| 
 | ||||
|                 </LinearLayout> | ||||
| 
 | ||||
|             </LinearLayout> | ||||
| 
 | ||||
|         </com.kongzue.dialogx.util.views.MaxRelativeLayout> | ||||
| 
 | ||||
|     </RelativeLayout> | ||||
| 
 | ||||
| </com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout> | ||||
| @ -0,0 +1,72 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:id="@+id/box_root" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:orientation="vertical" | ||||
|     app:baseFocusable="false"> | ||||
| 
 | ||||
|     <LinearLayout | ||||
|         android:id="@+id/box_body" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_alignParentBottom="true" | ||||
|         android:layout_centerHorizontal="true" | ||||
|         android:layout_marginLeft="35dp" | ||||
|         android:layout_marginRight="35dp" | ||||
|         android:layout_marginBottom="100dp" | ||||
|         android:background="@drawable/rect_dialogx_material_poptip_bkg" | ||||
|         android:elevation="20dp" | ||||
|         android:gravity="center_vertical" | ||||
|         android:minHeight="50dp" | ||||
|         android:orientation="horizontal"> | ||||
| 
 | ||||
|         <ImageView | ||||
|             android:id="@+id/img_dialogx_pop_icon" | ||||
|             android:layout_width="26dp" | ||||
|             android:layout_height="26dp" | ||||
|             android:layout_marginLeft="15dp" | ||||
|             android:layout_marginRight="-5dp" | ||||
|             android:visibility="gone" /> | ||||
| 
 | ||||
|         <TextView | ||||
|             android:id="@+id/txt_dialogx_pop_text" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_marginLeft="15dp" | ||||
|             android:layout_marginTop="10dp" | ||||
|             android:layout_marginRight="15dp" | ||||
|             android:layout_marginBottom="10dp" | ||||
|             android:gravity="left|center_vertical" | ||||
|             android:text="Sure?" | ||||
|             android:textColor="@color/black" | ||||
|             android:textSize="14dp" /> | ||||
| 
 | ||||
|         <RelativeLayout | ||||
|             android:id="@+id/box_custom" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:visibility="gone" /> | ||||
| 
 | ||||
|         <TextView | ||||
|             android:id="@+id/txt_dialogx_button" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="match_parent" | ||||
|             android:layout_marginLeft="-15dp" | ||||
|             android:layout_marginTop="5dp" | ||||
|             android:layout_marginRight="5dp" | ||||
|             android:layout_marginBottom="5dp" | ||||
|             android:background="@drawable/button_dialogx_material_light" | ||||
|             android:gravity="left|center_vertical" | ||||
|             android:paddingLeft="10dp" | ||||
|             android:paddingRight="10dp" | ||||
|             android:singleLine="true" | ||||
|             android:text="Dismiss" | ||||
|             android:textColor="@color/dialogxColorBlue" | ||||
|             android:textSize="14dp" | ||||
|             android:visibility="gone" /> | ||||
| 
 | ||||
|     </LinearLayout> | ||||
| 
 | ||||
| </com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout> | ||||
| @ -0,0 +1,72 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:id="@+id/box_root" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:orientation="vertical" | ||||
|     app:baseFocusable="false"> | ||||
| 
 | ||||
|     <LinearLayout | ||||
|         android:id="@+id/box_body" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_alignParentBottom="true" | ||||
|         android:layout_centerHorizontal="true" | ||||
|         android:layout_marginLeft="35dp" | ||||
|         android:layout_marginRight="35dp" | ||||
|         android:layout_marginBottom="100dp" | ||||
|         android:background="@drawable/rect_dialogx_material_poptip_bkg_night" | ||||
|         android:elevation="10dp" | ||||
|         android:gravity="center_vertical" | ||||
|         android:minHeight="50dp" | ||||
|         android:orientation="horizontal"> | ||||
| 
 | ||||
|         <ImageView | ||||
|             android:id="@+id/img_dialogx_pop_icon" | ||||
|             android:layout_width="26dp" | ||||
|             android:layout_height="26dp" | ||||
|             android:layout_marginLeft="15dp" | ||||
|             android:layout_marginRight="-5dp" | ||||
|             android:visibility="gone" /> | ||||
| 
 | ||||
|         <TextView | ||||
|             android:id="@+id/txt_dialogx_pop_text" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_marginLeft="15dp" | ||||
|             android:layout_marginTop="10dp" | ||||
|             android:layout_marginRight="15dp" | ||||
|             android:layout_marginBottom="10dp" | ||||
|             android:gravity="left|center_vertical" | ||||
|             android:text="Sure?" | ||||
|             android:textColor="@color/white" | ||||
|             android:textSize="14dp" /> | ||||
| 
 | ||||
|         <RelativeLayout | ||||
|             android:id="@+id/box_custom" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:visibility="gone" /> | ||||
| 
 | ||||
|         <TextView | ||||
|             android:id="@+id/txt_dialogx_button" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="match_parent" | ||||
|             android:layout_marginLeft="-15dp" | ||||
|             android:layout_marginTop="5dp" | ||||
|             android:layout_marginRight="5dp" | ||||
|             android:layout_marginBottom="5dp" | ||||
|             android:background="@drawable/button_dialogx_material_night" | ||||
|             android:gravity="left|center_vertical" | ||||
|             android:paddingLeft="10dp" | ||||
|             android:paddingRight="10dp" | ||||
|             android:singleLine="true" | ||||
|             android:text="Dismiss" | ||||
|             android:textColor="@color/dialogxPopButtonBlueDark" | ||||
|             android:textSize="14dp" | ||||
|             android:visibility="gone" /> | ||||
| 
 | ||||
|     </LinearLayout> | ||||
| 
 | ||||
| </com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout> | ||||
| @ -0,0 +1,60 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:id="@+id/box_root" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:background="@color/black40" | ||||
|     android:orientation="vertical"> | ||||
| 
 | ||||
|     <com.kongzue.dialogx.util.views.MaxRelativeLayout | ||||
|         android:id="@+id/bkg" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_centerInParent="true" | ||||
|         android:minWidth="125dp" | ||||
|         android:minHeight="125dp"> | ||||
| 
 | ||||
|         <com.kongzue.dialogx.util.views.BlurView | ||||
|             android:id="@+id/blurView" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:tag="blurView" /> | ||||
| 
 | ||||
|         <LinearLayout | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_centerInParent="true" | ||||
|             android:gravity="center_horizontal" | ||||
|             android:paddingTop="1.5dp" | ||||
|             android:orientation="vertical"> | ||||
| 
 | ||||
|             <RelativeLayout | ||||
|                 android:id="@+id/box_progress" | ||||
|                 android:layout_width="65dp" | ||||
|                 android:layout_height="65dp"/> | ||||
| 
 | ||||
|             <RelativeLayout | ||||
|                 android:id="@+id/box_customView" | ||||
|                 android:layout_width="65dp" | ||||
|                 android:layout_height="65dp" | ||||
|                 android:visibility="gone" /> | ||||
| 
 | ||||
|             <TextView | ||||
|                 android:id="@+id/txt_info" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_marginLeft="15dp" | ||||
|                 android:layout_marginTop="10dp" | ||||
|                 android:layout_marginRight="15dp" | ||||
|                 android:gravity="center" | ||||
|                 android:maxLines="3" | ||||
|                 android:text="Please Wait" | ||||
|                 android:textColor="@color/white" | ||||
|                 android:textSize="14dp" /> | ||||
| 
 | ||||
|         </LinearLayout> | ||||
| 
 | ||||
|     </com.kongzue.dialogx.util.views.MaxRelativeLayout> | ||||
| 
 | ||||
| </com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout> | ||||
| After Width: | Height: | Size: 2.6 KiB | 
| After Width: | Height: | Size: 2.4 KiB | 
| After Width: | Height: | Size: 2.6 KiB | 
| After Width: | Height: | Size: 2.9 KiB | 
| @ -0,0 +1,28 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <resources> | ||||
| 
 | ||||
|     <declare-styleable name="MaxRelativeLayout"> | ||||
|         <attr name="maxLayoutWidth" format="dimension"/> | ||||
|         <attr name="maxLayoutHeight" format="dimension"/> | ||||
|         <attr name="lockWidth" format="boolean"/> | ||||
|         <attr name="interceptTouch" format="boolean"/> | ||||
|     </declare-styleable> | ||||
| 
 | ||||
|     <declare-styleable name="RealtimeBlurView"> | ||||
|         <attr name="realtimeBlurRadius" format="dimension"/> | ||||
|         <attr name="realtimeDownsampleFactor" format="float"/> | ||||
|         <attr name="realtimeOverlayColor" format="color"/> | ||||
|         <attr name="radius" format="dimension"/> | ||||
|     </declare-styleable> | ||||
| 
 | ||||
|     <declare-styleable name="ProgressView"> | ||||
|         <attr name="progressStrokeWidth" format="dimension"/> | ||||
|         <attr name="progressStrokeColor" format="color"/> | ||||
|     </declare-styleable> | ||||
| 
 | ||||
|     <declare-styleable name="DialogXBaseRelativeLayout"> | ||||
|         <attr name="baseFocusable" format="boolean"/> | ||||
|     </declare-styleable> | ||||
| 
 | ||||
| 
 | ||||
| </resources> | ||||
| @ -0,0 +1,40 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <resources> | ||||
|     <color name="colorAccent">#2196F3</color> | ||||
| 
 | ||||
|     <color name="dark">#353535</color> | ||||
|     <color name="black">#000</color> | ||||
|     <color name="black90">#E6000000</color> | ||||
|     <color name="black80">#CC000000</color> | ||||
|     <color name="black75">#BF000000</color> | ||||
|     <color name="black70">#B3000000</color> | ||||
|     <color name="black60">#99000000</color> | ||||
|     <color name="black50">#80000000</color> | ||||
|     <color name="black40">#66000000</color> | ||||
|     <color name="black30">#4D000000</color> | ||||
|     <color name="black25">#40000000</color> | ||||
|     <color name="black20">#33000000</color> | ||||
|     <color name="black10">#1A000000</color> | ||||
|     <color name="empty">#00000000</color> | ||||
| 
 | ||||
|     <color name="white">#fff</color> | ||||
|     <color name="white90">#E6ffffff</color> | ||||
|     <color name="white80">#CCffffff</color> | ||||
|     <color name="white75">#BFffffff</color> | ||||
|     <color name="white70">#B3ffffff</color> | ||||
|     <color name="white60">#99ffffff</color> | ||||
|     <color name="white50">#80ffffff</color> | ||||
|     <color name="white40">#66ffffff</color> | ||||
|     <color name="white30">#4Dffffff</color> | ||||
|     <color name="white25">#40ffffff</color> | ||||
|     <color name="white20">#33ffffff</color> | ||||
|     <color name="white10">#1Affffff</color> | ||||
| 
 | ||||
|     <color name="dialogxColorBlue">#2196F3</color> | ||||
| 
 | ||||
|     <color name="dialogxMaterialDarkDialogBkgColor">#343434</color> | ||||
|     <color name="dialogxWaitBkgLight">#F5F6F7</color> | ||||
|     <color name="dialogxWaitBkgDark">#232323</color> | ||||
| 
 | ||||
|     <color name="dialogxPopButtonBlueDark">#86B3D6</color> | ||||
| </resources> | ||||
| @ -0,0 +1,6 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <resources> | ||||
|     <style name="DialogXCompatThemeLight" parent="Theme.AppCompat.Light.NoActionBar"/> | ||||
| 
 | ||||
|     <style name="DialogXCompatThemeDark" parent="Theme.AppCompat.NoActionBar"/> | ||||
| </resources> | ||||
Some files were not shown because too many files have changed in this diff Show More
					Loading…
					
					
				
		Reference in new issue