FullScreenDialog.java 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. package com.kongzue.dialogx.dialogs;
  2. import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
  3. import android.animation.ObjectAnimator;
  4. import android.animation.ValueAnimator;
  5. import android.app.Activity;
  6. import android.graphics.Outline;
  7. import android.graphics.Rect;
  8. import android.graphics.drawable.GradientDrawable;
  9. import android.os.Build;
  10. import android.view.RoundedCorner;
  11. import android.view.View;
  12. import android.view.ViewGroup;
  13. import android.view.ViewOutlineProvider;
  14. import android.view.WindowInsets;
  15. import android.view.animation.DecelerateInterpolator;
  16. import android.widget.RelativeLayout;
  17. import androidx.annotation.ColorInt;
  18. import androidx.annotation.ColorRes;
  19. import androidx.lifecycle.Lifecycle;
  20. import com.kongzue.dialogx.DialogX;
  21. import com.kongzue.dialogx.R;
  22. import com.kongzue.dialogx.interfaces.BaseDialog;
  23. import com.kongzue.dialogx.interfaces.DialogConvertViewInterface;
  24. import com.kongzue.dialogx.interfaces.DialogLifecycleCallback;
  25. import com.kongzue.dialogx.interfaces.DialogXAnimInterface;
  26. import com.kongzue.dialogx.interfaces.DialogXBaseBottomDialog;
  27. import com.kongzue.dialogx.interfaces.DialogXRunnable;
  28. import com.kongzue.dialogx.interfaces.DialogXStyle;
  29. import com.kongzue.dialogx.interfaces.OnBackPressedListener;
  30. import com.kongzue.dialogx.interfaces.OnBackgroundMaskClickListener;
  31. import com.kongzue.dialogx.interfaces.OnBindView;
  32. import com.kongzue.dialogx.interfaces.OnSafeInsetsChangeListener;
  33. import com.kongzue.dialogx.interfaces.ScrollController;
  34. import com.kongzue.dialogx.util.FullScreenDialogTouchEventInterceptor;
  35. import com.kongzue.dialogx.util.views.ActivityScreenShotImageView;
  36. import com.kongzue.dialogx.util.views.DialogXBaseRelativeLayout;
  37. import com.kongzue.dialogx.util.views.MaxRelativeLayout;
  38. import java.lang.reflect.Method;
  39. import java.util.HashMap;
  40. /**
  41. * @author: Kongzue
  42. * @github: https://github.com/kongzue/
  43. * @homepage: http://kongzue.com/
  44. * @mail: myzcxhh@live.cn
  45. * @createTime: 2020/10/6 15:17
  46. */
  47. public class FullScreenDialog extends BaseDialog implements DialogXBaseBottomDialog {
  48. public static final int ACTIVITY_CONTENT_RADIUS_KEEP = -2;
  49. public static final int ACTIVITY_CONTENT_RADIUS_DEFAULT = -1;
  50. public static int overrideEnterDuration = -1;
  51. public static int overrideExitDuration = -1;
  52. public static BOOLEAN overrideCancelable;
  53. protected OnBindView<FullScreenDialog> onBindView;
  54. protected OnBackPressedListener<FullScreenDialog> onBackPressedListener;
  55. protected BOOLEAN privateCancelable;
  56. protected boolean hideZoomBackground;
  57. protected float backgroundRadius = DialogX.defaultFullScreenDialogBackgroundRadius;
  58. protected float activityContentRadius = ACTIVITY_CONTENT_RADIUS_DEFAULT;
  59. protected boolean allowInterceptTouch = true;
  60. protected DialogXAnimInterface<FullScreenDialog> dialogXAnimImpl;
  61. protected boolean bottomNonSafetyAreaBySelf = false;
  62. protected boolean hideActivityContentView;
  63. protected Integer maskColor = null;
  64. protected DialogLifecycleCallback<FullScreenDialog> dialogLifecycleCallback;
  65. protected OnBackgroundMaskClickListener<FullScreenDialog> onBackgroundMaskClickListener;
  66. protected FullScreenDialog me = this;
  67. protected FullScreenDialog() {
  68. super();
  69. }
  70. public static FullScreenDialog build() {
  71. return new FullScreenDialog();
  72. }
  73. public static FullScreenDialog build(OnBindView<FullScreenDialog> onBindView) {
  74. return new FullScreenDialog(onBindView);
  75. }
  76. public FullScreenDialog(OnBindView<FullScreenDialog> onBindView) {
  77. this.onBindView = onBindView;
  78. }
  79. public static FullScreenDialog show(OnBindView<FullScreenDialog> onBindView) {
  80. FullScreenDialog FullScreenDialog = new FullScreenDialog(onBindView);
  81. FullScreenDialog.show();
  82. return FullScreenDialog;
  83. }
  84. public FullScreenDialog show() {
  85. if (isHide && getDialogView() != null && isShow) {
  86. if (hideWithExitAnim && getDialogImpl() != null) {
  87. getDialogView().setVisibility(View.VISIBLE);
  88. getDialogImpl().getDialogXAnimImpl().doShowAnim(me, getDialogImpl().bkg);
  89. } else {
  90. getDialogView().setVisibility(View.VISIBLE);
  91. }
  92. return this;
  93. }
  94. super.beforeShow();
  95. if (getDialogView() == null) {
  96. View dialogView = createView(isLightTheme() ? R.layout.layout_dialogx_fullscreen : R.layout.layout_dialogx_fullscreen_dark);
  97. dialogImpl = new DialogImpl(dialogView);
  98. if (dialogView != null) dialogView.setTag(me);
  99. show(dialogView);
  100. } else {
  101. show(getDialogView());
  102. }
  103. return this;
  104. }
  105. public void show(Activity activity) {
  106. super.beforeShow();
  107. if (getDialogView() == null) {
  108. View dialogView = createView(isLightTheme() ? R.layout.layout_dialogx_fullscreen : R.layout.layout_dialogx_fullscreen_dark);
  109. dialogImpl = new DialogImpl(dialogView);
  110. if (dialogView != null) dialogView.setTag(me);
  111. show(activity, dialogView);
  112. } else {
  113. show(activity, getDialogView());
  114. }
  115. }
  116. protected DialogImpl dialogImpl;
  117. public class DialogImpl implements DialogConvertViewInterface {
  118. private FullScreenDialogTouchEventInterceptor fullScreenDialogTouchEventInterceptor;
  119. public ActivityScreenShotImageView imgZoomActivity;
  120. public DialogXBaseRelativeLayout boxRoot;
  121. public RelativeLayout boxBkg;
  122. public MaxRelativeLayout bkg;
  123. public RelativeLayout boxCustom;
  124. public ScrollController scrollView;
  125. public DialogImpl setScrollView(ScrollController scrollView) {
  126. this.scrollView = scrollView;
  127. return this;
  128. }
  129. public DialogImpl(View convertView) {
  130. if (convertView == null) return;
  131. setDialogView(convertView);
  132. imgZoomActivity = convertView.findViewById(R.id.img_zoom_activity);
  133. boxRoot = convertView.findViewById(R.id.box_root);
  134. boxBkg = convertView.findViewById(R.id.box_bkg);
  135. bkg = convertView.findViewById(R.id.bkg);
  136. boxCustom = convertView.findViewById(R.id.box_custom);
  137. imgZoomActivity.hideActivityContentView = hideActivityContentView;
  138. imgZoomActivity.bindDialog(FullScreenDialog.this);
  139. if (hideZoomBackground) {
  140. convertView.setBackgroundResource(R.color.black20);
  141. imgZoomActivity.setVisibility(View.GONE);
  142. } else {
  143. convertView.setBackgroundResource(R.color.black);
  144. imgZoomActivity.setVisibility(View.VISIBLE);
  145. }
  146. init();
  147. dialogImpl = this;
  148. refreshView();
  149. }
  150. public float bkgEnterAimY = -1;
  151. protected int enterY;
  152. private Rect mUnsafeRect = new Rect(0, 0, 0, 0);
  153. public float getEnterY() {
  154. return Math.max(0, boxRoot.getSafeHeight() - enterY);
  155. }
  156. @Override
  157. public void init() {
  158. boxRoot.setParentDialog(me);
  159. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  160. getDialogView().setTranslationZ(getThisOrderIndex());
  161. }
  162. boxRoot.setOnLifecycleCallBack(new DialogXBaseRelativeLayout.OnLifecycleCallBack() {
  163. @Override
  164. public void onShow() {
  165. isShow = true;
  166. preShow = false;
  167. setLifecycleState(Lifecycle.State.CREATED);
  168. onDialogShow();
  169. getDialogLifecycleCallback().onShow(me);
  170. FullScreenDialog.this.onShow(me);
  171. }
  172. @Override
  173. public void onDismiss() {
  174. isShow = false;
  175. getDialogLifecycleCallback().onDismiss(me);
  176. FullScreenDialog.this.onDismiss(me);
  177. fullScreenDialogTouchEventInterceptor = null;
  178. dialogImpl = null;
  179. dialogLifecycleCallback = null;
  180. setLifecycleState(Lifecycle.State.DESTROYED);
  181. System.gc();
  182. }
  183. });
  184. boxRoot.setOnBackPressedListener(new DialogXBaseRelativeLayout.PrivateBackPressedListener() {
  185. @Override
  186. public boolean onBackPressed() {
  187. if (onBackPressedListener != null) {
  188. if (onBackPressedListener.onBackPressed(me)) {
  189. dismiss();
  190. }
  191. } else {
  192. if (isCancelable()) {
  193. dismiss();
  194. }
  195. }
  196. return true;
  197. }
  198. });
  199. fullScreenDialogTouchEventInterceptor = new FullScreenDialogTouchEventInterceptor(me, dialogImpl);
  200. boxRoot.setBkgAlpha(0f);
  201. bkg.setY(boxRoot.getHeight());
  202. boxRoot.post(new Runnable() {
  203. @Override
  204. public void run() {
  205. getDialogXAnimImpl().doShowAnim(me, bkg);
  206. setLifecycleState(Lifecycle.State.RESUMED);
  207. }
  208. });
  209. boxRoot.setOnSafeInsetsChangeListener(new OnSafeInsetsChangeListener() {
  210. @Override
  211. public void onChange(Rect unsafeRect) {
  212. mUnsafeRect.set(unsafeRect);
  213. makeEnterY();
  214. if (!enterAnimRunning) {
  215. bkg.setY(getEnterY());
  216. }
  217. }
  218. });
  219. bkg.setOnYChanged(new MaxRelativeLayout.OnYChanged() {
  220. @Override
  221. public void y(float y) {
  222. float realY = y + bkg.getTop();
  223. float zoomScale = 1 - (boxRoot.getHeight() - realY) * 0.00002f;
  224. if (zoomScale > 1) zoomScale = 1;
  225. if (!hideZoomBackground) {
  226. imgZoomActivity.setScale(zoomScale);
  227. imgZoomActivity.setRadius(
  228. getActivityZoomRadius(getDeviceRadius(), getActivityContentRadius(), ((boxRoot.getHeight() - realY) / boxRoot.getHeight()))
  229. );
  230. }
  231. }
  232. });
  233. /**
  234. * 给自定义布局增加监听,如果布局高度发生改变,则重新计算位置,位置发生变化,则再次使用动画移动布局到指定位置
  235. * 目的是给自定义布局高度为wrap_content的用于纠正布局的Y轴位置
  236. */
  237. boxCustom.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
  238. @Override
  239. public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
  240. int oldHeight = oldBottom - oldTop;
  241. int newHeight = bottom - top;
  242. if (oldHeight != newHeight) {
  243. /**
  244. * 高度发生改变
  245. * 这里判断是否在两种动画途中
  246. */
  247. if (!enterAnimRunning && !boxRoot.getFitSystemBarUtils().isInSmoothingPadding()) {
  248. makeEnterY();
  249. float newBkgEnterAimY = boxRoot.getSafeHeight() - mUnsafeRect.bottom - enterY - boxRoot.getUnsafePlace().top;
  250. if (newBkgEnterAimY < 0) newBkgEnterAimY = 0;
  251. if (newBkgEnterAimY != bkgEnterAimY && bkg.getY() != newBkgEnterAimY) {
  252. float oldVal = bkgEnterAimY;
  253. bkgEnterAimY = newBkgEnterAimY;
  254. //需要重新定义终点
  255. doShowAnimRepeat((int) oldVal, (int) newBkgEnterAimY, true);
  256. } else if (bkg.getY() != newBkgEnterAimY) {
  257. bkg.setY(newBkgEnterAimY);
  258. }
  259. }
  260. }
  261. }
  262. });
  263. onDialogInit();
  264. }
  265. private boolean isMatchParentHeightCustomView() {
  266. if (onBindView != null && onBindView.getCustomView() != null) {
  267. ViewGroup.LayoutParams lp = onBindView.getCustomView().getLayoutParams();
  268. if (lp != null) {
  269. return lp.height == MATCH_PARENT;
  270. }
  271. }
  272. return false;
  273. }
  274. private void makeEnterY() {
  275. int customViewHeight = boxCustom.getHeight();
  276. if (customViewHeight == 0 || isMatchParentHeightCustomView()) {
  277. customViewHeight = ((int) boxRoot.getSafeHeight());
  278. }
  279. enterY = customViewHeight;
  280. }
  281. @Override
  282. public void refreshView() {
  283. if (boxRoot == null || getOwnActivity() == null) {
  284. return;
  285. }
  286. boxRoot.setAutoUnsafePlacePadding(isEnableImmersiveMode());
  287. boxRoot.setRootPadding(screenPaddings[0], screenPaddings[1], screenPaddings[2], screenPaddings[3]);
  288. if (backgroundColor != null) {
  289. tintColor(bkg, backgroundColor);
  290. }
  291. bkg.setMaxWidth(getMaxWidth());
  292. bkg.setMaxHeight(getMaxHeight());
  293. bkg.setMinimumWidth(getMinWidth());
  294. bkg.setMinimumHeight(getMinHeight());
  295. if (isCancelable()) {
  296. boxRoot.setOnClickListener(new View.OnClickListener() {
  297. @Override
  298. public void onClick(View v) {
  299. if (onBackgroundMaskClickListener == null || !onBackgroundMaskClickListener.onClick(me, v)) {
  300. doDismiss(v);
  301. }
  302. }
  303. });
  304. } else {
  305. boxRoot.setOnClickListener(null);
  306. }
  307. if (backgroundRadius > -1) {
  308. if (bkg.getBackground() instanceof GradientDrawable) {
  309. GradientDrawable gradientDrawable = (GradientDrawable) bkg.getBackground();
  310. if (gradientDrawable != null) gradientDrawable.setCornerRadii(new float[]{
  311. backgroundRadius, backgroundRadius, backgroundRadius, backgroundRadius, 0, 0, 0, 0
  312. });
  313. }
  314. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
  315. bkg.setOutlineProvider(new ViewOutlineProvider() {
  316. @Override
  317. public void getOutline(View view, Outline outline) {
  318. outline.setRoundRect(0, 0, view.getWidth(), (int) (view.getHeight() + backgroundRadius), backgroundRadius);
  319. }
  320. });
  321. bkg.setClipToOutline(true);
  322. }
  323. }
  324. if (maskColor != null) {
  325. boxRoot.setBackgroundColor(maskColor);
  326. }
  327. if (onBindView != null) {
  328. onBindView.bindParent(boxCustom, me);
  329. if (onBindView.getCustomView() instanceof ScrollController) {
  330. scrollView = (ScrollController) onBindView.getCustomView();
  331. } else {
  332. View scrollController = onBindView.getCustomView().findViewWithTag("ScrollController");
  333. if (scrollController instanceof ScrollController) {
  334. scrollView = (ScrollController) scrollController;
  335. }
  336. }
  337. }
  338. if (hideZoomBackground) {
  339. getDialogView().setBackgroundResource(R.color.black20);
  340. imgZoomActivity.setVisibility(View.GONE);
  341. } else {
  342. getDialogView().setBackgroundResource(R.color.black);
  343. imgZoomActivity.setVisibility(View.VISIBLE);
  344. }
  345. fullScreenDialogTouchEventInterceptor.refresh(me, this);
  346. onDialogRefreshUI();
  347. }
  348. @Override
  349. public void doDismiss(View v) {
  350. if (FullScreenDialog.this.preDismiss(FullScreenDialog.this)) {
  351. return;
  352. }
  353. if (v != null) v.setEnabled(false);
  354. if (getOwnActivity() == null) return;
  355. if (!dismissAnimFlag && getDialogXAnimImpl() != null) {
  356. dismissAnimFlag = true;
  357. getDialogXAnimImpl().doExitAnim(me, bkg);
  358. runOnMainDelay(new Runnable() {
  359. @Override
  360. public void run() {
  361. if (boxRoot != null) {
  362. boxRoot.setVisibility(View.GONE);
  363. }
  364. dismiss(getDialogView());
  365. }
  366. }, getExitAnimationDuration());
  367. }
  368. }
  369. public void preDismiss() {
  370. if (isCancelable()) {
  371. doDismiss(boxRoot);
  372. } else {
  373. long exitAnimDurationTemp = 300;
  374. if (overrideExitDuration >= 0) {
  375. exitAnimDurationTemp = overrideExitDuration;
  376. }
  377. if (exitAnimDuration >= 0) {
  378. exitAnimDurationTemp = exitAnimDuration;
  379. }
  380. ObjectAnimator exitAnim = ObjectAnimator.ofFloat(bkg, "y", bkg.getY(), bkgEnterAimY);
  381. exitAnim.setDuration(exitAnimDurationTemp);
  382. exitAnim.start();
  383. }
  384. }
  385. private boolean enterAnimRunning = true;
  386. /**
  387. * 弹窗显示的动画
  388. * 动画执行途中实时检测终点是否改变,如果改变则中断这次动画重新设置新终点的动画并执行
  389. *
  390. * @param start 起点位置
  391. * @param end 终点位置
  392. */
  393. private void doShowAnimRepeat(int start, int end, boolean isRepeat) {
  394. enterAnimRunning = true;
  395. long enterAnimDurationTemp = getEnterAnimationDuration();
  396. ValueAnimator enterAnimVal = ValueAnimator.ofInt(start, end);
  397. enterAnimVal.setDuration(enterAnimDurationTemp);
  398. enterAnimVal.setInterpolator(new DecelerateInterpolator());
  399. enterAnimVal.addUpdateListener(animation -> {
  400. int thisVal = (int) animation.getAnimatedValue();
  401. bkg.setY(thisVal);
  402. makeEnterY();
  403. float newBkgEnterAimY = boxRoot.getSafeHeight() - enterY;
  404. if (newBkgEnterAimY < 0) newBkgEnterAimY = 0;
  405. if (newBkgEnterAimY != bkgEnterAimY) {
  406. bkgEnterAimY = newBkgEnterAimY;
  407. //需要重新定义终点
  408. animation.cancel();
  409. doShowAnimRepeat(thisVal, (int) newBkgEnterAimY, true);
  410. } else if (thisVal >= end) {
  411. enterAnimRunning = false;
  412. }
  413. });
  414. enterAnimVal.start();
  415. bkg.setVisibility(View.VISIBLE);
  416. if (!isRepeat) {
  417. ValueAnimator bkgAlpha = ValueAnimator.ofFloat(0f, 1f);
  418. bkgAlpha.setDuration(enterAnimDurationTemp);
  419. bkgAlpha.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  420. @Override
  421. public void onAnimationUpdate(ValueAnimator animation) {
  422. float value = (float) animation.getAnimatedValue();
  423. boxRoot.setBkgAlpha(value);
  424. }
  425. });
  426. bkgAlpha.start();
  427. }
  428. }
  429. protected DialogXAnimInterface<FullScreenDialog> getDialogXAnimImpl() {
  430. if (dialogXAnimImpl == null) {
  431. dialogXAnimImpl = new DialogXAnimInterface<FullScreenDialog>() {
  432. @Override
  433. public void doShowAnim(FullScreenDialog dialog, ViewGroup dialogBodyView) {
  434. // long enterAnimDurationTemp = getEnterAnimationDuration();
  435. makeEnterY();
  436. bkgEnterAimY = boxRoot.getSafeHeight() - enterY;
  437. if (bkgEnterAimY < 0) bkgEnterAimY = 0;
  438. //启动带监控终点位置变化的动画
  439. doShowAnimRepeat(boxRoot.getHeight(), (int) bkgEnterAimY, false);
  440. // ObjectAnimator enterAnim = ObjectAnimator.ofFloat(bkg, "y", boxRoot.getHeight(), bkgEnterAimY);
  441. // enterAnim.setDuration(enterAnimDurationTemp);
  442. // enterAnim.setInterpolator(new DecelerateInterpolator());
  443. // enterAnim.start();
  444. // bkg.setVisibility(View.VISIBLE);
  445. //
  446. // ValueAnimator bkgAlpha = ValueAnimator.ofFloat(0f, 1f);
  447. // bkgAlpha.setDuration(enterAnimDurationTemp);
  448. // bkgAlpha.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  449. // @Override
  450. // public void onAnimationUpdate(ValueAnimator animation) {
  451. // float value = (float) animation.getAnimatedValue();
  452. // boxRoot.setBkgAlpha(value);
  453. // enterAnimRunning = !(value == 1f);
  454. // }
  455. // });
  456. // bkgAlpha.start();
  457. }
  458. @Override
  459. public void doExitAnim(FullScreenDialog dialog, ViewGroup dialogBodyView) {
  460. long exitAnimDurationTemp = getExitAnimationDuration();
  461. ObjectAnimator exitAnim = ObjectAnimator.ofFloat(bkg, "y", bkg.getY(), boxBkg.getHeight());
  462. exitAnim.setDuration(exitAnimDurationTemp);
  463. exitAnim.start();
  464. ValueAnimator bkgAlpha = ValueAnimator.ofFloat(1f, 0f);
  465. bkgAlpha.setDuration(exitAnimDurationTemp);
  466. bkgAlpha.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  467. @Override
  468. public void onAnimationUpdate(ValueAnimator animation) {
  469. float value = (float) animation.getAnimatedValue();
  470. boxRoot.setBkgAlpha(value);
  471. enterAnimRunning = !(value == 1f);
  472. }
  473. });
  474. bkgAlpha.start();
  475. }
  476. };
  477. }
  478. return dialogXAnimImpl;
  479. }
  480. public long getExitAnimationDuration() {
  481. long exitAnimDurationTemp = 300;
  482. if (overrideExitDuration >= 0) {
  483. exitAnimDurationTemp = overrideExitDuration;
  484. }
  485. if (exitAnimDuration != -1) {
  486. exitAnimDurationTemp = exitAnimDuration;
  487. }
  488. return exitAnimDurationTemp;
  489. }
  490. public long getEnterAnimationDuration() {
  491. long enterAnimDurationTemp = 300;
  492. if (overrideEnterDuration >= 0) {
  493. enterAnimDurationTemp = overrideEnterDuration;
  494. }
  495. if (enterAnimDuration >= 0) {
  496. enterAnimDurationTemp = enterAnimDuration;
  497. }
  498. return enterAnimDurationTemp;
  499. }
  500. }
  501. @Override
  502. public String dialogKey() {
  503. return getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")";
  504. }
  505. public void refreshUI() {
  506. if (getDialogImpl() == null) return;
  507. runOnMain(new Runnable() {
  508. @Override
  509. public void run() {
  510. if (dialogImpl != null) dialogImpl.refreshView();
  511. }
  512. });
  513. }
  514. public void dismiss() {
  515. runOnMain(new Runnable() {
  516. @Override
  517. public void run() {
  518. if (dialogImpl == null) return;
  519. dialogImpl.doDismiss(null);
  520. }
  521. });
  522. }
  523. public DialogLifecycleCallback<FullScreenDialog> getDialogLifecycleCallback() {
  524. return dialogLifecycleCallback == null ? new DialogLifecycleCallback<FullScreenDialog>() {
  525. } : dialogLifecycleCallback;
  526. }
  527. public FullScreenDialog setDialogLifecycleCallback(DialogLifecycleCallback<FullScreenDialog> dialogLifecycleCallback) {
  528. this.dialogLifecycleCallback = dialogLifecycleCallback;
  529. if (isShow) dialogLifecycleCallback.onShow(me);
  530. return this;
  531. }
  532. public OnBackPressedListener<FullScreenDialog> getOnBackPressedListener() {
  533. return (OnBackPressedListener<FullScreenDialog>) onBackPressedListener;
  534. }
  535. public FullScreenDialog setOnBackPressedListener(OnBackPressedListener<FullScreenDialog> onBackPressedListener) {
  536. this.onBackPressedListener = onBackPressedListener;
  537. refreshUI();
  538. return this;
  539. }
  540. public FullScreenDialog setStyle(DialogXStyle style) {
  541. this.style = style;
  542. return this;
  543. }
  544. public FullScreenDialog setTheme(DialogX.THEME theme) {
  545. this.theme = theme;
  546. return this;
  547. }
  548. public boolean isCancelable() {
  549. if (privateCancelable != null) {
  550. return privateCancelable == BOOLEAN.TRUE;
  551. }
  552. if (overrideCancelable != null) {
  553. return overrideCancelable == BOOLEAN.TRUE;
  554. }
  555. return cancelable;
  556. }
  557. public FullScreenDialog setCancelable(boolean cancelable) {
  558. this.privateCancelable = cancelable ? BOOLEAN.TRUE : BOOLEAN.FALSE;
  559. refreshUI();
  560. return this;
  561. }
  562. public DialogImpl getDialogImpl() {
  563. return dialogImpl;
  564. }
  565. public FullScreenDialog setCustomView(OnBindView<FullScreenDialog> onBindView) {
  566. this.onBindView = onBindView;
  567. refreshUI();
  568. return this;
  569. }
  570. public View getCustomView() {
  571. if (onBindView == null) return null;
  572. return onBindView.getCustomView();
  573. }
  574. public FullScreenDialog removeCustomView() {
  575. this.onBindView.clean();
  576. refreshUI();
  577. return this;
  578. }
  579. public int getBackgroundColor() {
  580. return backgroundColor;
  581. }
  582. public FullScreenDialog setBackgroundColor(@ColorInt int backgroundColor) {
  583. this.backgroundColor = backgroundColor;
  584. refreshUI();
  585. return this;
  586. }
  587. public FullScreenDialog setBackgroundColorRes(@ColorRes int backgroundColorRes) {
  588. this.backgroundColor = getColor(backgroundColorRes);
  589. refreshUI();
  590. return this;
  591. }
  592. public long getEnterAnimDuration() {
  593. return enterAnimDuration;
  594. }
  595. public FullScreenDialog setEnterAnimDuration(long enterAnimDuration) {
  596. this.enterAnimDuration = enterAnimDuration;
  597. return this;
  598. }
  599. public long getExitAnimDuration() {
  600. return exitAnimDuration;
  601. }
  602. public FullScreenDialog setExitAnimDuration(long exitAnimDuration) {
  603. this.exitAnimDuration = exitAnimDuration;
  604. return this;
  605. }
  606. public boolean isHideZoomBackground() {
  607. return hideZoomBackground;
  608. }
  609. public FullScreenDialog setHideZoomBackground(boolean hideZoomBackground) {
  610. this.hideZoomBackground = hideZoomBackground;
  611. refreshUI();
  612. return this;
  613. }
  614. @Override
  615. public void restartDialog() {
  616. if (getDialogView() != null) {
  617. dismiss(getDialogView());
  618. isShow = false;
  619. }
  620. if (getDialogImpl().boxCustom != null) {
  621. getDialogImpl().boxCustom.removeAllViews();
  622. }
  623. enterAnimDuration = 0;
  624. View dialogView = createView(isLightTheme() ? R.layout.layout_dialogx_fullscreen : R.layout.layout_dialogx_fullscreen_dark);
  625. dialogImpl = new DialogImpl(dialogView);
  626. if (dialogView != null) dialogView.setTag(me);
  627. show(dialogView);
  628. }
  629. public void hide() {
  630. isHide = true;
  631. hideWithExitAnim = false;
  632. if (getDialogView() != null) {
  633. getDialogView().setVisibility(View.GONE);
  634. }
  635. }
  636. protected boolean hideWithExitAnim;
  637. public void hideWithExitAnim() {
  638. hideWithExitAnim = true;
  639. isHide = true;
  640. if (getDialogImpl() != null) {
  641. getDialogImpl().getDialogXAnimImpl().doExitAnim(me, getDialogImpl().bkg);
  642. runOnMainDelay(new Runnable() {
  643. @Override
  644. public void run() {
  645. if (getDialogView() != null) {
  646. getDialogView().setVisibility(View.GONE);
  647. }
  648. }
  649. }, getDialogImpl().getExitAnimationDuration());
  650. }
  651. }
  652. @Override
  653. protected void shutdown() {
  654. dismiss();
  655. }
  656. public FullScreenDialog setMaxWidth(int maxWidth) {
  657. this.maxWidth = maxWidth;
  658. refreshUI();
  659. return this;
  660. }
  661. public FullScreenDialog setMaxHeight(int maxHeight) {
  662. this.maxHeight = maxHeight;
  663. refreshUI();
  664. return this;
  665. }
  666. public FullScreenDialog setMinHeight(int minHeight) {
  667. this.minHeight = minHeight;
  668. refreshUI();
  669. return this;
  670. }
  671. public FullScreenDialog setMinWidth(int minWidth) {
  672. this.minWidth = minWidth;
  673. refreshUI();
  674. return this;
  675. }
  676. public FullScreenDialog setDialogImplMode(DialogX.IMPL_MODE dialogImplMode) {
  677. this.dialogImplMode = dialogImplMode;
  678. return this;
  679. }
  680. public OnBackgroundMaskClickListener<FullScreenDialog> getOnBackgroundMaskClickListener() {
  681. return onBackgroundMaskClickListener;
  682. }
  683. public FullScreenDialog setOnBackgroundMaskClickListener(OnBackgroundMaskClickListener<FullScreenDialog> onBackgroundMaskClickListener) {
  684. this.onBackgroundMaskClickListener = onBackgroundMaskClickListener;
  685. return this;
  686. }
  687. public FullScreenDialog setRadius(float radiusPx) {
  688. backgroundRadius = radiusPx;
  689. refreshUI();
  690. return this;
  691. }
  692. public float getRadius() {
  693. return backgroundRadius;
  694. }
  695. public boolean isAllowInterceptTouch() {
  696. return allowInterceptTouch;
  697. }
  698. public FullScreenDialog setAllowInterceptTouch(boolean allowInterceptTouch) {
  699. this.allowInterceptTouch = allowInterceptTouch;
  700. refreshUI();
  701. return this;
  702. }
  703. public DialogXAnimInterface<FullScreenDialog> getDialogXAnimImpl() {
  704. return dialogXAnimImpl;
  705. }
  706. public FullScreenDialog setDialogXAnimImpl(DialogXAnimInterface<FullScreenDialog> dialogXAnimImpl) {
  707. this.dialogXAnimImpl = dialogXAnimImpl;
  708. return this;
  709. }
  710. public FullScreenDialog setRootPadding(int padding) {
  711. this.screenPaddings = new int[]{padding, padding, padding, padding};
  712. refreshUI();
  713. return this;
  714. }
  715. public FullScreenDialog setRootPadding(int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
  716. this.screenPaddings = new int[]{paddingLeft, paddingTop, paddingRight, paddingBottom};
  717. refreshUI();
  718. return this;
  719. }
  720. /**
  721. * 用于使用 new 构建实例时,override 的生命周期事件
  722. * 例如:
  723. * new FullScreenDialog() {
  724. *
  725. * @param dialog self
  726. * @Override public void onShow(FullScreenDialog dialog) {
  727. * //...
  728. * }
  729. * }
  730. */
  731. protected void onShow(FullScreenDialog dialog) {
  732. }
  733. /**
  734. * 用于使用 new 构建实例时,override 的生命周期事件
  735. * 例如:
  736. * new FullScreenDialog() {
  737. *
  738. * @param dialog self
  739. * @Override public boolean onDismiss(FullScreenDialog dialog) {
  740. * WaitDialog.show("Please Wait...");
  741. * if (dialog.getButtonSelectResult() == BUTTON_SELECT_RESULT.BUTTON_OK) {
  742. * //点击了OK的情况
  743. * //...
  744. * } else {
  745. * //其他按钮点击、对话框dismiss的情况
  746. * //...
  747. * }
  748. * return false;
  749. * }
  750. * }
  751. */
  752. //用于使用 new 构建实例时,override 的生命周期事件
  753. protected void onDismiss(FullScreenDialog dialog) {
  754. }
  755. public boolean isBottomNonSafetyAreaBySelf() {
  756. return bottomNonSafetyAreaBySelf;
  757. }
  758. public FullScreenDialog setBottomNonSafetyAreaBySelf(boolean bottomNonSafetyAreaBySelf) {
  759. this.bottomNonSafetyAreaBySelf = bottomNonSafetyAreaBySelf;
  760. return this;
  761. }
  762. /**
  763. * 是否在显示 FullScreenDialog 时不对 activity 的界面内容进行渲染,这将提升一定的性能
  764. * 只可以在使用 build 方法构建且在执行show方法之前使用
  765. * 但这将引发一些问题,例如输入法弹出时 FullScreenDialog 无法上浮等
  766. *
  767. * @param hideActivityContentView 是否显示 activity 的界面内容
  768. * @return this
  769. */
  770. public FullScreenDialog hideActivityContentView(boolean hideActivityContentView) {
  771. this.hideActivityContentView = hideActivityContentView;
  772. return this;
  773. }
  774. public FullScreenDialog setMaskColor(@ColorInt int maskColor) {
  775. this.maskColor = maskColor;
  776. refreshUI();
  777. return this;
  778. }
  779. public float getActivityContentRadius() {
  780. return activityContentRadius >= 0 ? activityContentRadius : activityContentRadius == ACTIVITY_CONTENT_RADIUS_KEEP ? getDeviceRadius() : (getRadius() >= 0 ? getRadius() : dip2px(15));
  781. }
  782. private Integer deviceRadiusCache;
  783. public int getDeviceRadius() {
  784. if (deviceRadiusCache == null) {
  785. deviceRadiusCache = 0;
  786. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
  787. WindowInsets rootInsets = getRootFrameLayout() == null ? publicWindowInsets() : getRootFrameLayout().getRootWindowInsets();
  788. if (rootInsets != null) {
  789. RoundedCorner lT = rootInsets.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT);
  790. RoundedCorner rT = rootInsets.getRoundedCorner(RoundedCorner.POSITION_TOP_RIGHT);
  791. if (lT != null && rT != null) {
  792. deviceRadiusCache = Math.max(lT.getRadius(), rT.getRadius());
  793. }
  794. }
  795. }
  796. if (deviceRadiusCache == 0) {
  797. String manufacturer = Build.MANUFACTURER.toLowerCase();
  798. if ("xiaomi".equals(manufacturer)) {
  799. try {
  800. Class<?> systemPropertiesClass = Class.forName("android.os.SystemProperties");
  801. Method getIntMethod = systemPropertiesClass.getMethod("getInt", String.class, int.class);
  802. deviceRadiusCache = (int) getIntMethod.invoke(null, "ro.miui.notch.radius", 0);
  803. } catch (Exception e) {
  804. e.printStackTrace();
  805. }
  806. }
  807. }
  808. if (deviceRadiusCache == 0) {
  809. try {
  810. int resourceId = me.getResources().getIdentifier("rounded_corner_radius", "dimen", "android");
  811. if (resourceId > 0) {
  812. deviceRadiusCache = me.getResources().getDimensionPixelSize(resourceId);
  813. }
  814. } catch (Exception e) {
  815. e.printStackTrace();
  816. }
  817. }
  818. }
  819. return deviceRadiusCache;
  820. }
  821. public FullScreenDialog setDeviceRadius(int deviceRadiusPx) {
  822. deviceRadiusCache = deviceRadiusPx;
  823. return this;
  824. }
  825. public FullScreenDialog setActivityContentRadius(float activityContentRadius) {
  826. this.activityContentRadius = activityContentRadius;
  827. return this;
  828. }
  829. private float getActivityZoomRadius(float startValue, float endValue, float progressValue) {
  830. return startValue + progressValue * (endValue - startValue);
  831. }
  832. public FullScreenDialog setData(String key, Object obj) {
  833. if (data == null) data = new HashMap<>();
  834. data.put(key, obj);
  835. return this;
  836. }
  837. public FullScreenDialog onShow(DialogXRunnable<FullScreenDialog> dialogXRunnable) {
  838. onShowRunnable = dialogXRunnable;
  839. if (isShow() && onShowRunnable != null) {
  840. onShowRunnable.run(this);
  841. }
  842. return this;
  843. }
  844. public FullScreenDialog onDismiss(DialogXRunnable<FullScreenDialog> dialogXRunnable) {
  845. onDismissRunnable = dialogXRunnable;
  846. return this;
  847. }
  848. public FullScreenDialog setEnableImmersiveMode(boolean enableImmersiveMode) {
  849. this.enableImmersiveMode = enableImmersiveMode;
  850. refreshUI();
  851. return this;
  852. }
  853. public FullScreenDialog setThisOrderIndex(int orderIndex) {
  854. this.thisOrderIndex = orderIndex;
  855. if (getDialogView() != null) {
  856. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  857. getDialogView().setTranslationZ(orderIndex);
  858. } else {
  859. error("DialogX: " + dialogKey() + " 执行 .setThisOrderIndex(" + orderIndex + ") 失败:系统不支持此方法,SDK-API 版本必须大于 21(LOLLIPOP)");
  860. }
  861. }
  862. return this;
  863. }
  864. public FullScreenDialog bringToFront() {
  865. setThisOrderIndex(getHighestOrderIndex());
  866. return this;
  867. }
  868. }