1818import android .view .View ;
1919import android .view .View .OnLayoutChangeListener ;
2020import android .view .View .OnTouchListener ;
21+ import android .view .ViewGroup ;
2122import android .view .Window ;
2223import android .view .WindowInsets ;
2324import android .view .WindowManager ;
2425import android .view .WindowManager .LayoutParams ;
26+ import android .webkit .WebView ;
27+ import android .widget .ListView ;
28+ import android .widget .ScrollView ;
29+ import android .widget .SeekBar ;
2530import com .hjq .window .EasyWindow ;
2631
2732/**
3338public abstract class BaseDraggable implements OnTouchListener {
3439
3540 private EasyWindow <?> mEasyWindow ;
36- private View mDecorView ;
41+ private ViewGroup mDecorView ;
3742
3843 /** 是否允许移动到挖孔屏区域 */
3944 private boolean mAllowMoveToScreenNotch = true ;
@@ -53,6 +58,9 @@ public abstract class BaseDraggable implements OnTouchListener {
5358 /** 当前屏幕物理尺寸 */
5459 private double mPhysicalScreenSize ;
5560
61+ /** 需要消费触摸事件的 View(可能为空) */
62+ private View mConsumeTouchView ;
63+
5664 /**
5765 * 判断当前是否处于触摸移动状态
5866 */
@@ -75,16 +83,37 @@ public void start(EasyWindow<?> easyWindow) {
7583
7684 @ Override
7785 public final boolean onTouch (View v , MotionEvent event ) {
78- if (event .getAction () == MotionEvent .ACTION_DOWN ) {
79- // 在按下的时候先更新一下窗口信息和坐标信息,否则点击可能会出现坐标偏移的问题
80- // 全局的悬浮窗在非全屏的页面创建,跳转到全屏的页面展示就会导致坐标偏移
81- // 这是因为在跳转到全屏的悬浮窗的时候没有更新当前 Window 信息导致的
82- // 目前能想到比较好的办法就是在悬浮窗移动前之前先更新 Window 信息和 View 坐标
83- // Github issue 地址:https://github.com/getActivity/EasyWindow/issues/69
84- refreshWindowInfo ();
85- refreshPhysicalScreenSize ();
86- refreshLocationCoordinate ();
86+ switch (event .getAction ()) {
87+ case MotionEvent .ACTION_DOWN :
88+ // 在按下的时候先更新一下窗口信息和坐标信息,否则点击可能会出现坐标偏移的问题
89+ // 全局的悬浮窗在非全屏的页面创建,跳转到全屏的页面展示就会导致坐标偏移
90+ // 这是因为在跳转到全屏的悬浮窗的时候没有更新当前 Window 信息导致的
91+ // 目前能想到比较好的办法就是在悬浮窗移动前之前先更新 Window 信息和 View 坐标
92+ // Github issue 地址:https://github.com/getActivity/EasyWindow/issues/69
93+ refreshWindowInfo ();
94+ refreshPhysicalScreenSize ();
95+ refreshLocationCoordinate ();
96+
97+ mConsumeTouchView = null ;
98+ View consumeTouchEventView = findNeedConsumeTouchView (event , mDecorView );
99+ if (consumeTouchEventView != null && consumeTouchEventView .dispatchTouchEvent (event )) {
100+ mConsumeTouchView = consumeTouchEventView ;
101+ return true ;
102+ }
103+ break ;
104+ case MotionEvent .ACTION_UP :
105+ case MotionEvent .ACTION_CANCEL :
106+ if (mConsumeTouchView != null ) {
107+ mConsumeTouchView = null ;
108+ return true ;
109+ }
110+ default :
111+ if (mConsumeTouchView != null ) {
112+ return mConsumeTouchView .dispatchTouchEvent (event );
113+ }
114+ break ;
87115 }
116+
88117 return onDragWindow (mEasyWindow , mDecorView , event );
89118 }
90119
@@ -545,6 +574,67 @@ protected float getMinTouchDistance() {
545574 Resources .getSystem ().getDisplayMetrics ());
546575 }
547576
577+ /**
578+ * 寻找需要消费触摸事件的 View
579+ */
580+ protected View findNeedConsumeTouchView (MotionEvent event , ViewGroup viewGroup ) {
581+ int childCount = viewGroup .getChildCount ();
582+ for (int i = 0 ; i < childCount ; i ++) {
583+
584+ View childView = viewGroup .getChildAt (i );
585+ int [] location = new int [2 ];
586+ childView .getLocationOnScreen (location );
587+ int left = location [0 ];
588+ int top = location [1 ];
589+ int right = left + childView .getWidth ();
590+ int bottom = top + childView .getHeight ();
591+
592+ float x = event .getRawX ();
593+ float y = event .getRawY ();
594+
595+ // 判断触摸位置是否在这个 View 内
596+ if (x >= left && x <= right && y >= top && y <= bottom ) {
597+ if (isViewNeedConsumeTouchEvent (childView )) {
598+ return childView ;
599+ } else if (childView instanceof ViewGroup ) {
600+ return findNeedConsumeTouchView (event , (ViewGroup ) childView );
601+ }
602+ }
603+ }
604+ return null ;
605+ }
606+
607+ /**
608+ * 判断 View 是否需要消费当前触摸事件
609+ */
610+ protected boolean isViewNeedConsumeTouchEvent (View view ) {
611+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .JELLY_BEAN && view instanceof ViewGroup && view .isScrollContainer ()) {
612+ return true ;
613+ }
614+
615+ if (view instanceof WebView || view instanceof ScrollView || view instanceof ListView || view instanceof SeekBar ) {
616+ return true ;
617+ }
618+
619+ Class <? extends View > viewClass = view .getClass ();
620+
621+ try {
622+ // NestedScrollingChild 的子类有:RecyclerView、NestedScrollView、SwipeRefreshLayout 等等
623+ if (viewClass .isAssignableFrom (Class .forName ("androidx.core.view.NestedScrollingChild" )) ||
624+ viewClass .isAssignableFrom (Class .forName ("android.support.v4.view.NestedScrollingChild" ))) {
625+ return true ;
626+ }
627+
628+ if (viewClass .isAssignableFrom (Class .forName ("androidx.viewpager.widget.ViewPager" )) ||
629+ viewClass .isAssignableFrom (Class .forName ("android.support.v4.view.ViewPager" ))) {
630+ return true ;
631+ }
632+
633+ } catch (ClassNotFoundException ignored ) {}
634+
635+ return false ;
636+ }
637+
548638 /**
549639 * 获取物理的屏幕尺寸
550640 */
0 commit comments