44import android .app .Activity ;
55import android .content .Context ;
66import android .content .res .Resources ;
7+ import android .graphics .Point ;
78import android .graphics .Rect ;
89import android .os .Build ;
10+ import android .os .Build .VERSION ;
11+ import android .os .Build .VERSION_CODES ;
12+ import android .util .DisplayMetrics ;
913import android .util .TypedValue ;
14+ import android .view .Display ;
1015import android .view .DisplayCutout ;
1116import android .view .Gravity ;
1217import 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