Pin color picker actions in popup footer

This commit is contained in:
7015725
2026-05-23 06:00:44 +08:00
parent 757a60d15d
commit 095f7ccb39
4 changed files with 86 additions and 63 deletions

View File

@@ -109,6 +109,46 @@ FloatBallAppWM.prototype.showColorPickerPopup = function(opts) {
var isFollowTheme = !currentColor; var isFollowTheme = !currentColor;
var currentBaseRgbHex = extractTintRgbHex(currentColor); var currentBaseRgbHex = extractTintRgbHex(currentColor);
var currentAlphaByte = extractTintAlphaByte(currentColor); var currentAlphaByte = extractTintAlphaByte(currentColor);
var alphaSeek = null;
var alphaValTv = null;
var updatePreviewFn = function() {};
var updateValueTvFn = function() {};
var refreshRecentGridFn = function() {};
var refreshCommonGridFn = function() {};
var syncRgbSeeksFn = function() {};
// 操作按钮:对齐设置页/按钮管理页的 chip + 主按钮视觉。
function createColorPanelActionButton(label, primary, onClick) {
var b = new android.widget.TextView(context);
b.setText(label);
b.setGravity(android.view.Gravity.CENTER);
b.setSingleLine(true);
b.setTypeface(null, android.graphics.Typeface.BOLD);
try { b.setIncludeFontPadding(false); } catch(eFontPad) {}
if (primary) {
b.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 15);
b.setTextColor(android.graphics.Color.WHITE);
b.setPadding(self.dp(18), 0, self.dp(18), 0);
try { b.setMinHeight(self.dp(52)); } catch(eMinH1) {}
try { b.setBackground(self.ui.createStrokeDrawable(T.primaryDeep, self.withAlpha(T.brown || T.primaryDeep, isDark ? 0.28 : 0.18), self.dp(1), self.dp(26))); } catch(eBg1) {}
try { b.setElevation(self.dp(1)); } catch(eElev) {}
} else {
b.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 15);
b.setTextColor(T.brown || T.sub);
b.setPadding(self.dp(16), 0, self.dp(16), 0);
try { b.setMinHeight(self.dp(52)); } catch(eMinH2) {}
try { b.setBackground(self.ui.createStrokeDrawable(T.card2 || T.card, self.withAlpha(T.stroke || T.brown, isDark ? 0.42 : 0.55), self.dp(1), self.dp(26))); } catch(eBg2) {}
try { b.setElevation(self.dp(1)); } catch(eElev2) {}
}
try { b.setClickable(true); b.setFocusable(true); } catch(eClickable) {}
b.setOnClickListener(new android.view.View.OnClickListener({
onClick: function(v) {
self.touchActivity();
try { if (onClick) onClick(v); } catch(eBtn) { safeLog(self.L, 'e', "color panel action err=" + String(eBtn)); }
}
}));
return b;
}
var popupResult = self.showPopupOverlay({ var popupResult = self.showPopupOverlay({
title: "换颜色", title: "换颜色",
@@ -146,7 +186,7 @@ FloatBallAppWM.prototype.showColorPickerPopup = function(opts) {
try { try {
var parsed = android.graphics.Color.parseColor(selectedColor); var parsed = android.graphics.Color.parseColor(selectedColor);
dr.setColorFilter(parsed, android.graphics.PorterDuff.Mode.SRC_IN); dr.setColorFilter(parsed, android.graphics.PorterDuff.Mode.SRC_IN);
} catch(e) { safeLog(null, 'e', "catch " + String(e)); } } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
} else { } else {
try { dr.clearColorFilter(); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } try { dr.clearColorFilter(); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
} }
@@ -154,8 +194,9 @@ FloatBallAppWM.prototype.showColorPickerPopup = function(opts) {
} else { } else {
previewIv.setImageDrawable(null); previewIv.setImageDrawable(null);
} }
} catch(e) { safeLog(null, 'e', "catch " + String(e)); } } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
} }
updatePreviewFn = updatePreview;
updatePreview(); updatePreview();
// ========== 最近使用颜色 ========== // ========== 最近使用颜色 ==========
@@ -239,6 +280,7 @@ FloatBallAppWM.prototype.showColorPickerPopup = function(opts) {
} }
} catch(e) { safeLog(null, 'e', "catch " + String(e)); } } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
} }
refreshRecentGridFn = refreshRecentGrid;
refreshRecentGrid(); refreshRecentGrid();
// 21 色常用颜色 // 21 色常用颜色
@@ -328,6 +370,7 @@ FloatBallAppWM.prototype.showColorPickerPopup = function(opts) {
} }
} catch(e) { safeLog(null, 'e', "catch " + String(e)); } } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
} }
refreshCommonGridFn = refreshCommonGrid;
// 颜色值显示 // 颜色值显示
var valueTv = new android.widget.TextView(context); var valueTv = new android.widget.TextView(context);
@@ -339,6 +382,7 @@ FloatBallAppWM.prototype.showColorPickerPopup = function(opts) {
function updateValueTv() { function updateValueTv() {
valueTv.setText(isFollowTheme ? "当前:跟随岛屿主题" : ("当前:" + (selectedColor || "无"))); valueTv.setText(isFollowTheme ? "当前:跟随岛屿主题" : ("当前:" + (selectedColor || "无")));
} }
updateValueTvFn = updateValueTv;
updateValueTv(); updateValueTv();
// RGB 滑块 // RGB 滑块
@@ -412,6 +456,7 @@ FloatBallAppWM.prototype.showColorPickerPopup = function(opts) {
rgbValTvs[2].setText(String(initB)); rgbValTvs[2].setText(String(initB));
} catch(e) { safeLog(null, 'e', "catch " + String(e)); } } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
} }
syncRgbSeeksFn = syncRgbSeeks;
syncRgbSeeks(); syncRgbSeeks();
// 透明度滑块 // 透明度滑块
@@ -427,14 +472,14 @@ FloatBallAppWM.prototype.showColorPickerPopup = function(opts) {
alphaLabel.setMinWidth(self.dp(20)); alphaLabel.setMinWidth(self.dp(20));
alphaRow.addView(alphaLabel); alphaRow.addView(alphaLabel);
var alphaSeek = new android.widget.SeekBar(context); alphaSeek = new android.widget.SeekBar(context);
alphaSeek.setMax(255); alphaSeek.setMax(255);
var alphaSeekLp = new android.widget.LinearLayout.LayoutParams(0, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT, 1); var alphaSeekLp = new android.widget.LinearLayout.LayoutParams(0, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT, 1);
alphaSeekLp.setMargins(self.dp(8), 0, self.dp(8), 0); alphaSeekLp.setMargins(self.dp(8), 0, self.dp(8), 0);
alphaSeek.setLayoutParams(alphaSeekLp); alphaSeek.setLayoutParams(alphaSeekLp);
alphaRow.addView(alphaSeek); alphaRow.addView(alphaSeek);
var alphaValTv = new android.widget.TextView(context); alphaValTv = new android.widget.TextView(context);
alphaValTv.setTextColor(subTextColor); alphaValTv.setTextColor(subTextColor);
alphaValTv.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 11); alphaValTv.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 11);
alphaValTv.setMinWidth(self.dp(28)); alphaValTv.setMinWidth(self.dp(28));
@@ -460,59 +505,25 @@ FloatBallAppWM.prototype.showColorPickerPopup = function(opts) {
alphaValTv.setText(String(currentAlphaByte)); alphaValTv.setText(String(currentAlphaByte));
content.addView(alphaRow); content.addView(alphaRow);
// 操作按钮:对齐设置页/按钮管理页的 chip + 主按钮视觉 // 底部操作按钮放到 showPopupOverlay 的固定 footer 中,避免默认首屏看不到
function createColorPanelActionButton(label, primary, onClick) { },
var b = new android.widget.TextView(context); footerBuilder: function(footer, closePopup) {
b.setText(label);
b.setGravity(android.view.Gravity.CENTER);
b.setSingleLine(true);
b.setTypeface(null, android.graphics.Typeface.BOLD);
try { b.setIncludeFontPadding(false); } catch(eFontPad) {}
if (primary) {
// 与设置页底部“保存布置”一致主色胶囊、44dp 高、轻描边。
b.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 15);
// 颜色面板里不用高饱和青色,改成更沉稳的深绿主按钮。
b.setTextColor(android.graphics.Color.WHITE);
b.setPadding(self.dp(18), 0, self.dp(18), 0);
try { b.setMinHeight(self.dp(52)); } catch(eMinH1) {}
try { b.setBackground(self.ui.createStrokeDrawable(T.primaryDeep, self.withAlpha(T.brown || T.primaryDeep, isDark ? 0.28 : 0.18), self.dp(1), self.dp(26))); } catch(eBg1) {}
try { b.setElevation(self.dp(1)); } catch(eElev) {}
} else {
// 与设置页按钮一致:次级也用大圆角按钮,不再做小 chip。
b.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 15);
// 次级按钮走设置页里的奶油/描边感,不再用薄荷绿底。
b.setTextColor(T.brown || T.sub);
b.setPadding(self.dp(16), 0, self.dp(16), 0);
try { b.setMinHeight(self.dp(52)); } catch(eMinH2) {}
try { b.setBackground(self.ui.createStrokeDrawable(T.card2 || T.card, self.withAlpha(T.stroke || T.brown, isDark ? 0.42 : 0.55), self.dp(1), self.dp(26))); } catch(eBg2) {}
try { b.setElevation(self.dp(1)); } catch(eElev2) {}
}
try { b.setClickable(true); b.setFocusable(true); } catch(eClickable) {}
b.setOnClickListener(new android.view.View.OnClickListener({
onClick: function(v) {
self.touchActivity();
try { if (onClick) onClick(v); } catch(eBtn) { safeLog(self.L, 'e', "color panel action err=" + String(eBtn)); }
}
}));
return b;
}
var actionRow = new android.widget.LinearLayout(context); var actionRow = new android.widget.LinearLayout(context);
actionRow.setOrientation(android.widget.LinearLayout.HORIZONTAL); actionRow.setOrientation(android.widget.LinearLayout.HORIZONTAL);
actionRow.setGravity(android.view.Gravity.CENTER_VERTICAL); actionRow.setGravity(android.view.Gravity.CENTER_VERTICAL);
actionRow.setPadding(self.dp(10), self.dp(10), self.dp(10), self.dp(12)); actionRow.setPadding(self.dp(10), self.dp(6), self.dp(10), self.dp(4));
var btnClear = createColorPanelActionButton("恢复默认", false, function() { var btnClear = createColorPanelActionButton("恢复默认", false, function() {
isFollowTheme = true; isFollowTheme = true;
selectedColor = ""; selectedColor = "";
updatePreview();
updateValueTv();
refreshRecentGrid();
refreshCommonGrid();
syncRgbSeeks();
alphaSeek.setProgress(255);
alphaValTv.setText("255");
currentAlphaByte = 255; currentAlphaByte = 255;
try { updatePreviewFn(); } catch(eUp) {}
try { updateValueTvFn(); } catch(eVal) {}
try { refreshRecentGridFn(); } catch(eRecent) {}
try { refreshCommonGridFn(); } catch(eCommon) {}
try { syncRgbSeeksFn(); } catch(eSync) {}
try { if (alphaSeek) alphaSeek.setProgress(255); } catch(eAlphaSeek) {}
try { if (alphaValTv) alphaValTv.setText("255"); } catch(eAlphaTv) {}
}); });
var clearLp = new android.widget.LinearLayout.LayoutParams(0, self.dp(52)); var clearLp = new android.widget.LinearLayout.LayoutParams(0, self.dp(52));
clearLp.weight = 1; clearLp.weight = 1;
@@ -522,13 +533,9 @@ FloatBallAppWM.prototype.showColorPickerPopup = function(opts) {
var btnOk = createColorPanelActionButton("保存颜色", true, function() { var btnOk = createColorPanelActionButton("保存颜色", true, function() {
try { try {
var finalColor = isFollowTheme ? "" : String(selectedColor || ""); var finalColor = isFollowTheme ? "" : String(selectedColor || "");
if (!isFollowTheme && selectedColor) { if (!isFollowTheme && selectedColor) pushRecentColor(selectedColor);
pushRecentColor(selectedColor);
}
if (typeof onSelect === "function") { if (typeof onSelect === "function") {
try { onSelect(finalColor); } catch(eOnSelect) { try { onSelect(finalColor); } catch(eOnSelect) { safeLog(self.L, 'e', "colorPicker onSelect err=" + String(eOnSelect)); }
safeLog(self.L, 'e', "colorPicker onSelect err=" + String(eOnSelect));
}
} }
} catch(e) { } catch(e) {
safeLog(self.L, 'e', "colorPicker confirm err=" + String(e)); safeLog(self.L, 'e', "colorPicker confirm err=" + String(e));
@@ -540,7 +547,7 @@ FloatBallAppWM.prototype.showColorPickerPopup = function(opts) {
okLp.setMargins(self.dp(6), 0, 0, 0); okLp.setMargins(self.dp(6), 0, 0, 0);
actionRow.addView(btnOk, okLp); actionRow.addView(btnOk, okLp);
content.addView(actionRow, new android.widget.LinearLayout.LayoutParams( footer.addView(actionRow, new android.widget.LinearLayout.LayoutParams(
android.widget.LinearLayout.LayoutParams.MATCH_PARENT, android.widget.LinearLayout.LayoutParams.MATCH_PARENT,
android.widget.LinearLayout.LayoutParams.WRAP_CONTENT android.widget.LinearLayout.LayoutParams.WRAP_CONTENT
)); ));

View File

@@ -4592,6 +4592,7 @@ FloatBallAppWM.prototype.showPopupOverlay = function(opts) {
var title = String(opt.title || ""); var title = String(opt.title || "");
var onDismiss = (typeof opt.onDismiss === "function") ? opt.onDismiss : null; var onDismiss = (typeof opt.onDismiss === "function") ? opt.onDismiss : null;
var builder = (typeof opt.builder === "function") ? opt.builder : null; var builder = (typeof opt.builder === "function") ? opt.builder : null;
var footerBuilder = (typeof opt.footerBuilder === "function") ? opt.footerBuilder : null;
var PT = this.getIslandPickerTheme ? this.getIslandPickerTheme() : null; var PT = this.getIslandPickerTheme ? this.getIslandPickerTheme() : null;
var isDark = PT ? PT.isDark : this.isDarkTheme(); var isDark = PT ? PT.isDark : this.isDarkTheme();
@@ -4674,6 +4675,15 @@ FloatBallAppWM.prototype.showPopupOverlay = function(opts) {
)); ));
card.addView(scroll); card.addView(scroll);
var footer = new android.widget.LinearLayout(context);
footer.setOrientation(android.widget.LinearLayout.VERTICAL);
footer.setVisibility(android.view.View.GONE);
try { footer.setPadding(0, self.dp(6), 0, 0); } catch(eFooterPad) {}
card.addView(footer, new android.widget.LinearLayout.LayoutParams(
android.widget.LinearLayout.LayoutParams.MATCH_PARENT,
android.widget.LinearLayout.LayoutParams.WRAP_CONTENT
));
root.addView(card); root.addView(card);
root.setOnClickListener(new android.view.View.OnClickListener({ root.setOnClickListener(new android.view.View.OnClickListener({
@@ -4709,8 +4719,14 @@ FloatBallAppWM.prototype.showPopupOverlay = function(opts) {
if (typeof builder === "function") { if (typeof builder === "function") {
try { builder(content, closePopup); } catch(eB) { safeLog(self.L, 'e', "popup builder fail: " + String(eB)); } try { builder(content, closePopup); } catch(eB) { safeLog(self.L, 'e', "popup builder fail: " + String(eB)); }
} }
if (typeof footerBuilder === "function") {
try {
footerBuilder(footer, closePopup);
if (footer.getChildCount && footer.getChildCount() > 0) footer.setVisibility(android.view.View.VISIBLE);
} catch(eF) { safeLog(self.L, 'e', "popup footer builder fail: " + String(eF)); }
}
return { close: closePopup, content: content }; return { close: closePopup, content: content, footer: footer };
}; };
// 兼容旧入口:旧 ToolHub.js 不会自动加载新增 th_14_color_picker.js // 兼容旧入口:旧 ToolHub.js 不会自动加载新增 th_14_color_picker.js

View File

@@ -54,16 +54,16 @@
"size": 22308 "size": 22308
}, },
"th_14_color_picker.js": { "th_14_color_picker.js": {
"sha256": "d3ca89146e31e611e17d703ae9834d82794321e651b6ef156ade006227d231e7", "sha256": "2f6378fbb718d4b31cf11d3047cee6b32af93cfbb932442da29dd05225881432",
"size": 23587 "size": 23870
}, },
"th_14_icon_picker.js": { "th_14_icon_picker.js": {
"sha256": "1df5c4bf82e68de24d7b89c852a4d9878768451effe086e8ddb86620ecc98c35", "sha256": "1df5c4bf82e68de24d7b89c852a4d9878768451effe086e8ddb86620ecc98c35",
"size": 23906 "size": 23906
}, },
"th_14_panels.js": { "th_14_panels.js": {
"sha256": "1af01633720865a83a10a1e5261e3738d91be310195b014e17e579893eae90ee", "sha256": "fcbab7b835c4f020c258d8ddd81675e486572bc140dc6db4aa3bee3f9c2aa27d",
"size": 267207 "size": 268044
}, },
"th_14_schema_editor.js": { "th_14_schema_editor.js": {
"sha256": "5669d0b5a16f770bed24eedee24203df57f7cbc7910c840931e533adac1ef146", "sha256": "5669d0b5a16f770bed24eedee24203df57f7cbc7910c840931e533adac1ef146",
@@ -80,5 +80,5 @@
}, },
"keyId": "toolhub-targets-2026-rsa3072", "keyId": "toolhub-targets-2026-rsa3072",
"schema": 2, "schema": 2,
"version": 20260522213610 "version": 20260522220033
} }

View File

@@ -1 +1 @@
ipKGsoLWacyAl7V4tyWIsocOwZpxQujuC2v/Rg4bMJ6FpSmLI7KdwL9RFIWw4qRHN9/37S+0pkIjGj1FQeJ9dvnw80po2GI9hcZufG6Us4CTWeJrdEuGCTBI38yvPduhl/Wmdg1aGLVx9GqIcG+ALOLXslaHt2WVVgJQMShiGsZwgNRbFQ0uXhvT6EHzz3o09CPoF1E0xelI2r6EVlCX+iJtbvbHlsuCtmidPEHICK1ks6AsDT+O9YyFqEEDw0KP0KBQ3Y9ej+3RfmwNOrvKrVsm3Y3glb1biKnlXfSIjlArr/mQK/C6snUV3vX4hsu6lYnyhQQoSpMvtbZpjsf5yGFPKkx11Dqhc1MeVSTszhCEUP13jPS95EEv9CToV0k1B4kI9uFTP57Jityvx5NruFarBUvEvzyJKATb7o4a15hdwDfyLK+1ei7xLxWr/j5qOYtbvMgAf+KnmiRQauJS4az23DLMLypr0Jor4oBXL/SUCXCX2e0IK0Om/e54bE9v C96vTXwZOxNzf6dPnp6DLtQzgY1xdVSe+JAObGu78cZqXO4BNCooFVfLGN4/WaTICx6e6mJ/dtmRVnPtJVc39+EDSaDWUg1ELtD4pPW4u5a5r8qU0J7mCxpUvLcTowG0txvheU4Cu5FQqPdHuBgNiyS1J5pNu0WAHapVBhyR7PXgOA8gnzzSaYZyawO/tf6uG20nVS3cFnlcw+ImvmY0tdLUTnfoaRJZBZMDAy5P36oLZCb3NSoqKPSrNj2cWr6i0x+h5D1jdDxRDjBGpK/fRsJAh4CdZTch8pEQsHVlGakb5hLmGARF0WR3RMHOCVeJNj2LXza1ktx2apjfUPJj84neHBgTCj0BcfwrZ0VY52cwE7n5aJn9xdXMaOiPzlioF7fcN9gmMS6ib0+N9qpW2sqfSSXmiWVEuUvNS0f11w39WfzPI5UNE+rt5bwplIWCuiLPWu65wAewm5Fz+y49ysqYuhPJwUEfJ8HLn+wRJnFcaOdWGod2U3DSVLliwi5Y