Skip to content

Commit b823408

Browse files
committed
修复悬浮窗在超大物理尺寸的设备下单击操作会被框架判定为移动的问题
1 parent a623c5c commit b823408

File tree

1 file changed

+66
-2
lines changed

1 file changed

+66
-2
lines changed

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

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44
import android.app.Activity;
55
import android.content.Context;
66
import android.content.res.Resources;
7+
import android.graphics.Point;
78
import android.graphics.Rect;
89
import android.os.Build;
10+
import android.os.Build.VERSION;
11+
import android.os.Build.VERSION_CODES;
12+
import android.util.DisplayMetrics;
913
import android.util.TypedValue;
14+
import android.view.Display;
1015
import android.view.DisplayCutout;
1116
import android.view.Gravity;
1217
import android.view.MotionEvent;
@@ -45,6 +50,9 @@ public abstract class BaseDraggable implements OnTouchListener {
4550
private int mCurrentWindowInvisibleWidth;
4651
private int mCurrentWindowInvisibleHeight;
4752

53+
/** 当前屏幕物理尺寸 */
54+
private double mPhysicalScreenSize;
55+
4856
/**
4957
* 判断当前是否处于触摸移动状态
5058
*/
@@ -60,6 +68,7 @@ public void start(EasyWindow<?> easyWindow) {
6068
mDecorView.setOnTouchListener(this);
6169
mDecorView.post(() -> {
6270
refreshWindowInfo();
71+
refreshPhysicalScreenSize();
6372
refreshLocationCoordinate();
6473
});
6574
}
@@ -73,6 +82,7 @@ public final boolean onTouch(View v, MotionEvent event) {
7382
// 目前能想到比较好的办法就是在悬浮窗移动前之前先更新 Window 信息和 View 坐标
7483
// Github issue 地址:https://github.com/getActivity/EasyWindow/issues/69
7584
refreshWindowInfo();
85+
refreshPhysicalScreenSize();
7686
refreshLocationCoordinate();
7787
}
7888
return onDragWindow(mEasyWindow, mDecorView, event);
@@ -204,6 +214,38 @@ public void refreshWindowInfo() {
204214
*/
205215
}
206216

217+
/**
218+
* 刷新当前设备的物理屏幕尺寸
219+
*/
220+
public void refreshPhysicalScreenSize() {
221+
WindowManager windowManager = mEasyWindow.getWindowManager();
222+
if (windowManager == null) {
223+
return;
224+
}
225+
Display defaultDisplay = windowManager.getDefaultDisplay();
226+
if (defaultDisplay == null) {
227+
return;
228+
}
229+
230+
DisplayMetrics metrics = new DisplayMetrics();
231+
defaultDisplay.getMetrics(metrics);
232+
233+
float screenWidthInInches;
234+
float screenHeightInInches;
235+
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
236+
Point point = new Point();
237+
defaultDisplay.getRealSize(point);
238+
screenWidthInInches = point.x / metrics.xdpi;
239+
screenHeightInInches = point.y / metrics.ydpi;
240+
} else {
241+
screenWidthInInches = metrics.widthPixels / metrics.xdpi;
242+
screenHeightInInches = metrics.heightPixels / metrics.ydpi;
243+
}
244+
245+
// 勾股定理:直角三角形的两条直角边的平方和等于斜边的平方
246+
mPhysicalScreenSize = Math.sqrt(Math.pow(screenWidthInInches, 2) + Math.pow(screenHeightInInches, 2));
247+
}
248+
207249
/**
208250
* 刷新当前 View 在屏幕的坐标信息
209251
*/
@@ -230,6 +272,7 @@ public void onScreenOrientationChange() {
230272
if (!isFollowScreenRotationChanges()) {
231273
getEasyWindow().postDelayed(() -> {
232274
refreshWindowInfo();
275+
refreshPhysicalScreenSize();
233276
refreshLocationCoordinate();
234277
}, refreshDelayMillis);
235278
return;
@@ -284,6 +327,8 @@ public void onLayoutChange(View view, int left, int top, int right, int bottom,
284327
view.postDelayed(() -> {
285328
// 先刷新当前窗口信息
286329
refreshWindowInfo();
330+
// 刷新屏幕物理尺寸
331+
refreshPhysicalScreenSize();
287332
int x = Math.max((int) (mCurrentWindowWidth * percentX - viewWidth / 2f), 0);
288333
int y = Math.max((int) (mCurrentWindowHeight * percentY - viewWidth / 2f), 0);
289334
updateLocation(x, y);
@@ -299,6 +344,7 @@ public void onLayoutChange(View view, int left, int top, int right, int bottom,
299344
*/
300345
protected void onScreenRotateInfluenceCoordinateChangeFinish() {
301346
refreshWindowInfo();
347+
refreshPhysicalScreenSize();
302348
refreshLocationCoordinate();
303349
}
304350

@@ -484,8 +530,26 @@ protected float getMinTouchDistance() {
484530
// 疑问三:为什么要用 Resources.getSystem 来获取,而不是 context.getResources?
485531
// 这是因为如果用了 AutoSize 这个框架,上下文中的 1dp 就不是 3px 了
486532
// 使用 Resources.getSystem 能够保证 Resources 对象 dp 计算规则不被第三方框架篡改
487-
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1,
488-
Resources.getSystem().getDisplayMetrics());
533+
// 疑问四:为什么用物理屏幕尺寸来算出最小触摸距离呢?
534+
// 这是因为在大号的物理屏幕尺寸上面,单击悬浮窗的误差就不止 1dp,可能是更大的值,所以需要更大的值来兼容
535+
// Github issue:https://github.com/getActivity/EasyWindow/pull/79
536+
double physicalScreenSize = getPhysicalScreenSize();
537+
int dpValue;
538+
if (physicalScreenSize > 0) {
539+
// 市面上的平板最大尺寸不超过 15 英寸
540+
dpValue = (int) Math.ceil(physicalScreenSize / 15);
541+
} else {
542+
dpValue = 1;
543+
}
544+
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue,
545+
Resources.getSystem().getDisplayMetrics());
546+
}
547+
548+
/**
549+
* 获取物理的屏幕尺寸
550+
*/
551+
protected double getPhysicalScreenSize() {
552+
return mPhysicalScreenSize;
489553
}
490554

491555
/**

0 commit comments

Comments
 (0)