feat: adapt ToolApp size to screen

This commit is contained in:
7015725
2026-05-13 07:31:28 +08:00
parent 080cb9abf7
commit 09f2aa4d07
4 changed files with 113 additions and 20 deletions

View File

@@ -418,9 +418,14 @@ FloatBallAppWM.prototype.addPanel = function(panel, x, y, which) {
// }
}
var panelLp0 = null;
try { panelLp0 = panel.getLayoutParams(); } catch (ePanelLp) { panelLp0 = null; }
var panelW = (panelLp0 && Number(panelLp0.width) > 0) ? Number(panelLp0.width) : android.view.WindowManager.LayoutParams.WRAP_CONTENT;
var panelH = (panelLp0 && Number(panelLp0.height) > 0) ? Number(panelLp0.height) : android.view.WindowManager.LayoutParams.WRAP_CONTENT;
var lp = new android.view.WindowManager.LayoutParams(
android.view.WindowManager.LayoutParams.WRAP_CONTENT,
android.view.WindowManager.LayoutParams.WRAP_CONTENT,
panelW,
panelH,
android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
flags,
android.graphics.PixelFormat.TRANSLUCENT
@@ -607,6 +612,65 @@ FloatBallAppWM.prototype.setToolAppContent = function(contentView) {
return false;
};
FloatBallAppWM.prototype.calculateToolAppLayout = function(shell) {
var sw = Math.max(1, Number(this.state.screen && this.state.screen.w || 0));
var sh = Math.max(1, Number(this.state.screen && this.state.screen.h || 0));
if (sw <= 1 || sh <= 1) {
try { var ss = this.getScreenSizePx(); sw = ss.w; sh = ss.h; } catch (eScreen) {}
}
var shortSide = Math.min(sw, sh);
var longSide = Math.max(sw, sh);
var isLandscape = sw > sh;
var marginX = this.dp(12);
var marginTop = this.dp(14);
var marginBottom = this.dp(14);
var targetW;
var targetH;
if (shortSide < this.dp(420)) {
// 小屏/分屏:接近全屏,避免内容被裁剪。
marginX = this.dp(8);
marginTop = this.dp(8);
marginBottom = this.dp(8);
targetW = sw - marginX * 2;
targetH = sh - marginTop - marginBottom;
} else if (shortSide >= this.dp(720)) {
// 平板/大屏:不要铺满,保持卡片阅读宽度。
marginX = this.dp(28);
marginTop = this.dp(28);
marginBottom = this.dp(28);
targetW = Math.min(this.dp(680), Math.floor(sw * (isLandscape ? 0.56 : 0.72)));
targetH = Math.min(this.dp(780), sh - marginTop - marginBottom);
} else if (isLandscape) {
// 手机横屏:高度优先,宽度适当收窄。
marginX = this.dp(18);
marginTop = this.dp(12);
marginBottom = this.dp(12);
targetW = Math.min(this.dp(620), Math.floor(sw * 0.68));
targetH = sh - marginTop - marginBottom;
} else {
// 手机竖屏:左右留少量边距,高度随屏幕增长。
marginX = this.dp(12);
marginTop = this.dp(18);
marginBottom = this.dp(18);
targetW = Math.min(this.dp(560), sw - marginX * 2);
targetH = Math.min(Math.floor(sh * 0.90), sh - marginTop - marginBottom);
}
targetW = Math.max(this.dp(300), Math.min(targetW, sw - marginX * 2));
targetH = Math.max(this.dp(360), Math.min(targetH, sh - marginTop - marginBottom));
var x = Math.floor((sw - targetW) / 2);
var y = Math.floor((sh - targetH) / 2);
if (x < marginX) x = marginX;
if (y < marginTop) y = marginTop;
if (x + targetW > sw - marginX) x = Math.max(0, sw - marginX - targetW);
if (y + targetH > sh - marginBottom) y = Math.max(0, sh - marginBottom - targetH);
return { width: targetW, height: targetH, x: x, y: y, marginX: marginX, marginTop: marginTop, marginBottom: marginBottom, isLandscape: isLandscape, shortSide: shortSide, longSide: longSide };
};
FloatBallAppWM.prototype.showToolApp = function(route, resetStack) {
if (this.state.closing) return;
var r = this.isToolAppRoute(route) ? String(route) : "settings";
@@ -635,27 +699,21 @@ FloatBallAppWM.prototype.showToolApp = function(route, resetStack) {
this.updateToolAppShellChrome(this.getToolAppTitle(r), this.state.toolAppNavStack.length > 1);
this.setToolAppContent(raw);
var maxW = Math.floor(this.state.screen.w * 0.92);
var maxH = Math.floor(this.state.screen.h * 0.82);
shell.measure(
android.view.View.MeasureSpec.makeMeasureSpec(maxW, android.view.View.MeasureSpec.AT_MOST),
android.view.View.MeasureSpec.makeMeasureSpec(maxH, android.view.View.MeasureSpec.AT_MOST)
);
var pw = Math.max(this.dp(300), Math.min(maxW, shell.getMeasuredWidth()));
var ph = Math.max(this.dp(380), Math.min(maxH, shell.getMeasuredHeight()));
var layout = this.calculateToolAppLayout(shell);
var lp0 = shell.getLayoutParams();
if (!lp0) lp0 = new android.view.ViewGroup.LayoutParams(pw, ph);
lp0.width = pw; lp0.height = ph;
if (!lp0) lp0 = new android.view.ViewGroup.LayoutParams(layout.width, layout.height);
lp0.width = layout.width; lp0.height = layout.height;
shell.setLayoutParams(lp0);
if (!this.state.addedViewer || this.state.viewerPanel !== shell) {
var pos = this.getBestPanelPosition(pw, ph, this.state.ballLp.x, this.state.ballLp.y, this.getDockInfo().ballSize);
this.addPanel(shell, pos.x, pos.y, "tool_app");
this.addPanel(shell, layout.x, layout.y, "tool_app");
} else {
try {
if (this.state.viewerPanelLp) {
this.state.viewerPanelLp.width = pw;
this.state.viewerPanelLp.height = ph;
this.state.viewerPanelLp.width = layout.width;
this.state.viewerPanelLp.height = layout.height;
this.state.viewerPanelLp.x = layout.x;
this.state.viewerPanelLp.y = layout.y;
this.state.wm.updateViewLayout(shell, this.state.viewerPanelLp);
}
} catch (eUpd) { safeLog(this.L, 'w', "tool_app update layout fail: " + String(eUpd)); }

View File

@@ -58,8 +58,8 @@
"size": 237123
},
"th_15_extra.js": {
"sha256": "554092fb880e1f645e8665feac752b7412c3a9b604f960ad73f7fa889c8e39a8",
"size": 73786
"sha256": "44d19f0012f4182b9f9831d4f5a747b43d3b726f98e0480e6c79f54eeff70a5e",
"size": 76125
},
"th_16_entry.js": {
"sha256": "e7c99c3dfbd6aedab05551426955081ae6cae034754f2f557cefa01dc75dc001",
@@ -68,5 +68,5 @@
},
"keyId": "toolhub-targets-2026-rsa3072",
"schema": 2,
"version": 20260512232713
"version": 20260512233123
}

View File

@@ -1 +1 @@
Y5kHcy+jDtyrB0AAvEgLdWkQr85CJ7UAvOtzDrp93yI2c+PAItrzWjh+inSskBv7UBa7bHIDXGHVPBN9O5qIPn2Zgb01baozxz+KqO4WomLdEKWTOrRhrla2rJAKf7hcrTLnI2WjHWgg2kMikypvm1S45vcwu1u4uVBEFwE9EExrvjmQiHShqWTJ8ejiMbV3AqQFKCA0QpLujPscedW8YFJOpTJarwKIwSTuAGJdLtKh7ixgzB46kcqkxb+bVdi0+kEblY+heYlTxP5p7F75n0X1aIOuRXYnuGf3ODQi+rioTHYRTQGoJ36SNzxgIHS0JyEDgeduJEhaYaYXLz7BaKFFsJ+2SWPyKS0rx+XW+j91Am9C+wCXKNcPa5/r1y1D/hxtEHSK/YEYVX7IYrCNx3xMJVfILzpCB9lFpEiHNjw0qZU/hjXnRzJhstkK7wrMt6kfvmX7feG34a3t8jlDa0H7Kc3BfkO1wn+wT/P/VurdiaEa5xPU6OPUnyb4fdHY
eHDpnB+6LIjkd8UjiiNeI6CUb0vK01Dc+HGNJRLJBbjiRCLMTHYiDulV9qDmMDrNPJy4fKr8Wmdz6Lz0AMkv9cbWEut+Fb7jZJXzwIt967XJsKwyQMdPb/N7wZ5oLvdrDxJXbp833FKlnsNahhcrg92Jw3z5qRgBYJQ5JV4CKPkMAXG6w80Y1d7LUhbJsBUtZwGOA2qMykefFVl1qEO67Ljm0pyeqaFqTKcTmmIn955Ni4f8q/gaaR+mz66WhKy/YUhXIYwXSIsW4eF9kkDe3N2NW77goDNKAn4E1Hg9qsObiWxb452zVwhdR/S8J3nk7vLO6N/FVf0+PxT24W5G+S/BDChTz3fwOsS2DUI2ZkygFn9leF/z8Nmivf2utwkgrZbJ/xkSirvYxZ2KzwRY7VSLM7ESPBBpx52EVK6HlVuZL7v+rlr/Yb+lzXvhgtg9s4btLJH9GGtdJVPGItLEBPYd9fi8J+Xupd6nGDHFVMZqULXoK+3a96FqsQr2pqKB

View File

@@ -0,0 +1,35 @@
#!/usr/bin/env python3
import pathlib
import re
import sys
root = pathlib.Path(__file__).resolve().parents[1]
extra = (root / "code" / "th_15_extra.js").read_text(encoding="utf-8")
checks = []
def check(name, ok):
checks.append((name, bool(ok)))
check("has calculateToolAppLayout", "FloatBallAppWM.prototype.calculateToolAppLayout" in extra)
check("layout uses screen orientation", "isLandscape" in extra and "shortSide" in extra and "longSide" in extra)
check("layout has tiny screen branch", "shortSide < this.dp(420)" in extra)
check("layout has tablet/large screen branch", "shortSide >= this.dp(720)" in extra)
check("layout applies margins", "marginX" in extra and "marginTop" in extra and "marginBottom" in extra)
show_match = re.search(r"FloatBallAppWM\.prototype\.showToolApp\s*=\s*function\([^)]*\)\s*\{(?P<body>.*?)\n\};", extra, re.S)
show_body = show_match.group("body") if show_match else ""
check("showToolApp exists", bool(show_match))
check("showToolApp uses calculateToolAppLayout", "this.calculateToolAppLayout" in show_body)
check("showToolApp applies adaptive width", "layout.width" in show_body and "layout.height" in show_body)
check("showToolApp updates x/y when reusing root", "viewerPanelLp.x = layout.x" in show_body and "viewerPanelLp.y = layout.y" in show_body)
check("showToolApp addPanel uses adaptive x/y", "this.addPanel(shell, layout.x, layout.y" in show_body)
check("showToolApp no fixed 0.92/0.82 sizing", "0.92" not in show_body and "0.82" not in show_body)
failed = [name for name, ok in checks if not ok]
if failed:
print("ToolApp adaptive-size verification FAILED:")
for name in failed:
print(" - " + name)
sys.exit(1)
print("ToolApp adaptive-size verification OK")