Skip to content

Commit 7f04076

Browse files
committed
修正悬浮窗在移动时会拦截某些滚动容器触摸事件的问题
1 parent 03538af commit 7f04076

File tree

7 files changed

+242
-11
lines changed

7 files changed

+242
-11
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.hjq.window.demo;
2+
3+
import android.view.LayoutInflater;
4+
import android.view.View;
5+
import android.view.ViewGroup;
6+
import android.widget.TextView;
7+
import androidx.annotation.NonNull;
8+
import androidx.recyclerview.widget.RecyclerView;
9+
import com.hjq.window.demo.DemoAdapter.DemoViewHolder;
10+
import java.util.List;
11+
12+
public class DemoAdapter extends RecyclerView.Adapter<DemoViewHolder> {
13+
14+
private final List<String> mDataList;
15+
16+
public DemoAdapter(List<String> dataList) {
17+
mDataList = dataList;
18+
}
19+
20+
@NonNull
21+
@Override
22+
public DemoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
23+
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.window_list_item, parent, false);
24+
return new DemoViewHolder(view);
25+
}
26+
27+
@Override
28+
public void onBindViewHolder(@NonNull DemoViewHolder holder, int position) {
29+
String data = mDataList.get(position);
30+
holder.mTextview.setText(data);
31+
}
32+
33+
@Override
34+
public int getItemCount() {
35+
return mDataList.size();
36+
}
37+
38+
public static class DemoViewHolder extends RecyclerView.ViewHolder {
39+
40+
private final TextView mTextview;
41+
42+
public DemoViewHolder(@NonNull View itemView) {
43+
super(itemView);
44+
mTextview = itemView.findViewById(R.id.tv_window_list_item_text);
45+
}
46+
}
47+
}

app/src/main/java/com/hjq/window/demo/MainActivity.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import android.widget.TextView;
1212
import androidx.annotation.NonNull;
1313
import androidx.appcompat.app.AppCompatActivity;
14+
import androidx.recyclerview.widget.LinearLayoutManager;
15+
import androidx.recyclerview.widget.RecyclerView;
1416
import com.google.android.material.snackbar.Snackbar;
1517
import com.hjq.bar.OnTitleBarListener;
1618
import com.hjq.bar.TitleBar;
@@ -19,8 +21,11 @@
1921
import com.hjq.permissions.XXPermissions;
2022
import com.hjq.toast.Toaster;
2123
import com.hjq.window.EasyWindow;
24+
import com.hjq.window.EasyWindow.OnClickListener;
25+
import com.hjq.window.EasyWindow.OnWindowLifecycle;
2226
import com.hjq.window.draggable.MovingDraggable;
2327
import com.hjq.window.draggable.SpringBackDraggable;
28+
import java.util.ArrayList;
2429
import java.util.List;
2530

2631
/**
@@ -43,6 +48,7 @@ protected void onCreate(Bundle savedInstanceState) {
4348
findViewById(R.id.btn_main_click).setOnClickListener(this);
4449
findViewById(R.id.btn_main_view).setOnClickListener(this);
4550
findViewById(R.id.btn_main_input).setOnClickListener(this);
51+
findViewById(R.id.btn_main_list).setOnClickListener(this);
4652
findViewById(R.id.btn_main_draggable).setOnClickListener(this);
4753
findViewById(R.id.btn_main_global).setOnClickListener(this);
4854
findViewById(R.id.btn_main_utils).setOnClickListener(this);
@@ -184,6 +190,44 @@ public void onClick(final EasyWindow<?> easyWindow, TextView view) {
184190
})
185191
.show();
186192

193+
} else if (viewId == R.id.btn_main_list) {
194+
195+
EasyWindow.with(this)
196+
.setContentView(R.layout.window_list)
197+
.setAnimStyle(R.style.IOSAnimStyle)
198+
// 设置成可拖拽的
199+
.setDraggable(new MovingDraggable())
200+
.setOnClickListener(R.id.iv_window_list_close, new OnClickListener<ImageView>() {
201+
202+
@Override
203+
public void onClick(EasyWindow<?> easyWindow, ImageView view) {
204+
easyWindow.cancel();
205+
}
206+
})
207+
.setOnLongClickListener(R.id.iv_window_list_close, new EasyWindow.OnLongClickListener<View>() {
208+
@Override
209+
public boolean onLongClick(EasyWindow<?> easyWindow, View view) {
210+
Toaster.show("关闭按钮被长按了");
211+
return false;
212+
}
213+
})
214+
.setOnWindowLifecycle(new OnWindowLifecycle() {
215+
@Override
216+
public void onWindowShow(EasyWindow<?> easyWindow) {
217+
RecyclerView recyclerView = easyWindow.findViewById(R.id.rv_window_list_view);
218+
recyclerView.setLayoutManager(new LinearLayoutManager(easyWindow.getContext()));
219+
220+
List<String> dataList = new ArrayList<>();
221+
for (int i = 1; i <= 20; i++) {
222+
dataList.add("我是条目 " + i);
223+
}
224+
225+
DemoAdapter adapter = new DemoAdapter(dataList);
226+
recyclerView.setAdapter(adapter);
227+
}
228+
})
229+
.show();
230+
187231
} else if (viewId == R.id.btn_main_draggable) {
188232

189233
EasyWindow.with(this)

app/src/main/res/layout/activity_main.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@
8686
android:layout_marginTop="15dp"
8787
android:text="搭配软键盘弹出演示" />
8888

89+
<Button
90+
android:id="@+id/btn_main_list"
91+
android:layout_width="wrap_content"
92+
android:layout_height="wrap_content"
93+
android:layout_gravity="center_horizontal"
94+
android:layout_marginTop="15dp"
95+
android:text="搭配 RecyclerView 演示" />
96+
8997
<Button
9098
android:id="@+id/btn_main_draggable"
9199
android:layout_width="wrap_content"
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
4+
android:layout_width="wrap_content"
5+
android:layout_height="wrap_content"
6+
android:layout_gravity="center"
7+
android:layout_margin="100dp"
8+
android:background="@drawable/dialog_toast_bg"
9+
android:gravity="center"
10+
android:minWidth="120dp"
11+
android:minHeight="120dp"
12+
android:orientation="vertical">
13+
14+
<ImageView
15+
android:id="@+id/iv_window_list_close"
16+
android:layout_width="20dp"
17+
android:layout_height="20dp"
18+
android:layout_gravity="end"
19+
android:layout_margin="15dp"
20+
android:src="@android:drawable/ic_menu_close_clear_cancel" />
21+
22+
<androidx.recyclerview.widget.RecyclerView
23+
android:id="@+id/rv_window_list_view"
24+
android:layout_width="match_parent"
25+
android:layout_height="200dp"
26+
tools:listitem="@layout/window_list_item" />
27+
28+
</LinearLayout>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
4+
android:id="@+id/tv_window_list_item_text"
5+
android:layout_width="wrap_content"
6+
android:layout_height="wrap_content"
7+
android:layout_marginLeft="15dp"
8+
android:layout_marginTop="14dp"
9+
android:layout_marginRight="15dp"
10+
android:layout_marginBottom="14dp"
11+
android:maxLines="3"
12+
android:textColor="#ffffff"
13+
android:textSize="14sp"
14+
tools:text="1" />

library/src/main/java/com/hjq/window/EasyWindow.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,7 @@ public Context getContext() {
12191219
/**
12201220
* 获取根布局(可能为空)
12211221
*/
1222-
public View getDecorView() {
1222+
public ViewGroup getDecorView() {
12231223
return mDecorView;
12241224
}
12251225

library/src/main/java/com/hjq/window/draggable/BaseDraggable.java

Lines changed: 100 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,15 @@
1818
import android.view.View;
1919
import android.view.View.OnLayoutChangeListener;
2020
import android.view.View.OnTouchListener;
21+
import android.view.ViewGroup;
2122
import android.view.Window;
2223
import android.view.WindowInsets;
2324
import android.view.WindowManager;
2425
import android.view.WindowManager.LayoutParams;
26+
import android.webkit.WebView;
27+
import android.widget.ListView;
28+
import android.widget.ScrollView;
29+
import android.widget.SeekBar;
2530
import com.hjq.window.EasyWindow;
2631

2732
/**
@@ -33,7 +38,7 @@
3338
public 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

Comments
 (0)