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