diff --git a/code/th_04_theme.js b/code/th_04_theme.js index 6017c88..5d6f7ba 100644 --- a/code/th_04_theme.js +++ b/code/th_04_theme.js @@ -846,33 +846,49 @@ FloatBallAppWM.prototype.applyTextColorRecursive = function(v, colorInt) { }; FloatBallAppWM.prototype.updatePanelBackground = function(panelView) { - // 这段代码的主要内容/用途:统一为"主面板/设置面板/查看器面板"应用背景与文字颜色(自动/亮/暗三档),并输出调试日志(命中哪个颜色)。 + // 这段代码的主要内容/用途:统一为"主面板/设置面板/查看器面板"应用背景与文字颜色;SETTINGS_THEME=animal 时使用动物岛色,monet 时保持系统莫奈。 try { var bg = new android.graphics.drawable.GradientDrawable(); - bg.setCornerRadius(this.dp(22)); + var isDark = this.isDarkTheme(); + var settTheme = "animal"; + try { settTheme = String(this.config.SETTINGS_THEME || "animal"); } catch(eSetTheme) { settTheme = "animal"; } - var bgInt = this.getPanelBgColorInt(); + var bgInt = 0; + var tc = 0; + var stroke = 0; + var radiusDp = 22; + + if (settTheme === "animal" && this.getAnimalIslandTheme) { + var T = this.getAnimalIslandTheme(); + bgInt = this.withAlpha(isDark ? T.bg : T.bg2, isDark ? 0.96 : 0.94); + tc = T.text; + stroke = this.withAlpha(T.stroke, isDark ? 0.28 : 0.34); + radiusDp = 30; + } else { + bgInt = this.getPanelBgColorInt(); + tc = this.getPanelTextColorInt(bgInt); + var outlineColor = this.ui.colors._monetOutline || (isDark ? android.graphics.Color.parseColor("#8E918F") : android.graphics.Color.parseColor("#747775")); + stroke = this.withAlpha(outlineColor, isDark ? 0.26 : 0.20); + } + + bg.setCornerRadius(this.dp(radiusDp)); bg.setColor(bgInt); // 轻量描边:亮色时更明显,暗色时也保留一点边界(不提供自定义输入,避免设置页复杂化) var sw = this.dp(1); - var isDark = this.isDarkTheme(); - var outlineColor = this.ui.colors._monetOutline || (isDark ? android.graphics.Color.parseColor("#8E918F") : android.graphics.Color.parseColor("#747775")); - var stroke = this.withAlpha(outlineColor, isDark ? 0.26 : 0.20); try { bg.setStroke(sw, stroke); } catch(eS) { safeLog(null, 'e', "catch " + String(eS)); } panelView.setBackground(bg); - var tc = this.getPanelTextColorInt(bgInt); try { themeBgInt = bgInt; themeTextInt = tc; } catch(eT) { safeLog(null, 'e', "catch " + String(eT)); } this.applyTextColorRecursive(panelView, tc); - try { _th_log(this.L, "d", "[t]apply bg=" + _th_hex(bgInt) + " tx=" + _th_hex(tc)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } - + try { _th_log(this.L, "d", "[t]apply theme=" + settTheme + " bg=" + _th_hex(bgInt) + " tx=" + _th_hex(tc)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } try { _th_log(this.L, "d", - "[theme:apply] isDark=" + isDark + + "[theme:apply] theme=" + settTheme + + " isDark=" + isDark + " bg=" + _th_hex(bgInt) + " " + _th_argb(bgInt) + " text=" + _th_hex(tc) + " " + _th_argb(tc) + " stroke=" + _th_hex(stroke) diff --git a/code/th_15_extra.js b/code/th_15_extra.js index 7f764e0..292bab5 100644 --- a/code/th_15_extra.js +++ b/code/th_15_extra.js @@ -83,23 +83,50 @@ FloatBallAppWM.prototype.buildPanelView = function(panelType) { var isDark = this.isDarkTheme(); var C = this.ui.colors; + var settTheme = "animal"; + try { settTheme = String(this.config.SETTINGS_THEME || "animal"); } catch(eSetTheme) { settTheme = "animal"; } + var useAnimalPanel = (settTheme === "animal" && this.getAnimalIslandTheme); + var TPanel = null; + try { if (useAnimalPanel) TPanel = this.getAnimalIslandTheme(); } catch(eTPanel) { TPanel = null; useAnimalPanel = false; } + var bgColor = isDark ? C.bgDark : C.bgLight; var cardColor = isDark ? C.cardDark : C.cardLight; var textColor = isDark ? C.textPriDark : C.textPriLight; + var panelStrokeColor = isDark ? C.dividerDark : C.dividerLight; + var cardStrokeColor = isDark ? C.dividerDark : C.dividerLight; + var pressedCardColor = this.withAlpha(C.primary, 0.20); + var iconBubbleColor = pressedCardColor; + var iconTintColor = textColor; + var panelRadiusDp = 22; + var cardRadiusDp = 12; + var panelElevationDp = 8; + var cardElevationDp = 2; + + if (useAnimalPanel && TPanel) { + bgColor = this.withAlpha(isDark ? TPanel.bg : TPanel.bg2, isDark ? 0.96 : 0.94); + cardColor = TPanel.card; + textColor = TPanel.text; + panelStrokeColor = this.withAlpha(TPanel.stroke, isDark ? 0.28 : 0.34); + cardStrokeColor = this.withAlpha(TPanel.stroke, isDark ? 0.26 : 0.34); + pressedCardColor = isDark ? this.withAlpha(TPanel.primarySoft, 0.92) : this.withAlpha(TPanel.primarySoft, 0.98); + iconBubbleColor = isDark ? this.withAlpha(TPanel.card2, 0.92) : TPanel.primarySoft; + iconTintColor = TPanel.sub; + panelRadiusDp = 30; + cardRadiusDp = 22; + panelElevationDp = isDark ? 2 : 3; + cardElevationDp = isDark ? 1 : 2; + } var panel = new android.widget.LinearLayout(context); panel.setOrientation(android.widget.LinearLayout.VERTICAL); - // 面板背景:走统一主题色 API(支持 Monet、模板、自定义) - // 先用 updatePanelBackground 垫底,后续再加按钮等内容 - // 先设一个临时背景避免裸窗口闪烁 + // 面板背景:走统一主题色 API(支持 Monet/动物岛/自定义) + // 先设一个柔和临时背景避免裸窗口闪烁,最后再由 updatePanelBackground 统一兜底 try { - var tmpBg = new android.graphics.drawable.GradientDrawable(); - tmpBg.setColor(this.withAlpha(bgColor, this.config.PANEL_BG_ALPHA)); - tmpBg.setCornerRadius(this.dp(16)); + var tmpBg = this.ui.createStrokeDrawable(bgColor, panelStrokeColor, this.dp(1), this.dp(panelRadiusDp)); panel.setBackground(tmpBg); } catch(eTmp) {}; - try { panel.setElevation(this.dp(8)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } + try { panel.setElevation(this.dp(panelElevationDp)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } var padDp = this.config.PANEL_PADDING_DP; panel.setPadding( @@ -161,6 +188,25 @@ FloatBallAppWM.prototype.buildPanelView = function(panelType) { var self = this; + function makePanelCellDrawable(fillColor, pressColor, strokeColor, radiusDp) { + var sd = new android.graphics.drawable.StateListDrawable(); + var p = self.ui.createStrokeDrawable(pressColor, strokeColor, self.dp(1), self.dp(radiusDp)); + var n = self.ui.createStrokeDrawable(fillColor, strokeColor, self.dp(1), self.dp(radiusDp)); + sd.addState([android.R.attr.state_pressed], p); + sd.addState([], n); + return sd; + } + + function isAppLikeIcon(btnObj) { + try { + if (!btnObj) return false; + var tp = (btnObj.type == null) ? "" : String(btnObj.type); + var pkg = (btnObj.pkg == null) ? "" : String(btnObj.pkg); + if ((tp === "app" || tp === "shortcut") && pkg.length > 0) return true; + } catch(eAppLike) {} + return false; + } + scroll.setOnTouchListener(new JavaAdapter(android.view.View.OnTouchListener, { onTouch: function(v, e) { self.touchActivity(); return false; } })); @@ -193,10 +239,10 @@ FloatBallAppWM.prototype.buildPanelView = function(panelType) { lp.setMargins(gapPx, gapPx, gapPx, gapPx); cell.setLayoutParams(lp); - // 单元格背景:如果是有功能的按钮,给个卡片背景;否则透明 + // 单元格背景:如果是有功能的按钮,给柔和卡片背景;否则透明 if (btnCfg) { - cell.setBackground(self.ui.createRoundDrawable(cardColor, self.dp(12))); - try { cell.setElevation(self.dp(2)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } + cell.setBackground(makePanelCellDrawable(cardColor, pressedCardColor, cardStrokeColor, cardRadiusDp)); + try { cell.setElevation(self.dp(cardElevationDp)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } } else { // 空格子占位 } @@ -207,9 +253,9 @@ FloatBallAppWM.prototype.buildPanelView = function(panelType) { iv.setImageDrawable(dr); // 如果图标是白色的(通常是系统图标),且我们在亮色卡片上,可能需要染色 // 但 resolveIconDrawable 逻辑比较复杂,这里暂时不强制染色,除非用户配置了 TINT - if (!isDark && btnCfg && !btnCfg.type && !btnCfg.pkg) { - // 简单的系统图标在亮色模式下可能看不清,染成深色 - try { iv.setColorFilter(C.textPriLight, android.graphics.PorterDuff.Mode.SRC_IN); } catch(eCF) { safeLog(null, 'e', "catch " + String(eCF)); } + if (btnCfg && !isAppLikeIcon(btnCfg) && !btnCfg.iconPath) { + // ShortX/系统图标与问号占位走主题色,避免灰黑重阴影感 + try { iv.setColorFilter(useAnimalPanel ? iconTintColor : (isDark ? C.textPriDark : C.textPriLight), android.graphics.PorterDuff.Mode.SRC_IN); } catch(eCF) { safeLog(null, 'e', "catch " + String(eCF)); } } } @@ -218,7 +264,23 @@ FloatBallAppWM.prototype.buildPanelView = function(panelType) { this.dp(this.config.PANEL_ICON_SIZE_DP) ); iv.setLayoutParams(ivLp); - cell.addView(iv); + if (btnCfg && useAnimalPanel && !isAppLikeIcon(btnCfg)) { + var iconBubble = new android.widget.FrameLayout(context); + iconBubble.setForegroundGravity(android.view.Gravity.CENTER); + iconBubble.setBackground(self.ui.createStrokeDrawable(iconBubbleColor, self.withAlpha(TPanel.stroke, isDark ? 0.20 : 0.24), self.dp(1), self.dp(15))); + iconBubble.setPadding(self.dp(4), self.dp(4), self.dp(4), self.dp(4)); + var bubbleLp = new android.widget.LinearLayout.LayoutParams(self.dp(38), self.dp(38)); + iconBubble.setLayoutParams(bubbleLp); + var ivInBubbleLp = new android.widget.FrameLayout.LayoutParams( + self.dp(self.config.PANEL_ICON_SIZE_DP), + self.dp(self.config.PANEL_ICON_SIZE_DP), + android.view.Gravity.CENTER + ); + iconBubble.addView(iv, ivInBubbleLp); + cell.addView(iconBubble); + } else { + cell.addView(iv); + } if (this.config.PANEL_LABEL_ENABLED) { var tv = new android.widget.TextView(context); @@ -242,7 +304,7 @@ FloatBallAppWM.prototype.buildPanelView = function(panelType) { (function(index, btnObj) { cell.setClickable(true); // 使用 Ripple 效果增强点击反馈 - var rippleDr = self.ui.createRippleDrawable(cardColor, self.withAlpha(C.primary, 0.2), self.dp(12)); + var rippleDr = makePanelCellDrawable(cardColor, pressedCardColor, cardStrokeColor, cardRadiusDp); cell.setBackground(rippleDr); cell.setOnClickListener(new android.view.View.OnClickListener({ diff --git a/manifest.json b/manifest.json index 63d92e6..236599b 100644 --- a/manifest.json +++ b/manifest.json @@ -14,8 +14,8 @@ "size": 5598 }, "th_04_theme.js": { - "sha256": "11f5971378f2ded631a5066ba158452f5a030aa2efac26f6b16928ce779f193b", - "size": 40227 + "sha256": "35ca63c9b142c0debc54f6ffd4742b29585f7c77d39c6bc334dc8fb6c76d372f", + "size": 40814 }, "th_05_persistence.js": { "sha256": "7d913b2caddf04c41ca13023c06763c03a7e372bb31080af37e7a3b2aa81d5f8", @@ -58,8 +58,8 @@ "size": 262019 }, "th_15_extra.js": { - "sha256": "36a7adf784921de6f4c66a772175ec99e61c9f5be8545cc6cb394c0f96601033", - "size": 97990 + "sha256": "9880128b2d5ad5abedd38aa732bf1934e2e97535aea13095a62c5ac8c71293e7", + "size": 101106 }, "th_16_entry.js": { "sha256": "e7c99c3dfbd6aedab05551426955081ae6cae034754f2f557cefa01dc75dc001", @@ -68,5 +68,5 @@ }, "keyId": "toolhub-targets-2026-rsa3072", "schema": 2, - "version": 20260518190147 + "version": 20260518192400 } diff --git a/manifest.sig b/manifest.sig index 0c58888..483cb7d 100644 --- a/manifest.sig +++ b/manifest.sig @@ -1 +1 @@ -VZkj5FB7IIEkKImiDaunHarfhGsZ8aXkVOeGHBdwrapSZJ9AZZ/7CMt6qSG3PI4GBHfcp229jIWWOI5T6rCND1piKdLmYAkPNjXW47X0xaB6YMvyXKALuPVvm+mFcAqNXBtOlQNjWPAnimdypVmlnzc1wIkGAPWTJRpDRD2bSvHFbZeFyZp8qhyAu5pR4GisecgEZ5gqTgE+BDo+gs3LjpLphekeg9bZWzKX4p1hsttPM2oC6rMLW4SkPaqVsOWJOxJgOAaoZP9dR2bh4/W97WM1dGqxrdANmofg+wpwA2p7KH9DUxPdJqwIe6adCiLP/jXwb2twLuZvY5AuMWj8Im4c4yAmUrE2RdocHl6NStykcx3b9WlQPHPHBfYHFka47+3qHSYPnB5IyxCGMC1d4XxZ34nhbc7yE9aFarjQC9ky1KtBS2hvM58MzE87GiudEb2DJRNYbebdh0/pocnDSXb1rKy16TQWFBk9r1xS7F/mviDN9vKsL1My47q6kLrd +N8cv7NaVdm1RcA8QxFnyYyuJEk84L9XPqaZmRtjIjkwdulNa6tJu2r4luZrqtip0eUHtBkbcDnTHDaUS6vfWmT6i/4Wdzoa8fujHfJrpZbqWJseMshzjJZazPn9eUmQcPxhDEahksGu48W9aGrscfsnQgI4qeih/dhs/sNCdVlPqQ1oil+dAnqZ9UWmWMVODEapHXSkANPWopeXBAs5Gw3KJhhUb4wKb/bHUJ4FxTfJr77dXbdWNXn84fbPzIOkLt5Ru6j7b5SJF1+vHrgJy4U3yamlrYdsOie5qjNqDlquhKR4eiM7sTialhtPKmWB7temDCQL0z0c5BZkqolnOP68SRB3DqcRozYmjrWjWKM1Ji2epwiSjHICgXoauDTrVmHuLPXU+1Y30Ao33Y/OXF1bkhklKwkESnG2x8k2SpROP9DCkcFteNkZZTViAPM6E50cV5WYrrCJw3LCzeilAEKvjYHic7LqS7xW0Uj/53VEXa0b1IK29WldWpEpVbemQ