Fix ToolApp edge back touch interception
This commit is contained in:
@@ -102,7 +102,7 @@ var ConfigValidator = {
|
||||
CLICK_SLOP_DP: { type: "int", min: 2, max: 20, default: 6 },
|
||||
TOOLAPP_BACK_EDGE_WIDTH_DP: { type: "int", min: 1, max: 120, default: 24 },
|
||||
ENABLE_TOOLAPP_INNER_BACK_STRIPS: { type: "bool", default: false },
|
||||
ENABLE_TOOLAPP_SCREEN_BACK_STRIPS: { type: "bool", default: true },
|
||||
ENABLE_TOOLAPP_SCREEN_BACK_STRIPS: { type: "bool", default: false },
|
||||
TOOLAPP_BACK_COMMIT_DISTANCE_DP: { type: "int", min: 1, max: 480, default: 72 },
|
||||
TOOLAPP_BACK_PROGRESS_DISTANCE_DP: { type: "int", min: 1, max: 720, default: 180 },
|
||||
|
||||
@@ -738,7 +738,7 @@ var ConfigManager = {
|
||||
CLICK_SLOP_DP: 6,
|
||||
TOOLAPP_BACK_EDGE_WIDTH_DP: 24,
|
||||
ENABLE_TOOLAPP_INNER_BACK_STRIPS: false,
|
||||
ENABLE_TOOLAPP_SCREEN_BACK_STRIPS: true,
|
||||
ENABLE_TOOLAPP_SCREEN_BACK_STRIPS: false,
|
||||
TOOLAPP_BACK_COMMIT_DISTANCE_DP: 72,
|
||||
TOOLAPP_BACK_PROGRESS_DISTANCE_DP: 180,
|
||||
ENABLE_BOUNCE: true,
|
||||
@@ -850,9 +850,9 @@ var ConfigManager = {
|
||||
|
||||
{ type: "section", name: "触摸与手势" },
|
||||
{ key: "CLICK_SLOP_DP", name: "点击位移阈值(dp)", type: "int", min: 1, max: 40, step: 1 },
|
||||
{ key: "TOOLAPP_BACK_EDGE_WIDTH_DP", name: "返回热区宽度", type: "int", min: 1, max: 120, step: 1 },
|
||||
{ key: "ENABLE_TOOLAPP_INNER_BACK_STRIPS", name: "启用页面内左右滑动返回", type: "bool" },
|
||||
{ key: "ENABLE_TOOLAPP_SCREEN_BACK_STRIPS", name: "启用屏幕边缘返回热区(排查用)", type: "bool" },
|
||||
{ key: "TOOLAPP_BACK_EDGE_WIDTH_DP", name: "返回起手边缘宽度", type: "int", min: 1, max: 120, step: 1 },
|
||||
{ key: "ENABLE_TOOLAPP_INNER_BACK_STRIPS", name: "启用旧版页面覆盖热区(不推荐)", type: "bool" },
|
||||
{ key: "ENABLE_TOOLAPP_SCREEN_BACK_STRIPS", name: "启用旧版屏幕覆盖热区(已禁用)", type: "bool" },
|
||||
{ key: "TOOLAPP_BACK_COMMIT_DISTANCE_DP", name: "设置页返回触发距离", type: "int", min: 1, max: 480, step: 1 },
|
||||
{ key: "TOOLAPP_BACK_PROGRESS_DISTANCE_DP", name: "设置页返回动画距离", type: "int", min: 1, max: 720, step: 1 },
|
||||
{ key: "ENABLE_LONG_PRESS", name: "启用长按", type: "bool" },
|
||||
|
||||
@@ -322,9 +322,7 @@ FloatBallAppWM.prototype.applyImmediateEffectsForKey = function(k) {
|
||||
if (k === "TOOLAPP_BACK_EDGE_WIDTH_DP" || k === "ENABLE_TOOLAPP_INNER_BACK_STRIPS") {
|
||||
try {
|
||||
if (this.state.toolAppActive) {
|
||||
if (k === "TOOLAPP_BACK_EDGE_WIDTH_DP" && this.updateToolAppInnerBackEdgeWidth) {
|
||||
this.updateToolAppInnerBackEdgeWidth();
|
||||
} else if (this.showToolApp) {
|
||||
if (k === "ENABLE_TOOLAPP_INNER_BACK_STRIPS" && this.showToolApp) {
|
||||
this.showToolApp(this.state.toolAppRoute || "settings", false);
|
||||
}
|
||||
if (this.refreshToolAppScreenBackStrips) this.refreshToolAppScreenBackStrips();
|
||||
|
||||
@@ -1139,58 +1139,9 @@ FloatBallAppWM.prototype.isToolAppScreenBackStripsEnabled = function() {
|
||||
};
|
||||
|
||||
FloatBallAppWM.prototype.showToolAppScreenBackStrips = function() {
|
||||
try {
|
||||
if (!this.state.wm || !this.state.toolAppActive) return false;
|
||||
if (!this.hasToolAppBackTarget || !this.hasToolAppBackTarget()) {
|
||||
this.hideToolAppScreenBackStrips();
|
||||
return false;
|
||||
}
|
||||
this.hideToolAppScreenBackStrips();
|
||||
|
||||
var sw = Math.max(1, Number(this.state.screen && this.state.screen.w || 0));
|
||||
if (sw <= 1) {
|
||||
try { var ss = this.getScreenSizePx(); sw = ss.w; } catch (eScreen) {}
|
||||
}
|
||||
var stripDp = Number(this.config.TOOLAPP_BACK_EDGE_WIDTH_DP || 24);
|
||||
if (isNaN(stripDp)) stripDp = 24;
|
||||
if (stripDp < 1) stripDp = 1;
|
||||
if (stripDp > 120) stripDp = 120;
|
||||
var stripW = this.dp(stripDp);
|
||||
var flags = android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
|
||||
android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
|
||||
|
||||
var left = this.createToolAppEdgeBackStrip(0);
|
||||
var lpL = new android.view.WindowManager.LayoutParams(
|
||||
stripW,
|
||||
android.view.WindowManager.LayoutParams.MATCH_PARENT,
|
||||
android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
|
||||
flags,
|
||||
android.graphics.PixelFormat.TRANSLUCENT
|
||||
);
|
||||
lpL.gravity = android.view.Gravity.START | android.view.Gravity.TOP;
|
||||
lpL.x = 0;
|
||||
lpL.y = 0;
|
||||
|
||||
var right = this.createToolAppEdgeBackStrip(1);
|
||||
var lpR = new android.view.WindowManager.LayoutParams(
|
||||
stripW,
|
||||
android.view.WindowManager.LayoutParams.MATCH_PARENT,
|
||||
android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
|
||||
flags,
|
||||
android.graphics.PixelFormat.TRANSLUCENT
|
||||
);
|
||||
lpR.gravity = android.view.Gravity.START | android.view.Gravity.TOP;
|
||||
lpR.x = Math.max(0, sw - stripW);
|
||||
lpR.y = 0;
|
||||
|
||||
this.state.wm.addView(left, lpL);
|
||||
this.state.wm.addView(right, lpR);
|
||||
this.state.toolAppScreenBackStrips = [left, right];
|
||||
return true;
|
||||
} catch (e) {
|
||||
this.hideToolAppScreenBackStrips();
|
||||
safeLog(this.L, 'w', "show tool app screen back strips fail: " + String(e));
|
||||
}
|
||||
// 兼容旧配置入口:不再创建覆盖 ToolApp 内容区的 MATCH_PARENT 透明触摸层。
|
||||
// 主要返回手势已迁移到 ToolApp root 的 onInterceptTouchEvent,避免遮挡列表/按钮/SeekBar/Switch。
|
||||
try { this.hideToolAppScreenBackStrips(); } catch(eHide) {}
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -1247,7 +1198,108 @@ FloatBallAppWM.prototype.buildToolAppShell = function(contentView, title, canBac
|
||||
var shellPad = spec ? spec.shellPadding : this.dp(6);
|
||||
var outerRadius = spec ? spec.outerRadius : this.dp(26);
|
||||
var topBarHeight = spec ? spec.topBarHeight : this.dp(56);
|
||||
var root = new android.widget.FrameLayout(context);
|
||||
var rootDownX = 0;
|
||||
var rootDownY = 0;
|
||||
var rootEdge = -1;
|
||||
var rootBackActive = false;
|
||||
var rootBackMoved = false;
|
||||
var root = new JavaAdapter(android.widget.FrameLayout, {
|
||||
onInterceptTouchEvent: function(ev) {
|
||||
try {
|
||||
if (!ev) return false;
|
||||
var action = ev.getActionMasked();
|
||||
if (action === android.view.MotionEvent.ACTION_DOWN) {
|
||||
rootDownX = ev.getX();
|
||||
rootDownY = ev.getY();
|
||||
rootBackActive = false;
|
||||
rootBackMoved = false;
|
||||
rootEdge = -1;
|
||||
var canBackNow = !!(self.state && self.state.toolAppActive && self.hasToolAppBackTarget && self.hasToolAppBackTarget());
|
||||
if (canBackNow) {
|
||||
var edgeW = self.getToolAppBackEdgeWidthPx ? self.getToolAppBackEdgeWidthPx() : self.dp(24);
|
||||
var rw = 0;
|
||||
try { rw = this.getWidth(); } catch(eW) { rw = 0; }
|
||||
if (rootDownX <= edgeW) rootEdge = 0;
|
||||
else if (rw > 0 && rootDownX >= rw - edgeW) rootEdge = 1;
|
||||
}
|
||||
// DOWN 必须放行给子控件,避免按钮/列表/Switch/SeekBar 被边缘手势抢走。
|
||||
return false;
|
||||
}
|
||||
if (action === android.view.MotionEvent.ACTION_MOVE) {
|
||||
if (rootEdge < 0) return false;
|
||||
var dx = ev.getX() - rootDownX;
|
||||
var dy = ev.getY() - rootDownY;
|
||||
var adx = Math.abs(dx);
|
||||
var ady = Math.abs(dy);
|
||||
var validDir = (rootEdge === 0 && dx > 0) || (rootEdge === 1 && dx < 0);
|
||||
var slopDp = Number(self.config.CLICK_SLOP_DP || 6) * 2;
|
||||
if (isNaN(slopDp)) slopDp = 12;
|
||||
if (slopDp < 12) slopDp = 12;
|
||||
if (slopDp > 40) slopDp = 40;
|
||||
var touchSlop = self.dp(slopDp);
|
||||
if (validDir && adx > touchSlop && adx > ady * 1.2) {
|
||||
rootBackActive = true;
|
||||
rootBackMoved = true;
|
||||
try { self.prepareToolAppBackPreview(rootEdge); } catch(ePrep) { try { safeLog(self.L, 'w', 'root back preview prepare fail: ' + String(ePrep)); } catch(eLogPrep) {} }
|
||||
try { safeLog(self.L, 'd', 'root edge back intercept edge=' + String(rootEdge) + ' dx=' + String(dx)); } catch(eMoveLog) {}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
} catch(e) {
|
||||
try { safeLog(self.L, 'w', 'tool app root intercept fail: ' + String(e)); } catch(eLog) {}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
onTouchEvent: function(ev) {
|
||||
try {
|
||||
if (!ev) return false;
|
||||
var action = ev.getActionMasked();
|
||||
if (!rootBackActive) return false;
|
||||
if (action === android.view.MotionEvent.ACTION_MOVE) {
|
||||
var mx = ev.getX() - rootDownX;
|
||||
var my = ev.getY() - rootDownY;
|
||||
var validDir2 = (rootEdge === 0 && mx > 0) || (rootEdge === 1 && mx < 0);
|
||||
if (validDir2 && Math.abs(mx) > Math.abs(my) * 1.2) {
|
||||
var triggerDp = Number(self.config.TOOLAPP_BACK_PROGRESS_DISTANCE_DP || 180);
|
||||
if (isNaN(triggerDp)) triggerDp = 180;
|
||||
if (triggerDp < 1) triggerDp = 1;
|
||||
if (triggerDp > 720) triggerDp = 720;
|
||||
var triggerDistance = self.dp(triggerDp);
|
||||
var p = Math.min(1, Math.abs(mx) / triggerDistance);
|
||||
self.applyToolAppBackPreviewProgress(rootEdge, p, Math.abs(mx));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (action === android.view.MotionEvent.ACTION_UP || action === android.view.MotionEvent.ACTION_CANCEL) {
|
||||
var ux = ev.getX() - rootDownX;
|
||||
var uy = ev.getY() - rootDownY;
|
||||
var commitDp = Number(self.config.TOOLAPP_BACK_COMMIT_DISTANCE_DP || 72);
|
||||
if (isNaN(commitDp)) commitDp = 72;
|
||||
if (commitDp < 1) commitDp = 1;
|
||||
if (commitDp > 480) commitDp = 480;
|
||||
var completeDistance = self.dp(commitDp);
|
||||
var okDir = (rootEdge === 0 && ux > completeDistance) || (rootEdge === 1 && ux < -completeDistance);
|
||||
var ok = (action === android.view.MotionEvent.ACTION_UP) && rootBackMoved && okDir && Math.abs(ux) > Math.abs(uy) * 1.2;
|
||||
var edgeDone = rootEdge;
|
||||
rootBackActive = false;
|
||||
rootBackMoved = false;
|
||||
rootEdge = -1;
|
||||
self.finishToolAppBackPreview(edgeDone, ok);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
} catch(e2) {
|
||||
try { self.clearToolAppBackPreview(true); } catch(eClear) {}
|
||||
try { safeLog(self.L, 'w', 'tool app root back touch fail: ' + String(e2)); } catch(eLog2) {}
|
||||
}
|
||||
rootBackActive = false;
|
||||
rootBackMoved = false;
|
||||
rootEdge = -1;
|
||||
return false;
|
||||
}
|
||||
}, context);
|
||||
var body = new android.widget.LinearLayout(context);
|
||||
body.setOrientation(android.widget.LinearLayout.VERTICAL);
|
||||
// 外层薄荷容器本身就是整张“岛屿设置”卡片:四角统一圆角,并给底部留出完整收口。
|
||||
@@ -1313,30 +1365,12 @@ FloatBallAppWM.prototype.buildToolAppShell = function(contentView, title, canBac
|
||||
hostLp.setMargins((spec && (spec.isExpandedWidth || spec.isWideWidth)) ? this.dp(4) : this.dp(6), 0, (spec && (spec.isExpandedWidth || spec.isWideWidth)) ? this.dp(4) : this.dp(6), (spec && (spec.isExpandedWidth || spec.isWideWidth)) ? this.dp(4) : this.dp(6));
|
||||
body.addView(host, hostLp);
|
||||
|
||||
// 页面内透明返回热区可能覆盖内容区左右边缘的真实按钮/列表项/颜色面板。
|
||||
// 默认关闭页面内热区;默认启用更窄的屏幕边缘热区,更贴近全面屏返回习惯。
|
||||
// 兼容旧设置:不再添加页面内透明返回热区。
|
||||
// 返回手势由 root.onInterceptTouchEvent 按“边缘起手 + 横向阈值 + 方向正确”延迟拦截,避免覆盖控件。
|
||||
try {
|
||||
var enableInnerBackStrip = false;
|
||||
try { enableInnerBackStrip = parseBooleanLike(this.config.ENABLE_TOOLAPP_INNER_BACK_STRIPS); } catch(eCfg) { enableInnerBackStrip = false; }
|
||||
if (enableInnerBackStrip) {
|
||||
var stripW = this.getToolAppBackEdgeWidthPx ? this.getToolAppBackEdgeWidthPx() : this.dp(24);
|
||||
var leftStrip = this.createToolAppEdgeBackStrip(0);
|
||||
var leftLp = new android.widget.FrameLayout.LayoutParams(stripW, -1);
|
||||
leftLp.gravity = android.view.Gravity.START | android.view.Gravity.TOP;
|
||||
leftLp.topMargin = topBarHeight + this.dp(8);
|
||||
root.addView(leftStrip, leftLp);
|
||||
var rightStrip = this.createToolAppEdgeBackStrip(1);
|
||||
var rightLp = new android.widget.FrameLayout.LayoutParams(stripW, -1);
|
||||
rightLp.gravity = android.view.Gravity.END | android.view.Gravity.TOP;
|
||||
rightLp.topMargin = topBarHeight + this.dp(8);
|
||||
root.addView(rightStrip, rightLp);
|
||||
this.state.toolAppInnerBackLeftStrip = leftStrip;
|
||||
this.state.toolAppInnerBackRightStrip = rightStrip;
|
||||
} else {
|
||||
this.state.toolAppInnerBackLeftStrip = null;
|
||||
this.state.toolAppInnerBackRightStrip = null;
|
||||
}
|
||||
} catch (eStrip) { safeLog(this.L, 'w', "add edge back strip fail: " + String(eStrip)); }
|
||||
} catch (eStrip) { safeLog(this.L, 'w', "clear edge back strip state fail: " + String(eStrip)); }
|
||||
|
||||
this.state.toolAppRoot = root;
|
||||
this.state.toolAppBody = body;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"alg": "SHA256withRSA",
|
||||
"files": {
|
||||
"th_01_base.js": {
|
||||
"sha256": "f8651c6ec22e7d06bb3ef2097ee8909523b149afbf5d8b34f9b5c79d8507598a",
|
||||
"size": 57150
|
||||
"sha256": "f228e3fda85ab9946934a9950515556d75df110da88432b339258036b8f3a3e2",
|
||||
"size": 57166
|
||||
},
|
||||
"th_02_core.js": {
|
||||
"sha256": "3c5c498d200e961d48fc9ca3f885475e770ecb32b83ec6a89d23df3f88aed1c9",
|
||||
@@ -18,8 +18,8 @@
|
||||
"size": 42568
|
||||
},
|
||||
"th_05_persistence.js": {
|
||||
"sha256": "59fc504c04f6ea397faee33567a773fca175379cba812c37b8ae8c626bc34002",
|
||||
"size": 15861
|
||||
"sha256": "1bec9f5bda8e5ae82f2a42707c59e72f4819fffc200d74ae55f191a76009af9b",
|
||||
"size": 15754
|
||||
},
|
||||
"th_06_icon_parser.js": {
|
||||
"sha256": "25b95a5df634a7ee359f3ab798e4d3154a71c24016f7b4bf8a658096644b2484",
|
||||
@@ -58,8 +58,8 @@
|
||||
"size": 304993
|
||||
},
|
||||
"th_15_extra.js": {
|
||||
"sha256": "97b3118f13328e9717f8931bec0c59fa2192f303aa5964cb483c9599a9d6ec02",
|
||||
"size": 115930
|
||||
"sha256": "fb8349a61771903a8c2a3ca6fee15f8df88af79b684e7b444b35c38bcf354ed5",
|
||||
"size": 117741
|
||||
},
|
||||
"th_16_entry.js": {
|
||||
"sha256": "6c59d9891cd010647f84c3db93f1cf95c7bbfb758470ea21044bf72eb8ff73d1",
|
||||
@@ -68,5 +68,5 @@
|
||||
},
|
||||
"keyId": "toolhub-targets-2026-rsa3072",
|
||||
"schema": 2,
|
||||
"version": 20260521225420
|
||||
"version": 20260521235402
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
lHCOD29vBFlyfpr/VbWetJp809qyTfiuiRcRmP3KTTCyHDUgyAJSpnLiUaBPdI3y9841uz6M22OY9uL/2FlXnfLUtyimTM0EMJd5CL3EyY4LTNsoRZWb20CHz/DY0jBBH1lT03j3EM6kQgWijxeyh2ynHk79UQzuFtcrnCAYUYqh1Gu4SxJ/eAWVPJ5788gr2hiiDClCvaOY6QUPAifwJ5zBkDSx4+k9gfI4XSKnnJmqFpdjtj5cLsYUuRWzmIlvTV55JQgqtjrLUKSVdoAXEai6twmjbwLOTlq/kBDFB4w/kxT0cjHQgZCwYpIclo0drday2Qs1NKtIHi0AktisuZf7QXgp29kx6PWI7iQL0RRfxRqGUSN640k8q0QTZwgLB3OP7k5URVVQX1lCbgWJ+o4RBBaX9OjfNc6QNJV01keK069jVUgiBa2LPnp6gwzuSbTmaPglaKW4J7WWXUtitIAvZ/Ah+aa124XoSvxdRdpZPgvsHORycXhgN5Y4qTuG
|
||||
Ho5g8n2gFgHoMdeo0wpzG4b3ufGTSs7Ht1MbGOGU0h0r/u3QRAJKJTCf1JPmSb6mWCOdM8ZL+LD0u8dfpJd9f4AdIJm+PNHH60YGa6QFEAuzh13eh1wQrd2S/gTSQGMSFqQPKRhdMzuTTBJEgMGK0S3siZP6RPK0hdocs5EpFnAtNd6HZWglcds1FVHMCwYiT1JCffRl+azDDaYlo5JqfdPz6hxfQkw+MEY5hQJ0veSbpuv5wNWRZ1OaPgIdwu7BMnGjbCR8BbYylXBkbB0K2K8FKeLDvuPY9je64xSgN1+dJpV1QTr+52BwxDH53u0L7ZVMYOJwOpdtLNhHNVjKJFJn3vcn2jS0DrX6uP9w/qI9X7Ss2bn8Xf/bkaMj6UpOOB+arkme8P2bM+ziGA/CL2n7SLsicvbUv3eNWRsjwTw9EIUx/sEqo6tr+m88eorZo7C3Idy5gdCtVjSSN3kef1XbHtOQshBZwXYpmFYPtRS0WxqEF7F/desj7k7ztnHv
|
||||
|
||||
Reference in New Issue
Block a user