diff --git a/code/th_02_core.js b/code/th_02_core.js index 1e370cd..77575a0 100644 --- a/code/th_02_core.js +++ b/code/th_02_core.js @@ -43,6 +43,8 @@ function FloatBallAppWM(logger) { viewerPanelLp: null, viewerPanelType: null, panelBackCallbackEntries: [], + predictiveBackIndicatorView: null, + predictiveBackIndicatorLp: null, // 设置类 UI App 化:单窗口页面栈(settings -> 子页面 -> 编辑页) toolAppActive: false, diff --git a/code/th_09_animation.js b/code/th_09_animation.js index 62ce117..4e6982d 100644 --- a/code/th_09_animation.js +++ b/code/th_09_animation.js @@ -266,13 +266,77 @@ FloatBallAppWM.prototype.handleSystemUiDismiss = function(reason) { return false; }; +FloatBallAppWM.prototype.hidePanelPredictiveBackIndicator = function() { + try { + var v = this.state.predictiveBackIndicatorView; + if (v && this.state.wm) { + try { this.state.wm.removeView(v); } catch (eRm) {} + } + this.state.predictiveBackIndicatorView = null; + this.state.predictiveBackIndicatorLp = null; + } catch (e) {} +}; + +FloatBallAppWM.prototype.showPanelPredictiveBackIndicator = function(edge) { + try { + if (!this.state.wm) return null; + var v = this.state.predictiveBackIndicatorView; + var lp = this.state.predictiveBackIndicatorLp; + var size = this.dp(46); + var edgeLeft = Number(edge) !== 1; + if (!v) { + v = new android.widget.TextView(context); + v.setText(edgeLeft ? "‹" : "›"); + v.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 30); + v.setTypeface(null, android.graphics.Typeface.BOLD); + v.setGravity(android.view.Gravity.CENTER); + v.setTextColor(android.graphics.Color.WHITE); + try { + var bg = new android.graphics.drawable.GradientDrawable(); + bg.setShape(android.graphics.drawable.GradientDrawable.OVAL); + var c = (this.ui && this.ui.colors && this.ui.colors.primary) ? this.ui.colors.primary : android.graphics.Color.parseColor("#005BC0"); + bg.setColor(this.withAlpha ? this.withAlpha(c, 0.92) : c); + v.setBackground(bg); + v.setElevation(this.dp(12)); + } catch (eBg) {} + lp = new android.view.WindowManager.LayoutParams( + size, + size, + android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, + android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | + android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | + android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, + android.graphics.PixelFormat.TRANSLUCENT + ); + lp.gravity = (edgeLeft ? android.view.Gravity.START : android.view.Gravity.END) | android.view.Gravity.CENTER_VERTICAL; + lp.x = this.dp(6); + lp.y = 0; + v.setAlpha(0); + try { this.state.wm.addView(v, lp); } catch (eAdd) { return null; } + this.state.predictiveBackIndicatorView = v; + this.state.predictiveBackIndicatorLp = lp; + } else { + try { v.setText(edgeLeft ? "‹" : "›"); } catch (eTxt) {} + if (lp) { + lp.gravity = (edgeLeft ? android.view.Gravity.START : android.view.Gravity.END) | android.view.Gravity.CENTER_VERTICAL; + } + } + return v; + } catch (e) { + safeLog(this.L, 'w', "show predictive back indicator fail: " + String(e)); + } + return null; +}; + FloatBallAppWM.prototype.resetPanelPredictiveBackVisual = function(panel) { try { - if (!panel) return; - panel.setAlpha(1.0); - panel.setTranslationX(0); - panel.setScaleX(1.0); - panel.setScaleY(1.0); + if (panel) { + panel.setAlpha(1.0); + panel.setTranslationX(0); + panel.setScaleX(1.0); + panel.setScaleY(1.0); + } + this.hidePanelPredictiveBackIndicator(); } catch (e) {} }; @@ -292,6 +356,15 @@ FloatBallAppWM.prototype.applyPanelPredictiveBackProgress = function(panel, even var s = 1.0 - 0.025 * p; panel.setScaleX(s); panel.setScaleY(s); + + // overlay 窗口下系统自己的预测性返回箭头在部分 ColorOS 版本不可见,额外绘制一个轻量边缘提示。 + var ind = this.showPanelPredictiveBackIndicator(edge); + if (ind) { + ind.setAlpha(Math.min(1.0, 0.20 + 0.80 * p)); + ind.setScaleX(0.82 + 0.22 * p); + ind.setScaleY(0.82 + 0.22 * p); + ind.setTranslationX(dir * this.dp(18) * p); + } } catch (e) {} }; diff --git a/manifest.json b/manifest.json index efed64e..6db5d1d 100644 --- a/manifest.json +++ b/manifest.json @@ -6,8 +6,8 @@ "size": 52546 }, "th_02_core.js": { - "sha256": "2274feddccb87873d81ac0337e14de9998bb9fa8600cccfe16cbc4552d05284b", - "size": 4237 + "sha256": "72c208f17d79c35926f30ab00482f0cf901d7aa42a2c703836e35b6d9953840a", + "size": 4313 }, "th_03_icon.js": { "sha256": "717f7f37474d3616c2cd944581455f600020a850ec8812100d0546ec1302c987", @@ -34,8 +34,8 @@ "size": 7938 }, "th_09_animation.js": { - "sha256": "f7083cbbc1b3efad1dcbccf19185cf1ee530172164da40f94dadc50fc5e3d763", - "size": 31917 + "sha256": "35cb81040678cfb164992f1369fdb303424457fafa6a6fe0c74cbf9736f1263d", + "size": 34943 }, "th_10_shell.js": { "sha256": "0ed793079c2f6ba7d29f4c0d411705cb72419f45f572cbe37ed32ac16527a8bc", @@ -68,5 +68,5 @@ }, "keyId": "toolhub-targets-2026-rsa3072", "schema": 2, - "version": 20260512124303 + "version": 20260512232015 } diff --git a/manifest.sig b/manifest.sig index d617dda..421429c 100644 --- a/manifest.sig +++ b/manifest.sig @@ -1 +1 @@ -SZay6+P/vnwc/F7V2bwkn3pXI8IQ1aa3fLJI3/LaW3H9lYQuqIErWsbYVIzxvprjgs0KM3iEbynlIkvJDFVggvLcXoo/yZZAu1K10ZhuH7KACG1MGk7ViiGRzW5GMSLvM5zW2qtN2V/+Lj/c9XNZDxIS8hMswKaolXTWYwsiw1NKhWOjRxwzgXuzai2TMQdJRZM3frGsgt9sB/78fDczyFD9NPYkeAjywnAjnH6iLCaAEH8PsrFECDuwYqn4uE3sxO4XGp/JPEX6Un1zQB1QgaN+rTWjyCbAIqapBqb8xulY7/m8wUo9Ei+VnozOFbseldO/2axsFHeXa6XKttTuXKQvcYjWeYpezgDiPsXzoAtJyAS2JZ2lNsOGurHQuBBA6pH93+hP8sCltNzNgtZMT7lJhZxRH4+pFvm6bf3W9ZSSdNGlvAQ6hHok3U+k6YuSoBzT8IZHDyv1iW2p9KB655W0qYVMRn+Y73YXAhdfVlC/m0jhBkfiOLtulHn8x96z +PnK7gl+dD9S3+8iK6E0lRmWVT8ike/ZOKniNy3O3yIdUGIkLiMBQXSLshHsj4bL15MQOweu8o9FLSEgqj1Htk4Viao7K8QbYhaf92LMVnPMXiPcA0d6t/v0VO/QSNQT5h74dVCk9fnwBlzwrGrSsRUU5ejuwyDMyEOPFhZQLnetpjql2NSRQEOOX0UNfAT4BHjV/MSchiAzJE+wcAPudNLqdOGjKN2flmU8YVOt9zc2PFszCYW4gtWMp0ETCkp3Uw3BbY8FPkbz8u17zM8+WDrrHBUMAoMtUULtcHX0EBgrRsCvLPeSKJSWuJaltLYA5A+tAGz9w2BccptGrQhO4Sn7rMWOpqn+2ajkiutTllPYPGvOTSI6m+GiOvctuIG9NyeR8BJEdX4IVkY9f+wh2Qmp1HliKU6YOoy/hvpAa36nm1UNGzYuJ195TqBv6CFU6eEkdLb0IXHvDnmHX3KB39q5OyItyST5eKKnQ5irEo3AkPTOktqnJSSbGy4IbxOwD