|
@@ -0,0 +1,320 @@
|
|
|
|
|
+package com.atmob.elec_asst.base;
|
|
|
|
|
+
|
|
|
|
|
+import android.app.Activity;
|
|
|
|
|
+import android.app.Dialog;
|
|
|
|
|
+import android.content.Context;
|
|
|
|
|
+import android.os.Handler;
|
|
|
|
|
+import android.os.Looper;
|
|
|
|
|
+import android.view.Gravity;
|
|
|
|
|
+import android.view.LayoutInflater;
|
|
|
|
|
+import android.view.View;
|
|
|
|
|
+import android.view.Window;
|
|
|
|
|
+import android.view.WindowManager;
|
|
|
|
|
+
|
|
|
|
|
+import androidx.annotation.CallSuper;
|
|
|
|
|
+import androidx.annotation.IntDef;
|
|
|
|
|
+import androidx.annotation.NonNull;
|
|
|
|
|
+import androidx.annotation.Nullable;
|
|
|
|
|
+import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
|
+import androidx.databinding.ViewDataBinding;
|
|
|
|
|
+import androidx.lifecycle.Lifecycle;
|
|
|
|
|
+import androidx.lifecycle.LifecycleEventObserver;
|
|
|
|
|
+import androidx.lifecycle.LifecycleOwner;
|
|
|
|
|
+import androidx.lifecycle.LifecycleRegistry;
|
|
|
|
|
+import androidx.viewbinding.ViewBinding;
|
|
|
|
|
+
|
|
|
|
|
+import java.lang.annotation.ElementType;
|
|
|
|
|
+import java.lang.annotation.Retention;
|
|
|
|
|
+import java.lang.annotation.RetentionPolicy;
|
|
|
|
|
+import java.lang.annotation.Target;
|
|
|
|
|
+import java.lang.reflect.InvocationTargetException;
|
|
|
|
|
+import java.lang.reflect.Method;
|
|
|
|
|
+import java.lang.reflect.ParameterizedType;
|
|
|
|
|
+
|
|
|
|
|
+public class BaseDialog<T extends ViewBinding> extends Dialog implements Comparable<BaseDialog<T>>,
|
|
|
|
|
+ LifecycleOwner, LifecycleEventObserver {
|
|
|
|
|
+
|
|
|
|
|
+ protected T binding;
|
|
|
|
|
+
|
|
|
|
|
+ private Handler handler;
|
|
|
|
|
+
|
|
|
|
|
+ private int gravity;
|
|
|
|
|
+
|
|
|
|
|
+ private int margin;
|
|
|
|
|
+
|
|
|
|
|
+ private boolean isUseQueue = true;
|
|
|
|
|
+
|
|
|
|
|
+ private LifecycleRegistry lifecycleRegistry;
|
|
|
|
|
+
|
|
|
|
|
+ private Lifecycle ownerActivityLifecycle;
|
|
|
|
|
+
|
|
|
|
|
+ @Retention(RetentionPolicy.SOURCE)
|
|
|
|
|
+ @IntDef({
|
|
|
|
|
+ HIGH_PRIORITY,
|
|
|
|
|
+ DEFAULT_PRIORITY,
|
|
|
|
|
+ LOW_PRIORITY
|
|
|
|
|
+ })
|
|
|
|
|
+ @interface Priority {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ static final int HIGH_PRIORITY = 100;
|
|
|
|
|
+
|
|
|
|
|
+ static final int DEFAULT_PRIORITY = 50;
|
|
|
|
|
+ static final int LOW_PRIORITY = 0;
|
|
|
|
|
+ private OnDismissListener onDismissListener;
|
|
|
|
|
+
|
|
|
|
|
+ private OnShowListener onShowListener;
|
|
|
|
|
+ private boolean widthFullScreen;
|
|
|
|
|
+ private boolean heightFullScreen;
|
|
|
|
|
+
|
|
|
|
|
+ public BaseDialog(@NonNull Context context) {
|
|
|
|
|
+ super(context);
|
|
|
|
|
+ init(context);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public BaseDialog(@NonNull Context context, int themeResId) {
|
|
|
|
|
+ super(context, themeResId);
|
|
|
|
|
+ init(context);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ protected BaseDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) {
|
|
|
|
|
+ super(context, cancelable, cancelListener);
|
|
|
|
|
+ init(context);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void init(Context context) {
|
|
|
|
|
+ handler = new Handler(Looper.getMainLooper());
|
|
|
|
|
+
|
|
|
|
|
+ lifecycleRegistry = new LifecycleRegistry(this);
|
|
|
|
|
+
|
|
|
|
|
+ initBinding();
|
|
|
|
|
+
|
|
|
|
|
+ initDialogParams();
|
|
|
|
|
+
|
|
|
|
|
+ initDialogOwner(context);
|
|
|
|
|
+
|
|
|
|
|
+ initListener();
|
|
|
|
|
+
|
|
|
|
|
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void initDialogOwner(Context context) {
|
|
|
|
|
+ Activity activity = context instanceof Activity ? ((Activity) context) : null;
|
|
|
|
|
+ if (activity != null) {
|
|
|
|
|
+ setOwnerActivity(activity);
|
|
|
|
|
+ }
|
|
|
|
|
+ AppCompatActivity appCompatActivity = activity instanceof AppCompatActivity ? ((AppCompatActivity) activity) : null;
|
|
|
|
|
+ if (appCompatActivity != null) {
|
|
|
|
|
+ ownerActivityLifecycle = appCompatActivity.getLifecycle();
|
|
|
|
|
+ ownerActivityLifecycle.addObserver(this);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void initListener() {
|
|
|
|
|
+ super.setOnDismissListener(dialog -> {
|
|
|
|
|
+ if (lifecycleRegistry.getCurrentState() != Lifecycle.State.DESTROYED) {
|
|
|
|
|
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (onDismissListener != null) {
|
|
|
|
|
+ onDismissListener.onDismiss(dialog);
|
|
|
|
|
+ }
|
|
|
|
|
+ onDismiss();
|
|
|
|
|
+ if (useQueue()) {
|
|
|
|
|
+ DialogQueue.nextDialog();
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ super.setOnShowListener(dialog -> {
|
|
|
|
|
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
|
|
|
|
|
+ if (onShowListener != null) {
|
|
|
|
|
+ onShowListener.onShow(dialog);
|
|
|
|
|
+ }
|
|
|
|
|
+ onShow();
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void initDialogParams() {
|
|
|
|
|
+ Class<? extends BaseDialog> aClass = this.getClass();
|
|
|
|
|
+ FullScreen annotation = aClass.getAnnotation(FullScreen.class);
|
|
|
|
|
+ if (annotation != null) {
|
|
|
|
|
+ widthFullScreen = annotation.width();
|
|
|
|
|
+ heightFullScreen = annotation.height();
|
|
|
|
|
+ gravity = annotation.gravity();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void initBinding() {
|
|
|
|
|
+ ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
|
|
|
|
|
+ if (type == null) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ Class<? extends ViewBinding> bindingClass = (Class<? extends ViewBinding>) type.getActualTypeArguments()[0];
|
|
|
|
|
+ try {
|
|
|
|
|
+ Method inflate = bindingClass.getMethod("inflate", LayoutInflater.class);
|
|
|
|
|
+ binding = (T) inflate.invoke(null, getLayoutInflater());
|
|
|
|
|
+ } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ }
|
|
|
|
|
+ ViewDataBinding viewDataBinding = binding instanceof ViewDataBinding ? ((ViewDataBinding) binding) : null;
|
|
|
|
|
+ if (viewDataBinding != null) {
|
|
|
|
|
+ viewDataBinding.setLifecycleOwner(this);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (binding != null) {
|
|
|
|
|
+ setContentView(binding.getRoot());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void setMargin(int margin) {
|
|
|
|
|
+ this.margin = margin;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ protected void onShow() {
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ protected void onDismiss() {
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void setOnDismissListener(@Nullable OnDismissListener listener) {
|
|
|
|
|
+ onDismissListener = listener;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void setOnShowListener(@Nullable OnShowListener listener) {
|
|
|
|
|
+ onShowListener = listener;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ @CallSuper
|
|
|
|
|
+ public void show() {
|
|
|
|
|
+ if (useQueue()) {
|
|
|
|
|
+ DialogQueue.requestShow(this);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ showInternal();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void showInternal() {
|
|
|
|
|
+ if (couldShow()) {
|
|
|
|
|
+ super.show();
|
|
|
|
|
+ Window window = getWindow();
|
|
|
|
|
+ WindowManager.LayoutParams attributes = window.getAttributes();
|
|
|
|
|
+ attributes.height = heightFullScreen ? WindowManager.LayoutParams.MATCH_PARENT : WindowManager.LayoutParams.WRAP_CONTENT;
|
|
|
|
|
+ attributes.width = widthFullScreen ? WindowManager.LayoutParams.MATCH_PARENT : WindowManager.LayoutParams.WRAP_CONTENT;
|
|
|
|
|
+ attributes.gravity = gravity;
|
|
|
|
|
+ //todo 暂时只处理TOP的margin,bottom待添加
|
|
|
|
|
+ if (gravity == Gravity.TOP) {
|
|
|
|
|
+ attributes.y = margin;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ window.setAttributes(attributes);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if (useQueue()) {
|
|
|
|
|
+ DialogQueue.nextDialog();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean couldShow() {
|
|
|
|
|
+ if (isShowing()) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (getOwnerActivity() != null) {
|
|
|
|
|
+ return !getOwnerActivity().isDestroyed() && !getOwnerActivity().isFinishing();
|
|
|
|
|
+ }
|
|
|
|
|
+ Context context = getContext();
|
|
|
|
|
+ if (context instanceof Activity) {
|
|
|
|
|
+ Activity activity = (Activity) context;
|
|
|
|
|
+ return !activity.isDestroyed() && !activity.isFinishing();
|
|
|
|
|
+ }
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ @CallSuper
|
|
|
|
|
+ public void dismiss() {
|
|
|
|
|
+ handler.post(() -> {
|
|
|
|
|
+ if (isShowing() && isDecorViewAttach()) {
|
|
|
|
|
+ super.dismiss();
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean isDecorViewAttach() {
|
|
|
|
|
+ Window window = getWindow();
|
|
|
|
|
+ if (window == null) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ View decorView = window.getDecorView();
|
|
|
|
|
+ if (decorView == null) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ return decorView.isAttachedToWindow();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int compareTo(BaseDialog other) {
|
|
|
|
|
+ if (other == null) {
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (getPriority() == other.getPriority()) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ return getPriority() < other.getPriority() ? 1 : -1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Priority
|
|
|
|
|
+ protected int getPriority() {
|
|
|
|
|
+ return DEFAULT_PRIORITY;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ protected boolean useQueue() {
|
|
|
|
|
+ return isUseQueue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void setUseQueue(boolean isUseQueue) {
|
|
|
|
|
+ this.isUseQueue = isUseQueue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ @NonNull
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public Lifecycle getLifecycle() {
|
|
|
|
|
+ return lifecycleRegistry;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
|
|
|
|
|
+ if (event == Lifecycle.Event.ON_DESTROY) {
|
|
|
|
|
+ if (ownerActivityLifecycle != null) {
|
|
|
|
|
+ ownerActivityLifecycle.removeObserver(this);
|
|
|
|
|
+ }
|
|
|
|
|
+ dismiss();
|
|
|
|
|
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!isShowing()) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (event == Lifecycle.Event.ON_RESUME) {
|
|
|
|
|
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
|
|
|
|
|
+ } else if (event == Lifecycle.Event.ON_PAUSE) {
|
|
|
|
|
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
|
|
|
|
|
+ } else if (event == Lifecycle.Event.ON_START) {
|
|
|
|
|
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
|
|
|
|
|
+ } else if (event == Lifecycle.Event.ON_STOP) {
|
|
|
|
|
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Target(ElementType.TYPE)
|
|
|
|
|
+ @Retention(RetentionPolicy.RUNTIME)
|
|
|
|
|
+ public @interface FullScreen {
|
|
|
|
|
+ boolean width() default true;
|
|
|
|
|
+
|
|
|
|
|
+ boolean height() default true;
|
|
|
|
|
+
|
|
|
|
|
+ int gravity() default Gravity.CENTER;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+}
|