新增种植计划相关
This commit is contained in:
parent
f1bad8266e
commit
a91d71e1d8
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,2 +0,0 @@
|
||||
#Tue May 20 10:45:30 CST 2025
|
||||
gradle.version=7.3.3
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -27,11 +27,10 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(path: ':DialogX')
|
||||
api project(path: ':DialogXMaterialYou')
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
def dialogx_version = "0.0.49"
|
||||
api "com.kongzue.dialogx:DialogX:${dialogx_version}"
|
||||
api "com.kongzue.dialogx.style:DialogXMaterialYouStyle:${dialogx_version}"
|
||||
implementation 'com.github.bumptech.glide:glide:4.12.0'
|
||||
implementation "androidx.recyclerview:recyclerview:1.2.1"
|
||||
api 'com.github.getActivity:XXPermissions:21.3'
|
||||
|
1
DialogX/.gitignore
vendored
Normal file
1
DialogX/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
39
DialogX/build.gradle
Normal file
39
DialogX/build.gradle
Normal file
@ -0,0 +1,39 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 33
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 33
|
||||
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
viewBinding {
|
||||
enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
from android.sourceSets.main.java.srcDirs
|
||||
classifier = 'sources'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives sourcesJar
|
||||
}
|
||||
dependencies {
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
compileOnly files('libs\\androidx-rs.jar')
|
||||
api files('libs\\DialogXInterface.jar')
|
||||
}
|
BIN
DialogX/libs/DialogXInterface.jar
Normal file
BIN
DialogX/libs/DialogXInterface.jar
Normal file
Binary file not shown.
BIN
DialogX/libs/androidx-rs.jar
Normal file
BIN
DialogX/libs/androidx-rs.jar
Normal file
Binary file not shown.
21
DialogX/proguard-rules.pro
vendored
Normal file
21
DialogX/proguard-rules.pro
vendored
Normal file
@ -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
|
4
DialogX/src/main/AndroidManifest.xml
Normal file
4
DialogX/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.kongzue.dialogx">
|
||||
|
||||
</manifest>
|
217
DialogX/src/main/java/com/kongzue/dialogx/DialogX.java
Normal file
217
DialogX/src/main/java/com/kongzue/dialogx/DialogX.java
Normal file
@ -0,0 +1,217 @@
|
||||
package com.kongzue.dialogx;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
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.DialogListBuilder;
|
||||
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;
|
||||
|
||||
//对话框最大高度(像素)
|
||||
public static int dialogMaxHeight;
|
||||
|
||||
//对话框最小宽度(像素)
|
||||
public static int dialogMinWidth;
|
||||
|
||||
//对话框最小高度(像素)
|
||||
public static int dialogMinHeight;
|
||||
|
||||
//是否允许 InputDialog 自动弹出键盘
|
||||
public static boolean autoShowInputKeyboard = true;
|
||||
|
||||
//同时只显示一个 PopTip
|
||||
public static boolean onlyOnePopTip = false;
|
||||
|
||||
//同时只显示一个 PopNotification
|
||||
public static boolean onlyOnePopNotification = true;
|
||||
|
||||
//默认按钮文字样式
|
||||
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,为 null 不生效)
|
||||
public static Integer backgroundColor = null;
|
||||
|
||||
//默认 TipDialog 和 WaitDialog 背景颜色(值为 ColorInt,为 null 不生效)
|
||||
public static Integer tipBackgroundColor = null;
|
||||
|
||||
/**
|
||||
* 重写 TipDialog 和 WaitDialog 进度动画颜色,
|
||||
* 注意此属性为覆盖性质,即设置此值将替换提示框原本的进度动画的颜色,包括亮暗色切换的颜色变化也将被替代
|
||||
* (值为 ColorInt,为 null 不生效)
|
||||
*/
|
||||
public static Integer tipProgressColor = null;
|
||||
|
||||
//默认对话框默认是否可以点击外围遮罩区域或返回键关闭,此开关不影响提示框(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;
|
||||
|
||||
/**
|
||||
* 声明:若 Activity 已使用沉浸式适配请开启(已废弃)
|
||||
* <p>
|
||||
* 请注意,若你没有使用沉浸式适配,请关闭此选项,此选项将影响对话框布局是否允许延伸至导航栏背后显示
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean useActivityLayoutTranslationNavigationBar = false;
|
||||
|
||||
/**
|
||||
* 设置 BottomDialog 导航栏背景颜色
|
||||
* 彩蛋:a_man 私人定制款属性
|
||||
*/
|
||||
public static int bottomDialogNavbarColor = Color.TRANSPARENT;
|
||||
|
||||
//触摸滑动触发阈值,影响 BottomDialog、FullScreenDialog 下滑关闭触发距离,单位:像素
|
||||
public static int touchSlideTriggerThreshold = dip2px(35);
|
||||
|
||||
//Window 模式使用全局悬浮窗,需要 SYSTEM_ALERT_WINDOW 权限
|
||||
public static boolean globalHoverWindow = false;
|
||||
|
||||
//部分插屏广告 SDK 可能出现背景黑屏的问题,在这里配置需要 DialogX 屏蔽的 Activity 的包名以屏蔽对该 activity 的支持:
|
||||
public static String[] unsupportedActivitiesPackageNames = new String[]{
|
||||
"com.bytedance.sdk.openadsdk.stub.activity",
|
||||
"com.mobile.auth.gatewayauth",
|
||||
"com.google.android.gms.ads"
|
||||
};
|
||||
|
||||
public static int defaultMessageDialogBackgroundRadius = -1;
|
||||
|
||||
public static int defaultBottomDialogBackgroundRadius = -1;
|
||||
|
||||
public static int defaultFullScreenDialogBackgroundRadius = -1;
|
||||
|
||||
public static int defaultWaitAndTipDialogBackgroundRadius = -1;
|
||||
|
||||
public static int defaultPopMenuBackgroundRadius = -1;
|
||||
|
||||
public static int defaultPopTipBackgroundRadius = -1;
|
||||
|
||||
public static int defaultPopNotificationBackgroundRadius = -1;
|
||||
|
||||
//开启沉浸式适配
|
||||
public static boolean enableImmersiveMode = true;
|
||||
|
||||
//沉浸式忽略左右的非安全区
|
||||
public static boolean ignoreUnsafeInsetsHorizontal = false;
|
||||
|
||||
public enum THEME {
|
||||
LIGHT, DARK, AUTO
|
||||
}
|
||||
|
||||
public enum IMPL_MODE {
|
||||
VIEW, WINDOW, DIALOG_FRAGMENT, FLOATING_ACTIVITY
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
private static int dip2px(float dpValue) {
|
||||
final float scale = Resources.getSystem().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
public static DialogListBuilder showDialogList(BaseDialog... dialogs) {
|
||||
return DialogListBuilder.create(dialogs).show();
|
||||
}
|
||||
|
||||
// 默认消息对话框标题文本
|
||||
public static CharSequence defaultMessageDialogTitleText;
|
||||
|
||||
// 等待提示框默认文本
|
||||
public static CharSequence defaultWaitDialogWaitingText;
|
||||
|
||||
// 成功提示框默认文本
|
||||
public static CharSequence defaultTipDialogSuccessText;
|
||||
|
||||
// 错误提示框默认文本
|
||||
public static CharSequence defaultTipDialogErrorText;
|
||||
|
||||
// 警告提示框默认文本
|
||||
public static CharSequence defaultTipDialogWarningText;
|
||||
}
|
1449
DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomDialog.java
Normal file
1449
DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomDialog.java
Normal file
File diff suppressed because it is too large
Load Diff
1605
DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomMenu.java
Normal file
1605
DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomMenu.java
Normal file
File diff suppressed because it is too large
Load Diff
1226
DialogX/src/main/java/com/kongzue/dialogx/dialogs/CustomDialog.java
Normal file
1226
DialogX/src/main/java/com/kongzue/dialogx/dialogs/CustomDialog.java
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,852 @@
|
||||
package com.kongzue.dialogx.dialogs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.kongzue.dialogx.DialogX;
|
||||
import com.kongzue.dialogx.R;
|
||||
import com.kongzue.dialogx.interfaces.DialogLifecycleCallback;
|
||||
import com.kongzue.dialogx.interfaces.DialogXAnimInterface;
|
||||
import com.kongzue.dialogx.interfaces.DialogXRunnable;
|
||||
import com.kongzue.dialogx.interfaces.DialogXStyle;
|
||||
import com.kongzue.dialogx.interfaces.OnBackPressedListener;
|
||||
import com.kongzue.dialogx.interfaces.OnBackgroundMaskClickListener;
|
||||
import com.kongzue.dialogx.interfaces.OnBindView;
|
||||
import com.kongzue.dialogx.interfaces.OnDialogButtonClickListener;
|
||||
import com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2022/8/19 16:35
|
||||
*/
|
||||
public class GuideDialog extends CustomDialog {
|
||||
|
||||
public enum STAGE_LIGHT_TYPE {
|
||||
RECTANGLE, //矩形
|
||||
SQUARE_OUTSIDE, //方形(外围)
|
||||
SQUARE_INSIDE, //方形(内围)
|
||||
CIRCLE_OUTSIDE, //圆形(外围)
|
||||
CIRCLE_INSIDE, //圆形(内围)
|
||||
}
|
||||
|
||||
protected STAGE_LIGHT_TYPE stageLightType = STAGE_LIGHT_TYPE.CIRCLE_OUTSIDE;
|
||||
protected Drawable tipImage;
|
||||
protected float stageLightFilletRadius; //舞台灯光部分的圆角
|
||||
protected Integer maskColor = null;
|
||||
protected OnDialogButtonClickListener<GuideDialog> onStageLightPathClickListener;
|
||||
protected int[] baseViewLocationCoordinateCompensation = new int[4];
|
||||
|
||||
protected GuideDialog() {
|
||||
super();
|
||||
enterAnimResId = R.anim.anim_dialogx_alpha_enter;
|
||||
exitAnimResId = R.anim.anim_dialogx_default_exit;
|
||||
this.alignViewGravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
|
||||
}
|
||||
|
||||
public static GuideDialog build() {
|
||||
return new GuideDialog();
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.stageLightType = stageLightType;
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, OnBindView<CustomDialog> onBindView, int alignBaseViewGravity) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.stageLightType = stageLightType;
|
||||
this.onBindView = onBindView;
|
||||
this.alignViewGravity = alignBaseViewGravity;
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, int tipImageResId, int alignBaseViewGravity) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.tipImage = getResources().getDrawable(tipImageResId);
|
||||
this.stageLightType = stageLightType;
|
||||
this.alignViewGravity = alignBaseViewGravity;
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, Bitmap tipImage, int alignBaseViewGravity) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.tipImage = new BitmapDrawable(getResources(), tipImage);
|
||||
this.stageLightType = stageLightType;
|
||||
this.alignViewGravity = alignBaseViewGravity;
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, Drawable tipImage, int alignBaseViewGravity) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.tipImage = tipImage;
|
||||
this.stageLightType = stageLightType;
|
||||
this.alignViewGravity = alignBaseViewGravity;
|
||||
}
|
||||
|
||||
public GuideDialog(int tipImageResId) {
|
||||
this();
|
||||
this.tipImage = getResources().getDrawable(tipImageResId);
|
||||
}
|
||||
|
||||
public GuideDialog(Bitmap tipImage) {
|
||||
this();
|
||||
this.tipImage = new BitmapDrawable(getResources(), tipImage);
|
||||
}
|
||||
|
||||
public GuideDialog(Drawable tipImage) {
|
||||
this();
|
||||
this.tipImage = tipImage;
|
||||
}
|
||||
|
||||
public GuideDialog(int tipImageResId, ALIGN align) {
|
||||
this();
|
||||
this.tipImage = getResources().getDrawable(tipImageResId);
|
||||
this.align = align;
|
||||
}
|
||||
|
||||
public GuideDialog(Bitmap tipImage, ALIGN align) {
|
||||
this();
|
||||
this.tipImage = new BitmapDrawable(getResources(), tipImage);
|
||||
this.align = align;
|
||||
}
|
||||
|
||||
public GuideDialog(Drawable tipImage, ALIGN align) {
|
||||
this();
|
||||
this.tipImage = tipImage;
|
||||
this.align = align;
|
||||
}
|
||||
|
||||
public GuideDialog(OnBindView<CustomDialog> onBindView) {
|
||||
this();
|
||||
this.onBindView = onBindView;
|
||||
}
|
||||
|
||||
public GuideDialog(OnBindView<CustomDialog> onBindView, ALIGN align) {
|
||||
this();
|
||||
this.onBindView = onBindView;
|
||||
this.align = align;
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, int tipImageResId) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.tipImage = getResources().getDrawable(tipImageResId);
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, Bitmap tipImage) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.tipImage = new BitmapDrawable(getResources(), tipImage);
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, Drawable tipImage) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.tipImage = tipImage;
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, int tipImageResId) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.stageLightType = stageLightType;
|
||||
this.tipImage = getResources().getDrawable(tipImageResId);
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, Bitmap tipImage) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.stageLightType = stageLightType;
|
||||
this.tipImage = new BitmapDrawable(getResources(), tipImage);
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, STAGE_LIGHT_TYPE stageLightType, Drawable tipImage) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.stageLightType = stageLightType;
|
||||
this.tipImage = tipImage;
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, int tipImageResId, int alignBaseViewGravity) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.alignViewGravity = alignBaseViewGravity;
|
||||
this.tipImage = getResources().getDrawable(tipImageResId);
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, Bitmap tipImage, int alignBaseViewGravity) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.alignViewGravity = alignBaseViewGravity;
|
||||
this.tipImage = new BitmapDrawable(getResources(), tipImage);
|
||||
}
|
||||
|
||||
public GuideDialog(View baseView, Drawable tipImage, int alignBaseViewGravity) {
|
||||
this();
|
||||
this.baseView(baseView);
|
||||
this.alignViewGravity = alignBaseViewGravity;
|
||||
this.tipImage = tipImage;
|
||||
}
|
||||
|
||||
//静态方法
|
||||
public static GuideDialog show(OnBindView<CustomDialog> onBindView) {
|
||||
GuideDialog guideDialog = new GuideDialog(onBindView);
|
||||
guideDialog.show();
|
||||
return guideDialog;
|
||||
}
|
||||
|
||||
public static GuideDialog show(OnBindView<CustomDialog> onBindView, ALIGN align) {
|
||||
GuideDialog guideDialog = new GuideDialog(onBindView);
|
||||
guideDialog.align = align;
|
||||
guideDialog.show();
|
||||
return guideDialog;
|
||||
}
|
||||
|
||||
public static GuideDialog show(int tipImageResId) {
|
||||
return new GuideDialog(tipImageResId).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(Bitmap tipImage) {
|
||||
return new GuideDialog(tipImage).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(Drawable tipImage) {
|
||||
return new GuideDialog(tipImage).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(int tipImageResId, ALIGN align) {
|
||||
GuideDialog guideDialog = new GuideDialog(tipImageResId, align);
|
||||
guideDialog.align = align;
|
||||
return guideDialog.show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(Bitmap tipImage, ALIGN align) {
|
||||
GuideDialog guideDialog = new GuideDialog(tipImage, align);
|
||||
guideDialog.align = align;
|
||||
return guideDialog.show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(Drawable tipImage, ALIGN align) {
|
||||
return new GuideDialog(tipImage, align).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType) {
|
||||
return new GuideDialog(baseView, stageLightType).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, OnBindView<CustomDialog> onBindView, int alignBaseViewGravity) {
|
||||
return new GuideDialog(baseView, stageLightType, onBindView, alignBaseViewGravity).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, int tipImageResId, int alignBaseViewGravity) {
|
||||
return new GuideDialog(baseView, stageLightType, tipImageResId, alignBaseViewGravity).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, Bitmap tipImage, int alignBaseViewGravity) {
|
||||
return new GuideDialog(baseView, stageLightType, tipImage, alignBaseViewGravity).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, Drawable tipImage, int alignBaseViewGravity) {
|
||||
return new GuideDialog(baseView, stageLightType, tipImage, alignBaseViewGravity).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, int tipImageResId) {
|
||||
return new GuideDialog(baseView, tipImageResId).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, Bitmap tipImage) {
|
||||
return new GuideDialog(baseView, tipImage).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, Drawable tipImage) {
|
||||
return new GuideDialog(baseView, tipImage).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, int tipImageResId) {
|
||||
return new GuideDialog(baseView, stageLightType, tipImageResId).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, Bitmap tipImage) {
|
||||
return new GuideDialog(baseView, stageLightType, tipImage).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, STAGE_LIGHT_TYPE stageLightType, Drawable tipImage) {
|
||||
return new GuideDialog(baseView, stageLightType, tipImage).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, int tipImageResId, int alignBaseViewGravity) {
|
||||
return new GuideDialog(baseView, tipImageResId, alignBaseViewGravity).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, Bitmap tipImage, int alignBaseViewGravity) {
|
||||
return new GuideDialog(baseView, tipImage, alignBaseViewGravity).show();
|
||||
}
|
||||
|
||||
public static GuideDialog show(View baseView, Drawable tipImage, int alignBaseViewGravity) {
|
||||
return new GuideDialog(baseView, tipImage, alignBaseViewGravity).show();
|
||||
}
|
||||
|
||||
//执行方法
|
||||
public GuideDialog show() {
|
||||
super.show();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog show(Activity activity) {
|
||||
super.show(activity);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dialogKey() {
|
||||
return getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")";
|
||||
}
|
||||
|
||||
public GuideDialog setDialogLifecycleCallback(DialogLifecycleCallback<CustomDialog> dialogLifecycleCallback) {
|
||||
this.dialogLifecycleCallback = dialogLifecycleCallback;
|
||||
if (isShow) dialogLifecycleCallback.onShow(me);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setOnBackPressedListener(OnBackPressedListener<CustomDialog> onBackPressedListener) {
|
||||
this.onBackPressedListener = onBackPressedListener;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setStyle(DialogXStyle style) {
|
||||
this.style = style;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setTheme(DialogX.THEME theme) {
|
||||
this.theme = theme;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setCancelable(boolean cancelable) {
|
||||
this.privateCancelable = cancelable ? BOOLEAN.TRUE : BOOLEAN.FALSE;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog.DialogImpl getDialogImpl() {
|
||||
return dialogImpl;
|
||||
}
|
||||
|
||||
public GuideDialog setCustomView(OnBindView<CustomDialog> onBindView) {
|
||||
this.onBindView = onBindView;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog removeCustomView() {
|
||||
this.onBindView.clean();
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setEnterAnimResId(int enterAnimResId) {
|
||||
this.enterAnimResId = enterAnimResId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setExitAnimResId(int exitAnimResId) {
|
||||
this.exitAnimResId = exitAnimResId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setAnimResId(int enterAnimResId, int exitAnimResId) {
|
||||
this.enterAnimResId = enterAnimResId;
|
||||
this.exitAnimResId = exitAnimResId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setAlign(ALIGN align) {
|
||||
this.align = align;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setAutoUnsafePlacePadding(boolean autoUnsafePlacePadding) {
|
||||
super.setAutoUnsafePlacePadding(autoUnsafePlacePadding);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setFullScreen(boolean fullscreen) {
|
||||
super.setFullScreen(fullscreen);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setMaskColor(@ColorInt int maskColor) {
|
||||
this.maskColor = maskColor;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setEnterAnimDuration(long enterAnimDuration) {
|
||||
this.enterAnimDuration = enterAnimDuration;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setExitAnimDuration(long exitAnimDuration) {
|
||||
this.exitAnimDuration = exitAnimDuration;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setDialogImplMode(DialogX.IMPL_MODE dialogImplMode) {
|
||||
this.dialogImplMode = dialogImplMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setBkgInterceptTouch(boolean bkgInterceptTouch) {
|
||||
this.bkgInterceptTouch = bkgInterceptTouch;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setAlignBaseViewGravity(View baseView, int alignGravity) {
|
||||
this.baseView(baseView);
|
||||
this.alignViewGravity = alignGravity;
|
||||
baseViewLoc = new int[4];
|
||||
baseView.getLocationInWindow(baseViewLoc);
|
||||
setFullScreen(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setAlignBaseViewGravity(View baseView) {
|
||||
this.baseView(baseView);
|
||||
baseViewLoc = new int[4];
|
||||
baseView.getLocationInWindow(baseViewLoc);
|
||||
setFullScreen(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setAlignBaseViewGravity(int alignGravity) {
|
||||
this.alignViewGravity = alignGravity;
|
||||
if (baseView() != null) {
|
||||
baseViewLoc = new int[4];
|
||||
baseView().getLocationInWindow(baseViewLoc);
|
||||
}
|
||||
setFullScreen(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setAlignBaseViewGravity(View baseView, int alignGravity, int marginLeft,
|
||||
int marginTop, int marginRight, int marginBottom) {
|
||||
this.marginRelativeBaseView = new int[]{marginLeft, marginTop, marginRight, marginBottom};
|
||||
return setAlignBaseViewGravity(baseView, alignGravity);
|
||||
}
|
||||
|
||||
public GuideDialog setBaseViewMargin(int[] marginRelativeBaseView) {
|
||||
this.marginRelativeBaseView = marginRelativeBaseView;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setBaseViewMargin(int marginLeft, int marginTop,
|
||||
int marginRight, int marginBottom) {
|
||||
this.marginRelativeBaseView = new int[]{marginLeft, marginTop, marginRight, marginBottom};
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setBaseViewMarginLeft(int marginLeft) {
|
||||
this.marginRelativeBaseView[0] = marginLeft;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setBaseViewMarginTop(int marginTop) {
|
||||
this.marginRelativeBaseView[1] = marginTop;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setBaseViewMarginRight(int marginRight) {
|
||||
this.marginRelativeBaseView[2] = marginRight;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setBaseViewMarginBottom(int marginBottom) {
|
||||
this.marginRelativeBaseView[3] = marginBottom;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置对话框 UI 宽度(单位:像素)
|
||||
*
|
||||
* @param width 宽度(像素)
|
||||
* @return CustomDialog实例
|
||||
*/
|
||||
public GuideDialog setWidth(int width) {
|
||||
this.width = width;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置对话框 UI 高度(单位:像素)
|
||||
*
|
||||
* @param height 高度(像素)
|
||||
* @return CustomDialog实例
|
||||
*/
|
||||
public GuideDialog setHeight(int height) {
|
||||
this.height = height;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setOnBackgroundMaskClickListener(OnBackgroundMaskClickListener<CustomDialog> onBackgroundMaskClickListener) {
|
||||
this.onBackgroundMaskClickListener = onBackgroundMaskClickListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDialogShow() {
|
||||
super.onDialogShow();
|
||||
if (baseView() == null) {
|
||||
super.setMaskColor(maskColor == null ? getColor(R.color.black50) : maskColor);
|
||||
}
|
||||
}
|
||||
|
||||
View stageLightPathStub;
|
||||
|
||||
@Override
|
||||
protected void onDialogRefreshUI() {
|
||||
super.onDialogRefreshUI();
|
||||
if (onBindView == null && tipImage != null) {
|
||||
getDialogImpl().boxCustom.setFocusable(false);
|
||||
getDialogImpl().boxCustom.setFocusableInTouchMode(false);
|
||||
getDialogImpl().boxCustom.setOnClickListener(null);
|
||||
getDialogImpl().boxCustom.setClickable(false);
|
||||
|
||||
ImageView imageView = new ImageView(getOwnActivity());
|
||||
imageView.setImageDrawable(tipImage);
|
||||
imageView.setAdjustViewBounds(true);
|
||||
imageView.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
onBindView = new OnBindView<CustomDialog>(imageView) {
|
||||
@Override
|
||||
public void onBind(CustomDialog dialog, View v) {
|
||||
|
||||
}
|
||||
};
|
||||
onBindView.bindParent(getDialogImpl().boxCustom, me);
|
||||
}
|
||||
if (getOnStageLightPathClickListener() != null && baseView() != null) {
|
||||
stageLightPathStub = new View(getOwnActivity());
|
||||
stageLightPathStub.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (!getOnStageLightPathClickListener().onClick(GuideDialog.this, v)) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
});
|
||||
getDialogImpl().boxRoot.addView(stageLightPathStub);
|
||||
} else {
|
||||
if (stageLightPathStub != null && stageLightPathStub.getParent() instanceof ViewGroup) {
|
||||
((ViewGroup) stageLightPathStub.getParent()).removeView(stageLightPathStub);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int[] baseViewLocCache;
|
||||
|
||||
@Override
|
||||
protected void onGetBaseViewLoc(int[] baseViewLoc) {
|
||||
if (Arrays.equals(baseViewLoc, baseViewLocCache)) {
|
||||
return;
|
||||
}
|
||||
if (getDialogImpl() == null) {
|
||||
return;
|
||||
}
|
||||
Bitmap bkg = Bitmap.createBitmap(getDialogImpl().boxRoot.getWidth(), getDialogImpl().boxRoot.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bkg);
|
||||
|
||||
int x = baseViewLoc[0] + baseViewLocationCoordinateCompensation[0];
|
||||
int y = baseViewLoc[1] + baseViewLocationCoordinateCompensation[1];
|
||||
int w = baseViewLoc[2] + baseViewLocationCoordinateCompensation[2];
|
||||
int h = baseViewLoc[3] + baseViewLocationCoordinateCompensation[3];
|
||||
int hW = w / 2;
|
||||
int hH = h / 2;
|
||||
|
||||
if (stageLightPathStub != null && (stageLightPathStub.getX() != x || stageLightPathStub.getY() != y)) {
|
||||
RelativeLayout.LayoutParams rLp = (RelativeLayout.LayoutParams) stageLightPathStub.getLayoutParams();
|
||||
if (rLp == null) {
|
||||
rLp = new RelativeLayout.LayoutParams(w, h);
|
||||
} else {
|
||||
rLp.width = w;
|
||||
rLp.height = h;
|
||||
}
|
||||
stageLightPathStub.setLayoutParams(rLp);
|
||||
stageLightPathStub.setX(x);
|
||||
stageLightPathStub.setY(y);
|
||||
}
|
||||
|
||||
switch (stageLightType) {
|
||||
case CIRCLE_OUTSIDE: {
|
||||
int r = (int) Math.sqrt(hW * hW + hH * hH);
|
||||
canvas.drawCircle(x + hW, y + hH, r, getStageLightPaint());
|
||||
}
|
||||
break;
|
||||
case CIRCLE_INSIDE: {
|
||||
int r = Math.min(w, h) / 2;
|
||||
canvas.drawCircle(x + hW, y + hH, r, getStageLightPaint());
|
||||
}
|
||||
break;
|
||||
case RECTANGLE: {
|
||||
canvas.drawRoundRect(new RectF(x, y, x + w, y + h), stageLightFilletRadius, stageLightFilletRadius, getStageLightPaint());
|
||||
}
|
||||
break;
|
||||
case SQUARE_INSIDE: {
|
||||
int r = Math.min(w, h);
|
||||
canvas.drawRoundRect(new RectF(x + hW - r / 2, y + hH - r / 2, x + hW - r / 2 + r, y + hH - r / 2 + r), stageLightFilletRadius, stageLightFilletRadius, getStageLightPaint());
|
||||
}
|
||||
break;
|
||||
case SQUARE_OUTSIDE: {
|
||||
int r = Math.max(w, h);
|
||||
canvas.drawRoundRect(new RectF(x + hW - r / 2, y + hH - r / 2, x + hW - r / 2 + r, y + hH - r / 2 + r), stageLightFilletRadius, stageLightFilletRadius, getStageLightPaint());
|
||||
}
|
||||
break;
|
||||
}
|
||||
stageLightPaint.setXfermode(null);
|
||||
canvas.drawColor(maskColor == null ? getColor(R.color.black50) : maskColor, PorterDuff.Mode.SRC_OUT);
|
||||
|
||||
BitmapDrawable bkgDrawable = new BitmapDrawable(getResources(), bkg);
|
||||
getDialogImpl().boxRoot.setBackground(bkgDrawable);
|
||||
baseViewLocCache = Arrays.copyOf(baseViewLoc, 4);
|
||||
}
|
||||
|
||||
Paint stageLightPaint;
|
||||
|
||||
private Paint getStageLightPaint() {
|
||||
if (stageLightPaint == null) {
|
||||
stageLightPaint = new Paint();
|
||||
stageLightPaint.setColor(Color.RED);
|
||||
stageLightPaint.setStyle(Paint.Style.FILL);
|
||||
stageLightPaint.setAntiAlias(true);
|
||||
}
|
||||
return stageLightPaint;
|
||||
}
|
||||
|
||||
public STAGE_LIGHT_TYPE getStageLightType() {
|
||||
return stageLightType;
|
||||
}
|
||||
|
||||
public GuideDialog setStageLightType(STAGE_LIGHT_TYPE stageLightType) {
|
||||
this.stageLightType = stageLightType;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Drawable getTipImage() {
|
||||
return tipImage;
|
||||
}
|
||||
|
||||
public GuideDialog setTipImage(int tipImageResId) {
|
||||
this.tipImage = getResources().getDrawable(tipImageResId);
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setTipImage(Bitmap tipImage) {
|
||||
this.tipImage = new BitmapDrawable(getResources(), tipImage);
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setTipImage(Drawable tipImage) {
|
||||
this.tipImage = tipImage;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getStageLightFilletRadius() {
|
||||
return stageLightFilletRadius;
|
||||
}
|
||||
|
||||
public GuideDialog setStageLightFilletRadius(float stageLightFilletRadius) {
|
||||
this.stageLightFilletRadius = stageLightFilletRadius;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public OnDialogButtonClickListener<GuideDialog> getOnStageLightPathClickListener() {
|
||||
return onStageLightPathClickListener;
|
||||
}
|
||||
|
||||
public GuideDialog setOnStageLightPathClickListener(OnDialogButtonClickListener<GuideDialog> onStageLightPathClickListener) {
|
||||
this.onStageLightPathClickListener = onStageLightPathClickListener;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public DialogXAnimInterface<CustomDialog> getDialogXAnimImpl() {
|
||||
return dialogXAnimImpl;
|
||||
}
|
||||
|
||||
public GuideDialog setDialogXAnimImpl(DialogXAnimInterface<CustomDialog> dialogXAnimImpl) {
|
||||
this.dialogXAnimImpl = dialogXAnimImpl;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setRootPadding(int padding) {
|
||||
this.screenPaddings = new int[]{padding, padding, padding, padding};
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setRootPadding(int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
|
||||
this.screenPaddings = new int[]{paddingLeft, paddingTop, paddingRight, paddingBottom};
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public int[] getBaseViewLocationCoordinateCompensation() {
|
||||
return baseViewLocationCoordinateCompensation;
|
||||
}
|
||||
|
||||
public GuideDialog setBaseViewLocationCoordinateCompensation(int[] baseViewLocationCoordinateCompensation) {
|
||||
this.baseViewLocationCoordinateCompensation = baseViewLocationCoordinateCompensation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setBaseViewLocationCoordinateCompensation(int px) {
|
||||
this.baseViewLocationCoordinateCompensation = new int[]{px, px, px, px};
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setBaseViewLocationCoordinateCompensation(int pxX, int pxY, int pxR, int pxB) {
|
||||
this.baseViewLocationCoordinateCompensation = new int[]{pxX, pxY, pxR, pxB};
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setBaseViewLocationCoordinateCompensationLeft(int pxX) {
|
||||
this.baseViewLocationCoordinateCompensation[0] = pxX;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setBaseViewLocationCoordinateCompensationTop(int pxY) {
|
||||
this.baseViewLocationCoordinateCompensation[1] = pxY;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setBaseViewLocationCoordinateCompensationRight(int pxR) {
|
||||
this.baseViewLocationCoordinateCompensation[2] = pxR;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setBaseViewLocationCoordinateCompensationBottom(int pxB) {
|
||||
this.baseViewLocationCoordinateCompensation[3] = pxB;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getBaseViewLocationCoordinateCompensationLeft() {
|
||||
return baseViewLocationCoordinateCompensation[0];
|
||||
}
|
||||
|
||||
public int getBaseViewLocationCoordinateCompensationTop() {
|
||||
return baseViewLocationCoordinateCompensation[1];
|
||||
}
|
||||
|
||||
public int getBaseViewLocationCoordinateCompensationRight() {
|
||||
return baseViewLocationCoordinateCompensation[2];
|
||||
}
|
||||
|
||||
public int getBaseViewLocationCoordinateCompensationBottom() {
|
||||
return baseViewLocationCoordinateCompensation[3];
|
||||
}
|
||||
|
||||
public GuideDialog setData(String key, Object obj) {
|
||||
if (data == null) data = new HashMap<>();
|
||||
data.put(key, obj);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog onShow(DialogXRunnable<CustomDialog> dialogXRunnable) {
|
||||
onShowRunnable = dialogXRunnable;
|
||||
if (isShow() && onShowRunnable != null) {
|
||||
onShowRunnable.run(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog onDismiss(DialogXRunnable<CustomDialog> dialogXRunnable) {
|
||||
onDismissRunnable = dialogXRunnable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setEnableImmersiveMode(boolean enableImmersiveMode) {
|
||||
this.enableImmersiveMode = enableImmersiveMode;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setThisOrderIndex(int orderIndex) {
|
||||
this.thisOrderIndex = orderIndex;
|
||||
if (getDialogView() != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getDialogView().setTranslationZ(orderIndex);
|
||||
} else {
|
||||
error("DialogX: " + dialogKey() + " 执行 .setThisOrderIndex("+orderIndex+") 失败:系统不支持此方法,SDK-API 版本必须大于 21(LOLLIPOP)");
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog bringToFront() {
|
||||
setThisOrderIndex(getHighestOrderIndex());
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog setActionRunnable(int actionId, DialogXRunnable<CustomDialog> runnable) {
|
||||
dialogActionRunnableMap.put(actionId, runnable);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog cleanAction(int actionId){
|
||||
dialogActionRunnableMap.remove(actionId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuideDialog cleanAllAction(){
|
||||
dialogActionRunnableMap.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
// for BaseDialog use
|
||||
public void callDialogDismiss(){
|
||||
dismiss();
|
||||
}
|
||||
|
||||
public GuideDialog bindDismissWithLifecycleOwner(LifecycleOwner owner){
|
||||
super.bindDismissWithLifecycleOwnerPrivate(owner);
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,759 @@
|
||||
package com.kongzue.dialogx.dialogs;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.kongzue.dialogx.DialogX;
|
||||
import com.kongzue.dialogx.R;
|
||||
import com.kongzue.dialogx.interfaces.DialogLifecycleCallback;
|
||||
import com.kongzue.dialogx.interfaces.DialogXAnimInterface;
|
||||
import com.kongzue.dialogx.interfaces.DialogXRunnable;
|
||||
import com.kongzue.dialogx.interfaces.DialogXStyle;
|
||||
import com.kongzue.dialogx.interfaces.OnBackPressedListener;
|
||||
import com.kongzue.dialogx.interfaces.OnBackgroundMaskClickListener;
|
||||
import com.kongzue.dialogx.interfaces.OnBindView;
|
||||
import com.kongzue.dialogx.interfaces.OnInputDialogButtonClickListener;
|
||||
import com.kongzue.dialogx.util.InputInfo;
|
||||
import com.kongzue.dialogx.util.TextInfo;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @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 static InputDialog build(DialogXStyle style) {
|
||||
InputDialog dialog = new InputDialog();
|
||||
dialog.setStyle(style);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static InputDialog build(OnBindView<MessageDialog> onBindView) {
|
||||
return new InputDialog().setCustomView(onBindView);
|
||||
}
|
||||
|
||||
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<MessageDialog> getOnBackPressedListener() {
|
||||
return (OnBackPressedListener<MessageDialog>) onBackPressedListener;
|
||||
}
|
||||
|
||||
public InputDialog setOnBackPressedListener(OnBackPressedListener<MessageDialog> 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 restartDialog() {
|
||||
if (getDialogView() != null) {
|
||||
dismiss(getDialogView());
|
||||
isShow = false;
|
||||
}
|
||||
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;
|
||||
View dialogView = createView(layoutId);
|
||||
dialogImpl = new DialogImpl(dialogView);
|
||||
if (dialogView != null) dialogView.setTag(me);
|
||||
show(dialogView);
|
||||
setInputText(inputText);
|
||||
}
|
||||
|
||||
public InputDialog setAnimResId(int enterResId, int exitResId) {
|
||||
customEnterAnimResId = enterResId;
|
||||
customExitAnimResId = exitResId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setEnterAnimResId(int enterResId) {
|
||||
customEnterAnimResId = enterResId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setExitAnimResId(int exitResId) {
|
||||
customExitAnimResId = exitResId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setMaxWidth(int maxWidth) {
|
||||
this.maxWidth = maxWidth;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setMaxHeight(int maxHeight) {
|
||||
this.maxHeight = maxHeight;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setMinHeight(int minHeight) {
|
||||
this.minHeight = minHeight;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setMinWidth(int minWidth) {
|
||||
this.minWidth = minWidth;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setDialogImplMode(DialogX.IMPL_MODE dialogImplMode) {
|
||||
this.dialogImplMode = dialogImplMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isBkgInterceptTouch() {
|
||||
return bkgInterceptTouch;
|
||||
}
|
||||
|
||||
public InputDialog setBkgInterceptTouch(boolean bkgInterceptTouch) {
|
||||
this.bkgInterceptTouch = bkgInterceptTouch;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OnBackgroundMaskClickListener<MessageDialog> getOnBackgroundMaskClickListener() {
|
||||
return onBackgroundMaskClickListener;
|
||||
}
|
||||
|
||||
public InputDialog setOnBackgroundMaskClickListener(OnBackgroundMaskClickListener<MessageDialog> onBackgroundMaskClickListener) {
|
||||
this.onBackgroundMaskClickListener = onBackgroundMaskClickListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setRadius(float radiusPx) {
|
||||
backgroundRadius = radiusPx;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setTitleIcon(Bitmap titleIcon) {
|
||||
this.titleIcon = new BitmapDrawable(getResources(), titleIcon);
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setTitleIcon(int titleIconResId) {
|
||||
this.titleIcon = getResources().getDrawable(titleIconResId);
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setTitleIcon(Drawable titleIcon) {
|
||||
this.titleIcon = titleIcon;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public DialogXAnimInterface<MessageDialog> getDialogXAnimImpl() {
|
||||
return dialogXAnimImpl;
|
||||
}
|
||||
|
||||
public InputDialog setDialogXAnimImpl(DialogXAnimInterface<MessageDialog> dialogXAnimImpl) {
|
||||
this.dialogXAnimImpl = dialogXAnimImpl;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setRootPadding(int padding) {
|
||||
this.screenPaddings = new int[]{padding, padding, padding, padding};
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setRootPadding(int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
|
||||
this.screenPaddings = new int[]{paddingLeft, paddingTop, paddingRight, paddingBottom};
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setDialogLifecycleCallback(DialogLifecycleCallback<MessageDialog> dialogLifecycleCallback) {
|
||||
this.dialogLifecycleCallback = dialogLifecycleCallback;
|
||||
if (isShow) dialogLifecycleCallback.onShow(me);
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setData(String key, Object obj) {
|
||||
if (data == null) data = new HashMap<>();
|
||||
data.put(key, obj);
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog onShow(DialogXRunnable<MessageDialog> dialogXRunnable) {
|
||||
onShowRunnable = dialogXRunnable;
|
||||
if (isShow() && onShowRunnable != null) {
|
||||
onShowRunnable.run(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog onDismiss(DialogXRunnable<MessageDialog> dialogXRunnable) {
|
||||
onDismissRunnable = dialogXRunnable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setEnableImmersiveMode(boolean enableImmersiveMode) {
|
||||
this.enableImmersiveMode = enableImmersiveMode;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog appendMessage(CharSequence message){
|
||||
this.message = TextUtils.concat(this.message, message);
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setThisOrderIndex(int orderIndex) {
|
||||
this.thisOrderIndex = orderIndex;
|
||||
if (getDialogView() != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getDialogView().setTranslationZ(orderIndex);
|
||||
} else {
|
||||
error("DialogX: " + dialogKey() + " 执行 .setThisOrderIndex("+orderIndex+") 失败:系统不支持此方法,SDK-API 版本必须大于 21(LOLLIPOP)");
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog bringToFront() {
|
||||
setThisOrderIndex(getHighestOrderIndex());
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog setActionRunnable(int actionId, DialogXRunnable<MessageDialog> runnable) {
|
||||
dialogActionRunnableMap.put(actionId, runnable);
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog cleanAction(int actionId){
|
||||
dialogActionRunnableMap.remove(actionId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputDialog cleanAllAction(){
|
||||
dialogActionRunnableMap.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
// for BaseDialog use
|
||||
public void callDialogDismiss(){
|
||||
dismiss();
|
||||
}
|
||||
|
||||
public InputDialog bindDismissWithLifecycleOwner(LifecycleOwner owner){
|
||||
super.bindDismissWithLifecycleOwnerPrivate(owner);
|
||||
return this;
|
||||
}
|
||||
}
|
1612
DialogX/src/main/java/com/kongzue/dialogx/dialogs/MessageDialog.java
Normal file
1612
DialogX/src/main/java/com/kongzue/dialogx/dialogs/MessageDialog.java
Normal file
File diff suppressed because it is too large
Load Diff
1601
DialogX/src/main/java/com/kongzue/dialogx/dialogs/MessageMenu.java
Normal file
1601
DialogX/src/main/java/com/kongzue/dialogx/dialogs/MessageMenu.java
Normal file
File diff suppressed because it is too large
Load Diff
1632
DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopMenu.java
Normal file
1632
DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopMenu.java
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1566
DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopTip.java
Normal file
1566
DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopTip.java
Normal file
File diff suppressed because it is too large
Load Diff
313
DialogX/src/main/java/com/kongzue/dialogx/dialogs/TipDialog.java
Normal file
313
DialogX/src/main/java/com/kongzue/dialogx/dialogs/TipDialog.java
Normal file
@ -0,0 +1,313 @@
|
||||
package com.kongzue.dialogx.dialogs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.kongzue.dialogx.DialogX;
|
||||
import com.kongzue.dialogx.interfaces.DialogXAnimInterface;
|
||||
import com.kongzue.dialogx.interfaces.DialogXRunnable;
|
||||
import com.kongzue.dialogx.interfaces.OnBackPressedListener;
|
||||
import com.kongzue.dialogx.interfaces.OnBackgroundMaskClickListener;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @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 {
|
||||
|
||||
/**
|
||||
* 参数 duration 使用此值,或小于 0 的任意整数时,
|
||||
* TipDialog 将不自动关闭
|
||||
*/
|
||||
public static final int NO_AUTO_DISMISS = -1;
|
||||
|
||||
protected TipDialog() {
|
||||
super();
|
||||
}
|
||||
|
||||
public static WaitDialog showTipWithDefaultText(TYPE tip) {
|
||||
return WaitDialog.showTipWithDefaultText(tip);
|
||||
}
|
||||
|
||||
public static WaitDialog show(int messageResId) {
|
||||
return show((Activity) null, messageResId);
|
||||
}
|
||||
|
||||
public static WaitDialog show(Activity activity, int messageResId) {
|
||||
WaitDialog dialog = getInstance(activity);
|
||||
if (dialog != null) {
|
||||
dialog.setTip(messageResId, TYPE.WARNING);
|
||||
if (dialog.getDialogImpl() == null) {
|
||||
dialog.show();
|
||||
} else {
|
||||
dialog.cancelDelayDismissTimer();
|
||||
}
|
||||
return dialog;
|
||||
} else {
|
||||
return instanceBuild();
|
||||
}
|
||||
}
|
||||
|
||||
public static WaitDialog show(CharSequence message) {
|
||||
return show(null, message);
|
||||
}
|
||||
|
||||
public static WaitDialog show(Activity activity, CharSequence message) {
|
||||
WaitDialog dialog = getInstance(activity);
|
||||
if (dialog != null) {
|
||||
dialog.setTip(message, TYPE.WARNING);
|
||||
if (dialog.getDialogImpl() == null) {
|
||||
dialog.show();
|
||||
} else {
|
||||
dialog.cancelDelayDismissTimer();
|
||||
}
|
||||
return dialog;
|
||||
} else {
|
||||
return instanceBuild();
|
||||
}
|
||||
}
|
||||
|
||||
public static WaitDialog show(int messageResId, TYPE tip) {
|
||||
return show(null, messageResId, tip);
|
||||
}
|
||||
|
||||
public static WaitDialog show(Activity activity, int messageResId, TYPE tip) {
|
||||
WaitDialog dialog = getInstance(activity);
|
||||
if (dialog != null) {
|
||||
dialog.setTip(messageResId, tip);
|
||||
if (dialog.getDialogImpl() == null) {
|
||||
dialog.show();
|
||||
} else {
|
||||
dialog.cancelDelayDismissTimer();
|
||||
}
|
||||
return dialog;
|
||||
} else {
|
||||
return instanceBuild();
|
||||
}
|
||||
}
|
||||
|
||||
public static WaitDialog show(CharSequence message, TYPE tip) {
|
||||
return show(null, message, tip);
|
||||
}
|
||||
|
||||
public static WaitDialog show(Activity activity, CharSequence message, TYPE tip) {
|
||||
WaitDialog dialog = getInstance(activity);
|
||||
if (dialog != null) {
|
||||
dialog.setTip(message, tip);
|
||||
if (dialog.getDialogImpl() == null) {
|
||||
dialog.show();
|
||||
} else {
|
||||
dialog.cancelDelayDismissTimer();
|
||||
}
|
||||
return dialog;
|
||||
} else {
|
||||
return instanceBuild();
|
||||
}
|
||||
}
|
||||
|
||||
public static WaitDialog show(int messageResId, TYPE tip, long duration) {
|
||||
return show(null, messageResId, tip, duration);
|
||||
}
|
||||
|
||||
public static WaitDialog show(Activity activity, int messageResId, TYPE tip, long duration) {
|
||||
WaitDialog dialog = getInstance(activity);
|
||||
if (dialog != null) {
|
||||
dialog.setTip(messageResId, tip);
|
||||
dialog.setTipShowDuration(duration);
|
||||
if (dialog.getDialogImpl() == null) {
|
||||
dialog.show();
|
||||
} else {
|
||||
dialog.cancelDelayDismissTimer();
|
||||
}
|
||||
return dialog;
|
||||
} else {
|
||||
return instanceBuild();
|
||||
}
|
||||
}
|
||||
|
||||
public static WaitDialog show(CharSequence message, TYPE tip, long duration) {
|
||||
return show(null, message, tip, duration);
|
||||
}
|
||||
|
||||
public static WaitDialog show(Activity activity, CharSequence message, TYPE tip, long duration) {
|
||||
WaitDialog dialog = getInstance(activity);
|
||||
if (dialog != null) {
|
||||
dialog.setTip(message, tip);
|
||||
dialog.setTipShowDuration(duration);
|
||||
if (dialog.getDialogImpl() == null) {
|
||||
dialog.show();
|
||||
} else {
|
||||
dialog.cancelDelayDismissTimer();
|
||||
}
|
||||
return dialog;
|
||||
} else {
|
||||
return instanceBuild();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dialogKey() {
|
||||
return getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")";
|
||||
}
|
||||
|
||||
public TipDialog setMaxWidth(int maxWidth) {
|
||||
this.maxWidth = maxWidth;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog setMaxHeight(int maxHeight) {
|
||||
this.maxHeight = maxHeight;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog setMinHeight(int minHeight) {
|
||||
this.minHeight = minHeight;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog setMinWidth(int minWidth) {
|
||||
this.minWidth = minWidth;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog setDialogImplMode(DialogX.IMPL_MODE dialogImplMode) {
|
||||
this.dialogImplMode = dialogImplMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isBkgInterceptTouch() {
|
||||
return bkgInterceptTouch;
|
||||
}
|
||||
|
||||
public TipDialog setBkgInterceptTouch(boolean bkgInterceptTouch) {
|
||||
this.bkgInterceptTouch = bkgInterceptTouch;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OnBackgroundMaskClickListener<WaitDialog> getOnBackgroundMaskClickListener() {
|
||||
return onBackgroundMaskClickListener;
|
||||
}
|
||||
|
||||
public TipDialog setOnBackgroundMaskClickListener(OnBackgroundMaskClickListener<WaitDialog> onBackgroundMaskClickListener) {
|
||||
this.onBackgroundMaskClickListener = onBackgroundMaskClickListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog setRadius(float radiusPx) {
|
||||
backgroundRadius = radiusPx;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getRadius() {
|
||||
return backgroundRadius;
|
||||
}
|
||||
|
||||
public TipDialog setDialogXAnimImpl(DialogXAnimInterface<WaitDialog> dialogXAnimImpl) {
|
||||
this.dialogXAnimImpl = dialogXAnimImpl;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog setOnBackPressedListener(OnBackPressedListener<WaitDialog> onBackPressedListener) {
|
||||
this.onBackPressedListener = onBackPressedListener;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog setRootPadding(int padding) {
|
||||
this.screenPaddings = new int[]{padding, padding, padding, padding};
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog setRootPadding(int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
|
||||
this.screenPaddings = new int[]{paddingLeft, paddingTop, paddingRight, paddingBottom};
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog setData(String key, Object obj) {
|
||||
if (data == null) data = new HashMap<>();
|
||||
data.put(key, obj);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog onShow(DialogXRunnable<WaitDialog> dialogXRunnable) {
|
||||
onShowRunnable = dialogXRunnable;
|
||||
if (isShow() && onShowRunnable != null) {
|
||||
onShowRunnable.run(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog onDismiss(DialogXRunnable<WaitDialog> dialogXRunnable) {
|
||||
onDismissRunnable = dialogXRunnable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog setEnableImmersiveMode(boolean enableImmersiveMode) {
|
||||
this.enableImmersiveMode = enableImmersiveMode;
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog appendMessage(CharSequence message) {
|
||||
this.message = TextUtils.concat(this.message, message);
|
||||
refreshUI();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog setThisOrderIndex(int orderIndex) {
|
||||
this.thisOrderIndex = orderIndex;
|
||||
if (getDialogView() != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getDialogView().setTranslationZ(orderIndex);
|
||||
} else {
|
||||
error("DialogX: " + dialogKey() + " 执行 .setThisOrderIndex(" + orderIndex + ") 失败:系统不支持此方法,SDK-API 版本必须大于 21(LOLLIPOP)");
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog bringToFront() {
|
||||
setThisOrderIndex(getHighestOrderIndex());
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog setActionRunnable(int actionId, DialogXRunnable<WaitDialog> runnable) {
|
||||
dialogActionRunnableMap.put(actionId, runnable);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog cleanAction(int actionId){
|
||||
dialogActionRunnableMap.remove(actionId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TipDialog cleanAllAction(){
|
||||
dialogActionRunnableMap.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
// for BaseDialog use
|
||||
public void callDialogDismiss(){
|
||||
dismiss();
|
||||
}
|
||||
|
||||
public TipDialog bindDismissWithLifecycleOwner(LifecycleOwner owner){
|
||||
super.bindDismissWithLifecycleOwnerPrivate(owner);
|
||||
return this;
|
||||
}
|
||||
}
|
1347
DialogX/src/main/java/com/kongzue/dialogx/dialogs/WaitDialog.java
Normal file
1347
DialogX/src/main/java/com/kongzue/dialogx/dialogs/WaitDialog.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,229 @@
|
||||
package com.kongzue.dialogx.impl;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.ArrayMap;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.kongzue.dialogx.DialogX;
|
||||
import com.kongzue.dialogx.interfaces.BaseDialog;
|
||||
import com.kongzue.dialogx.util.DialogXFloatingWindowActivity;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.kongzue.dialogx.DialogX.error;
|
||||
|
||||
/**
|
||||
* @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;
|
||||
private static ActivityLifecycleImpl activityLifecycle;
|
||||
private static Application application;
|
||||
|
||||
public ActivityLifecycleImpl(ActivityLifecycleImpl.onActivityResumeCallBack onActivityResumeCallBack) {
|
||||
this.onActivityResumeCallBack = onActivityResumeCallBack;
|
||||
}
|
||||
|
||||
public static void init(Context context, ActivityLifecycleImpl.onActivityResumeCallBack onActivityResumeCallBack) {
|
||||
if (context != null) {
|
||||
Application application = getApplicationContext(context);
|
||||
if (application == null) {
|
||||
error("DialogX 未初始化(E1)。\n请检查是否在启动对话框前进行初始化操作,使用以下代码进行初始化:\nDialogX.init(context);\n\n另外建议您前往查看 DialogX 的文档进行使用:https://github.com/kongzue/DialogX");
|
||||
return;
|
||||
}
|
||||
|
||||
ActivityLifecycleImpl.application = application;
|
||||
if (activityLifecycle != null) {
|
||||
application.unregisterActivityLifecycleCallbacks(activityLifecycle);
|
||||
}
|
||||
application.registerActivityLifecycleCallbacks(activityLifecycle = new ActivityLifecycleImpl(onActivityResumeCallBack));
|
||||
} else {
|
||||
if (ActivityLifecycleImpl.application != null) {
|
||||
init(ActivityLifecycleImpl.application, onActivityResumeCallBack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Application getApplicationContext(Context context) {
|
||||
if (context != null) {
|
||||
return (Application) context.getApplicationContext();
|
||||
}
|
||||
try {
|
||||
Application application = (Application) Class.forName("android.app.ActivityThread").getMethod("currentApplication").invoke(null, (Object[]) null);
|
||||
return application;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
|
||||
Object activityThread = activityThreadClass.getDeclaredMethod("currentActivityThread").invoke(null);
|
||||
Method getApplicationMethod = activityThreadClass.getDeclaredMethod("getApplication");
|
||||
Application application = (Application) getApplicationMethod.invoke(activityThread);
|
||||
return application;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
Application application = (Application) Class.forName("android.app.AppGlobals").getMethod("getInitialApplication").invoke(null, (Object[]) null);
|
||||
return application;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
error("DialogX.init: 初始化异常,请确保init方法内传入的Context是有效的。");
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Application getApplicationContext() {
|
||||
if (application != null) {
|
||||
return application;
|
||||
}
|
||||
try {
|
||||
Application application = (Application) Class.forName("android.app.ActivityThread").getMethod("currentApplication").invoke(null, (Object[]) null);
|
||||
return application;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
|
||||
Object activityThread = activityThreadClass.getDeclaredMethod("currentActivityThread").invoke(null);
|
||||
Method getApplicationMethod = activityThreadClass.getDeclaredMethod("getApplication");
|
||||
Application application = (Application) getApplicationMethod.invoke(activityThread);
|
||||
return application;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
Application application = (Application) Class.forName("android.app.AppGlobals").getMethod("getInitialApplication").invoke(null, (Object[]) null);
|
||||
return application;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Activity getTopActivity() {
|
||||
try {
|
||||
Class activityThreadClass = Class.forName("android.app.ActivityThread");
|
||||
Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null);
|
||||
Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
|
||||
activitiesField.setAccessible(true);
|
||||
Map<Object, Object> activities;
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
activities = (HashMap<Object, Object>) activitiesField.get(activityThread);
|
||||
} else {
|
||||
activities = (ArrayMap<Object, Object>) activitiesField.get(activityThread);
|
||||
}
|
||||
if (activities.size() < 1) {
|
||||
return null;
|
||||
}
|
||||
for (Object activityRecord : activities.values()) {
|
||||
Class activityRecordClass = activityRecord.getClass();
|
||||
Field pausedField = activityRecordClass.getDeclaredField("paused");
|
||||
pausedField.setAccessible(true);
|
||||
if (!pausedField.getBoolean(activityRecord)) {
|
||||
Field activityField = activityRecordClass.getDeclaredField("activity");
|
||||
activityField.setAccessible(true);
|
||||
Activity activity = (Activity) activityField.get(activityRecord);
|
||||
return activity;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
|
||||
if (onActivityResumeCallBack != null) {
|
||||
if (activity instanceof DialogXFloatingWindowActivity) {
|
||||
return;
|
||||
}
|
||||
onActivityResumeCallBack.getActivity(activity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void onActivityStarted(@NonNull Activity activity) {
|
||||
if (application == null) {
|
||||
BaseDialog.init(activity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void onActivityPreResumed(@NonNull Activity activity) {
|
||||
// Application.ActivityLifecycleCallbacks.super.onActivityPreResumed(activity); // # Android 4.4 bug,此代码将导致在 Android 4.4 上闪退,错误原因:java.lang.VerifyError
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
callOnResume(activity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void onActivityResumed(@NonNull Activity activity) {
|
||||
if (activity.isDestroyed() || activity.isFinishing() || activity instanceof DialogXFloatingWindowActivity) {
|
||||
return;
|
||||
}
|
||||
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
callOnResume(activity);
|
||||
}
|
||||
BaseDialog.onActivityResume(activity);
|
||||
}
|
||||
|
||||
private void callOnResume(Activity activity) {
|
||||
if (activity.isDestroyed() || activity.isFinishing() || activity instanceof DialogXFloatingWindowActivity) {
|
||||
return;
|
||||
}
|
||||
if (onActivityResumeCallBack != null) {
|
||||
onActivityResumeCallBack.getActivity(activity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void onActivityPaused(@NonNull Activity activity) {
|
||||
}
|
||||
|
||||
|
||||
public void onActivityStopped(@NonNull Activity activity) {
|
||||
}
|
||||
|
||||
|
||||
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
|
||||
|
||||
}
|
||||
|
||||
public void onActivityDestroyed(@NonNull Activity activity) {
|
||||
if (BaseDialog.getTopActivity() == activity) {
|
||||
BaseDialog.cleanContext();
|
||||
}
|
||||
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.Q) {
|
||||
BaseDialog.recycleDialog(activity);
|
||||
}
|
||||
}
|
||||
|
||||
public void onActivityPreDestroyed(@NonNull final Activity activity) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
BaseDialog.recycleDialog(activity);
|
||||
}
|
||||
}
|
||||
|
||||
public interface onActivityResumeCallBack {
|
||||
void getActivity(Activity activity);
|
||||
}
|
||||
|
||||
public static boolean isExemptActivities(Activity activity) {
|
||||
if (activity == null) return true;
|
||||
for (String packageName : DialogX.unsupportedActivitiesPackageNames) {
|
||||
if (activity.getClass().getName().contains(packageName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -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,137 @@
|
||||
package com.kongzue.dialogx.impl;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
|
||||
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||
import static com.kongzue.dialogx.DialogX.error;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.kongzue.dialogx.interfaces.BaseDialog;
|
||||
import com.kongzue.dialogx.interfaces.NoTouchInterface;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2021/7/28 15:45
|
||||
*/
|
||||
public class DialogFragmentImpl extends DialogFragment {
|
||||
|
||||
public DialogFragmentImpl() {
|
||||
}
|
||||
|
||||
private View dialogView;
|
||||
private BaseDialog baseDialog;
|
||||
|
||||
public DialogFragmentImpl(BaseDialog baseDialog, View dialogView) {
|
||||
this.dialogView = dialogView;
|
||||
this.baseDialog = baseDialog;
|
||||
activityWeakReference = new WeakReference<>(baseDialog.getOwnActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return dialogView;
|
||||
}
|
||||
|
||||
WeakReference<Activity> activityWeakReference = null;
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
final Activity activity = activityWeakReference.get();
|
||||
|
||||
if (getDialog() == null) return;
|
||||
Window dialogWindow = getDialog().getWindow();
|
||||
if (dialogWindow == null) return;
|
||||
dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
|
||||
|
||||
dialogWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
||||
|
||||
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
|
||||
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
lp.height = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
lp.dimAmount = 0f;
|
||||
lp.format = PixelFormat.TRANSPARENT;
|
||||
dialogView.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
for (BaseDialog dialog : BaseDialog.getRunningDialogList()) {
|
||||
if (dialog.getOwnActivity() == activity && dialog != baseDialog && dialog.getDialogImplMode() == baseDialog.getDialogImplMode()) {
|
||||
if (!(dialog instanceof NoTouchInterface) && dialog.getDialogView() != null) {
|
||||
Log.e(">>>", "onTouch: dialog=" + dialog + " baseDialog="+baseDialog );
|
||||
dialog.getDialogView().dispatchTouchEvent(event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (baseDialog instanceof NoTouchInterface) {
|
||||
return activity.dispatchTouchEvent(event);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
dialogWindow.setAttributes(lp);
|
||||
dialogWindow.addFlags(FLAG_TRANSLUCENT_STATUS);
|
||||
dialogWindow.getDecorView().setPadding(0, 0, 0, 0);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||
}
|
||||
dialogWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
int visibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
|
||||
if (activity != null) {
|
||||
if ((activity.getWindow().getDecorView().getSystemUiVisibility() & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) == View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) {
|
||||
visibility = visibility | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
|
||||
}
|
||||
}
|
||||
dialogWindow.getDecorView().setSystemUiVisibility(visibility);
|
||||
dialogWindow.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
|
||||
dialogWindow.setStatusBarColor(Color.TRANSPARENT);
|
||||
dialogWindow.setNavigationBarColor(Color.TRANSPARENT);
|
||||
} else {
|
||||
dialogWindow.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(FragmentManager manager, @Nullable String tag) {
|
||||
if (manager == null) {
|
||||
error("DialogX.DialogFragment 模式无法支持非 AppCompatActivity 启动。");
|
||||
return;
|
||||
}
|
||||
//super.show(manager, tag);
|
||||
|
||||
FragmentTransaction ft = manager.beginTransaction();
|
||||
ft.add(this, tag);
|
||||
ft.commitAllowingStateLoss();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss() {
|
||||
dismissAllowingStateLoss();
|
||||
}
|
||||
}
|
1173
DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseDialog.java
Normal file
1173
DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseDialog.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,14 @@
|
||||
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/22 15:07
|
||||
*/
|
||||
public interface BaseOnDialogClickCallback {
|
||||
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public interface BlurViewType {
|
||||
void setOverlayColor(@Nullable Integer color);
|
||||
void setRadiusPx(@Nullable Float r);
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2022/12/11 17:39
|
||||
*/
|
||||
public abstract class BottomDialogSlideEventLifecycleCallback<D extends BaseDialog> extends DialogLifecycleCallback<D> {
|
||||
|
||||
public boolean onSlideClose(D dialog) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onSlideTouchEvent(D dialog, View v, MotionEvent event) {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -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,52 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LifecycleRegistry;
|
||||
|
||||
import com.kongzue.dialogx.DialogX;
|
||||
|
||||
/**
|
||||
* @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> implements LifecycleOwner {
|
||||
|
||||
private final LifecycleRegistry registry = new LifecycleRegistry(this);
|
||||
|
||||
public void onShow(T dialog) {
|
||||
try {
|
||||
//概率性报 no event down from INITIALIZED,目前尚不清楚为何
|
||||
if (registry.getCurrentState() != Lifecycle.State.CREATED) {
|
||||
registry.setCurrentState(Lifecycle.State.CREATED);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
if (DialogX.dialogLifeCycleListener != null && DialogX.dialogLifeCycleListener != this) {
|
||||
DialogX.dialogLifeCycleListener.onShow(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
public void onDismiss(T dialog) {
|
||||
try {
|
||||
if (registry.getCurrentState() != Lifecycle.State.DESTROYED) {
|
||||
//概率性报 no event down from INITIALIZED,目前尚不清楚为何
|
||||
registry.setCurrentState(Lifecycle.State.DESTROYED);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
if (DialogX.dialogLifeCycleListener != null && DialogX.dialogLifeCycleListener != this) {
|
||||
DialogX.dialogLifeCycleListener.onDismiss(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Lifecycle getLifecycle() {
|
||||
return registry;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.kongzue.dialogx.util.ObjectRunnable;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2022/9/5 9:21
|
||||
*/
|
||||
public abstract class DialogXAnimInterface<D> {
|
||||
|
||||
public void doShowAnim(D dialog, ViewGroup dialogBodyView) {
|
||||
}
|
||||
|
||||
public void doExitAnim(D dialog, ViewGroup dialogBodyView) {
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
public interface DialogXBaseBottomDialog {
|
||||
boolean isBottomNonSafetyAreaBySelf();
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
public interface DialogXRunnable<D> {
|
||||
|
||||
void run(D dialog);
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
public interface DialogXSafetyModeInterface {
|
||||
int getDialogXSafetyMode();
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
import android.view.WindowInsets;
|
||||
|
||||
public interface DynamicWindowInsetsAnimationListener {
|
||||
|
||||
void onChange(WindowInsets windowInsets);
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
import android.widget.ImageView;
|
||||
|
||||
public abstract class MenuIconAdapter<D extends BaseDialog> extends OnIconChangeCallBack<D> {
|
||||
|
||||
public MenuIconAdapter() {
|
||||
}
|
||||
|
||||
public MenuIconAdapter(boolean autoTintIconInLightOrDarkMode) {
|
||||
super(autoTintIconInLightOrDarkMode);
|
||||
}
|
||||
|
||||
public abstract boolean applyIcon(D dialog, int index, String menuText, ImageView iconImageView);
|
||||
|
||||
@Override
|
||||
public int getIcon(D dialog, int index, String menuText) {
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2023/2/22 16:47
|
||||
*/
|
||||
public interface MenuItemLayoutRefreshCallback<D> {
|
||||
|
||||
void getView(D dialog, int position, View convertView, ViewGroup parent);
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
import com.kongzue.dialogx.util.TextInfo;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2022/1/22 21:32
|
||||
*/
|
||||
public abstract class MenuItemTextInfoInterceptor<D extends BaseDialog> {
|
||||
|
||||
private boolean autoTintIconInLightOrDarkMode;
|
||||
|
||||
public MenuItemTextInfoInterceptor() {
|
||||
}
|
||||
|
||||
public MenuItemTextInfoInterceptor(boolean autoTintIconInLightOrDarkMode) {
|
||||
this.autoTintIconInLightOrDarkMode = autoTintIconInLightOrDarkMode;
|
||||
}
|
||||
|
||||
public abstract TextInfo menuItemTextInfo(D dialog, int index, String menuText);
|
||||
|
||||
public boolean isAutoTintIconInLightOrDarkMode() {
|
||||
return autoTintIconInLightOrDarkMode;
|
||||
}
|
||||
}
|
@ -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: 2022/7/19 17:37
|
||||
*/
|
||||
public interface NoTouchInterface {
|
||||
}
|
@ -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<D extends BaseDialog> {
|
||||
boolean onBackPressed(D dialog);
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
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: 2022/7/8 16:27
|
||||
*/
|
||||
public interface OnBackgroundMaskClickListener<D extends BaseDialog> {
|
||||
boolean onClick(D dialog, View v);
|
||||
}
|
@ -0,0 +1,225 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.kongzue.dialogx.DialogX;
|
||||
import com.kongzue.dialogx.util.views.ExtendChildLayoutParamsFrameLayout;
|
||||
|
||||
import static com.kongzue.dialogx.DialogX.ERROR_INIT_TIPS;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* @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;
|
||||
private final int PARENT_FLAG = -109;
|
||||
|
||||
public OnBindView(int layoutResId) {
|
||||
if (BaseDialog.getTopActivity() == null) {
|
||||
DialogX.error(ERROR_INIT_TIPS);
|
||||
return;
|
||||
}
|
||||
this.layoutResId = layoutResId;
|
||||
customView = LayoutInflater.from(BaseDialog.getTopActivity()).inflate(layoutResId, new RelativeLayout(BaseDialog.getTopActivity()), false);
|
||||
}
|
||||
|
||||
public OnBindView(int layoutResId, boolean async) {
|
||||
if (BaseDialog.getTopActivity() == null) {
|
||||
DialogX.error(ERROR_INIT_TIPS);
|
||||
return;
|
||||
}
|
||||
this.layoutResId = layoutResId;
|
||||
if (async) {
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
synchronized (OnBindView.this) {
|
||||
customView = LayoutInflater.from(BaseDialog.getTopActivity()).inflate(layoutResId, new RelativeLayout(BaseDialog.getTopActivity()), false);
|
||||
if (waitBindRunnable != null) {
|
||||
waitBindRunnable.run();
|
||||
waitBindRunnable = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
} else {
|
||||
customView = LayoutInflater.from(BaseDialog.getTopActivity()).inflate(layoutResId, new RelativeLayout(BaseDialog.getTopActivity()), false);
|
||||
}
|
||||
}
|
||||
|
||||
public OnBindView(View customView) {
|
||||
this.customView = customView;
|
||||
}
|
||||
|
||||
private androidx.fragment.app.Fragment fragment;
|
||||
private android.app.Fragment supportFragment;
|
||||
private int fragmentParentId = View.NO_ID;
|
||||
|
||||
private int getFragmentParentId() {
|
||||
if (fragmentParentId == View.NO_ID) {
|
||||
fragmentParentId = View.generateViewId();
|
||||
}
|
||||
return fragmentParentId;
|
||||
}
|
||||
|
||||
public OnBindView(androidx.fragment.app.Fragment fragment) {
|
||||
if (BaseDialog.getTopActivity() == null) return;
|
||||
this.customView = new ExtendChildLayoutParamsFrameLayout(BaseDialog.getTopActivity());
|
||||
this.customView.setId(getFragmentParentId());
|
||||
this.fragment = fragment;
|
||||
this.supportFragment = null;
|
||||
}
|
||||
|
||||
public OnBindView(android.app.Fragment supportFragment) {
|
||||
if (BaseDialog.getTopActivity() == null) return;
|
||||
this.customView = new ExtendChildLayoutParamsFrameLayout(BaseDialog.getTopActivity());
|
||||
this.customView.setId(getFragmentParentId());
|
||||
this.supportFragment = supportFragment;
|
||||
this.fragment = null;
|
||||
}
|
||||
|
||||
public abstract void onBind(D dialog, View v);
|
||||
|
||||
public void setEvent(D dialog, View v){}
|
||||
|
||||
public void onFragmentBind(D dialog, View frameLayout, androidx.fragment.app.Fragment fragment, androidx.fragment.app.FragmentManager fragmentManager) {
|
||||
}
|
||||
|
||||
public void onFragmentBind(D dialog, View frameLayout, android.app.Fragment fragment, android.app.FragmentManager fragmentManager) {
|
||||
}
|
||||
|
||||
public int getLayoutResId() {
|
||||
return layoutResId;
|
||||
}
|
||||
|
||||
public OnBindView<D> setLayoutResId(int layoutResId) {
|
||||
this.layoutResId = layoutResId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public View getCustomView() {
|
||||
if (customView == null) {
|
||||
customView = LayoutInflater.from(BaseDialog.getTopActivity()).inflate(layoutResId, new RelativeLayout(BaseDialog.getTopActivity()), false);
|
||||
}
|
||||
return customView;
|
||||
}
|
||||
|
||||
public OnBindView<D> setCustomView(View customView) {
|
||||
this.customView = customView;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void clean() {
|
||||
layoutResId = 0;
|
||||
customView = null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void bindParent(ViewGroup parentView) {
|
||||
if (getCustomView() == null) {
|
||||
waitBind(parentView, null);
|
||||
return;
|
||||
}
|
||||
if (getCustomView().getParent() != null) {
|
||||
if (getCustomView().getParent() == parentView) {
|
||||
return;
|
||||
}
|
||||
((ViewGroup) getCustomView().getParent()).removeView(getCustomView());
|
||||
}
|
||||
ViewGroup.LayoutParams lp = parentView.getLayoutParams();
|
||||
if (lp == null) {
|
||||
lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
parentView.addView(getCustomView(), lp);
|
||||
}
|
||||
|
||||
public void bindParent(ViewGroup parentView, BaseDialog dialog) {
|
||||
if (getCustomView() == null) {
|
||||
waitBind(parentView, null);
|
||||
return;
|
||||
}
|
||||
if (getCustomView().getParent() == parentView || parentView.getTag(PARENT_FLAG) == getCustomView().toString()) {
|
||||
return;
|
||||
}
|
||||
if (getCustomView().getParent() != null) {
|
||||
((ViewGroup) getCustomView().getParent()).removeView(getCustomView());
|
||||
}
|
||||
ViewGroup.LayoutParams lp = getCustomView().getLayoutParams();
|
||||
if (lp == null) {
|
||||
lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
parentView.addView(getCustomView(), lp);
|
||||
onBind((D) dialog, getCustomView());
|
||||
callSetEvent((D) dialog, getCustomView());
|
||||
if (fragment != null || supportFragment != null) {
|
||||
if (dialog.getDialogImplMode() != DialogX.IMPL_MODE.VIEW) {
|
||||
BaseDialog.error(dialog.dialogKey() + "非 VIEW 实现模式不支持 fragment 作为子布局显示。\n" +
|
||||
"其原因为 Window 中不存在 FragmentManager,无法对子布局中的 fragment 进行管理。");
|
||||
return;
|
||||
}
|
||||
getCustomView().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (fragment != null && getCustomView() instanceof FrameLayout && dialog.getOwnActivity() instanceof AppCompatActivity) {
|
||||
AppCompatActivity appCompatActivity = (AppCompatActivity) dialog.getOwnActivity();
|
||||
androidx.fragment.app.FragmentTransaction transaction = appCompatActivity.getSupportFragmentManager().beginTransaction();
|
||||
transaction.add(getFragmentParentId(), fragment);
|
||||
transaction.commit();
|
||||
onFragmentBind((D) dialog, getCustomView(), fragment, appCompatActivity.getSupportFragmentManager());
|
||||
}
|
||||
if (supportFragment != null && getCustomView() instanceof FrameLayout && dialog.getOwnActivity() instanceof Activity) {
|
||||
Activity activity = dialog.getOwnActivity();
|
||||
android.app.FragmentTransaction transaction = activity.getFragmentManager().beginTransaction();
|
||||
transaction.add(getFragmentParentId(), supportFragment);
|
||||
transaction.commit();
|
||||
onFragmentBind((D) dialog, getCustomView(), supportFragment, activity.getFragmentManager());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private int dialogHash, parentViewHash;
|
||||
|
||||
private void callSetEvent(D dialog, View view) {
|
||||
if (dialog.hashCode() != dialogHash || view.hashCode() != parentViewHash) {
|
||||
dialogHash = dialog.hashCode();
|
||||
parentViewHash = view.hashCode();
|
||||
setEvent(dialog, getCustomView());
|
||||
}
|
||||
}
|
||||
|
||||
private Runnable waitBindRunnable;
|
||||
|
||||
private void waitBind(ViewGroup parentView, BaseDialog dialog) {
|
||||
waitBindRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (getCustomView() == null) {
|
||||
if (dialog == null) {
|
||||
bindParent(parentView);
|
||||
} else {
|
||||
bindParent(parentView, dialog);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
import static com.kongzue.dialogx.interfaces.BaseDialog.error;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewbinding.ViewBinding;
|
||||
|
||||
import com.kongzue.dialogx.R;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public abstract class OnBindingView<D, VB extends ViewBinding> extends OnBindView<D> {
|
||||
|
||||
protected VB binding;
|
||||
|
||||
public OnBindingView(VB binding) {
|
||||
super(binding.getRoot());
|
||||
this.binding = binding;
|
||||
}
|
||||
|
||||
public OnBindingView() {
|
||||
super((View) null);
|
||||
setCustomView(getBindingRootView(getViewBinding()));
|
||||
this.binding = (VB) getCustomView().getTag(R.id.dialogx_view_binding_tag_key);
|
||||
}
|
||||
|
||||
public OnBindingView(Class viewBindingClass) {
|
||||
super(getBindingRootView(getViewBinding(viewBindingClass)));
|
||||
this.binding = (VB) getCustomView().getTag(R.id.dialogx_view_binding_tag_key);
|
||||
}
|
||||
|
||||
public OnBindingView(String viewBindingClassName) {
|
||||
super(getBindingRootView(getViewBinding(viewBindingClassName)));
|
||||
this.binding = (VB) getCustomView().getTag(R.id.dialogx_view_binding_tag_key);
|
||||
}
|
||||
|
||||
private static View getBindingRootView(ViewBinding viewBinding) {
|
||||
if (viewBinding == null) {
|
||||
return new View(BaseDialog.getContext());
|
||||
}
|
||||
View view = viewBinding.getRoot();
|
||||
view.setTag(R.id.dialogx_view_binding_tag_key, viewBinding);
|
||||
return view;
|
||||
}
|
||||
|
||||
private ViewBinding getViewBinding() {
|
||||
Type superclass = getClass().getGenericSuperclass();
|
||||
if (superclass instanceof ParameterizedType) {
|
||||
Class<VB> clazz = (Class<VB>) ((ParameterizedType) superclass).getActualTypeArguments()[1];
|
||||
return getViewBinding(clazz);
|
||||
} else {
|
||||
error("DialogX: OnBindingView初始化异常,若要使用无参构建,必须指定ViewBinding泛型");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static ViewBinding getViewBinding(String bindingClassName) {
|
||||
try {
|
||||
return getViewBinding(Class.forName(bindingClassName));
|
||||
} catch (ClassNotFoundException e) {
|
||||
error("DialogX: OnBindingView初始化异常,未能根据bindingClassName:" + bindingClassName + "找到对应的ViewBinding,请尝试指定ViewBinding实例");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static ViewBinding getViewBinding(Class bindingClass) {
|
||||
try {
|
||||
Method inflateMethod = bindingClass.getMethod("inflate", LayoutInflater.class);
|
||||
return (ViewBinding) inflateMethod.invoke((Object) null, LayoutInflater.from(BaseDialog.getContext()));
|
||||
} catch (Exception var5) {
|
||||
error("DialogX: OnBindingView初始化异常,未能根据bindingClass找到对应的ViewBinding,请尝试指定ViewBinding实例");
|
||||
var5.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public OnBindingView(int layoutResId) {
|
||||
super(layoutResId);
|
||||
}
|
||||
|
||||
public OnBindingView(int layoutResId, boolean async) {
|
||||
super(layoutResId, async);
|
||||
}
|
||||
|
||||
public OnBindingView(View customView) {
|
||||
super(customView);
|
||||
}
|
||||
|
||||
public OnBindingView(Fragment fragment) {
|
||||
super(fragment);
|
||||
}
|
||||
|
||||
public OnBindingView(android.app.Fragment supportFragment) {
|
||||
super(supportFragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(D dialog, View v) {
|
||||
onBind(dialog, v, binding);
|
||||
}
|
||||
|
||||
public abstract void onBind(D dialog, View v, VB binding);
|
||||
}
|
@ -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 dialog, View v);
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
/**
|
||||
* @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<D extends BaseDialog> {
|
||||
|
||||
public OnIconChangeCallBack() {
|
||||
}
|
||||
|
||||
private Boolean autoTintIconInLightOrDarkMode;
|
||||
|
||||
public OnIconChangeCallBack(boolean autoTintIconInLightOrDarkMode) {
|
||||
this.autoTintIconInLightOrDarkMode = autoTintIconInLightOrDarkMode;
|
||||
}
|
||||
|
||||
public abstract int getIcon(D dialog, 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 dialog, View v, String inputStr);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
public interface OnMenuButtonClickListener<D extends BaseDialog> extends BaseOnDialogClickCallback{
|
||||
|
||||
boolean onClick(D dialog, View v);
|
||||
}
|
@ -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 index);
|
||||
}
|
@ -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 index, boolean select) {
|
||||
|
||||
}
|
||||
|
||||
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,41 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.view.View;
|
||||
|
||||
public abstract class PopMoveDisplacementInterceptor<D extends BaseDialog> {
|
||||
|
||||
/**
|
||||
* 重置提示对话框新增时,旧的对话框让位位移的动画具体参数
|
||||
*
|
||||
* @param index 对话框索引
|
||||
* @param dialog 对话框
|
||||
* @param fromY 从哪来
|
||||
* @param toY 往哪去
|
||||
* @param dialogHeight 对话框本身的高度
|
||||
* @param allTipSize 提示框总数
|
||||
* @param moveBack 是否向后位移
|
||||
* @return 你要改为往哪去
|
||||
*/
|
||||
public float resetAnimY(int index, D dialog, float fromY, float toY, int dialogHeight, int allTipSize, boolean moveBack) {
|
||||
return toY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 动画更新器
|
||||
*
|
||||
* @param index 对话框索引
|
||||
* @param dialog 对话框
|
||||
* @param dialogBody 对话框内容布局
|
||||
* @param fromY 从哪来
|
||||
* @param toY 往哪去
|
||||
* @param progress 动画进度(0f~1f)
|
||||
* @param animation 动画执行器
|
||||
* @param allTipSize 提示框总数
|
||||
* @param moveBack 是否向后位移
|
||||
* @return 返回true表示拦截处理,否则依然会执行原本的动画
|
||||
*/
|
||||
public boolean animUpdater(int index, D dialog, View dialogBody, float fromY, float toY, float progress, ValueAnimator animation, int allTipSize, boolean moveBack) {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
public enum SELECT_MODE {
|
||||
NONE, SINGLE, MULTIPLE
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.kongzue.dialogx.interfaces;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2021/8/5 8:39
|
||||
*/
|
||||
public interface ScrollController {
|
||||
|
||||
/**
|
||||
* 返回已滚动的距离
|
||||
* 若该距离为 0,BottomDialog、FullScreenDialog 将直接接管和衔接触控事件
|
||||
* 若距离不为 0,由本控件处理触控事件
|
||||
*
|
||||
* @return 已滚动的距离
|
||||
*/
|
||||
int getScrollDistance();
|
||||
|
||||
/**
|
||||
* 设置是否可以滑动
|
||||
* 若可以滑动,BottomDialog、FullScreenDialog 将尝试接管和衔接触控事件,
|
||||
* 若不可以滑动,BottomDialog、FullScreenDialog 将直接拦截触控事件
|
||||
*
|
||||
* @return 是否可以滑动
|
||||
*/
|
||||
boolean isCanScroll();
|
||||
|
||||
/**
|
||||
* BottomDialog、FullScreenDialog 在接管触控事件时会通过此方法传入 lockScroll,
|
||||
* 若 lockScroll 为真,请勿处理任何触摸事件。
|
||||
*
|
||||
* 举例:建议增加以下代码:
|
||||
* @Override
|
||||
* public boolean onTouchEvent(MotionEvent event) {
|
||||
* if (lockScroll) return false;
|
||||
* return super.onTouchEvent(event);
|
||||
* }
|
||||
*
|
||||
* @param lockScroll 是否锁定滑动
|
||||
*/
|
||||
void lockScroll(boolean lockScroll);
|
||||
|
||||
boolean isLockScroll();
|
||||
}
|
@ -0,0 +1,336 @@
|
||||
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 extends 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 DefaultHorizontalButtonRes();
|
||||
}
|
||||
|
||||
public class DefaultHorizontalButtonRes extends 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 DefaultVerticalButtonRes();
|
||||
}
|
||||
|
||||
public class DefaultVerticalButtonRes extends 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 DefaultWaitTipRes();
|
||||
}
|
||||
|
||||
public class DefaultWaitTipRes extends 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 DefaultBottomDialogRes();
|
||||
}
|
||||
|
||||
public class DefaultBottomDialogRes extends 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 DefaultPopTipSettings();
|
||||
}
|
||||
|
||||
public class DefaultPopTipSettings extends 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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tintIcon() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopNotificationSettings popNotificationSettings() {
|
||||
return new DefaultPopNotificationSettings();
|
||||
}
|
||||
|
||||
public class DefaultPopNotificationSettings extends PopNotificationSettings{
|
||||
@Override
|
||||
public int layout(boolean light) {
|
||||
return light ? R.layout.layout_dialogx_popnotification_material : R.layout.layout_dialogx_popnotification_material_dark;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopNotificationSettings.ALIGN align() {
|
||||
return ALIGN.TOP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int enterAnimResId(boolean light) {
|
||||
return R.anim.anim_dialogx_notification_enter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int exitAnimResId(boolean light) {
|
||||
return R.anim.anim_dialogx_notification_exit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tintIcon() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopMenuSettings popMenuSettings() {
|
||||
return new DefaultPopMenuSettings();
|
||||
}
|
||||
|
||||
public class DefaultPopMenuSettings extends PopMenuSettings{
|
||||
@Override
|
||||
public int layout(boolean light) {
|
||||
return light ? R.layout.layout_dialogx_popmenu_material : R.layout.layout_dialogx_popmenu_material_dark;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlurBackgroundSetting blurBackgroundSettings() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int backgroundMaskColorRes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int overrideMenuDividerDrawableRes(boolean b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int overrideMenuDividerHeight(boolean b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int overrideMenuTextColor(boolean light) {
|
||||
return light ? R.color.black90 : R.color.white90;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int overrideMenuItemLayoutRes(boolean b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int overrideMenuItemBackgroundRes(boolean b, int i, int i1, boolean b1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int overrideSelectionMenuBackgroundColor(boolean b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean selectionImageTint(boolean b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int paddingVertical() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tintButtonBackground() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2021/12/20 15:21
|
||||
*/
|
||||
public interface ActivityRunnable {
|
||||
void run(Activity activity);
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.RectF;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.kongzue.dialogx.DialogX;
|
||||
import com.kongzue.dialogx.dialogs.BottomDialog;
|
||||
import com.kongzue.dialogx.interfaces.BottomDialogSlideEventLifecycleCallback;
|
||||
import com.kongzue.dialogx.interfaces.ScrollController;
|
||||
|
||||
/**
|
||||
* @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;
|
||||
private boolean onlyRestrictingSlideTouchEventsToScrollLayoutAreas = false;
|
||||
/**
|
||||
* 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);
|
||||
* }
|
||||
*/
|
||||
View interceptTouchView = impl.bkg;
|
||||
if (me.isAllowInterceptTouch()) {
|
||||
if (isOnlyRestrictingSlideTouchEventsToScrollLayoutAreas()){
|
||||
impl.bkg.setOnTouchListener(null);
|
||||
interceptTouchView = (View) impl.scrollView;
|
||||
}
|
||||
View finalInterceptTouchView = interceptTouchView;
|
||||
interceptTouchView.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (me.getDialogLifecycleCallback() instanceof BottomDialogSlideEventLifecycleCallback) {
|
||||
if (((BottomDialogSlideEventLifecycleCallback) me.getDialogLifecycleCallback()).onSlideTouchEvent(me, v, event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//这里 return 什么实际上无关紧要,重点在于 MaxRelativeLayout.java(dispatchTouchEvent:184) 的事件分发会独立触发此处的额外滑动事件
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
bkgTouchDownY = event.getY();
|
||||
isBkgTouched = true;
|
||||
bkgOldY = impl.boxBkg.getY();
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (isBkgTouched && me.isAllowInterceptTouch()) {
|
||||
float aimY = impl.boxBkg.getY() + event.getY() - bkgTouchDownY;
|
||||
if (impl.scrollView.isCanScroll() && touchInScrollView(finalInterceptTouchView, impl.scrollView, event)) {
|
||||
if (aimY > impl.boxRoot.getUnsafePlace().top) {
|
||||
if (impl.scrollView.getScrollDistance() == 0) {
|
||||
impl.scrollView.lockScroll(true);
|
||||
impl.boxBkg.setY(aimY);
|
||||
} else {
|
||||
bkgTouchDownY = event.getY();
|
||||
}
|
||||
} else {
|
||||
impl.scrollView.lockScroll(false);
|
||||
impl.boxBkg.setY(impl.boxRoot.getUnsafePlace().top);
|
||||
}
|
||||
} else {
|
||||
if (aimY > impl.boxRoot.getUnsafePlace().top) {
|
||||
impl.boxBkg.setY(aimY);
|
||||
return true;
|
||||
} else {
|
||||
impl.boxBkg.setY(impl.boxRoot.getUnsafePlace().top);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
scrolledY = impl.scrollView.getScrollDistance();
|
||||
isBkgTouched = false;
|
||||
if (bkgOldY == impl.boxRoot.getUnsafePlace().top) {
|
||||
if (impl.boxBkg.getY() > impl.boxRoot.getUnsafePlace().top + impl.bkgEnterAimY + DialogX.touchSlideTriggerThreshold) {
|
||||
impl.preDismiss();
|
||||
} else if (impl.boxBkg.getY() != bkgOldY) {
|
||||
ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.boxBkg, "y", impl.boxBkg.getY(),
|
||||
impl.bkgEnterAimY);
|
||||
enterAnim.setDuration(300);
|
||||
enterAnim.start();
|
||||
}
|
||||
} else {
|
||||
if (impl.boxBkg.getY() > bkgOldY + DialogX.touchSlideTriggerThreshold) {
|
||||
impl.preDismiss();
|
||||
} else if (impl.boxBkg.getY() != bkgOldY) {
|
||||
ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.boxBkg, "y", impl.boxBkg.getY(), impl.boxRoot.getUnsafePlace().top);
|
||||
enterAnim.setDuration(300);
|
||||
enterAnim.start();
|
||||
}
|
||||
}
|
||||
if (impl.scrollView instanceof ScrollController) {
|
||||
impl.scrollView.lockScroll(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (impl.scrollView instanceof ScrollController) {
|
||||
((ScrollController) impl.scrollView).lockScroll(false);
|
||||
}
|
||||
interceptTouchView.setOnTouchListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 MotionEvent 触摸点是否在 scrollView 相对于对话框移动布局 slideView 范围内
|
||||
*
|
||||
* @param slideView 对话框移动布局
|
||||
* @param scrollView 内部滚动布局
|
||||
* @param event 触摸事件
|
||||
* @return 是否在范围内
|
||||
*/
|
||||
private boolean touchInScrollView(View slideView, ScrollController scrollView, MotionEvent event) {
|
||||
View scrollViewImpl = (View) scrollView;
|
||||
RectF scrollViewLocation = new RectF();
|
||||
int[] scrollViewScreenLoc = new int[2];
|
||||
int[] rootViewScreenLoc = new int[2];
|
||||
scrollViewImpl.getLocationInWindow(scrollViewScreenLoc);
|
||||
slideView.getLocationInWindow(rootViewScreenLoc);
|
||||
|
||||
scrollViewLocation.left = scrollViewScreenLoc[0] - rootViewScreenLoc[0];
|
||||
scrollViewLocation.top = scrollViewScreenLoc[1] - rootViewScreenLoc[1];
|
||||
scrollViewLocation.right = scrollViewLocation.left + scrollViewImpl.getWidth();
|
||||
scrollViewLocation.bottom = scrollViewLocation.top + scrollViewImpl.getHeight();
|
||||
|
||||
return event.getX() >= scrollViewLocation.left && event.getX() <= scrollViewLocation.right &&
|
||||
event.getY() >= scrollViewLocation.top && event.getY() <= scrollViewLocation.bottom;
|
||||
}
|
||||
|
||||
private int dip2px(float dpValue) {
|
||||
final float scale = Resources.getSystem().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
public boolean isOnlyRestrictingSlideTouchEventsToScrollLayoutAreas() {
|
||||
return onlyRestrictingSlideTouchEventsToScrollLayoutAreas;
|
||||
}
|
||||
|
||||
public BottomDialogTouchEventInterceptor setOnlyRestrictingSlideTouchEventsToScrollLayoutAreas(boolean onlyRestrictingSlideTouchEventsToScrollLayoutAreas) {
|
||||
this.onlyRestrictingSlideTouchEventsToScrollLayoutAreas = onlyRestrictingSlideTouchEventsToScrollLayoutAreas;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,278 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import static com.kongzue.dialogx.interfaces.BaseDialog.isNull;
|
||||
import static com.kongzue.dialogx.interfaces.BaseDialog.useTextInfo;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Space;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.kongzue.dialogx.R;
|
||||
import com.kongzue.dialogx.dialogs.BottomMenu;
|
||||
import com.kongzue.dialogx.interfaces.MenuIconAdapter;
|
||||
import com.kongzue.dialogx.interfaces.SELECT_MODE;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: <a href="https://github.com/kongzue/">空祖Github</a>
|
||||
* @homepage: <a href="http://kongzue.com/">主页</a>
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2020/10/7 0:00
|
||||
*/
|
||||
public class BottomMenuArrayAdapter extends BaseAdapter {
|
||||
|
||||
private BottomMenu bottomMenu;
|
||||
public List<CharSequence> objects;
|
||||
public Context context;
|
||||
|
||||
public BottomMenuArrayAdapter(BottomMenu bottomMenu, Context context, List<CharSequence> objects) {
|
||||
this.objects = objects;
|
||||
this.context = context;
|
||||
this.bottomMenu = bottomMenu;
|
||||
}
|
||||
|
||||
class ViewHolder {
|
||||
ImageView imgDialogxMenuIcon;
|
||||
ImageView imgDialogxMenuSelection;
|
||||
TextView txtDialogxMenuText;
|
||||
Space spaceDialogxRightPadding;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
TextInfo defaultMenuTextInfo;
|
||||
|
||||
@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 (!isNull(bottomMenu.getTitle()) || !isNull(bottomMenu.getMessage()) || 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.imgDialogxMenuSelection = convertView.findViewById(R.id.img_dialogx_menu_selection);
|
||||
viewHolder.txtDialogxMenuText = convertView.findViewById(R.id.txt_dialogx_menu_text);
|
||||
viewHolder.spaceDialogxRightPadding = convertView.findViewById(R.id.space_dialogx_right_padding);
|
||||
|
||||
convertView.setTag(viewHolder);
|
||||
} else {
|
||||
viewHolder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
if (!bottomMenu.isMenuItemEnable(position)) {
|
||||
convertView.setAlpha(0.4f);
|
||||
} else {
|
||||
convertView.setAlpha(1f);
|
||||
}
|
||||
if (bottomMenu.getSelectMode() == 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() == 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) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
convertView.setBackgroundTintList(ColorStateList.valueOf(context.getResources().getColor(overrideSelectionBackgroundColorRes)));
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (defaultMenuTextInfo == null) {
|
||||
defaultMenuTextInfo = new TextInfo().setShowEllipsis(viewHolder.txtDialogxMenuText.getEllipsize() == TextUtils.TruncateAt.END).setFontColor(viewHolder.txtDialogxMenuText.getTextColors().getDefaultColor()).setBold(viewHolder.txtDialogxMenuText.getPaint().isFakeBoldText()).setFontSize(px2dip(viewHolder.txtDialogxMenuText.getTextSize())).setGravity(viewHolder.txtDialogxMenuText.getGravity()).setMaxLines(viewHolder.txtDialogxMenuText.getMaxLines());
|
||||
}
|
||||
viewHolder.txtDialogxMenuText.setText(text);
|
||||
viewHolder.txtDialogxMenuText.setTextColor(context.getResources().getColor(textColor));
|
||||
if (bottomMenu.getMenuItemTextInfoInterceptor() != null) {
|
||||
TextInfo textInfo = bottomMenu.getMenuItemTextInfoInterceptor().menuItemTextInfo(bottomMenu, position, text.toString());
|
||||
if (textInfo != null) {
|
||||
useTextInfo(viewHolder.txtDialogxMenuText, textInfo);
|
||||
} else {
|
||||
if (bottomMenu.getMenuTextInfo() != null) {
|
||||
useTextInfo(viewHolder.txtDialogxMenuText, bottomMenu.getMenuTextInfo());
|
||||
} else {
|
||||
useTextInfo(viewHolder.txtDialogxMenuText, defaultMenuTextInfo);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (bottomMenu.getMenuTextInfo() != null) {
|
||||
useTextInfo(viewHolder.txtDialogxMenuText, bottomMenu.getMenuTextInfo());
|
||||
}
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
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) {
|
||||
if (bottomMenu.getOnIconChangeCallBack() instanceof MenuIconAdapter) {
|
||||
boolean result = ((MenuIconAdapter) bottomMenu.getOnIconChangeCallBack()).applyIcon(bottomMenu, position, text.toString(), viewHolder.imgDialogxMenuIcon);
|
||||
boolean autoTintIconInLightOrDarkMode = bottomMenu.getOnIconChangeCallBack().isAutoTintIconInLightOrDarkMode() == null ? bottomMenu.isAutoTintIconInLightOrDarkMode() : bottomMenu.getOnIconChangeCallBack().isAutoTintIconInLightOrDarkMode();
|
||||
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(result ? View.VISIBLE : View.GONE);
|
||||
if (result) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (autoTintIconInLightOrDarkMode) {
|
||||
viewHolder.imgDialogxMenuIcon.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(textColor)));
|
||||
}
|
||||
}
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int resId = bottomMenu.getOnIconChangeCallBack().getIcon(bottomMenu, position, text.toString());
|
||||
boolean autoTintIconInLightOrDarkMode = bottomMenu.getOnIconChangeCallBack().isAutoTintIconInLightOrDarkMode() == null ? bottomMenu.isAutoTintIconInLightOrDarkMode() : bottomMenu.getOnIconChangeCallBack().isAutoTintIconInLightOrDarkMode();
|
||||
|
||||
if (resId != 0) {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.VISIBLE);
|
||||
viewHolder.imgDialogxMenuIcon.setImageResource(resId);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (autoTintIconInLightOrDarkMode) {
|
||||
viewHolder.imgDialogxMenuIcon.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(textColor)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.GONE);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (bottomMenu.getIconResIds() != null) {
|
||||
int resId = bottomMenu.getIconResIds(position);
|
||||
boolean autoTintIconInLightOrDarkMode = bottomMenu.isAutoTintIconInLightOrDarkMode();
|
||||
|
||||
if (resId != 0) {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.VISIBLE);
|
||||
viewHolder.imgDialogxMenuIcon.setImageResource(resId);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (autoTintIconInLightOrDarkMode) {
|
||||
viewHolder.imgDialogxMenuIcon.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(textColor)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.GONE);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.GONE);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bottomMenu.getMenuMenuItemLayoutRefreshCallback() != null) {
|
||||
bottomMenu.getMenuMenuItemLayoutRefreshCallback().getView(bottomMenu, position, convertView, parent);
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
|
||||
private int px2dip(float pxValue) {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (pxValue / scale + 0.5f);
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import com.kongzue.dialogx.interfaces.BaseDialog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2022/8/8 15:08
|
||||
*/
|
||||
public class DialogListBuilder {
|
||||
|
||||
ArrayList<BaseDialog> dialogs;
|
||||
|
||||
public static DialogListBuilder create(BaseDialog... dialogs) {
|
||||
DialogListBuilder builder = new DialogListBuilder();
|
||||
for (BaseDialog d : dialogs) {
|
||||
if (d != null) builder.add(d);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
public DialogListBuilder add(BaseDialog dialog) {
|
||||
if (dialogs == null) {
|
||||
dialogs = new ArrayList<>();
|
||||
}
|
||||
if (dialog == null || dialog.isShow() || dialog.isPreShow()) {
|
||||
return this;
|
||||
}
|
||||
dialog.setDialogListBuilder(this);
|
||||
dialogs.add(dialog);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DialogListBuilder show() {
|
||||
if (dialogs == null || dialogs.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
while (!dialogs.isEmpty() && dialogs.get(0) == null) {
|
||||
dialogs.remove(0);
|
||||
}
|
||||
dialogs.get(0).show();
|
||||
return this;
|
||||
}
|
||||
|
||||
public void showNext() {
|
||||
if (dialogs == null || dialogs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
while (!dialogs.isEmpty() && dialogs.get(0) == null) {
|
||||
dialogs.remove(0);
|
||||
}
|
||||
if (!dialogs.isEmpty() && dialogs.get(0) != null) {
|
||||
dialogs.get(0).show();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
if (dialogs == null) {
|
||||
return true;
|
||||
}
|
||||
while (!dialogs.isEmpty() && dialogs.get(0) == null) {
|
||||
dialogs.remove(0);
|
||||
}
|
||||
return dialogs.isEmpty();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
dialogs.clear();
|
||||
}
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.kongzue.dialogx.R;
|
||||
import com.kongzue.dialogx.interfaces.BaseDialog;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2021/12/20 14:58
|
||||
*/
|
||||
public class DialogXFloatingWindowActivity extends AppCompatActivity {
|
||||
|
||||
static WeakReference<DialogXFloatingWindowActivity> dialogXFloatingWindowActivity;
|
||||
int fromActivityHashCode;
|
||||
List<String> shownDialogXList = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
dialogXFloatingWindowActivity = new WeakReference<>(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.layout_dialogx_empty);
|
||||
|
||||
int fromActivityUiStatus = getIntent().getIntExtra("fromActivityUiStatus", 0);
|
||||
if (fromActivityUiStatus == 0) {
|
||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||
} else {
|
||||
getWindow().getDecorView().setSystemUiVisibility(fromActivityUiStatus | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||
}
|
||||
|
||||
setFromActivityHashCode(getIntent().getIntExtra("from", 0));
|
||||
String dialogXKey;
|
||||
ActivityRunnable activityRunnable = BaseDialog.getActivityRunnable(dialogXKey = getIntent().getStringExtra("dialogXKey"));
|
||||
if (activityRunnable == null) {
|
||||
finish();
|
||||
} else {
|
||||
shownDialogXList.add(dialogXKey);
|
||||
activityRunnable.run(this);
|
||||
}
|
||||
|
||||
getWindow().getDecorView().setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (event.getAction() != MotionEvent.ACTION_CANCEL && getFromActivity() != null) {
|
||||
if (getFromActivity() != null && !(getFromActivity() instanceof DialogXFloatingWindowActivity)) {
|
||||
return getFromActivity().dispatchTouchEvent(event);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isSameFrom(int fromActivityHashCode) {
|
||||
return fromActivityHashCode == this.fromActivityHashCode;
|
||||
}
|
||||
|
||||
public void showDialogX(String dialogXKey) {
|
||||
ActivityRunnable activityRunnable = BaseDialog.getActivityRunnable(dialogXKey);
|
||||
if (activityRunnable != null) {
|
||||
shownDialogXList.add(dialogXKey);
|
||||
activityRunnable.run(this);
|
||||
}
|
||||
}
|
||||
|
||||
public int getFromActivityHashCode() {
|
||||
return fromActivityHashCode;
|
||||
}
|
||||
|
||||
public DialogXFloatingWindowActivity setFromActivityHashCode(int fromActivityHashCode) {
|
||||
this.fromActivityHashCode = fromActivityHashCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static DialogXFloatingWindowActivity getDialogXFloatingWindowActivity() {
|
||||
if (dialogXFloatingWindowActivity == null) return null;
|
||||
return dialogXFloatingWindowActivity.get();
|
||||
}
|
||||
|
||||
public void finish(String dialogXKey) {
|
||||
shownDialogXList.remove(dialogXKey);
|
||||
if (shownDialogXList.isEmpty()) {
|
||||
if (dialogXFloatingWindowActivity != null) {
|
||||
dialogXFloatingWindowActivity.clear();
|
||||
}
|
||||
dialogXFloatingWindowActivity = null;
|
||||
super.finish();
|
||||
int version = Integer.valueOf(Build.VERSION.SDK_INT);
|
||||
if (version > 5) {
|
||||
overridePendingTransition(0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void finish() {
|
||||
if (dialogXFloatingWindowActivity != null) {
|
||||
dialogXFloatingWindowActivity.clear();
|
||||
}
|
||||
dialogXFloatingWindowActivity = null;
|
||||
super.finish();
|
||||
int version = Integer.valueOf(Build.VERSION.SDK_INT);
|
||||
if (version > 5) {
|
||||
overridePendingTransition(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isScreenshot;
|
||||
|
||||
public boolean isScreenshot() {
|
||||
return isScreenshot;
|
||||
}
|
||||
|
||||
public DialogXFloatingWindowActivity setScreenshot(boolean screenshot) {
|
||||
isScreenshot = screenshot;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 原始用户操作界面
|
||||
*/
|
||||
WeakReference<Activity> fromActivity;
|
||||
|
||||
public Activity getFromActivity() {
|
||||
return fromActivity == null ? null : fromActivity.get();
|
||||
}
|
||||
|
||||
public DialogXFloatingWindowActivity setFromActivity(Activity fromActivity) {
|
||||
this.fromActivity = new WeakReference<>(fromActivity);
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import com.kongzue.dialogx.DialogX;
|
||||
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: 2022/5/17 15:16
|
||||
*/
|
||||
public class DialogXImplModeAgent {
|
||||
|
||||
private DialogX.IMPL_MODE implMode;
|
||||
private WeakReference<BaseDialog> dialogWeakReference;
|
||||
|
||||
public DialogXImplModeAgent(DialogX.IMPL_MODE implMode, BaseDialog dialog) {
|
||||
this.implMode = implMode;
|
||||
this.dialogWeakReference = new WeakReference<>(dialog);
|
||||
}
|
||||
|
||||
public DialogX.IMPL_MODE getImplMode() {
|
||||
return implMode;
|
||||
}
|
||||
|
||||
public DialogXImplModeAgent setImplMode(DialogX.IMPL_MODE implMode) {
|
||||
this.implMode = implMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BaseDialog getDialog() {
|
||||
if (dialogWeakReference == null) {
|
||||
return null;
|
||||
}
|
||||
return dialogWeakReference.get();
|
||||
}
|
||||
|
||||
public DialogXImplModeAgent setDialogWeakReference(BaseDialog dialog) {
|
||||
this.dialogWeakReference = new WeakReference<>(dialog);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void recycle() {
|
||||
if (dialogWeakReference != null) dialogWeakReference.clear();
|
||||
dialogWeakReference = null;
|
||||
implMode = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,200 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
public class DialogXValueAnimator {
|
||||
|
||||
public static final int RESTART = 1;
|
||||
public static final int REVERSE = 2;
|
||||
public static final int INFINITE = -1;
|
||||
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
|
||||
private long duration;
|
||||
private long startTime;
|
||||
private boolean isRunning = false;
|
||||
private ValueUpdateListener listener;
|
||||
private Interpolator interpolator;
|
||||
private float startValue;
|
||||
private float endValue;
|
||||
private int repeatCount = 0;
|
||||
private int currentRepeatCount = 0;
|
||||
private int refreshInterval = 16; // 控制更新频率,默认 60 FPS
|
||||
|
||||
public static DialogXValueAnimator ofFloat(float start, float end){
|
||||
return new DialogXValueAnimator(start, end);
|
||||
}
|
||||
|
||||
public DialogXValueAnimator(float startValue, float endValue) {
|
||||
this.startValue = startValue;
|
||||
this.endValue = endValue;
|
||||
}
|
||||
|
||||
public void setFloatValues(float start, float end) {
|
||||
startValue = start;
|
||||
endValue = end;
|
||||
}
|
||||
|
||||
public void addUpdateListener(ValueUpdateListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (isRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
isRunning = true;
|
||||
startTime = System.currentTimeMillis();
|
||||
|
||||
// 开启一个线程用于更新动画
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (isRunning) {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long elapsed = currentTime - startTime;
|
||||
|
||||
if (elapsed < duration) {
|
||||
float fraction = (float) elapsed / duration;
|
||||
|
||||
// 使用插值器处理动画进度
|
||||
if (interpolator != null) {
|
||||
fraction = interpolator.getInterpolation(fraction);
|
||||
}
|
||||
|
||||
float animatedValue = startValue + fraction * (endValue - startValue);
|
||||
|
||||
// 通知监听器
|
||||
if (listener != null) {
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onValueUpdate(animatedValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 动画结束
|
||||
isRunning = false;
|
||||
|
||||
onAnimationEnd();
|
||||
|
||||
// 处理重复播放
|
||||
if (repeatCount == INFINITE || currentRepeatCount < repeatCount) {
|
||||
currentRepeatCount++;
|
||||
startTime = System.currentTimeMillis();
|
||||
isRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(refreshInterval);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private Handler getHandler() {
|
||||
if (handler==null) {
|
||||
handler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
private void onAnimationEnd() {
|
||||
|
||||
}
|
||||
|
||||
public long getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public DialogXValueAnimator setDuration(long duration) {
|
||||
this.duration = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public DialogXValueAnimator setStartTime(long startTime) {
|
||||
this.startTime = startTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueUpdateListener getListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
public DialogXValueAnimator setListener(ValueUpdateListener listener) {
|
||||
this.listener = listener;
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getStartValue() {
|
||||
return startValue;
|
||||
}
|
||||
|
||||
public DialogXValueAnimator setStartValue(float startValue) {
|
||||
this.startValue = startValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getEndValue() {
|
||||
return endValue;
|
||||
}
|
||||
|
||||
public DialogXValueAnimator setEndValue(float endValue) {
|
||||
this.endValue = endValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
public void setInterpolator(Interpolator interpolator) {
|
||||
this.interpolator = interpolator;
|
||||
}
|
||||
|
||||
public void setRepeatCount(int repeatCount) {
|
||||
this.repeatCount = repeatCount;
|
||||
}
|
||||
|
||||
// 监听器接口
|
||||
public interface ValueUpdateListener {
|
||||
void onValueUpdate(float animatedValue);
|
||||
}
|
||||
|
||||
public Interpolator getInterpolator() {
|
||||
return interpolator;
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
public int getRepeatCount() {
|
||||
return repeatCount;
|
||||
}
|
||||
|
||||
public int getCurrentRepeatCount() {
|
||||
return currentRepeatCount;
|
||||
}
|
||||
|
||||
public int getRefreshInterval() {
|
||||
return refreshInterval;
|
||||
}
|
||||
|
||||
public DialogXValueAnimator setRefreshInterval(int refreshInterval) {
|
||||
this.refreshInterval = refreshInterval;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
public class DialogXViewLoc {
|
||||
|
||||
public static boolean skipErrorLoc = true;
|
||||
|
||||
private float x;
|
||||
private float y;
|
||||
private float w;
|
||||
private float h;
|
||||
|
||||
public float getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public DialogXViewLoc setX(float x) {
|
||||
this.x = x;
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public DialogXViewLoc setY(float y) {
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getW() {
|
||||
return w;
|
||||
}
|
||||
|
||||
public DialogXViewLoc setW(float w) {
|
||||
this.w = w;
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getH() {
|
||||
return h;
|
||||
}
|
||||
|
||||
public DialogXViewLoc setH(float h) {
|
||||
this.h = h;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isSameLoc(int[] loc) {
|
||||
if (loc.length == 2) {
|
||||
return x == loc[0] && y == loc[1];
|
||||
}
|
||||
if (loc.length == 4) {
|
||||
return x == loc[0] && y == loc[1] && w == loc[2] && h == loc[3];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void set(int[] loc) {
|
||||
if (loc.length == 2) {
|
||||
if (skipErrorLoc) {
|
||||
if (loc[0] != 0) {
|
||||
x = loc[0];
|
||||
}
|
||||
if (loc[1] != 0) {
|
||||
y = loc[1];
|
||||
}
|
||||
} else {
|
||||
x = loc[0];
|
||||
y = loc[1];
|
||||
}
|
||||
}
|
||||
if (loc.length == 4) {
|
||||
if (skipErrorLoc) {
|
||||
if (loc[0] != 0) {
|
||||
x = loc[0];
|
||||
}
|
||||
if (loc[1] != 0) {
|
||||
y = loc[1];
|
||||
}
|
||||
} else {
|
||||
x = loc[0];
|
||||
y = loc[1];
|
||||
}
|
||||
w = loc[2];
|
||||
h = loc[3];
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.RectF;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.kongzue.dialogx.DialogX;
|
||||
import com.kongzue.dialogx.dialogs.FullScreenDialog;
|
||||
import com.kongzue.dialogx.interfaces.ScrollController;
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
if (me.isAllowInterceptTouch()) {
|
||||
View touchView = impl.boxCustom;
|
||||
if (impl.scrollView != null) {
|
||||
touchView = impl.bkg;
|
||||
}
|
||||
touchView.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 (impl.scrollView != null && impl.scrollView.isCanScroll() && touchInScrollView(v, impl.scrollView, event)) {
|
||||
if (aimY > me.getDialogImpl().getEnterY()) {
|
||||
if (impl.scrollView.getScrollDistance() == 0) {
|
||||
if (impl.scrollView instanceof ScrollController) {
|
||||
((ScrollController) impl.scrollView).lockScroll(true);
|
||||
}
|
||||
impl.bkg.setY(aimY);
|
||||
} else {
|
||||
bkgTouchDownY = event.getY();
|
||||
}
|
||||
} else {
|
||||
if (impl.scrollView instanceof ScrollController) {
|
||||
((ScrollController) impl.scrollView).lockScroll(false);
|
||||
}
|
||||
aimY = (me.getDialogImpl().getEnterY());
|
||||
impl.bkg.setY(aimY);
|
||||
}
|
||||
} else {
|
||||
if (aimY < me.getDialogImpl().getEnterY()) {
|
||||
aimY = me.getDialogImpl().getEnterY();
|
||||
}
|
||||
impl.bkg.setY(aimY);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
isBkgTouched = false;
|
||||
if (bkgOldY == me.getDialogImpl().getEnterY()) {
|
||||
if (impl.bkg.getY() < DialogX.touchSlideTriggerThreshold) {
|
||||
ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.bkg, "y", impl.bkg.getY(), me.getDialogImpl().getEnterY());
|
||||
enterAnim.setDuration(300);
|
||||
enterAnim.start();
|
||||
} else if (impl.bkg.getY() > impl.getEnterY() + DialogX.touchSlideTriggerThreshold) {
|
||||
impl.preDismiss();
|
||||
} else {
|
||||
ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.bkg, "y", impl.bkg.getY(), impl.getEnterY());
|
||||
enterAnim.setDuration(300);
|
||||
enterAnim.start();
|
||||
}
|
||||
} else {
|
||||
if (impl.bkg.getY() < bkgOldY - DialogX.touchSlideTriggerThreshold) {
|
||||
ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.bkg, "y", impl.bkg.getY(), me.getDialogImpl().getEnterY());
|
||||
enterAnim.setDuration(300);
|
||||
enterAnim.start();
|
||||
} else if (impl.bkg.getY() > bkgOldY + DialogX.touchSlideTriggerThreshold) {
|
||||
impl.preDismiss();
|
||||
} else {
|
||||
ObjectAnimator enterAnim = ObjectAnimator.ofFloat(impl.bkg, "y", impl.bkg.getY(), impl.getEnterY());
|
||||
enterAnim.setDuration(300);
|
||||
enterAnim.start();
|
||||
}
|
||||
}
|
||||
if (impl.scrollView instanceof ScrollController) {
|
||||
impl.scrollView.lockScroll(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
View touchView = impl.boxCustom;
|
||||
if (impl.scrollView != null) {
|
||||
touchView = impl.bkg;
|
||||
}
|
||||
if (impl.scrollView instanceof ScrollController) {
|
||||
((ScrollController) impl.scrollView).lockScroll(false);
|
||||
}
|
||||
touchView.setOnTouchListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 MotionEvent 触摸点是否在 scrollView 相对于对话框移动布局 slideView 范围内
|
||||
*
|
||||
* @param slideView 对话框移动布局
|
||||
* @param scrollView 内部滚动布局
|
||||
* @param event 触摸事件
|
||||
* @return 是否在范围内
|
||||
*/
|
||||
private boolean touchInScrollView(View slideView, ScrollController scrollView, MotionEvent event) {
|
||||
View scrollViewImpl = (View) scrollView;
|
||||
RectF scrollViewLocation = new RectF();
|
||||
int[] scrollViewScreenLoc = new int[2];
|
||||
int[] rootViewScreenLoc = new int[2];
|
||||
scrollViewImpl.getLocationInWindow(scrollViewScreenLoc);
|
||||
slideView.getLocationInWindow(rootViewScreenLoc);
|
||||
|
||||
scrollViewLocation.left = scrollViewScreenLoc[0] - rootViewScreenLoc[0];
|
||||
scrollViewLocation.top = scrollViewScreenLoc[1] - rootViewScreenLoc[1];
|
||||
scrollViewLocation.right = scrollViewLocation.left + scrollViewImpl.getWidth();
|
||||
scrollViewLocation.bottom = scrollViewLocation.top + scrollViewImpl.getHeight();
|
||||
|
||||
return event.getX() >= scrollViewLocation.left && event.getX() <= scrollViewLocation.right &&
|
||||
event.getY() >= scrollViewLocation.top && event.getY() <= scrollViewLocation.bottom;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
128
DialogX/src/main/java/com/kongzue/dialogx/util/InputInfo.java
Normal file
128
DialogX/src/main/java/com/kongzue/dialogx/util/InputInfo.java
Normal file
@ -0,0 +1,128 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import android.text.InputFilter;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 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; //默认选中所有文字(便于修改)
|
||||
|
||||
private Integer cursorColor; //输入框光标颜色
|
||||
private Integer bottomLineColor;//输入框横线颜色
|
||||
|
||||
private InputFilter[] inputFilters; //输入过滤器
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public Integer getCursorColor() {
|
||||
return cursorColor;
|
||||
}
|
||||
|
||||
public InputInfo setCursorColor(@ColorInt int cursorColor) {
|
||||
this.cursorColor = cursorColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputInfo setThemeColor(@ColorInt int themeColor) {
|
||||
this.cursorColor = themeColor;
|
||||
this.bottomLineColor = themeColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Integer getBottomLineColor() {
|
||||
return bottomLineColor;
|
||||
}
|
||||
|
||||
public InputInfo setBottomLineColor(int bottomLineColor) {
|
||||
this.bottomLineColor = bottomLineColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputFilter[] getInputFilters() {
|
||||
return inputFilters;
|
||||
}
|
||||
|
||||
public InputInfo setInputFilters(InputFilter[] inputFilters) {
|
||||
this.inputFilters = inputFilters;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputInfo addInputFilter(InputFilter inputFilter) {
|
||||
if (this.inputFilters == null) {
|
||||
this.inputFilters = new InputFilter[]{inputFilter};
|
||||
} else {
|
||||
this.inputFilters = Arrays.copyOf(this.inputFilters, this.inputFilters.length + 1);
|
||||
this.inputFilters[this.inputFilters.length - 1] = inputFilter;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputInfo removeInputFilter(InputFilter inputFilter) {
|
||||
if (this.inputFilters!= null) {
|
||||
for (int i = 0; i < this.inputFilters.length; i++) {
|
||||
if (this.inputFilters[i] == inputFilter) {
|
||||
this.inputFilters = Arrays.copyOf(this.inputFilters, this.inputFilters.length - 1);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.graphics.drawable.InsetDrawable;
|
||||
|
||||
public class ItemDivider {
|
||||
|
||||
private int left; //左边距(dp)
|
||||
private int right; //右边距(dp)
|
||||
private int width = 1; //分割线宽度(px)
|
||||
private int[] color = {0xFFDFE1E5, 0xFF3A3A3A}; //颜色
|
||||
|
||||
public ItemDivider() {
|
||||
}
|
||||
|
||||
public ItemDivider(int left, int right, int width) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public int getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public ItemDivider setLeft(int left) {
|
||||
this.left = left;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public ItemDivider setRight(int right) {
|
||||
this.right = right;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public ItemDivider setWidth(int width) {
|
||||
this.width = width;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getColor(boolean light) {
|
||||
return light ? color[0] : color[1];
|
||||
}
|
||||
|
||||
public ItemDivider setColor(boolean light, int color) {
|
||||
if (light) {
|
||||
this.color[0] = color;
|
||||
} else {
|
||||
this.color[1] = color;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemDivider setColor(int color) {
|
||||
this.color = new int[]{color, color};
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemDivider{" +
|
||||
"left(dp)=" + left +
|
||||
", right(dp)=" + right +
|
||||
", width(px)=" + width +
|
||||
", color(light)=" + String.format("#%06X", (0xFFFFFF & color[0])) +
|
||||
", color(night)=" + String.format("#%06X", (0xFFFFFF & color[1])) +
|
||||
'}';
|
||||
}
|
||||
|
||||
public Drawable createDividerDrawable(Context c, boolean light) {
|
||||
GradientDrawable dividerShape = new GradientDrawable();
|
||||
dividerShape.setShape(GradientDrawable.RECTANGLE);
|
||||
dividerShape.setColor(getColor(light));
|
||||
|
||||
InsetDrawable insetDivider = new InsetDrawable(
|
||||
dividerShape,
|
||||
dip2px(c, left), 0, dip2px(c, right), 0
|
||||
);
|
||||
return insetDivider;
|
||||
}
|
||||
|
||||
private int dip2px(Context c, float dpValue) {
|
||||
final float scale = c.getResources().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
}
|
@ -0,0 +1,270 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import static com.kongzue.dialogx.interfaces.BaseDialog.isNull;
|
||||
import static com.kongzue.dialogx.interfaces.BaseDialog.useTextInfo;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Space;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.kongzue.dialogx.R;
|
||||
import com.kongzue.dialogx.dialogs.MessageMenu;
|
||||
import com.kongzue.dialogx.interfaces.MenuIconAdapter;
|
||||
import com.kongzue.dialogx.interfaces.SELECT_MODE;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MessageMenuArrayAdapter extends BaseAdapter {
|
||||
private MessageMenu messageMenu;
|
||||
public List<CharSequence> objects;
|
||||
public Context context;
|
||||
|
||||
public MessageMenuArrayAdapter(MessageMenu messageMenu, Context context, List<CharSequence> objects) {
|
||||
this.objects = objects;
|
||||
this.context = context;
|
||||
this.messageMenu = messageMenu;
|
||||
}
|
||||
|
||||
class ViewHolder {
|
||||
ImageView imgDialogxMenuIcon;
|
||||
ImageView imgDialogxMenuSelection;
|
||||
TextView txtDialogxMenuText;
|
||||
Space spaceDialogxRightPadding;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
TextInfo defaultMenuTextInfo;
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
MessageMenuArrayAdapter.ViewHolder viewHolder = null;
|
||||
if (convertView == null) {
|
||||
viewHolder = new MessageMenuArrayAdapter.ViewHolder();
|
||||
LayoutInflater mInflater = LayoutInflater.from(context);
|
||||
|
||||
int resourceId = R.layout.item_dialogx_material_bottom_menu_normal_text;
|
||||
if (messageMenu.getStyle().overrideBottomDialogRes() != null) {
|
||||
resourceId = messageMenu.getStyle().overrideBottomDialogRes().overrideMenuItemLayout(messageMenu.isLightTheme(), position, getCount(), false);
|
||||
if (resourceId == 0) {
|
||||
resourceId = R.layout.item_dialogx_material_bottom_menu_normal_text;
|
||||
} else {
|
||||
if (!isNull(messageMenu.getTitle()) || !isNull(messageMenu.getMessage()) || messageMenu.getCustomView() != null) {
|
||||
if (position == 0) {
|
||||
resourceId = messageMenu.getStyle().overrideBottomDialogRes().overrideMenuItemLayout(messageMenu.isLightTheme(), position, getCount(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
convertView = mInflater.inflate(resourceId, null);
|
||||
|
||||
viewHolder.imgDialogxMenuIcon = convertView.findViewById(R.id.img_dialogx_menu_icon);
|
||||
viewHolder.imgDialogxMenuSelection = convertView.findViewById(R.id.img_dialogx_menu_selection);
|
||||
viewHolder.txtDialogxMenuText = convertView.findViewById(R.id.txt_dialogx_menu_text);
|
||||
viewHolder.spaceDialogxRightPadding = convertView.findViewById(R.id.space_dialogx_right_padding);
|
||||
|
||||
convertView.setTag(viewHolder);
|
||||
} else {
|
||||
viewHolder = (MessageMenuArrayAdapter.ViewHolder) convertView.getTag();
|
||||
}
|
||||
if (!messageMenu.isMenuItemEnable(position)) {
|
||||
convertView.setAlpha(0.4f);
|
||||
} else {
|
||||
convertView.setAlpha(1f);
|
||||
}
|
||||
if (messageMenu.getSelectMode() == SELECT_MODE.SINGLE) {
|
||||
if (viewHolder.imgDialogxMenuSelection != null) {
|
||||
if (messageMenu.getSelection() == position) {
|
||||
viewHolder.imgDialogxMenuSelection.setVisibility(View.VISIBLE);
|
||||
int overrideSelectionImageResId = messageMenu.getStyle().overrideBottomDialogRes().overrideSelectionImage(messageMenu.isLightTheme(), true);
|
||||
if (overrideSelectionImageResId != 0) {
|
||||
viewHolder.imgDialogxMenuSelection.setImageResource(overrideSelectionImageResId);
|
||||
}
|
||||
} else {
|
||||
int overrideSelectionImageResId = messageMenu.getStyle().overrideBottomDialogRes().overrideSelectionImage(messageMenu.isLightTheme(), false);
|
||||
if (overrideSelectionImageResId != 0) {
|
||||
viewHolder.imgDialogxMenuSelection.setVisibility(View.VISIBLE);
|
||||
viewHolder.imgDialogxMenuSelection.setImageResource(overrideSelectionImageResId);
|
||||
} else {
|
||||
viewHolder.imgDialogxMenuSelection.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (messageMenu.getSelectMode() == SELECT_MODE.MULTIPLE) {
|
||||
if (viewHolder.imgDialogxMenuSelection != null) {
|
||||
if (messageMenu.getSelectionList().contains(position)) {
|
||||
viewHolder.imgDialogxMenuSelection.setVisibility(View.VISIBLE);
|
||||
int overrideSelectionImageResId = messageMenu.getStyle().overrideBottomDialogRes().overrideMultiSelectionImage(messageMenu.isLightTheme(), true);
|
||||
if (overrideSelectionImageResId != 0) {
|
||||
viewHolder.imgDialogxMenuSelection.setImageResource(overrideSelectionImageResId);
|
||||
}
|
||||
} else {
|
||||
int overrideSelectionImageResId = messageMenu.getStyle().overrideBottomDialogRes().overrideMultiSelectionImage(messageMenu.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 (messageMenu.getStyle().overrideBottomDialogRes() != null) {
|
||||
overrideSelectionBackgroundColorRes = messageMenu.getStyle().overrideBottomDialogRes().overrideSelectionMenuBackgroundColor(messageMenu.isLightTheme());
|
||||
}
|
||||
if (messageMenu.getSelection() == position) {
|
||||
//选中的背景变色
|
||||
if (overrideSelectionBackgroundColorRes != 0) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
convertView.setBackgroundTintList(ColorStateList.valueOf(context.getResources().getColor(overrideSelectionBackgroundColorRes)));
|
||||
}
|
||||
}
|
||||
}
|
||||
CharSequence text = objects.get(position);
|
||||
|
||||
int textColor = messageMenu.isLightTheme() ? R.color.black90 : R.color.white90;
|
||||
if (messageMenu.getStyle().overrideBottomDialogRes() != null) {
|
||||
if (messageMenu.getStyle().overrideBottomDialogRes().overrideMenuTextColor(messageMenu.isLightTheme()) != 0) {
|
||||
textColor = messageMenu.getStyle().overrideBottomDialogRes().overrideMenuTextColor(messageMenu.isLightTheme());
|
||||
}
|
||||
}
|
||||
|
||||
if (null != text) {
|
||||
if (defaultMenuTextInfo == null) {
|
||||
defaultMenuTextInfo = new TextInfo().setShowEllipsis(viewHolder.txtDialogxMenuText.getEllipsize() == TextUtils.TruncateAt.END).setFontColor(viewHolder.txtDialogxMenuText.getTextColors().getDefaultColor()).setBold(viewHolder.txtDialogxMenuText.getPaint().isFakeBoldText()).setFontSize(px2dip(viewHolder.txtDialogxMenuText.getTextSize())).setGravity(viewHolder.txtDialogxMenuText.getGravity()).setMaxLines(viewHolder.txtDialogxMenuText.getMaxLines());
|
||||
}
|
||||
viewHolder.txtDialogxMenuText.setText(text);
|
||||
viewHolder.txtDialogxMenuText.setTextColor(context.getResources().getColor(textColor));
|
||||
if (messageMenu.getMenuItemTextInfoInterceptor() != null) {
|
||||
TextInfo textInfo = messageMenu.getMenuItemTextInfoInterceptor().menuItemTextInfo(messageMenu, position, text.toString());
|
||||
if (textInfo != null) {
|
||||
useTextInfo(viewHolder.txtDialogxMenuText, textInfo);
|
||||
} else {
|
||||
if (messageMenu.getMenuTextInfo() != null) {
|
||||
useTextInfo(viewHolder.txtDialogxMenuText, messageMenu.getMenuTextInfo());
|
||||
} else {
|
||||
useTextInfo(viewHolder.txtDialogxMenuText, defaultMenuTextInfo);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (messageMenu.getMenuTextInfo() != null) {
|
||||
useTextInfo(viewHolder.txtDialogxMenuText, messageMenu.getMenuTextInfo());
|
||||
}
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (viewHolder.imgDialogxMenuSelection != null) {
|
||||
if (messageMenu.getStyle().overrideBottomDialogRes() != null && messageMenu.getStyle().overrideBottomDialogRes().selectionImageTint(messageMenu.isLightTheme())) {
|
||||
viewHolder.imgDialogxMenuSelection.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(textColor)));
|
||||
} else {
|
||||
viewHolder.imgDialogxMenuSelection.setImageTintList(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messageMenu.getOnIconChangeCallBack() != null) {
|
||||
if (messageMenu.getOnIconChangeCallBack() instanceof MenuIconAdapter) {
|
||||
boolean result = ((MenuIconAdapter) messageMenu.getOnIconChangeCallBack()).applyIcon(messageMenu, position, text.toString(), viewHolder.imgDialogxMenuIcon);
|
||||
boolean autoTintIconInLightOrDarkMode = messageMenu.getOnIconChangeCallBack().isAutoTintIconInLightOrDarkMode() == null ? messageMenu.isAutoTintIconInLightOrDarkMode() : messageMenu.getOnIconChangeCallBack().isAutoTintIconInLightOrDarkMode();
|
||||
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(result ? View.VISIBLE : View.GONE);
|
||||
if (result) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (autoTintIconInLightOrDarkMode) {
|
||||
viewHolder.imgDialogxMenuIcon.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(textColor)));
|
||||
}
|
||||
}
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int resId = messageMenu.getOnIconChangeCallBack().getIcon(messageMenu, position, text.toString());
|
||||
boolean autoTintIconInLightOrDarkMode = messageMenu.getOnIconChangeCallBack().isAutoTintIconInLightOrDarkMode() == null ? messageMenu.isAutoTintIconInLightOrDarkMode() : messageMenu.getOnIconChangeCallBack().isAutoTintIconInLightOrDarkMode();
|
||||
|
||||
if (resId != 0) {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.VISIBLE);
|
||||
viewHolder.imgDialogxMenuIcon.setImageResource(resId);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (autoTintIconInLightOrDarkMode) {
|
||||
viewHolder.imgDialogxMenuIcon.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(textColor)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.GONE);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (messageMenu.getIconResIds() != null) {
|
||||
int resId = messageMenu.getIconResIds(position);
|
||||
boolean autoTintIconInLightOrDarkMode = messageMenu.isAutoTintIconInLightOrDarkMode();
|
||||
|
||||
if (resId != 0) {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.VISIBLE);
|
||||
viewHolder.imgDialogxMenuIcon.setImageResource(resId);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (autoTintIconInLightOrDarkMode) {
|
||||
viewHolder.imgDialogxMenuIcon.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(textColor)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.GONE);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.GONE);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (messageMenu.getMenuMenuItemLayoutRefreshCallback() != null) {
|
||||
messageMenu.getMenuMenuItemLayoutRefreshCallback().getView(messageMenu, position, convertView, parent);
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
|
||||
private int px2dip(float pxValue) {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (pxValue / scale + 0.5f);
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2022/8/26 17:10
|
||||
*/
|
||||
public abstract class ObjectRunnable<D> {
|
||||
public abstract void run(D d);
|
||||
}
|
@ -0,0 +1,218 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import static com.kongzue.dialogx.interfaces.BaseDialog.useTextInfo;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.os.Build;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Space;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.kongzue.dialogx.R;
|
||||
import com.kongzue.dialogx.dialogs.PopMenu;
|
||||
import com.kongzue.dialogx.interfaces.MenuIconAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2021/8/18 15:25
|
||||
*/
|
||||
public class PopMenuArrayAdapter extends BaseAdapter {
|
||||
|
||||
public List<CharSequence> menuList;
|
||||
public Context context;
|
||||
private PopMenu popMenu;
|
||||
LayoutInflater mInflater;
|
||||
|
||||
public PopMenuArrayAdapter(PopMenu popMenu, Context context, List<CharSequence> menuList) {
|
||||
this.popMenu = popMenu;
|
||||
this.menuList = menuList;
|
||||
this.context = context;
|
||||
mInflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
public List<CharSequence> getMenuList() {
|
||||
return menuList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
if (menuList == null) {
|
||||
menuList = new ArrayList<>();
|
||||
}
|
||||
return menuList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return menuList.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
ViewHolder viewHolder;
|
||||
if (convertView == null) {
|
||||
viewHolder = new ViewHolder();
|
||||
int resourceId = R.layout.item_dialogx_material_context_menu_normal_text;
|
||||
if (popMenu.getStyle().popMenuSettings() != null) {
|
||||
int customItemLayout = popMenu.getStyle().popMenuSettings().overrideMenuItemLayoutRes(popMenu.isLightTheme());
|
||||
if (customItemLayout != 0) {
|
||||
resourceId = customItemLayout;
|
||||
}
|
||||
}
|
||||
|
||||
convertView = mInflater.inflate(resourceId, null);
|
||||
|
||||
viewHolder.boxItem = convertView.findViewById(R.id.box_item);
|
||||
viewHolder.imgDialogxMenuIcon = convertView.findViewById(R.id.img_dialogx_menu_icon);
|
||||
viewHolder.txtDialogxMenuText = convertView.findViewById(R.id.txt_dialogx_menu_text);
|
||||
viewHolder.spaceDialogxRightPadding = convertView.findViewById(R.id.space_dialogx_right_padding);
|
||||
|
||||
convertView.setTag(viewHolder);
|
||||
} else {
|
||||
viewHolder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
if (!popMenu.isMenuItemEnable(position)) {
|
||||
convertView.setAlpha(0.4f);
|
||||
} else {
|
||||
convertView.setAlpha(1f);
|
||||
}
|
||||
int customBackgroundRes = popMenu.getStyle().popMenuSettings() == null ? 0 : popMenu.getStyle().popMenuSettings().overrideMenuItemBackgroundRes(popMenu.isLightTheme(), position, getCount(), false);
|
||||
if (customBackgroundRes != 0) {
|
||||
convertView.setBackgroundResource(customBackgroundRes);
|
||||
}
|
||||
if (viewHolder.boxItem != null) {
|
||||
if (popMenu.getPressedIndex() == position) {
|
||||
viewHolder.boxItem.setBackgroundResource(popMenu.isLightTheme() ? R.color.black5 : R.color.white5);
|
||||
} else {
|
||||
viewHolder.boxItem.setBackgroundResource(R.color.empty);
|
||||
}
|
||||
}
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.GONE);
|
||||
viewHolder.txtDialogxMenuText.setText(menuList.get(position));
|
||||
if (popMenu.getStyle().popMenuSettings() != null && popMenu.getStyle().popMenuSettings().paddingVertical() != 0) {
|
||||
if (position == 0) {
|
||||
convertView.setPadding(0, popMenu.getStyle().popMenuSettings().paddingVertical(), 0, 0);
|
||||
} else if (position == getCount() - 1) {
|
||||
convertView.setPadding(0, 0, 0, popMenu.getStyle().popMenuSettings().paddingVertical());
|
||||
} else {
|
||||
convertView.setPadding(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (popMenu.getMenuTextInfo() != null) {
|
||||
useTextInfo(viewHolder.txtDialogxMenuText, popMenu.getMenuTextInfo());
|
||||
}
|
||||
|
||||
int textColor = popMenu.isLightTheme() ? R.color.black90 : R.color.white90;
|
||||
viewHolder.txtDialogxMenuText.setTextColor(context.getResources().getColor(textColor));
|
||||
|
||||
if (popMenu.getOnIconChangeCallBack() != null) {
|
||||
if (popMenu.getOnIconChangeCallBack() instanceof MenuIconAdapter) {
|
||||
boolean result = ((MenuIconAdapter) popMenu.getOnIconChangeCallBack()).applyIcon(popMenu, position, menuList.get(position).toString(), viewHolder.imgDialogxMenuIcon);
|
||||
boolean autoTintIconInLightOrDarkMode = popMenu.getOnIconChangeCallBack().isAutoTintIconInLightOrDarkMode() == null ? popMenu.isAutoTintIconInLightOrDarkMode() : popMenu.getOnIconChangeCallBack().isAutoTintIconInLightOrDarkMode();
|
||||
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(result ? View.VISIBLE : View.GONE);
|
||||
if (result) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (autoTintIconInLightOrDarkMode) {
|
||||
viewHolder.imgDialogxMenuIcon.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(textColor)));
|
||||
}
|
||||
}
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
int resId = popMenu.getOnIconChangeCallBack().getIcon(popMenu, position, menuList.get(position).toString());
|
||||
boolean autoTintIconInLightOrDarkMode = popMenu.getOnIconChangeCallBack().isAutoTintIconInLightOrDarkMode() == null ? popMenu.isAutoTintIconInLightOrDarkMode() : popMenu.getOnIconChangeCallBack().isAutoTintIconInLightOrDarkMode();
|
||||
|
||||
if (resId != 0) {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.VISIBLE);
|
||||
viewHolder.imgDialogxMenuIcon.setImageResource(resId);
|
||||
if (isHaveProperties(viewHolder.txtDialogxMenuText.getGravity(), Gravity.CENTER) || isHaveProperties(viewHolder.txtDialogxMenuText.getGravity(), Gravity.CENTER_HORIZONTAL)) {
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (autoTintIconInLightOrDarkMode) {
|
||||
viewHolder.imgDialogxMenuIcon.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(textColor)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.GONE);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (popMenu.getIconResIds() != null) {
|
||||
int resId = popMenu.getIconResIds(position);
|
||||
boolean autoTintIconInLightOrDarkMode = popMenu.isAutoTintIconInLightOrDarkMode();
|
||||
|
||||
if (resId != 0) {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.VISIBLE);
|
||||
viewHolder.imgDialogxMenuIcon.setImageResource(resId);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (autoTintIconInLightOrDarkMode) {
|
||||
viewHolder.imgDialogxMenuIcon.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(textColor)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.GONE);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
viewHolder.imgDialogxMenuIcon.setVisibility(View.GONE);
|
||||
if (viewHolder.spaceDialogxRightPadding != null) {
|
||||
viewHolder.spaceDialogxRightPadding.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (popMenu.getMenuMenuItemLayoutRefreshCallback() != null) {
|
||||
popMenu.getMenuMenuItemLayoutRefreshCallback().getView(popMenu, position, convertView, parent);
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
private boolean isHaveProperties(int gravity, int property) {
|
||||
return (gravity & property) == property;
|
||||
}
|
||||
|
||||
class ViewHolder {
|
||||
LinearLayout boxItem;
|
||||
ImageView imgDialogxMenuIcon;
|
||||
TextView txtDialogxMenuText;
|
||||
Space spaceDialogxRightPadding;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2022/7/19 14:31
|
||||
*/
|
||||
public class PopValueAnimator extends ValueAnimator {
|
||||
|
||||
float startValue;
|
||||
float endValue;
|
||||
|
||||
public static PopValueAnimator ofFloat(float... values) {
|
||||
PopValueAnimator anim = new PopValueAnimator();
|
||||
anim.setFloatValues(values);
|
||||
return anim;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloatValues(float... values) {
|
||||
if (values.length > 1) {
|
||||
startValue = values[0];
|
||||
endValue = values[values.length - 1];
|
||||
}
|
||||
super.setFloatValues(values);
|
||||
}
|
||||
|
||||
public float getStartValue() {
|
||||
return startValue;
|
||||
}
|
||||
|
||||
public float getEndValue() {
|
||||
return endValue;
|
||||
}
|
||||
}
|
130
DialogX/src/main/java/com/kongzue/dialogx/util/TextInfo.java
Normal file
130
DialogX/src/main/java/com/kongzue/dialogx/util/TextInfo.java
Normal file
@ -0,0 +1,130 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import android.graphics.Typeface;
|
||||
import android.util.TypedValue;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
|
||||
/**
|
||||
* 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 FONT_SIZE_UNIT fontSizeUnit = FONT_SIZE_UNIT.DP; //字号单位
|
||||
private int gravity = -1; //对齐方式,值为-1时使用默认样式,取值可使用Gravity.CENTER等对齐方式
|
||||
private int fontColor = 1; //文字颜色,值为1时使用默认样式,取值可以用Color.rgb(r,g,b)等方式获取
|
||||
private boolean bold = false; //是否粗体
|
||||
private int maxLines = -1; //最大行数
|
||||
private boolean showEllipsis = false; //显示省略号
|
||||
private Typeface typeface; //指定字体样式
|
||||
|
||||
public enum FONT_SIZE_UNIT {
|
||||
DP,
|
||||
PX,
|
||||
SP
|
||||
}
|
||||
|
||||
public int getFontSize() {
|
||||
return fontSize;
|
||||
}
|
||||
|
||||
public int getFontSizeComplexUnit() {
|
||||
if (fontSizeUnit == null) {
|
||||
return TypedValue.COMPLEX_UNIT_DIP;
|
||||
}
|
||||
switch (fontSizeUnit) {
|
||||
case PX:
|
||||
return TypedValue.COMPLEX_UNIT_PX;
|
||||
case SP:
|
||||
return TypedValue.COMPLEX_UNIT_SP;
|
||||
default:
|
||||
return TypedValue.COMPLEX_UNIT_DIP;
|
||||
}
|
||||
}
|
||||
|
||||
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(@ColorInt int fontColor) {
|
||||
this.fontColor = fontColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isBold() {
|
||||
return bold;
|
||||
}
|
||||
|
||||
public TextInfo setBold(boolean bold) {
|
||||
this.bold = bold;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getMaxLines() {
|
||||
return maxLines;
|
||||
}
|
||||
|
||||
public TextInfo setMaxLines(int maxLines) {
|
||||
this.maxLines = maxLines;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isShowEllipsis() {
|
||||
return showEllipsis;
|
||||
}
|
||||
|
||||
public TextInfo setShowEllipsis(boolean showEllipsis) {
|
||||
this.showEllipsis = showEllipsis;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FONT_SIZE_UNIT getFontSizeUnit() {
|
||||
return fontSizeUnit;
|
||||
}
|
||||
|
||||
public TextInfo setFontSizeUnit(FONT_SIZE_UNIT fontSizeUnit) {
|
||||
this.fontSizeUnit = fontSizeUnit;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Typeface getTypeface() {
|
||||
return typeface;
|
||||
}
|
||||
|
||||
public TextInfo setTypeface(Typeface typeface) {
|
||||
this.typeface = typeface;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TextInfo{" +
|
||||
"fontSize=" + fontSize +
|
||||
", gravity=" + gravity +
|
||||
", fontColor=" + fontColor +
|
||||
", bold=" + bold +
|
||||
", maxLines=" + maxLines +
|
||||
", showEllipsis=" + showEllipsis +
|
||||
", typeface=" + typeface +
|
||||
'}';
|
||||
}
|
||||
}
|
136
DialogX/src/main/java/com/kongzue/dialogx/util/WindowUtil.java
Normal file
136
DialogX/src/main/java/com/kongzue/dialogx/util/WindowUtil.java
Normal file
@ -0,0 +1,136 @@
|
||||
package com.kongzue.dialogx.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.kongzue.dialogx.DialogX;
|
||||
import com.kongzue.dialogx.dialogs.PopTip;
|
||||
import com.kongzue.dialogx.interfaces.BaseDialog;
|
||||
import com.kongzue.dialogx.interfaces.NoTouchInterface;
|
||||
|
||||
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 abstract static class WindowSettings {
|
||||
|
||||
//自定义window参数
|
||||
public abstract WindowManager.LayoutParams overrideWindowLayoutParamsInterface(Context context, View dialogView, WindowManager.LayoutParams originWindowLayoutParams);
|
||||
|
||||
//自定义根布局
|
||||
public ViewGroup overrideRootView(Context context){return null;};
|
||||
}
|
||||
|
||||
//自定义window设置
|
||||
public static WindowSettings windowSettings;
|
||||
|
||||
public static void show(Activity activity, View dialogView, boolean touchEnable) {
|
||||
try {
|
||||
if (activity.getWindow().getDecorView().isAttachedToWindow()) {
|
||||
showNow(activity, dialogView, touchEnable);
|
||||
} else {
|
||||
activity.getWindow().getDecorView().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showNow(activity, dialogView, touchEnable);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (activity != null && !activity.isDestroyed()) {
|
||||
showNow(activity, dialogView, touchEnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void showNow(Activity activity, View dialogView, boolean touchEnable) {
|
||||
if (DialogX.globalHoverWindow && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(activity)) {
|
||||
Toast.makeText(activity, "使用 DialogX.globalHoverWindow 必须开启悬浮窗权限", Toast.LENGTH_LONG).show();
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
|
||||
activity.startActivity(intent);
|
||||
return;
|
||||
}
|
||||
ViewGroup customRootView = null;
|
||||
if (windowSettings != null) {
|
||||
customRootView = windowSettings.overrideRootView(activity);
|
||||
}
|
||||
ViewGroup rootLayout = customRootView == null ? new FrameLayout(activity) : customRootView;
|
||||
if (dialogView.getParent() != null) {
|
||||
((ViewGroup) dialogView.getParent()).removeView(dialogView);
|
||||
}
|
||||
rootLayout.addView(dialogView, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
|
||||
WindowManager manager = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
|
||||
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
|
||||
layoutParams.gravity = Gravity.CENTER_VERTICAL;
|
||||
layoutParams.format = PixelFormat.TRANSPARENT;
|
||||
if (DialogX.globalHoverWindow) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
layoutParams.type = TYPE_APPLICATION_OVERLAY;
|
||||
} else {
|
||||
layoutParams.type = TYPE_PHONE;
|
||||
}
|
||||
} else {
|
||||
layoutParams.type = TYPE_APPLICATION_ATTACHED_DIALOG;
|
||||
}
|
||||
layoutParams.flags = FLAG_FULLSCREEN |
|
||||
FLAG_TRANSLUCENT_STATUS |
|
||||
FLAG_TRANSLUCENT_NAVIGATION |
|
||||
FLAG_LAYOUT_IN_SCREEN
|
||||
;
|
||||
layoutParams.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
|
||||
if (!touchEnable) {
|
||||
dialogView.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
for (int i = BaseDialog.getRunningDialogList().size() - 1; i >= 0; i--) {
|
||||
BaseDialog baseDialog = BaseDialog.getRunningDialogList().get(i);
|
||||
if (!(baseDialog instanceof NoTouchInterface) && baseDialog.getOwnActivity() == activity) {
|
||||
if (baseDialog.getDialogView() == null) {
|
||||
return false;
|
||||
}
|
||||
return baseDialog.dispatchTouchEvent(event);
|
||||
}
|
||||
}
|
||||
return activity.dispatchTouchEvent(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
layoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||
}
|
||||
if (windowSettings != null) {
|
||||
WindowManager.LayoutParams layoutParamsTemp = windowSettings.overrideWindowLayoutParamsInterface(activity, dialogView, layoutParams);
|
||||
if (layoutParamsTemp != null) {
|
||||
layoutParams = layoutParamsTemp;
|
||||
}
|
||||
}
|
||||
manager.addView(rootLayout, layoutParams);
|
||||
}
|
||||
|
||||
public static void dismiss(View dialogView) {
|
||||
BaseDialog baseDialog = (BaseDialog) dialogView.getTag();
|
||||
if (baseDialog != null && baseDialog.getOwnActivity() != null) {
|
||||
WindowManager manager = (WindowManager) baseDialog.getOwnActivity().getSystemService(Context.WINDOW_SERVICE);
|
||||
manager.removeViewImmediate((View) dialogView.getParent());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,218 @@
|
||||
package com.kongzue.dialogx.util.views;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.kongzue.dialogx.DialogX;
|
||||
import com.kongzue.dialogx.impl.ActivityLifecycleImpl;
|
||||
import com.kongzue.dialogx.interfaces.BaseDialog;
|
||||
import com.kongzue.dialogx.util.DialogXFloatingWindowActivity;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2019/11/17 23:53
|
||||
*/
|
||||
@SuppressLint("AppCompatCustomView")
|
||||
public class ActivityScreenShotImageView extends ImageView {
|
||||
|
||||
public boolean hideActivityContentView;
|
||||
float width, height, mRadius;
|
||||
public static boolean useHardwareRenderingMode = true;
|
||||
|
||||
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) {
|
||||
requestLayoutType();
|
||||
}
|
||||
|
||||
private void requestLayoutType() {
|
||||
setLayerType(useHardwareRenderingMode ? LAYER_TYPE_HARDWARE : LAYER_TYPE_SOFTWARE, 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);
|
||||
if (width != getWidth() || height != getHeight()) {
|
||||
refreshImage();
|
||||
}
|
||||
width = getWidth();
|
||||
height = getHeight();
|
||||
}
|
||||
|
||||
boolean readyDraw = false;
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (!readyDraw) {
|
||||
super.onDraw(canvas);
|
||||
}
|
||||
if (width >= mRadius && height > mRadius) {
|
||||
if (isScreenshotSuccess) {
|
||||
canvas.drawColor(Color.BLACK);
|
||||
}
|
||||
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);
|
||||
}
|
||||
canvas.drawColor(Color.WHITE);
|
||||
super.onDraw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
if (!isScreenshotSuccess) refreshImage();
|
||||
}
|
||||
|
||||
private int screenWidth, screenHeight;
|
||||
|
||||
private void refreshImage() {
|
||||
if (!isAttachedToWindow()) {
|
||||
return;
|
||||
}
|
||||
if (screenWidth != getMeasuredWidth() || screenHeight != getMeasuredHeight()) {
|
||||
screenWidth = getMeasuredWidth();
|
||||
screenHeight = getMeasuredHeight();
|
||||
doScreenshotActivityAndZoom();
|
||||
}
|
||||
}
|
||||
|
||||
private void doScreenshotActivityAndZoom() {
|
||||
ViewGroup decorView = getDecorView();
|
||||
if (decorView == null) return;
|
||||
drawViewImage(decorView);
|
||||
setVisibility(VISIBLE);
|
||||
inited = true;
|
||||
}
|
||||
|
||||
private ViewGroup getDecorView() {
|
||||
if (dialog != null) {
|
||||
Activity ownActivity = dialog.getOwnActivity();
|
||||
return (ViewGroup) ownActivity.getWindow().getDecorView();
|
||||
}
|
||||
Activity topActivity = ActivityLifecycleImpl.getTopActivity();
|
||||
if (topActivity != null) {
|
||||
if (topActivity instanceof DialogXFloatingWindowActivity) {
|
||||
return (ViewGroup) ((DialogXFloatingWindowActivity) topActivity).getFromActivity().getWindow().getDecorView();
|
||||
}
|
||||
return (ViewGroup) topActivity.getWindow().getDecorView();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean inited = false;
|
||||
private boolean isScreenshotSuccess;
|
||||
private WeakReference<View> contentView;
|
||||
public static boolean hideContentView = false;
|
||||
|
||||
private void drawViewImage(View view) {
|
||||
if (view.getWidth() == 0 || view.getHeight() == 0) return;
|
||||
dialog.getDialogView().setVisibility(GONE);
|
||||
setContentViewVisibility(true);
|
||||
if (view.getWidth() + view.getHeight() == 0) {
|
||||
view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
|
||||
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
|
||||
}
|
||||
int viewWidth = view.getWidth();
|
||||
int viewHeight = view.getHeight();
|
||||
Bitmap bitmap = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
try {
|
||||
view.draw(canvas);
|
||||
} catch (Exception e) {
|
||||
if (DialogX.DEBUGMODE) e.printStackTrace();
|
||||
if (useHardwareRenderingMode) {
|
||||
useHardwareRenderingMode = false;
|
||||
requestLayoutType();
|
||||
drawViewImage(view);
|
||||
}
|
||||
}
|
||||
setImageBitmap(Bitmap.createBitmap(bitmap, 0, 0, view.getWidth(), view.getHeight()));
|
||||
isScreenshotSuccess = true;
|
||||
setContentViewVisibility(false);
|
||||
dialog.getDialogView().setVisibility(VISIBLE);
|
||||
dialog.getDialogView().requestFocus();
|
||||
}
|
||||
|
||||
protected void setContentViewVisibility(boolean show) {
|
||||
if (hideContentView || hideActivityContentView) {
|
||||
if (show) {
|
||||
if (contentView != null && contentView.get() != null) {
|
||||
contentView.get().setVisibility(VISIBLE);
|
||||
}
|
||||
} else {
|
||||
View userContentView = Objects.requireNonNull(getDecorView()).getChildAt(0);
|
||||
if (userContentView != null) {
|
||||
userContentView.setVisibility(GONE);
|
||||
contentView = new WeakReference<>(userContentView);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
setContentViewVisibility(true);
|
||||
if (contentView != null) {
|
||||
contentView.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void setScale(float scale) {
|
||||
setScaleX(scale);
|
||||
setScaleY(scale);
|
||||
readyDraw = true;
|
||||
}
|
||||
|
||||
BaseDialog dialog;
|
||||
|
||||
public void bindDialog(BaseDialog dialog) {
|
||||
this.dialog = dialog;
|
||||
}
|
||||
}
|
@ -0,0 +1,539 @@
|
||||
package com.kongzue.dialogx.util.views;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewOutlineProvider;
|
||||
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;
|
||||
|
||||
@Deprecated
|
||||
public class BlurView extends View {
|
||||
|
||||
private float mDownsampleFactor = 4;
|
||||
private int mOverlayColor = Color.WHITE;
|
||||
private float mBlurRadius = 35;
|
||||
private boolean overrideOverlayColor = false;
|
||||
private float mRadius = 0;
|
||||
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();
|
||||
private View mDecorView;
|
||||
private boolean mDifferentRoot;
|
||||
private static int RENDERING_COUNT;
|
||||
|
||||
private Paint mPaint;
|
||||
private RectF mRectF;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private boolean isInit = false;
|
||||
|
||||
Paint cutPaint;
|
||||
Paint overlayPaint;
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
if (!isInit && context != null) {
|
||||
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();
|
||||
|
||||
cutPaint = new Paint();
|
||||
cutPaint.setAntiAlias(true);
|
||||
cutPaint.setColor(mOverlayColor);
|
||||
|
||||
overlayPaint = new Paint();
|
||||
overlayPaint.setAntiAlias(true);
|
||||
|
||||
mRadius = a.getDimension(R.styleable.RealtimeBlurView_realtimeRadius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, context.getResources().getDisplayMetrics()));
|
||||
a.recycle();
|
||||
|
||||
isInit = true;
|
||||
|
||||
if (!isCompatMode()) {
|
||||
setOutlineProvider(new ViewOutlineProvider() {
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), mRadius);
|
||||
}
|
||||
});
|
||||
setClipToOutline(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCompatMode() {
|
||||
return Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP;
|
||||
}
|
||||
|
||||
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() {
|
||||
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) {
|
||||
supportRenderScript = false;
|
||||
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;
|
||||
decor.getLocationInWindow(locations);
|
||||
int x = -locations[0];
|
||||
int y = -locations[1];
|
||||
|
||||
getLocationInWindow(locations);
|
||||
x += locations[0];
|
||||
y += locations[1];
|
||||
|
||||
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();
|
||||
Activity activity;
|
||||
log(getContext());
|
||||
if (getContext() instanceof Activity) {
|
||||
activity = (Activity) getContext();
|
||||
} else {
|
||||
activity = BaseDialog.getTopActivity();
|
||||
}
|
||||
ViewGroup decorView = ((ViewGroup) activity.getWindow().getDecorView());
|
||||
if (decorView.getChildCount() >= 1) {
|
||||
mDecorView = decorView.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 || !supportRenderScript) {
|
||||
mRectF.right = getWidth();
|
||||
mRectF.bottom = getHeight();
|
||||
overlayPaint.setColor(needRemoveAlphaColor() ? removeAlphaColor(mOverlayColor) : mOverlayColor);
|
||||
canvas.drawRoundRect(mRectF, mRadius, mRadius, overlayPaint);
|
||||
} else {
|
||||
if (!mIsRendering && RENDERING_COUNT <= 0) {
|
||||
super.draw(canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if (isCompatMode()) {
|
||||
drawBlurredBitmapCompat(canvas);
|
||||
} else {
|
||||
drawBlurredBitmap(canvas, mBlurredBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawBlurredBitmapCompat(Canvas canvas) {
|
||||
if (mBlurredBitmap != null) {
|
||||
mRectDst.right = getWidth();
|
||||
mRectDst.bottom = getHeight();
|
||||
if (getWidth() > 0 && getHeight() > 0) {
|
||||
Bitmap readyDrawBitmap = getRoundedCornerBitmap(resizeImage(mBlurredBitmap, getWidth(), getHeight()), mRectDst);
|
||||
if (readyDrawBitmap != null) {
|
||||
canvas.drawBitmap(readyDrawBitmap, 0, 0, null);
|
||||
} else {
|
||||
Bitmap overlyBitmap = drawOverlyColor(Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888));
|
||||
if (overlyBitmap != null) canvas.drawBitmap(overlyBitmap, 0, 0, null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Bitmap overlyBitmap = drawOverlyColor(Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888));
|
||||
if (overlyBitmap != null) canvas.drawBitmap(overlyBitmap, 0, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawBlurredBitmap(Canvas canvas, Bitmap blurredBitmap) {
|
||||
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(needRemoveAlphaColor() ? removeAlphaColor(mOverlayColor) : mOverlayColor);
|
||||
} else {
|
||||
Bitmap overlyBitmap = drawOverlyColor(Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888));
|
||||
if (overlyBitmap != null) canvas.drawBitmap(overlyBitmap, 0, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
private Bitmap getRoundedCornerBitmap(Bitmap bitmap, Rect mRectDst) {
|
||||
bitmap = drawOverlyColor(resizeImage(bitmap, mRectDst.width(), mRectDst.height()));
|
||||
if (bitmap == null) return null;
|
||||
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(output);
|
||||
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
|
||||
Paint paint = new Paint();
|
||||
paint.setAntiAlias(true);
|
||||
paint.setShader(bitmapShader);
|
||||
canvas.drawRoundRect(new RectF(mRectDst), mRadius, mRadius, paint);
|
||||
return output;
|
||||
}
|
||||
|
||||
private Bitmap drawOverlyColor(Bitmap bitmap) {
|
||||
if (bitmap != null) {
|
||||
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(output);
|
||||
Rect originRect = new Rect();
|
||||
originRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
|
||||
canvas.drawBitmap(bitmap, originRect, originRect, overlayPaint);
|
||||
canvas.drawColor(needRemoveAlphaColor() ? removeAlphaColor(mOverlayColor) : mOverlayColor);
|
||||
return output;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Bitmap resizeImage(Bitmap bitmap, int newWidth, int newHeight) {
|
||||
if (bitmap != null) {
|
||||
int width = bitmap.getWidth();
|
||||
int height = bitmap.getHeight();
|
||||
float scaleWidth = ((float) newWidth) / width;
|
||||
float scaleHeight = ((float) newHeight) / height;
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postScale(scaleWidth, scaleHeight);
|
||||
return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
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 boolean needRemoveAlphaColor() {
|
||||
if (overrideOverlayColor) {
|
||||
return false;
|
||||
} else {
|
||||
return !(supportRenderScript && useBlur);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private static int replaceAlphaColor(@ColorInt int color, int alpha) {
|
||||
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;
|
||||
}
|
||||
|
||||
private static void log(Object o) {
|
||||
if (isDebug()) Log.i(">>>", "DialogX.BlurView: " + o.toString());
|
||||
}
|
||||
|
||||
public static void error(Object o) {
|
||||
if (isDebug()) Log.e(">>>", o.toString());
|
||||
}
|
||||
|
||||
public BlurView setOverrideOverlayColor(boolean overrideOverlayColor) {
|
||||
log("setOverrideOverlayColor: " + overrideOverlayColor);
|
||||
this.overrideOverlayColor = overrideOverlayColor;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
package com.kongzue.dialogx.util.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
import androidx.appcompat.view.ContextThemeWrapper;
|
||||
|
||||
import com.kongzue.dialogx.interfaces.BottomMenuListViewTouchEvent;
|
||||
import com.kongzue.dialogx.interfaces.DialogConvertViewInterface;
|
||||
import com.kongzue.dialogx.interfaces.ScrollController;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2020/10/6 23:42
|
||||
*/
|
||||
public class DialogListView extends ListView implements ScrollController {
|
||||
|
||||
private BottomMenuListViewTouchEvent bottomMenuListViewTouchEvent;
|
||||
|
||||
public DialogListView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public DialogListView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public DialogListView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
private DialogConvertViewInterface dialogImpl;
|
||||
|
||||
public DialogListView(DialogConvertViewInterface dialog, Context context) {
|
||||
super(context);
|
||||
dialogImpl = dialog;
|
||||
setVerticalScrollBarEnabled(false);
|
||||
}
|
||||
|
||||
public DialogListView(DialogConvertViewInterface dialog, Context context, int theme) {
|
||||
super(new ContextThemeWrapper(context, theme));
|
||||
dialogImpl = dialog;
|
||||
setVerticalScrollBarEnabled(false);
|
||||
}
|
||||
|
||||
// private int dip2px(float dpValue) {
|
||||
// final float scale = Resources.getSystem().getDisplayMetrics().density;
|
||||
// return (int) (dpValue * scale + 0.5f);
|
||||
// }
|
||||
//
|
||||
// private int mPosition;
|
||||
// private float touchDownY;
|
||||
//
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK;
|
||||
switch (actionMasked){
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if (bottomMenuListViewTouchEvent != null) {
|
||||
bottomMenuListViewTouchEvent.down(ev);
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (bottomMenuListViewTouchEvent != null) {
|
||||
bottomMenuListViewTouchEvent.move(ev);
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (bottomMenuListViewTouchEvent != null) {
|
||||
bottomMenuListViewTouchEvent.up(ev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return super.dispatchTouchEvent(ev);
|
||||
}
|
||||
|
||||
public BottomMenuListViewTouchEvent getBottomMenuListViewTouchEvent() {
|
||||
return bottomMenuListViewTouchEvent;
|
||||
}
|
||||
|
||||
public DialogListView setBottomMenuListViewTouchEvent(BottomMenuListViewTouchEvent bottomMenuListViewTouchEvent) {
|
||||
this.bottomMenuListViewTouchEvent = bottomMenuListViewTouchEvent;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollDistance() {
|
||||
View c = getChildAt(0);
|
||||
if (c == null) {
|
||||
return 0;
|
||||
}
|
||||
int firstVisiblePosition = getFirstVisiblePosition();
|
||||
int top = c.getTop();
|
||||
int scrollY = -top + firstVisiblePosition * c.getHeight();
|
||||
return scrollY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCanScroll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean lockScroll;
|
||||
|
||||
@Override
|
||||
public void lockScroll(boolean lockScroll) {
|
||||
this.lockScroll = lockScroll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (lockScroll) return false;
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLockScroll() {
|
||||
return lockScroll;
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package com.kongzue.dialogx.util.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.ScrollView;
|
||||
import com.kongzue.dialogx.interfaces.ScrollController;
|
||||
|
||||
/**
|
||||
* @author: Kongzue
|
||||
* @github: https://github.com/kongzue/
|
||||
* @homepage: http://kongzue.com/
|
||||
* @mail: myzcxhh@live.cn
|
||||
* @createTime: 2020/11/17 15:29
|
||||
*/
|
||||
public class DialogScrollView extends ScrollView implements ScrollController {
|
||||
|
||||
public DialogScrollView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public DialogScrollView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public DialogScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public DialogScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
boolean lockScroll;
|
||||
|
||||
@Override
|
||||
public boolean isLockScroll() {
|
||||
return lockScroll;
|
||||
}
|
||||
|
||||
public void lockScroll(boolean lockScroll) {
|
||||
this.lockScroll = lockScroll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollDistance() {
|
||||
return getScrollY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCanScroll() {
|
||||
View child = getChildAt(0);
|
||||
if (child != null) {
|
||||
int childHeight = child.getHeight();
|
||||
return getHeight() < childHeight;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@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,484 @@
|
||||
package com.kongzue.dialogx.util.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.annotation.Px;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import com.kongzue.dialogx.DialogX;
|
||||
import com.kongzue.dialogx.R;
|
||||
import com.kongzue.dialogx.interfaces.BaseDialog;
|
||||
import com.kongzue.dialogx.interfaces.DialogXBaseBottomDialog;
|
||||
import com.kongzue.dialogx.interfaces.DialogXSafetyModeInterface;
|
||||
import com.kongzue.dialogx.interfaces.NoTouchInterface;
|
||||
import com.kongzue.dialogx.interfaces.OnSafeInsetsChangeListener;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* @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 {
|
||||
|
||||
public static boolean debugMode = false;
|
||||
|
||||
private OnSafeInsetsChangeListener onSafeInsetsChangeListener;
|
||||
private WeakReference<BaseDialog> parentDialog;
|
||||
private boolean autoUnsafePlacePadding = true;
|
||||
private boolean focusable = true;
|
||||
private boolean interceptBack = true;
|
||||
|
||||
private OnLifecycleCallBack onLifecycleCallBack;
|
||||
private PrivateBackPressedListener onBackPressedListener;
|
||||
|
||||
private FitSystemBarUtils fitSystemBarUtils;
|
||||
|
||||
public FitSystemBarUtils getFitSystemBarUtils() {
|
||||
return fitSystemBarUtils;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
autoUnsafePlacePadding = a.getBoolean(R.styleable.DialogXBaseRelativeLayout_autoSafeArea, true);
|
||||
interceptBack = a.getBoolean(R.styleable.DialogXBaseRelativeLayout_interceptBack, true);
|
||||
a.recycle();
|
||||
isInited = true;
|
||||
}
|
||||
if (focusable) {
|
||||
setFocusable(true);
|
||||
setFocusableInTouchMode(true);
|
||||
}
|
||||
setBkgAlpha(0f);
|
||||
if (getParentDialog() != null && getParentDialog().getDialogImplMode() != DialogX.IMPL_MODE.VIEW) {
|
||||
setFitsSystemWindows(true);
|
||||
}
|
||||
setClipChildren(false);
|
||||
setClipToPadding(false);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
setDefaultFocusHighlightEnabled(false);
|
||||
}
|
||||
|
||||
//新增的 设置监听 OnApplyWindowInsetsListener
|
||||
log("KONGZUE DEBUG DIALOGX: create fitSystemBarUtils");
|
||||
fitSystemBarUtils = FitSystemBarUtils.attachView(this, new FitSystemBarUtils.CallBack() {
|
||||
@Override
|
||||
public boolean isEnable(FitSystemBarUtils.Orientation orientation) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsafeRect(int start, int top, int end, int bottom) {
|
||||
log("KONGZUE DEBUG DIALOGX: unsafeRect t=" + top + " b=" + bottom);
|
||||
if (unsafePlace == null) {
|
||||
unsafePlace = new Rect();
|
||||
}
|
||||
// TODO Fix bug #370 在这里对这个重新做下处理,未详细测试,比如键盘弹起时的情况
|
||||
Insets systemBarInsets = null;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && getRootWindowInsets() != null) {
|
||||
WindowInsetsCompat windowInsetsCompat = WindowInsetsCompat.toWindowInsetsCompat(getRootWindowInsets());
|
||||
boolean navigationBarsVisible = windowInsetsCompat.isVisible(WindowInsetsCompat.Type.navigationBars());
|
||||
boolean imeVisible = windowInsetsCompat.isVisible(WindowInsetsCompat.Type.ime());
|
||||
if (!imeVisible && navigationBarsVisible) {
|
||||
systemBarInsets = windowInsetsCompat.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
if (systemBarInsets.bottom == bottom && systemBarInsets.top == top && systemBarInsets.left == start && systemBarInsets.right == end) {
|
||||
systemBarInsets = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (systemBarInsets != null) {
|
||||
unsafePlace.left = Math.max(systemBarInsets.left, start);
|
||||
unsafePlace.top = Math.max(systemBarInsets.top, top);
|
||||
unsafePlace.right = Math.max(systemBarInsets.right, end);
|
||||
unsafePlace.bottom = Math.max(systemBarInsets.bottom, bottom);
|
||||
} else {
|
||||
unsafePlace.left = start;
|
||||
unsafePlace.top = top;
|
||||
unsafePlace.right = end;
|
||||
unsafePlace.bottom = bottom;
|
||||
}
|
||||
|
||||
if (onSafeInsetsChangeListener != null) {
|
||||
onSafeInsetsChangeListener.onChange(unsafePlace);
|
||||
}
|
||||
|
||||
setUnsafePadding(unsafePlace.left, unsafePlace.top, unsafePlace.right, unsafePlace.bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int initialPadding(FitSystemBarUtils.Orientation orientation) {
|
||||
switch (orientation) {
|
||||
case Start:
|
||||
return extraPadding[0];
|
||||
case Top:
|
||||
return extraPadding[1];
|
||||
case End:
|
||||
return extraPadding[2];
|
||||
case Bottom:
|
||||
return extraPadding[3];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setUnsafePadding(@Px int start, @Px int top, @Px int end, @Px int bottom) {
|
||||
log("KONGZUE DEBUG DIALOGX: setUnsafePadding=" + getParentDialog() + " t=" + top + " b=" + bottom);
|
||||
if (DialogX.ignoreUnsafeInsetsHorizontal) {
|
||||
log(" KONGZUE DEBUG DIALOGX: ignoreUnsafeInsetsHorizontal, start and end set 0");
|
||||
start = 0;
|
||||
end = 0;
|
||||
}
|
||||
if (isAlignBottomDialog(getParentDialog())) {
|
||||
log(" KONGZUE DEBUG DIALOGX: Dialog is align bottom");
|
||||
View dialogXSafetyArea = findViewWithTag("DialogXSafetyArea");
|
||||
if (dialogXSafetyArea instanceof DialogXSafetyModeInterface) {
|
||||
int dialogxSafetyMode = ((DialogXSafetyModeInterface) dialogXSafetyArea).getDialogXSafetyMode();
|
||||
boolean hasTop = (dialogxSafetyMode & 0x1) != 0;
|
||||
boolean hasLeft = (dialogxSafetyMode & 0x2) != 0;
|
||||
boolean hasBottom = (dialogxSafetyMode & 0x4) != 0;
|
||||
boolean hasRight = (dialogxSafetyMode & 0x8) != 0;
|
||||
log(" KONGZUE DEBUG DIALOGX: dialogXSafetyArea" + dialogXSafetyArea + " hasLeft=" + hasLeft + "hasTop=" + hasTop + " hasRight=" + hasRight + " hasBottom=" + hasBottom);
|
||||
dialogXSafetyArea.setPadding(hasLeft ? start : 0, hasTop ? top : 0, hasRight ? end : 0, hasBottom ? bottom : 0);
|
||||
if (hasTop) {
|
||||
top = 0;
|
||||
}
|
||||
if (hasLeft) {
|
||||
start = 0;
|
||||
}
|
||||
if (hasRight) {
|
||||
end = 0;
|
||||
}
|
||||
if (hasBottom) {
|
||||
bottom = 0;
|
||||
}
|
||||
} else {
|
||||
ViewGroup bkgView = findViewById(R.id.bkg);
|
||||
if (!((DialogXBaseBottomDialog) getParentDialog()).isBottomNonSafetyAreaBySelf() && bkgView != null) {
|
||||
log(" KONGZUE DEBUG DIALOGX: bkgView.setPadding b=" + bottom);
|
||||
bkgView.setPadding(0, 0, 0, bottom);
|
||||
}
|
||||
bottom = 0;
|
||||
}
|
||||
}
|
||||
if (isAutoUnsafePlacePadding()) {
|
||||
log(" KONGZUE DEBUG DIALOGX: root.setPadding t=" + top + " b=" + bottom);
|
||||
setPadding(start, top, end, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAlignBottomDialog(BaseDialog parentDialog) {
|
||||
return getParentDialog() instanceof DialogXBaseBottomDialog || findViewWithTag("DialogXSafetyArea") instanceof DialogXSafetyModeInterface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
log("#dispatchKeyEvent: KeyCode=" + event.getKeyCode());
|
||||
if (isAttachedToWindow() && event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode() == KeyEvent.KEYCODE_BACK && interceptBack) {
|
||||
if (onBackPressedListener != null && !parentDialog.get().isHide()) {
|
||||
return onBackPressedListener.onBackPressed();
|
||||
}
|
||||
}
|
||||
return super.dispatchKeyEvent(event);
|
||||
}
|
||||
|
||||
boolean touch;
|
||||
float touchDownX, touchDownY;
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
touch = true;
|
||||
touchDownX = event.getX();
|
||||
touchDownY = event.getY();
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (touch && findFocus() != this && getParentDialog() != null) {
|
||||
float deltaTouchOffset = getParentDialog().dip2px(5);
|
||||
if (Math.abs(event.getX() - touchDownX) <= deltaTouchOffset && Math.abs(event.getY() - touchDownY) <= deltaTouchOffset) {
|
||||
callOnClick();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (getParentDialog() instanceof NoTouchInterface) {
|
||||
return super.onTouchEvent(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();
|
||||
if (!isInEditMode()) {
|
||||
if (getParentDialog() == null || getParentDialog().getOwnActivity() == null) return;
|
||||
if (onLifecycleCallBack != null) {
|
||||
onLifecycleCallBack.onShow();
|
||||
}
|
||||
isLightMode = (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_NO;
|
||||
if (focusable) {
|
||||
requestFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
if (onLifecycleCallBack != null) {
|
||||
onLifecycleCallBack.onDismiss();
|
||||
}
|
||||
if (fitSystemBarUtils != null) {
|
||||
fitSystemBarUtils.recycle();
|
||||
}
|
||||
fitSystemBarUtils = null;
|
||||
onSafeInsetsChangeListener = null;
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performClick() {
|
||||
if (!isEnabled()) return false;
|
||||
return super.performClick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean callOnClick() {
|
||||
if (!isEnabled()) return false;
|
||||
return super.callOnClick();
|
||||
}
|
||||
|
||||
public DialogXBaseRelativeLayout setOnLifecycleCallBack(OnLifecycleCallBack onLifecycleCallBack) {
|
||||
this.onLifecycleCallBack = onLifecycleCallBack;
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getSafeHeight() {
|
||||
return getMeasuredHeight() - unsafePlace.bottom - unsafePlace.top;
|
||||
}
|
||||
|
||||
private WeakReference<View> requestFocusView;
|
||||
|
||||
public void bindFocusView(View view) {
|
||||
if (view != this) {
|
||||
requestFocusView = new WeakReference<>(view);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
|
||||
if (getParentDialog() != null && getParentDialog() instanceof NoTouchInterface) {
|
||||
return false;
|
||||
}
|
||||
if (direction == View.FOCUS_DOWN && requestFocusView != null && requestFocusView.get() != null && requestFocusView.get() != this) {
|
||||
return requestFocusView.get().requestFocus();
|
||||
}
|
||||
View findFocusView = findFocus();
|
||||
if (findFocusView != null && findFocusView != this) {
|
||||
findFocusView.requestFocus();
|
||||
return true;
|
||||
}
|
||||
return super.requestFocus(direction, previouslyFocusedRect);
|
||||
}
|
||||
|
||||
public void requestFocusOnResume() {
|
||||
View findFocusView = findFocus();
|
||||
if (findFocusView != null && findFocusView != this) {
|
||||
findFocusView.requestFocus();
|
||||
return;
|
||||
}
|
||||
requestFocus();
|
||||
}
|
||||
|
||||
public abstract static class OnLifecycleCallBack {
|
||||
public void onShow() {
|
||||
}
|
||||
|
||||
public abstract void onDismiss();
|
||||
}
|
||||
|
||||
protected Rect unsafePlace = new Rect();
|
||||
|
||||
public DialogXBaseRelativeLayout setOnBackPressedListener(PrivateBackPressedListener 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 Rect getUnsafePlace() {
|
||||
return unsafePlace;
|
||||
}
|
||||
|
||||
public DialogXBaseRelativeLayout setAutoUnsafePlacePadding(boolean autoUnsafePlacePadding) {
|
||||
this.autoUnsafePlacePadding = autoUnsafePlacePadding;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BaseDialog getParentDialog() {
|
||||
return parentDialog == null ? null : parentDialog.get();
|
||||
}
|
||||
|
||||
public DialogXBaseRelativeLayout setParentDialog(BaseDialog parentDialog) {
|
||||
this.parentDialog = new WeakReference<>(parentDialog);
|
||||
if (parentDialog != null && parentDialog.getDialogImplMode() != DialogX.IMPL_MODE.VIEW) {
|
||||
setFitsSystemWindows(true);
|
||||
}
|
||||
if (unsafePlace != null) {
|
||||
log("KONGZUE DEBUG DIALOGX: setParentDialog()=" + getParentDialog());
|
||||
setUnsafePadding(unsafePlace.left, unsafePlace.top, unsafePlace.right, unsafePlace.bottom);
|
||||
} else {
|
||||
log("KONGZUE DEBUG DIALOGX: setParentDialog() unsafePlace is null");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
boolean isLightMode = true;
|
||||
|
||||
@Override
|
||||
protected void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
boolean newLightStatus = ((newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_NO);
|
||||
if (isLightMode != newLightStatus && DialogX.globalTheme == DialogX.THEME.AUTO && getParentDialog() != null) {
|
||||
getParentDialog().restartDialog();
|
||||
}
|
||||
}
|
||||
|
||||
float nowBkgAlphaValue;
|
||||
|
||||
public DialogXBaseRelativeLayout setBkgAlpha(float alpha) {
|
||||
nowBkgAlphaValue = alpha;
|
||||
if (getBackground() != null) getBackground().mutate().setAlpha((int) (alpha * 255));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackground(Drawable background) {
|
||||
background.setAlpha((int) (nowBkgAlphaValue * 255));
|
||||
super.setBackground(background);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundColor(int color) {
|
||||
setBackground(new ColorDrawable(color));
|
||||
}
|
||||
|
||||
public boolean isBaseFocusable() {
|
||||
return focusable;
|
||||
}
|
||||
|
||||
public boolean isInterceptBack() {
|
||||
return interceptBack;
|
||||
}
|
||||
|
||||
public DialogXBaseRelativeLayout setInterceptBack(boolean interceptBack) {
|
||||
this.interceptBack = interceptBack;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisibility(int visibility) {
|
||||
if (visibility == GONE && getAlpha() == 0f) {
|
||||
setAlpha(0.01f);
|
||||
}
|
||||
super.setVisibility(visibility);
|
||||
}
|
||||
|
||||
public interface PrivateBackPressedListener {
|
||||
boolean onBackPressed();
|
||||
}
|
||||
|
||||
int[] extraPadding = new int[4];
|
||||
|
||||
public void setRootPadding(int left, int top, int right, int bottom) {
|
||||
extraPadding[0] = left;
|
||||
extraPadding[1] = top;
|
||||
extraPadding[2] = right;
|
||||
extraPadding[3] = bottom;
|
||||
}
|
||||
|
||||
public int getRootPaddingLeft() {
|
||||
return extraPadding[0];
|
||||
}
|
||||
|
||||
public int getRootPaddingTop() {
|
||||
return extraPadding[1];
|
||||
}
|
||||
|
||||
public int getRootPaddingRight() {
|
||||
return extraPadding[2];
|
||||
}
|
||||
|
||||
public int getRootPaddingBottom() {
|
||||
return extraPadding[3];
|
||||
}
|
||||
|
||||
public int getUseAreaWidth() {
|
||||
return getWidth() - getRootPaddingRight();
|
||||
}
|
||||
|
||||
public int getUseAreaHeight() {
|
||||
return getHeight() - getRootPaddingBottom();
|
||||
}
|
||||
|
||||
protected void log(String s) {
|
||||
if (debugMode && DialogX.DEBUGMODE) {
|
||||
Log.e(">>>", s);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.kongzue.dialogx.util.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class ExtendChildLayoutParamsFrameLayout extends FrameLayout {
|
||||
public ExtendChildLayoutParamsFrameLayout(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public ExtendChildLayoutParamsFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public ExtendChildLayoutParamsFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addView(View child, int index, ViewGroup.LayoutParams params) {
|
||||
setLayoutParams(new RelativeLayout.LayoutParams(params.width, params.height));
|
||||
super.addView(child, index, params);
|
||||
}
|
||||
}
|
@ -0,0 +1,637 @@
|
||||
package com.kongzue.dialogx.util.views;
|
||||
|
||||
import static androidx.core.view.WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowInsetsController;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.DisplayCutoutCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsAnimationCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import com.kongzue.dialogx.DialogX;
|
||||
import com.kongzue.dialogx.interfaces.BaseDialog;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FitSystemBarUtils {
|
||||
|
||||
//当前是否正在平滑填充中
|
||||
private boolean inSmoothingPadding = false;
|
||||
|
||||
public boolean isInSmoothingPadding() {
|
||||
return inSmoothingPadding;
|
||||
}
|
||||
|
||||
//是否需要处理挖孔屏,刘海屏
|
||||
public boolean safeCutOutPadding = true;
|
||||
|
||||
//是否需要平滑填充,仅在android R及以上生效,默认开启
|
||||
public boolean smoothPadding = true;
|
||||
|
||||
private View contentView;
|
||||
|
||||
private CallBack callBack;
|
||||
|
||||
private BaseDialog dialog;
|
||||
|
||||
/**
|
||||
* 绑定到View
|
||||
*
|
||||
* @param view 指定View
|
||||
*/
|
||||
public static FitSystemBarUtils attachView(View view) {
|
||||
return attachView(view, new CallBack() {
|
||||
@Override
|
||||
public boolean isEnable(Orientation orientation) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsafeRect(int start, int top, int end, int bottom) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int initialPadding(Orientation orientation) {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定到View
|
||||
*
|
||||
* @param view 指定View
|
||||
* @param callBack 用于判断是否需要某条边的padding,会非常频繁的调用,所以不要在里面做需要耗时的操作,以免卡UI线程
|
||||
*/
|
||||
public static FitSystemBarUtils attachView(View view, CallBack callBack) {
|
||||
return new FitSystemBarUtils(view, callBack);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 绑定到View
|
||||
*
|
||||
* @param view 指定View
|
||||
* @param start 是否需要paddingStart
|
||||
* @param top 是否需要paddingTop
|
||||
* @param end 是否需要paddingEnd
|
||||
* @param bottom 是否需要paddingBottom
|
||||
*/
|
||||
public static FitSystemBarUtils attachView(
|
||||
View view,
|
||||
boolean start,
|
||||
boolean top,
|
||||
boolean end,
|
||||
boolean bottom
|
||||
) {
|
||||
return attachView(view, new CallBack() {
|
||||
@Override
|
||||
public boolean isEnable(Orientation orientation) {
|
||||
switch (orientation) {
|
||||
case Start:
|
||||
return start;
|
||||
case Top:
|
||||
return top;
|
||||
case End:
|
||||
return end;
|
||||
case Bottom:
|
||||
return bottom;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsafeRect(int start, int top, int end, int bottom) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int initialPadding(Orientation orientation) {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private FitSystemBarUtils() {
|
||||
}
|
||||
|
||||
public FitSystemBarUtils(View view, CallBack callBack) {
|
||||
// view.setFitsSystemWindows(true);
|
||||
contentView = view;
|
||||
this.callBack = callBack;
|
||||
if (view instanceof DialogXBaseRelativeLayout) {
|
||||
dialog = ((DialogXBaseRelativeLayout) view).getParentDialog();
|
||||
}
|
||||
applyWindowInsets();
|
||||
}
|
||||
|
||||
View.OnLayoutChangeListener rootViewLayoutChangeListener;
|
||||
|
||||
public void applyWindowInsets() {
|
||||
// view.fitsSystemWindows = true
|
||||
//创建原始padding的快照
|
||||
RelativePadding initialPadding = new RelativePadding(
|
||||
ViewCompat.getPaddingStart(contentView),
|
||||
contentView.getPaddingTop(),
|
||||
ViewCompat.getPaddingEnd(contentView),
|
||||
contentView.getPaddingBottom()
|
||||
);
|
||||
//不带平滑变化的
|
||||
ViewCompat.setOnApplyWindowInsetsListener(contentView, (view, insets) -> {
|
||||
if (inSmoothingPadding) return insets;
|
||||
formatInsets(insets, new RelativePadding(initialPadding));
|
||||
return insets;
|
||||
});
|
||||
//带平滑变化的,但是支支持android R及以上
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
log("FitSystemBarUtils: setWindowInsetsAnimationCallback");
|
||||
ViewCompat.setWindowInsetsAnimationCallback(contentView,
|
||||
new WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_CONTINUE_ON_SUBTREE) {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public WindowInsetsCompat onProgress(
|
||||
@NonNull WindowInsetsCompat insets,
|
||||
@NonNull List<WindowInsetsAnimationCompat> runningAnimations
|
||||
) {
|
||||
log("FitSystemBarUtils: setWindowInsetsAnimationCallback#onProgress: " + insets);
|
||||
if (smoothPadding) {
|
||||
formatInsets(insets, new RelativePadding(initialPadding));
|
||||
}
|
||||
return insets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnd(@NonNull WindowInsetsAnimationCompat animation) {
|
||||
log("FitSystemBarUtils: setWindowInsetsAnimationCallback#onEnd ");
|
||||
inSmoothingPadding = false;
|
||||
super.onEnd(animation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepare(@NonNull WindowInsetsAnimationCompat animation) {
|
||||
inSmoothingPadding = smoothPadding;
|
||||
super.onPrepare(animation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (ViewCompat.isAttachedToWindow(contentView)) {
|
||||
log("FitSystemBarUtils: AttachedToWindow ok");
|
||||
ViewCompat.requestApplyInsets(contentView);
|
||||
} else {
|
||||
log("FitSystemBarUtils: wait AttachedToWindow");
|
||||
contentView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View view) {
|
||||
view.removeOnAttachStateChangeListener(this);
|
||||
|
||||
log("FitSystemBarUtils: onViewAttachedToWindow");
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH && (Build.VERSION.SDK_INT < Build.VERSION_CODES.R || getAppTargetSDKVersion() < Build.VERSION_CODES.R)) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
//修复<=API29的部分设备上存在的非安全区不回调的问题
|
||||
View parentView = (View) view.getParent();
|
||||
if (rootViewLayoutChangeListener != null) {
|
||||
parentView.removeOnLayoutChangeListener(rootViewLayoutChangeListener);
|
||||
}
|
||||
rootViewLayoutChangeListener = new View.OnLayoutChangeListener() {
|
||||
@Override
|
||||
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
|
||||
WindowInsets windowInsets = v.getRootView().getRootWindowInsets();
|
||||
if (windowInsets != null) {
|
||||
log(" FitSystemBarUtils: RootView get Insets");
|
||||
formatInsets(WindowInsetsCompat.toWindowInsetsCompat(windowInsets), new RelativePadding(initialPadding));
|
||||
} else {
|
||||
log(" FitSystemBarUtils: RootView not get Insets");
|
||||
}
|
||||
}
|
||||
};
|
||||
parentView.addOnLayoutChangeListener(rootViewLayoutChangeListener);
|
||||
parentView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View v) {
|
||||
parentView.removeOnLayoutChangeListener(rootViewLayoutChangeListener);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
View parentView = (View) view.getParent();
|
||||
ViewTreeObserver.OnPreDrawListener preDrawListener = new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
// 获取状态栏高度
|
||||
Rect insets = new Rect();
|
||||
parentView.getWindowVisibleDisplayFrame(insets);
|
||||
int statusBarHeight = insets.top;
|
||||
|
||||
// 获取导航栏高度
|
||||
int navigationBarHeight = 0;
|
||||
Resources resources = parentView.getResources();
|
||||
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
navigationBarHeight = resources.getDimensionPixelSize(resourceId);
|
||||
}
|
||||
|
||||
log("FitSystemBarUtils: below Android M use support mode: statusBarHeight=" + statusBarHeight + ", navigationBarHeight=" + navigationBarHeight);
|
||||
int deviceOrientation = checkOrientationAndStatusBarSide();
|
||||
log(" FitSystemBarUtils: deviceOrientation = " + deviceOrientation);
|
||||
switch (deviceOrientation) {
|
||||
case 1:
|
||||
case -1:
|
||||
initialPadding.end = navigationBarHeight;
|
||||
initialPadding.start = 0;
|
||||
break;
|
||||
default:
|
||||
initialPadding.top = statusBarHeight;
|
||||
initialPadding.bottom = navigationBarHeight;
|
||||
break;
|
||||
}
|
||||
|
||||
applyCallBack(initialPadding);
|
||||
|
||||
parentView.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
parentView.getViewTreeObserver().addOnPreDrawListener(preDrawListener);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ViewCompat.requestApplyInsets(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View view) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
RelativePadding relativePaddingCache;
|
||||
|
||||
/**
|
||||
* 针对不同版本处理Insets
|
||||
*/
|
||||
private void formatInsets(WindowInsetsCompat insetsCompat, RelativePadding initialPadding) {
|
||||
if (contentView == null || insetsCompat == null || initialPadding == null) return;
|
||||
|
||||
relativePaddingCache = initialPadding;
|
||||
int cutoutPaddingLeft = 0;
|
||||
int cutoutPaddingTop = 0;
|
||||
int cutoutPaddingRight = 0;
|
||||
int cutoutPaddingBottom = 0;
|
||||
|
||||
int systemWindowInsetLeft = 0;
|
||||
int systemWindowInsetTop = 0;
|
||||
int systemWindowInsetRight = 0;
|
||||
int systemWindowInsetBottom = 0;
|
||||
|
||||
if (safeCutOutPadding) {
|
||||
DisplayCutoutCompat displayCutout = insetsCompat.getDisplayCutout();
|
||||
if (null != displayCutout) {
|
||||
cutoutPaddingTop = displayCutout.getSafeInsetTop();
|
||||
cutoutPaddingLeft = displayCutout.getSafeInsetLeft();
|
||||
cutoutPaddingRight = displayCutout.getSafeInsetRight();
|
||||
cutoutPaddingBottom = displayCutout.getSafeInsetRight();
|
||||
}
|
||||
}
|
||||
Insets systemBars = insetsCompat.getInsets(
|
||||
WindowInsetsCompat.Type.ime() | WindowInsetsCompat.Type.systemBars()
|
||||
);
|
||||
systemWindowInsetLeft = systemBars.left;
|
||||
systemWindowInsetRight = systemBars.right;
|
||||
|
||||
//对api低于30的设备,做额外判断,api 30+的不需要这个
|
||||
int suv = contentView.getRootView().getWindowSystemUiVisibility();
|
||||
boolean statusBar = true;
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||
statusBar = (suv & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0;
|
||||
}
|
||||
boolean naviBar = true;
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||
naviBar = (suv & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
|
||||
}
|
||||
if (naviBar && (insetsCompat.isVisible(WindowInsetsCompat.Type.ime())
|
||||
|| insetsCompat.isVisible(WindowInsetsCompat.Type.navigationBars()))
|
||||
) {
|
||||
systemWindowInsetBottom = systemBars.bottom;
|
||||
}
|
||||
if (statusBar && insetsCompat.isVisible(WindowInsetsCompat.Type.statusBars())) {
|
||||
systemWindowInsetTop = systemBars.top;
|
||||
}
|
||||
if (isWrongInsets(systemBars)) {
|
||||
log(" FitSystemBarUtils: isWrongInsets try special mode...");
|
||||
int deviceOrientation = checkOrientationAndStatusBarSide();
|
||||
log(" FitSystemBarUtils: deviceOrientation = " + deviceOrientation);
|
||||
switch (deviceOrientation) {
|
||||
case 1:
|
||||
initialPadding.end = getStatusBarHeight();
|
||||
initialPadding.start = getNavigationBarHeight();
|
||||
break;
|
||||
default:
|
||||
initialPadding.top = getStatusBarHeight();
|
||||
initialPadding.bottom = getNavigationBarHeight();
|
||||
break;
|
||||
}
|
||||
addListenerWhenImeHeightChanged();
|
||||
} else {
|
||||
specialMode = false;
|
||||
if (callBack.isEnable(Orientation.Top)) {
|
||||
initialPadding.top += Math.max(systemWindowInsetTop, cutoutPaddingTop);
|
||||
}
|
||||
if (callBack.isEnable(Orientation.Bottom)) {
|
||||
initialPadding.bottom += Math.max(systemWindowInsetBottom, cutoutPaddingBottom);
|
||||
}
|
||||
|
||||
boolean isRtl =
|
||||
ViewCompat.getLayoutDirection(contentView) == ViewCompat.LAYOUT_DIRECTION_RTL;
|
||||
if (callBack.isEnable(Orientation.Start)) {
|
||||
if (isRtl) {
|
||||
initialPadding.start += Math.max(systemWindowInsetRight, cutoutPaddingRight);
|
||||
} else {
|
||||
initialPadding.start += Math.max(systemWindowInsetLeft, cutoutPaddingLeft);
|
||||
}
|
||||
}
|
||||
if (callBack.isEnable(Orientation.End)) {
|
||||
if (isRtl) {
|
||||
initialPadding.end += Math.max(systemWindowInsetLeft, cutoutPaddingLeft);
|
||||
} else {
|
||||
initialPadding.end += Math.max(systemWindowInsetRight, cutoutPaddingRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
applyCallBack(initialPadding);
|
||||
}
|
||||
|
||||
private void applyCallBack() {
|
||||
if (relativePaddingCache != null) {
|
||||
applyCallBack(relativePaddingCache);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyCallBack(RelativePadding initialPadding) {
|
||||
if (callBack == null) {
|
||||
return;
|
||||
}
|
||||
//加上用户自定义的
|
||||
initialPadding.start += callBack.initialPadding(Orientation.Start);
|
||||
initialPadding.top += callBack.initialPadding(Orientation.Top);
|
||||
initialPadding.end += callBack.initialPadding(Orientation.End);
|
||||
initialPadding.bottom += callBack.initialPadding(Orientation.Bottom);
|
||||
|
||||
initialPadding.applyToView(contentView);
|
||||
//四边 非安全区 传递回去
|
||||
log(" KONGZUE DEBUG DIALOGX FitSystemBarUtils callBack: left=" + initialPadding.start + " top=" + initialPadding.top +
|
||||
" right=" + initialPadding.end + " bottom=" + initialPadding.bottom + " specialMode=" + specialMode +
|
||||
" specialModeImeHeight=" + specialModeImeHeight
|
||||
);
|
||||
callBack.unsafeRect(
|
||||
initialPadding.start,
|
||||
initialPadding.top,
|
||||
initialPadding.end,
|
||||
initialPadding.bottom + (specialMode ? specialModeImeHeight : 0)
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isWrongInsets(Insets systemBars) {
|
||||
return systemBars.top == 0 && systemBars.bottom == 0 && systemBars.left == 0 && systemBars.right == 0;
|
||||
}
|
||||
|
||||
public interface CallBack {
|
||||
|
||||
//是否启用指定边的insets
|
||||
boolean isEnable(Orientation orientation);
|
||||
|
||||
//非安全区
|
||||
void unsafeRect(int start, int top, int end, int bottom);
|
||||
|
||||
//用户自定义的padding
|
||||
int initialPadding(Orientation orientation);
|
||||
}
|
||||
|
||||
public static class RelativePadding {
|
||||
int start;
|
||||
int top;
|
||||
int end;
|
||||
int bottom;
|
||||
|
||||
public RelativePadding(int start, int top, int end, int bottom) {
|
||||
this.start = start;
|
||||
this.top = top;
|
||||
this.end = end;
|
||||
this.bottom = bottom;
|
||||
}
|
||||
|
||||
public RelativePadding(RelativePadding other) {
|
||||
start = other.start;
|
||||
top = other.top;
|
||||
end = other.end;
|
||||
bottom = other.bottom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies this relative padding to the view.
|
||||
*/
|
||||
public void applyToView(View view) {
|
||||
if (view instanceof DialogXBaseRelativeLayout) {
|
||||
//((DialogXBaseRelativeLayout) view).setUnsafePadding(start, top, end, bottom);
|
||||
} else {
|
||||
ViewCompat.setPaddingRelative(view, start, top, end, bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Orientation {
|
||||
Start, Top, End, Bottom
|
||||
}
|
||||
|
||||
protected void log(String s) {
|
||||
if (DialogXBaseRelativeLayout.debugMode && DialogX.DEBUGMODE) {
|
||||
Log.e(">>>", s);
|
||||
}
|
||||
}
|
||||
|
||||
private int getStatusBarHeight() {
|
||||
if (isFullScreen() || getDecorView() == null) {
|
||||
return 0;
|
||||
}
|
||||
WindowInsetsController insetsController = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) ? getDecorView().getWindowInsetsController() : null;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && insetsController != null && (insetsController.getSystemBarsBehavior() & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) == 0) {
|
||||
return 0;
|
||||
}
|
||||
Resources res;
|
||||
if (contentView == null || contentView.getContext() == null) {
|
||||
res = Resources.getSystem();
|
||||
} else {
|
||||
res = contentView.getContext().getResources();
|
||||
}
|
||||
int result = 0;
|
||||
int resourceId = res.getIdentifier("status_bar_height", "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
result = res.getDimensionPixelSize(resourceId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int getNavigationBarHeight() {
|
||||
if (isFullScreen() || getDecorView() == null) {
|
||||
return 0;
|
||||
}
|
||||
WindowInsetsController insetsController = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) ? getDecorView().getWindowInsetsController() : null;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && insetsController != null && (insetsController.getSystemBarsBehavior() & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) == 0) {
|
||||
log("getNavigationBarHeight =0");
|
||||
return 0;
|
||||
}
|
||||
Resources res;
|
||||
if (contentView == null || contentView.getContext() == null) {
|
||||
res = Resources.getSystem();
|
||||
} else {
|
||||
res = contentView.getContext().getResources();
|
||||
}
|
||||
int result = 0;
|
||||
int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
result = res.getDimensionPixelSize(resourceId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isFullScreen() {
|
||||
Activity activity = getActivity();
|
||||
if (activity == null) {
|
||||
return false;
|
||||
}
|
||||
// 通过检查窗口标志来判断
|
||||
int flags = activity.getWindow().getAttributes().flags;
|
||||
if ((flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0) {
|
||||
return true;
|
||||
}
|
||||
// 通过检查系统 UI 标志来判断
|
||||
int uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility();
|
||||
if ((uiOptions & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int checkOrientationAndStatusBarSide() {
|
||||
Activity activity = getActivity();
|
||||
if (activity == null) {
|
||||
return 0;
|
||||
}
|
||||
// 判断是否为横屏
|
||||
if (activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
// 判断状态栏位置
|
||||
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
|
||||
switch (rotation) {
|
||||
case Surface.ROTATION_90:
|
||||
// 设备旋转了 90 度,状态栏在左侧
|
||||
return -1;
|
||||
case Surface.ROTATION_270:
|
||||
// 设备旋转了 270 度,状态栏在右侧
|
||||
return 1;
|
||||
default:
|
||||
// 其他情况,不应当发生在横屏状态
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int specialModeImeHeight;
|
||||
private boolean specialMode;
|
||||
private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener;
|
||||
|
||||
private View getDecorView() {
|
||||
Activity activity = getActivity();
|
||||
if (activity == null) {
|
||||
return null;
|
||||
}
|
||||
return activity.getWindow().getDecorView();
|
||||
}
|
||||
|
||||
private void addListenerWhenImeHeightChanged() {
|
||||
specialMode = true;
|
||||
View decorView = getDecorView();
|
||||
if (decorView == null) return;
|
||||
if (onGlobalLayoutListener != null) {
|
||||
decorView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
|
||||
}
|
||||
decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
Rect r = new Rect();
|
||||
decorView.getWindowVisibleDisplayFrame(r);
|
||||
int screenHeight = decorView.getHeight();
|
||||
WindowInsetsController insetsController = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) ? getDecorView().getWindowInsetsController() : null;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && insetsController != null && (insetsController.getSystemBarsBehavior() & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) == 0) {
|
||||
r.bottom = screenHeight;
|
||||
}
|
||||
int keypadHeight = screenHeight - r.bottom;
|
||||
if (keypadHeight != specialModeImeHeight) {
|
||||
specialModeImeHeight = keypadHeight;
|
||||
log(" FitSystemBarUtils: specialModeImeHeight=" + specialModeImeHeight);
|
||||
applyCallBack();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private int getAppTargetSDKVersion() {
|
||||
try {
|
||||
Context context = BaseDialog.getApplicationContext();
|
||||
if (context == null) {
|
||||
return -1;
|
||||
}
|
||||
PackageManager pm = context.getPackageManager();
|
||||
ApplicationInfo applicationInfo = pm.getApplicationInfo(context.getPackageName(), 0);
|
||||
int targetSdkVersion = applicationInfo.targetSdkVersion;
|
||||
return targetSdkVersion;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private Activity getActivity() {
|
||||
if (dialog == null) return BaseDialog.getTopActivity();
|
||||
return dialog.getOwnActivity();
|
||||
}
|
||||
|
||||
public void recycle() {
|
||||
View decorView = getDecorView();
|
||||
if (decorView != null && onGlobalLayoutListener != null) {
|
||||
decorView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
|
||||
}
|
||||
onGlobalLayoutListener = null;
|
||||
callBack = null;
|
||||
contentView = null;
|
||||
dialog = null;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user