refactor: prioritize OnBackAnimationCallback
This commit is contained in:
@@ -411,56 +411,66 @@ FloatBallAppWM.prototype.unregisterPanelPredictiveBack = function(panel) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
FloatBallAppWM.prototype.registerPanelPredictiveBack = function(panel, which) {
|
FloatBallAppWM.prototype.registerPanelPredictiveBack = function(panel, which) {
|
||||||
// Android 13+:注册 OnBackInvokedCallback;Android 14+ 优先使用 OnBackAnimationCallback,实现预测性返回手势进度动画。
|
// 返回注册优先级:Android 14+ OnBackAnimationCallback(有 progress)→ Android 13 OnBackInvokedCallback(仅最终返回)→ 旧系统 KEYCODE_BACK。
|
||||||
try {
|
try {
|
||||||
if (!panel) return false;
|
if (!panel) return false;
|
||||||
if (android.os.Build.VERSION.SDK_INT < 33) return false;
|
if (android.os.Build.VERSION.SDK_INT < 33) return false;
|
||||||
this.unregisterPanelPredictiveBack(panel);
|
this.unregisterPanelPredictiveBack(panel);
|
||||||
var dispatcher = null;
|
var dispatcher = null;
|
||||||
try { dispatcher = panel.findOnBackInvokedDispatcher(); } catch (eFind) { dispatcher = null; }
|
try { dispatcher = panel.findOnBackInvokedDispatcher(); } catch (eFind) { dispatcher = null; }
|
||||||
if (!dispatcher) return false;
|
if (!dispatcher) {
|
||||||
|
safeLog(this.L, 'w', "predictive back dispatcher missing which=" + String(which || ""));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var cb = null;
|
var cb = null;
|
||||||
|
var mode = "none";
|
||||||
var usedAnimation = false;
|
var usedAnimation = false;
|
||||||
|
|
||||||
|
function finishBack(reason) {
|
||||||
|
if (String(which || "") === "tool_app" && self.finishToolAppBackPreview && self.getToolAppPreviousStackEntry && self.getToolAppPreviousStackEntry()) {
|
||||||
|
var edge = 0;
|
||||||
|
try { edge = Number(self.state.toolAppBackEdge || 0); } catch (eEdge) { edge = 0; }
|
||||||
|
self.finishToolAppBackPreview(edge, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.resetPanelPredictiveBackVisual(panel);
|
||||||
|
self.handlePanelBack(which, reason || "predictive_back");
|
||||||
|
}
|
||||||
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= 34) {
|
if (android.os.Build.VERSION.SDK_INT >= 34) {
|
||||||
try {
|
try {
|
||||||
// 关键:不要只把 Class.forName() 的 Class 对象传给 JavaAdapter。
|
// 核心:优先创建真正的 android.window.OnBackAnimationCallback。
|
||||||
// 在部分 ColorOS/Rhino 组合里这样会被系统识别成普通 OnBackInvokedCallback,log 里表现为 mIsAnimationCallback=false。
|
// Class.forName 只用于预热/instanceof 校验;JavaAdapter 必须使用 Packages 下的接口对象。
|
||||||
// 先 forName 预热,再用 Packages.android.window.OnBackAnimationCallback 这个接口对象创建代理,确保 instanceof 命中。
|
|
||||||
var animCls = java.lang.Class.forName("android.window.OnBackAnimationCallback");
|
var animCls = java.lang.Class.forName("android.window.OnBackAnimationCallback");
|
||||||
var animIface = Packages.android.window.OnBackAnimationCallback;
|
cb = new JavaAdapter(Packages.android.window.OnBackAnimationCallback, {
|
||||||
cb = new JavaAdapter(animIface, {
|
|
||||||
onBackStarted: function(event) { self.applyPanelPredictiveBackProgress(panel, event); },
|
onBackStarted: function(event) { self.applyPanelPredictiveBackProgress(panel, event); },
|
||||||
onBackProgressed: function(event) { self.applyPanelPredictiveBackProgress(panel, event); },
|
onBackProgressed: function(event) { self.applyPanelPredictiveBackProgress(panel, event); },
|
||||||
onBackCancelled: function() { self.resetPanelPredictiveBackVisual(panel); },
|
onBackCancelled: function() { self.resetPanelPredictiveBackVisual(panel); },
|
||||||
onBackInvoked: function() {
|
onBackInvoked: function() { finishBack("predictive_back"); }
|
||||||
if (String(which || "") === "tool_app" && self.finishToolAppBackPreview && self.getToolAppPreviousStackEntry && self.getToolAppPreviousStackEntry()) {
|
|
||||||
var edge = 0;
|
|
||||||
try { edge = Number(self.state.toolAppBackEdge || 0); } catch (eEdge) { edge = 0; }
|
|
||||||
self.finishToolAppBackPreview(edge, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.resetPanelPredictiveBackVisual(panel);
|
|
||||||
self.handlePanelBack(which, "predictive_back");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
usedAnimation = !!animCls.isInstance(cb);
|
usedAnimation = !!animCls.isInstance(cb);
|
||||||
|
mode = usedAnimation ? "OnBackAnimationCallback" : "OnBackAnimationCallback-proxy-not-instance";
|
||||||
if (!usedAnimation) {
|
if (!usedAnimation) {
|
||||||
safeLog(self.L, 'w', "OnBackAnimationCallback proxy not instance; fallback may show mIsAnimationCallback=false");
|
safeLog(self.L, 'w', "OnBackAnimationCallback proxy not instance; fallback to final-only callback");
|
||||||
|
cb = null;
|
||||||
}
|
}
|
||||||
} catch (eAnim) {
|
} catch (eAnim) {
|
||||||
safeLog(self.L, 'w', "create OnBackAnimationCallback fail: " + String(eAnim));
|
safeLog(self.L, 'w', "create OnBackAnimationCallback fail: " + String(eAnim));
|
||||||
cb = null;
|
cb = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
try {
|
try {
|
||||||
var cbCls = java.lang.Class.forName("android.window.OnBackInvokedCallback");
|
var cbCls = java.lang.Class.forName("android.window.OnBackInvokedCallback");
|
||||||
cb = new JavaAdapter(cbCls, {
|
cb = new JavaAdapter(cbCls, {
|
||||||
onBackInvoked: function() { self.handlePanelBack(which, "on_back_invoked"); }
|
onBackInvoked: function() { finishBack("on_back_invoked"); }
|
||||||
});
|
});
|
||||||
|
mode = "OnBackInvokedCallback";
|
||||||
} catch (eCb) {
|
} catch (eCb) {
|
||||||
|
safeLog(self.L, 'w', "create OnBackInvokedCallback fail: " + String(eCb));
|
||||||
cb = null;
|
cb = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -468,14 +478,13 @@ FloatBallAppWM.prototype.registerPanelPredictiveBack = function(panel, which) {
|
|||||||
|
|
||||||
var priority = 0;
|
var priority = 0;
|
||||||
try {
|
try {
|
||||||
// ColorOS overlay 窗口用 PRIORITY_OVERLAY 时可能只触发最终返回,不给 CoreBackPreview 进度。
|
// 与规则文件实现保持一致:默认优先级最容易拿到系统 back pipeline;overlay priority 在 ColorOS 上可能只给最终回调。
|
||||||
// 这里对 ToolApp 也统一用 DEFAULT(0),与已验证规则文件实现一致,优先换取系统预测返回动画回调。
|
|
||||||
priority = android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT;
|
priority = android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT;
|
||||||
} catch (ePri) { priority = 0; }
|
} catch (ePri) { priority = 0; }
|
||||||
dispatcher.registerOnBackInvokedCallback(priority, cb);
|
dispatcher.registerOnBackInvokedCallback(priority, cb);
|
||||||
if (!this.state.panelBackCallbackEntries) this.state.panelBackCallbackEntries = [];
|
if (!this.state.panelBackCallbackEntries) this.state.panelBackCallbackEntries = [];
|
||||||
this.state.panelBackCallbackEntries.push({ view: panel, dispatcher: dispatcher, callback: cb, which: String(which || ""), animation: usedAnimation });
|
this.state.panelBackCallbackEntries.push({ view: panel, dispatcher: dispatcher, callback: cb, which: String(which || ""), animation: usedAnimation, mode: mode });
|
||||||
safeLog(this.L, 'i', "predictive back registered which=" + String(which || "") + " animation=" + String(usedAnimation));
|
safeLog(this.L, 'i', "back callback registered which=" + String(which || "") + " mode=" + mode + " priority=" + String(priority));
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
safeLog(this.L, 'w', "register predictive back fail which=" + String(which || "") + " err=" + String(e));
|
safeLog(this.L, 'w', "register predictive back fail which=" + String(which || "") + " err=" + String(e));
|
||||||
|
|||||||
@@ -34,8 +34,8 @@
|
|||||||
"size": 7938
|
"size": 7938
|
||||||
},
|
},
|
||||||
"th_09_animation.js": {
|
"th_09_animation.js": {
|
||||||
"sha256": "91c7793b4a03ac07f1b275486be4f2c5ed0142bdd13dbb13c107149791a84189",
|
"sha256": "b89876717fb62b4fd4249ce906b2741b90d25f7943c56b5afff3173ae9e41867",
|
||||||
"size": 38387
|
"size": 38495
|
||||||
},
|
},
|
||||||
"th_10_shell.js": {
|
"th_10_shell.js": {
|
||||||
"sha256": "0ed793079c2f6ba7d29f4c0d411705cb72419f45f572cbe37ed32ac16527a8bc",
|
"sha256": "0ed793079c2f6ba7d29f4c0d411705cb72419f45f572cbe37ed32ac16527a8bc",
|
||||||
@@ -68,5 +68,5 @@
|
|||||||
},
|
},
|
||||||
"keyId": "toolhub-targets-2026-rsa3072",
|
"keyId": "toolhub-targets-2026-rsa3072",
|
||||||
"schema": 2,
|
"schema": 2,
|
||||||
"version": 20260514103247
|
"version": 20260514104438
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
FaKtS+QxUdi5mfcpY1c3/2lFN/9ZYMdXlhIM+Mtvzyz+K4Kp27beml/iGWWvk6q2LxQnOT70DNwZA+GK5viK+5ENen0xW2cmDHw2ETdl/SZ9dPfZraw6yXgzEF+CGsqS02fU0rilIr5lOc9sEOPGA5QDP0CXvV7zzvOWaT0K5rUn7XoTsy4gVFHCPjVN1jCEsM3svFiq9bZdhjHrasqavFtQ0f0NfLCyJA/IRpGhCllOku2klSe/nOE+9fa7EvVsU6vWIxIR/sP667Xxob5GC9hG9mKtefCAtob0PTIquT8Y8pbKWm43FpRW+GXO5UpiUik9OHGjPNO+sYNB/vkukAMJMONvavmh/+DXqpaUqXv9Gm1KrCLh6ChJnjihPZk+Hro76okQW3pJhsblwaC3lj6aYUNeW901/yh8FQxQE3QQRi/S3RB5uskvqe92tbWXUdFrcazuvblplJ/2lnayrcR8ggzoLl+ZkDP1VtX3paNChhmO2NFtj9W7lOhUXvcG
|
lcUYKpPt8XY3inn6Lt0GjCE4zBryJiafB2j7gBT6DkH12WR4nF4u3zSlAEEKu+aKAfMUYfupb1qOltGliIy/RtVAPWcVClLuQEsCVsZ0lP9IUiXIrsoKCQLRnD6K+0lPqY1NDtZK/rouA3q+j9AIqcvA6KUH3dG44LufV59xAPo5/XGF96sUcLGdGueZbNOgxR0RhJll2cUtSAP78YQob8iZxzoF1HlhI0Wzhlgqpo2qQdHJzDGigalgYWYjjkxahhZGjQlw9xBrf5KMJK+h0nD8BeKWyOO+Ieh8fFSuTY6r7qu9tj5cTLVorgP86YjSHinInU5n/XUe9oHGOg8waN81M5XWurLfIsxL7Sth2skix+n3s6KcEDp5hhjzydmhayHt9v2scQUlnIZdA2S0yw5ewwVIzBT5ohPEeKmSYzGJJLJPTdXkLxUbsL/P+hFO7dxqm2qT/uGF6PRup60uGAG94MfJ6iIQeLjLbzy9nUel/K8e/x1jDXn0WWAIFY/u
|
||||||
|
|||||||
Reference in New Issue
Block a user