|
43 | 43 | import com.hjq.window.draggable.SpringBackWindowDraggableRule; |
44 | 44 | import java.lang.ref.Reference; |
45 | 45 | import java.lang.ref.WeakReference; |
| 46 | +import java.lang.reflect.Field; |
46 | 47 |
|
47 | 48 | /** |
48 | 49 | * author : Android 轮子哥 |
@@ -681,6 +682,47 @@ public X setBlurBehindRadius(@IntRange(from = 0) int blurBehindRadius) { |
681 | 682 | return (X) this; |
682 | 683 | } |
683 | 684 |
|
| 685 | + /** |
| 686 | + * 设置悬浮窗是否可以播放移动动画(Android 14 及以上才支持,框架兼容到 Android 4.3) |
| 687 | + * |
| 688 | + * @param enable 是否启用移动动画,系统默认为 true,设置为 false 可以让悬浮窗在移动时不播放动画,直接跳转到目标位置 |
| 689 | + */ |
| 690 | + @SuppressWarnings("JavaReflectionMemberAccess") |
| 691 | + public X setCanPlayMoveAnimation(boolean enable) { |
| 692 | + // 调用此方法可修复在 Android 13 ~ 14 当窗口内容大小改变时窗口位置会跳动的问题 |
| 693 | + // Github issue 地址:https://github.com/getActivity/EasyWindow/issues/83 |
| 694 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { |
| 695 | + mWindowParams.setCanPlayMoveAnimation(enable); |
| 696 | + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { |
| 697 | + // 查阅 Android 源码,发现 PRIVATE_FLAG_NO_MOVE_ANIMATION 是 从 Android 4.3 开始引入的,所以最低支持到 Android 4.3 |
| 698 | + // https://cs.android.com/android/platform/superproject/+/android-4.2.2_r1.2b:frameworks/base/core/java/android/view/WindowManager.java |
| 699 | + // https://cs.android.com/android/platform/superproject/+/android-4.3.1_r1:frameworks/base/core/java/android/view/WindowManager.java |
| 700 | + // 为了全 Android 版本的效果统一,Android 4.3 ~ Android 13 及以下通过私有标志反射实现 |
| 701 | + try { |
| 702 | + Class<WindowManager.LayoutParams> layoutParamsClass = WindowManager.LayoutParams.class; |
| 703 | + |
| 704 | + // 获取 privateFlags 字段 |
| 705 | + Field privateFlagsField = layoutParamsClass.getField("privateFlags"); |
| 706 | + // 获取 PRIVATE_FLAG_NO_MOVE_ANIMATION 标志值 |
| 707 | + Field noMoveAnimationFlagField = layoutParamsClass.getField("PRIVATE_FLAG_NO_MOVE_ANIMATION"); |
| 708 | + int noMoveAnimationFlag = noMoveAnimationFlagField.getInt(null); |
| 709 | + |
| 710 | + // 将标志位设置到 privateFlags 中 |
| 711 | + int currentPrivateFlags = privateFlagsField.getInt(mWindowParams); |
| 712 | + if (enable) { |
| 713 | + currentPrivateFlags &= ~noMoveAnimationFlag; |
| 714 | + } else { |
| 715 | + currentPrivateFlags |= noMoveAnimationFlag; |
| 716 | + } |
| 717 | + privateFlagsField.setInt(mWindowParams, currentPrivateFlags); |
| 718 | + |
| 719 | + } catch (Exception ignored) { |
| 720 | + // default implementation ignored |
| 721 | + } |
| 722 | + } |
| 723 | + return (X) this; |
| 724 | + } |
| 725 | + |
684 | 726 | /** |
685 | 727 | * 重新设置 WindowManager 参数集 |
686 | 728 | */ |
|
0 commit comments