diff --git a/powerbell/build.properties b/powerbell/build.properties index f071398..cff47d1 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Tue Dec 16 07:33:42 GMT 2025 +#Tue Dec 16 08:20:17 GMT 2025 stageCount=7 libraryProject= baseVersion=15.14 publishVersion=15.14.6 -buildCount=39 +buildCount=45 baseBetaVersion=15.14.7 diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/ColorPaletteDialog.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/ColorPaletteDialog.java index a246c8b..71395bc 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/ColorPaletteDialog.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/ColorPaletteDialog.java @@ -3,6 +3,7 @@ package cc.winboll.studio.powerbell.dialogs; import android.app.Dialog; import android.content.Context; import android.graphics.Color; +import android.graphics.drawable.GradientDrawable; import android.os.Bundle; import android.text.Editable; import android.text.TextUtils; @@ -13,8 +14,10 @@ import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.EditText; +import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.SeekBar; import android.widget.TextView; import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.powerbell.R; @@ -24,7 +27,7 @@ import cc.winboll.studio.powerbell.R; * @Date 2025/12/16 11:47 * @Describe 调色板对话框(支持颜色拾取、RGB输入、透明度/亮度调节,兼容 API29-30+ 小米机型) */ -public class ColorPaletteDialog extends Dialog implements View.OnClickListener { +public class ColorPaletteDialog extends Dialog implements View.OnClickListener, SeekBar.OnSeekBarChangeListener { // ====================== 常量定义(首屏可见,统一管理) ====================== public static final String TAG = "ColorPaletteDialog"; private static final int MAX_RGB_VALUE = 255; // RGB分量最大值(0-255) @@ -32,6 +35,8 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { private static final int BRIGHTNESS_STEP = 5; // 亮度调节步长(每次±5%,精准流畅) private static final int MIN_BRIGHTNESS = 10; // 亮度最小值(10%,避免全黑看不见) private static final int MAX_BRIGHTNESS = 200; // 亮度最大值(200%,避免过曝失真) + private static final int MAX_ALPHA_PERCENT = 100; // 透明度最大值(100%=不透明) + private static final int MIN_ALPHA_PERCENT = 0; // 透明度最小值(0%=完全透明) // ====================== 回调接口(紧跟常量,逻辑关联) ====================== public interface OnColorSelectedListener { @@ -39,12 +44,17 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { } // ====================== 成员变量(按优先级排序:核心数据→控件引用) ====================== - // 核心数据:原始基准值(用户输入/选择颜色时更新)+ 实时调节值(亮度变化时更新) + // 核心数据:原始基准值(用户输入/选择颜色时更新)+ 实时调节值(亮度/透明度变化时更新) private OnColorSelectedListener mListener; // 颜色选择回调(非空校验) private int mInitialColor; // 初始颜色(传入的默认颜色) - private int mCurrentColor; // 当前最终颜色(含亮度调节) + private int mCurrentColor; // 当前最终颜色(含亮度+透明度调节) private int mCurrentBrightnessPercent; // 当前亮度百分比(10%-200%) - private int mOriginalAlpha; // 原始透明度(固定,亮度不影响透明度) + // 透明度:百分比(0-100%,用户直观操作)+ 原始/实时值(0-255,颜色计算用) + private int mOriginalAlphaPercent; // 原始透明度百分比(基准值,用户输入/选色时更新) + private int mCurrentAlphaPercent; // 实时透明度百分比(调节进度条时更新) + private int mOriginalAlpha; // 原始透明度(0-255,基准值) + private int mCurrentAlpha; // 实时透明度(0-255,计算用) + // RGB:原始基准值+实时调节值 private int mOriginalR; // 原始R分量(基准值,用户输入/选色时更新) private int mOriginalG; // 原始G分量(基准值,用户输入/选色时更新) private int mOriginalB; // 原始B分量(基准值,用户输入/选色时更新) @@ -54,12 +64,14 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { // 并发控制标记:是否是应用程序自身在更新颜色(避免循环回调/重复触发) private static volatile boolean isAppSelfUpdatingColor = false; - // 控件引用(亮度改为「减号+数值+加号」底部布局) + // 控件引用(新增透明度进度条+文本) private ImageView ivColorPicker; // 颜色预览拾取框 private EditText etR; // R分量输入框(显示实时调节值) private EditText etG; // G分量输入框(显示实时调节值) private EditText etB; // B分量输入框(显示实时调节值) private EditText etColorValue; // 颜色值输入框(#AARRGGBB,显示最终值) + private SeekBar sbAlpha; // 透明度调节进度条(0-100%) + private TextView tvAlphaValue; // 透明度数值显示(X%) private TextView tvBrightnessMinus;// 亮度减少按钮(-) private TextView tvBrightnessValue;// 亮度数值显示(X%,直观易懂) private TextView tvBrightnessPlus; // 亮度增加按钮(+) @@ -77,8 +89,13 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { throw new IllegalArgumentException("OnColorSelectedListener can not be null!"); } - // 2. 解析初始颜色:原始基准值 = 实时值(初始无亮度调节) + // 2. 解析初始颜色:原始基准值 = 实时值(初始无调节) + // 透明度:初始颜色的alpha(0-255)转百分比(0-100%) this.mOriginalAlpha = Color.alpha(initialColor); + this.mOriginalAlphaPercent = alpha2Percent(mOriginalAlpha); + this.mCurrentAlpha = mOriginalAlpha; + this.mCurrentAlphaPercent = mOriginalAlphaPercent; + // RGB:初始颜色的RGB分量 this.mOriginalR = Color.red(initialColor); this.mOriginalG = Color.green(initialColor); this.mOriginalB = Color.blue(initialColor); @@ -92,6 +109,7 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { LogUtils.d(TAG, "init dialog success | 初始颜色:" + String.format("#%08X", initialColor) + " | 原始RGB:" + mOriginalR + "," + mOriginalG + "," + mOriginalB + + " | 原始透明度:" + mOriginalAlphaPercent + "%" + " | 初始亮度:" + mCurrentBrightnessPercent + "%"); } @@ -121,7 +139,7 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { // ====================== 初始化核心方法(职责单一,便于维护) ====================== /** - * 控件绑定(仅做ID绑定,无任何业务逻辑,避免初始化混乱) + * 控件绑定(新增透明度进度条+文本绑定) */ private void initViewBind(View view) { ivColorPicker = view.findViewById(R.id.iv_color_picker); @@ -129,6 +147,8 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { etG = view.findViewById(R.id.et_g); etB = view.findViewById(R.id.et_b); etColorValue = view.findViewById(R.id.et_color_value); + sbAlpha = view.findViewById(R.id.sb_alpha); + tvAlphaValue = view.findViewById(R.id.tv_alpha_value); tvBrightnessMinus = view.findViewById(R.id.tv_brightness_minus); tvBrightnessValue = view.findViewById(R.id.tv_brightness_value); tvBrightnessPlus = view.findViewById(R.id.tv_brightness_plus); @@ -137,6 +157,7 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { // 控件非空校验(小米低版本容错,绑定失败直接关闭对话框) if (ivColorPicker == null || etR == null || etG == null || etB == null || etColorValue == null + || sbAlpha == null || tvAlphaValue == null || tvBrightnessMinus == null || tvBrightnessValue == null || tvBrightnessPlus == null || tvConfirm == null || tvCancel == null) { LogUtils.e(TAG, "view bind failed | 请检查布局ID是否正确!"); @@ -161,15 +182,19 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { // 3. 颜色值输入框(显示当前最终颜色,格式#AARRGGBB,大写更规范) etColorValue.setText(String.format("#%08X", mCurrentColor)); - // 4. 亮度控件(显示默认100%,初始化按钮状态) + // 4. 透明度控件(进度条+文本,初始=原始透明度) + sbAlpha.setProgress(mCurrentAlphaPercent); + tvAlphaValue.setText(mCurrentAlphaPercent + "%"); + + // 5. 亮度控件(显示默认100%,初始化按钮状态) tvBrightnessValue.setText(mCurrentBrightnessPercent + "%"); updateBrightnessBtnStatus(); // 禁用边界值按钮(初始100%,都可用) - LogUtils.d(TAG, "init data complete | 原始透明度:" + mOriginalAlpha); + LogUtils.d(TAG, "init data complete | 原始透明度:" + mOriginalAlphaPercent + "%"); } /** - * 监听初始化(统一管理所有监听,延迟绑定避免初始化循环) + * 监听初始化(新增透明度进度条监听) */ private void initListener() { // 点击监听(按钮+颜色拾取框) @@ -178,7 +203,8 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { tvCancel.setOnClickListener(this); tvBrightnessMinus.setOnClickListener(this); tvBrightnessPlus.setOnClickListener(this); - + // 透明度进度条监听 + sbAlpha.setOnSeekBarChangeListener(this); // 输入框监听(RGB+颜色值,避免循环同步) initTextWatcherListener(); LogUtils.d(TAG, "all listener init complete | 监听绑定成功"); @@ -230,10 +256,47 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { }); } - // ====================== 颜色核心逻辑(按触发场景分类,重点修复RGB同步) ====================== + // ====================== 透明度进度条监听实现(核心新增) ====================== + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + // 仅处理用户手动拖动进度条(避免应用自身更新时触发) + if (fromUser && !isAppSelfUpdatingColor) { + updateAlphaBySeekBar(progress); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} + /** - * 核心计算:基于原始RGB+当前亮度,计算实时RGB+最终颜色(确保三个分量同时调节) - * 逻辑:亮度百分比→调节系数→原始RGB×系数→限制0-255→更新实时RGB+最终颜色 + * 拖动透明度进度条更新颜色(核心新增逻辑) + */ + private synchronized void updateAlphaBySeekBar(int alphaPercent) { + if (!isAppSelfUpdatingColor) { + isAppSelfUpdatingColor = true; // 标记为应用自身更新 + try { + // 更新实时透明度(百分比+0-255值) + mCurrentAlphaPercent = alphaPercent; + mCurrentAlpha = percent2Alpha(alphaPercent); + // 重新计算最终颜色(基于当前亮度+新透明度) + calculateBrightnessAndUpdate(); + // 同步所有控件 + updateAllViews(); + LogUtils.d(TAG, "update alpha by seekbar | 透明度:" + mCurrentAlphaPercent + "%"); + } finally { + // 直接释放标记,避免卡顿 + isAppSelfUpdatingColor = false; + } + } + } + + // ====================== 颜色核心逻辑(新增透明度参数,全功能兼容) ====================== + /** + * 核心计算:基于原始RGB+当前亮度+当前透明度,计算实时RGB+最终颜色 + * 逻辑:亮度百分比→调节系数→原始RGB×系数→限制0-255→拼接透明度→最终颜色 */ private void calculateBrightnessAndUpdate() { // 亮度百分比转调节系数(10%→0.1,100%→1.0,200%→2.0) @@ -244,8 +307,8 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { mCurrentG = Math.min(Math.max(Math.round(mOriginalG * brightnessFactor), 0), MAX_RGB_VALUE); mCurrentB = Math.min(Math.max(Math.round(mOriginalB * brightnessFactor), 0), MAX_RGB_VALUE); - // 拼接透明度+实时RGB,得到最终颜色(0xAARRGGBB) - mCurrentColor = Color.argb(mOriginalAlpha, mCurrentR, mCurrentG, mCurrentB); + // 拼接「实时透明度」+「实时RGB」,得到最终颜色(0xAARRGGBB) + mCurrentColor = Color.argb(mCurrentAlpha, mCurrentR, mCurrentG, mCurrentB); } /** @@ -263,7 +326,7 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { } /** - * 亮度调节核心方法(统一逻辑,加并发控制,同步RGB输入框) + * 亮度调节核心方法(统一逻辑,加并发控制,同步所有控件) */ private synchronized void changeBrightness(boolean isIncrease) { // 关键:判断非应用自身更新,才执行调节(避免重复触发/循环) @@ -277,9 +340,9 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { if (mCurrentBrightnessPercent <= MIN_BRIGHTNESS) return; // 达到最小值,不处理 mCurrentBrightnessPercent -= BRIGHTNESS_STEP; // 减少步长 } - // 计算亮度调节后的实时RGB+最终颜色 + // 计算亮度调节后的实时RGB+最终颜色(含当前透明度) calculateBrightnessAndUpdate(); - // 同步所有控件(重点:RGB输入框显示实时值) + // 同步所有控件 updateAllViews(); LogUtils.d(TAG, (isIncrease ? "increase" : "decrease") + " brightness | " + "亮度:" + mCurrentBrightnessPercent + "% | 实时RGB:" + mCurrentR + "," + mCurrentG + "," + mCurrentB); @@ -292,6 +355,7 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { /** * 解析颜色字符串(支持#RRGGBB/#AARRGGBB,容错处理,更新原始基准值+实时值) + * 新增:解析颜色的透明度,同步更新透明度进度条 */ private void parseColorFromStr(String colorStr, int triggerViewId) { // 关键:判断非应用自身更新,才执行解析(避免循环回调) @@ -315,11 +379,16 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { int parsedColor = Color.parseColor(colorStr); // 更新原始基准值(用户输入颜色,重置基准) + // 透明度:解析颜色的alpha(0-255)转百分比(0-100%) mOriginalAlpha = Color.alpha(parsedColor); + mOriginalAlphaPercent = alpha2Percent(mOriginalAlpha); + // RGB:解析颜色的RGB分量 mOriginalR = Color.red(parsedColor); mOriginalG = Color.green(parsedColor); mOriginalB = Color.blue(parsedColor); - // 更新实时值(原始值=实时值,无亮度调节) + // 更新实时值(原始值=实时值,无调节) + mCurrentAlpha = mOriginalAlpha; + mCurrentAlphaPercent = mOriginalAlphaPercent; mCurrentR = mOriginalR; mCurrentG = mOriginalG; mCurrentB = mOriginalB; @@ -330,7 +399,7 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { // 同步所有控件 updateAllViews(); LogUtils.d(TAG, "parse color success | 解析颜色:" + String.format("#%08X", parsedColor) - + " | 重置亮度:" + DEFAULT_BRIGHTNESS + "%"); + + " | 透明度:" + mCurrentAlphaPercent + "% | 重置亮度:" + DEFAULT_BRIGHTNESS + "%"); } catch (IllegalArgumentException e) { LogUtils.e(TAG, "parse color failed | 非法颜色格式,输入:" + colorStr, e); } finally { @@ -342,6 +411,7 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { /** * 通过RGB输入框更新颜色(用户输入后,更新原始基准值+实时值,重置亮度为100%) + * 新增:透明度基准值保持不变,仅更新RGB */ private synchronized void updateColorByRGB(int triggerViewId) { // 关键:判断非应用自身更新,才执行更新(避免循环回调) @@ -361,15 +431,15 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { mCurrentR = inputR; mCurrentG = inputG; mCurrentB = inputB; - // 重置亮度为100% + // 重置亮度为100%(透明度保持当前值不变) mCurrentBrightnessPercent = DEFAULT_BRIGHTNESS; - // 计算最终颜色(无亮度调节,直接拼接) - mCurrentColor = Color.argb(mOriginalAlpha, mCurrentR, mCurrentG, mCurrentB); + // 计算最终颜色(无亮度调节,拼接当前透明度) + mCurrentColor = Color.argb(mCurrentAlpha, mCurrentR, mCurrentG, mCurrentB); // 同步所有控件 updateAllViews(); LogUtils.d(TAG, "update color by RGB | 新原始RGB:" + mOriginalR + "," + mOriginalG + "," + mOriginalB - + " | 重置亮度:" + DEFAULT_BRIGHTNESS + "%"); + + " | 透明度:" + mCurrentAlphaPercent + "% | 重置亮度:" + DEFAULT_BRIGHTNESS + "%"); } catch (Exception e) { LogUtils.e(TAG, "update color by RGB failed", e); } finally { @@ -380,27 +450,31 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { } /** - * 核心同步:更新所有控件显示(统一方法,避免冗余,确保RGB输入框实时同步) + * 核心同步:更新所有控件显示(新增透明度控件同步,统一方法) */ private void updateAllViews() { - // 1. 同步颜色预览(显示最终颜色) + // 1. 同步颜色预览(显示最终颜色,含透明度+亮度) ivColorPicker.setBackgroundColor(mCurrentColor); - // 2. 同步RGB输入框(显示实时调节值,关键修复:亮度变化时更新) + // 2. 同步RGB输入框(显示实时调节值) etR.setText(String.valueOf(mCurrentR)); etG.setText(String.valueOf(mCurrentG)); etB.setText(String.valueOf(mCurrentB)); - // 3. 同步颜色值输入框(显示最终颜色,含亮度调节) + // 3. 同步颜色值输入框(显示最终颜色,含透明度,格式#AARRGGBB) etColorValue.setText(String.format("#%08X", mCurrentColor)); - // 4. 同步亮度控件(数值+按钮状态) + // 4. 同步透明度控件(进度条+文本,显示实时透明度) + sbAlpha.setProgress(mCurrentAlphaPercent); + tvAlphaValue.setText(mCurrentAlphaPercent + "%"); + + // 5. 同步亮度控件(数值+按钮状态) tvBrightnessValue.setText(mCurrentBrightnessPercent + "%"); updateBrightnessBtnStatus(); LogUtils.d(TAG, "sync all views complete | 最终颜色:" + String.format("#%08X", mCurrentColor) + " | 实时RGB:" + mCurrentR + "," + mCurrentG + "," + mCurrentB - + " | 亮度:" + mCurrentBrightnessPercent + "%"); + + " | 透明度:" + mCurrentAlphaPercent + "% | 亮度:" + mCurrentBrightnessPercent + "%"); } /** @@ -417,7 +491,21 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { tvBrightnessPlus.setTextColor(canPlus ? Color.BLACK : Color.parseColor("#CCCCCC")); } - // ====================== 工具方法(通用能力,下沉到底部,复用性强) ====================== + // ====================== 工具方法(新增透明度转换工具,通用复用) ====================== + /** + * 透明度:0-255 → 0-100%(颜色计算值转用户直观百分比) + */ + private int alpha2Percent(int alpha) { + return Math.round((float) alpha / MAX_RGB_VALUE * MAX_ALPHA_PERCENT); + } + + /** + * 透明度:0-100% → 0-255(用户操作百分比转颜色计算值) + */ + private int percent2Alpha(int percent) { + return Math.round((float) percent / MAX_ALPHA_PERCENT * MAX_RGB_VALUE); + } + /** * 解析输入值(限制0-255,非法输入返回0,容错处理) */ @@ -460,75 +548,109 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener { return (int) (dp * getContext().getResources().getDisplayMetrics().density + 0.5f); } - /** - * 显示系统颜色选择器(兼容API29-30,无高版本依赖,小米机型适配) - */ - private void showSystemColorPicker() { - LogUtils.d(TAG, "show system color picker | 兼容小米API29-30"); - final android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(getContext()); - builder.setTitle("选择基础颜色"); + /** + * 显示系统颜色选择器(兼容API29-30,无高版本依赖,小米机型适配) + * 核心调整:新增「水平滚动容器+颜色排列容器」二级结构,内置圆形按钮,无额外drawable依赖 + */ + private void showSystemColorPicker() { + LogUtils.d(TAG, "show system color picker | 兼容小米API29-30,支持横向滚动"); + final android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(getContext()); + builder.setTitle("选择基础颜色"); - // 常用基础色(10种,覆盖主流需求,可按需增减) + // 50种常用颜色:按「红→橙→黄→绿→青→蓝→紫→粉→棕→灰→黑白」彩虹光谱顺序排列 final int[] systemColors = { - 0xFFFFFFFF, 0xFF000000, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, - 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 0xFF888888, 0xFFAAAAAA + // 红色系(6种:深红→大红→浅红→玫红→暗红→橘红) + 0xFFCC0000, 0xFFFF0000, 0xFFFF6666, 0xFFFF1493, 0xFF8B0000, 0xFFFF4500, + // 橙色系(5种:深橙→橙→浅橙→橙黄→橘橙) + 0xFFCC6600, 0xFFFF8800, 0xFFFFAA33, 0xFFFFBB00, 0xFFF5A623, + // 黄色系(5种:深黄→黄→浅黄→鹅黄→金黄) + 0xFFCCCC00, 0xFFFFFF00, 0xFFFFEE99, 0xFFFFFACD, 0xFFFFD700, + // 绿色系(7种:深绿→绿→浅绿→草绿→薄荷绿→翠绿→墨绿) + 0xFF006600, 0xFF00FF00, 0xFF99FF99, 0xFF66CC66, 0xFF98FB98, 0xFF00FF99, 0xFF003300, + // 青色系(5种:深青→青→浅青→蓝绿→青绿) + 0xFF006666, 0xFF00FFFF, 0xFF99FFFF, 0xFF00CCCC, 0xFF40E0D0, + // 蓝色系(8种:深蓝→藏蓝→蓝→浅蓝→天蓝→宝蓝→湖蓝→靛蓝) + 0xFF0000CC, 0xFF00008B, 0xFF0000FF, 0xFF6666FF, 0xFF87CEEB, 0xFF0066FF, 0xFF0099FF, 0xFF4B0082, + // 紫色系(6种:深紫→紫→浅紫→紫罗兰→紫红→蓝紫) + 0xFF660099, 0xFF8800FF, 0xFFAA99FF, 0xFF9370DB, 0xFFCBC3E3, 0xFF8A2BE2, + // 粉色系(5种:深粉→粉→浅粉→嫩粉→桃粉) + 0xFFFF00FF, 0xFFFF99CC, 0xFFFFCCDD, 0xFFFFB6C1, 0xFFFFA5A5, + // 棕色系(4种:深棕→棕→浅棕→棕黄) + 0xFF8B4513, 0xFFA0522D, 0xFFD2B48C, 0xFFCD853F, + // 灰色系(6种:深灰→灰→浅灰→银灰→淡灰→浅银灰) + 0xFF333333, 0xFF666666, 0xFF888888, 0xFFAAAAAA, 0xFFCCCCCC, 0xFFE6E6E6, + // 黑白系(3种:黑→白→米白) + 0xFF000000, 0xFFFFFFFF, 0xFFFFFAFA }; - // 动态创建颜色选择布局(横向排列,适配小米屏幕) - LinearLayout colorLayout = new LinearLayout(getContext()); - colorLayout.setOrientation(LinearLayout.HORIZONTAL); - colorLayout.setGravity(Gravity.CENTER); - colorLayout.setPadding(dp2px(10), dp2px(10), dp2px(10), dp2px(10)); + // 1. 第一级:水平滚动容器 + HorizontalScrollView horizontalScrollView = new HorizontalScrollView(getContext()); + horizontalScrollView.setHorizontalScrollBarEnabled(true); + horizontalScrollView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); + horizontalScrollView.setPadding(dp2px(5), dp2px(5), dp2px(5), dp2px(5)); - // 循环添加颜色按钮(圆形,点击选择) - for (int i = 0; i < systemColors.length; i++) { - final int color = systemColors[i]; - ImageView colorBtn = new ImageView(getContext()); - LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(dp2px(40), dp2px(40)); - if (i != systemColors.length - 1) { - lp.setMargins(0, 0, dp2px(10), 0); // 低版本兼容setMargins(API29-30) - } - colorBtn.setLayoutParams(lp); - colorBtn.setBackgroundColor(color); - colorBtn.setClickable(true); - colorBtn.setFocusable(true); + // 2. 第二级:颜色排列容器(横向) + LinearLayout colorLayout = new LinearLayout(getContext()); + colorLayout.setOrientation(LinearLayout.HORIZONTAL); + colorLayout.setGravity(Gravity.CENTER_VERTICAL); + colorLayout.setPadding(dp2px(10), dp2px(10), dp2px(10), dp2px(10)); - // 点击选择颜色:更新原始基准值+实时值,重置亮度为100% - colorBtn.setOnClickListener(new View.OnClickListener() { + // 3. 循环添加颜色按钮(内置圆形效果,无额外依赖) + for (int i = 0; i < systemColors.length; i++) { + final int color = systemColors[i]; + ImageView colorBtn = new ImageView(getContext()); + LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(dp2px(40), dp2px(40)); + if (i != systemColors.length - 1) { + lp.setMargins(0, 0, dp2px(10), 0); // 按钮间距 + } + colorBtn.setLayoutParams(lp); + + // 核心:内置圆形背景(白色边框+圆形形状,无需drawable文件) + GradientDrawable circleBg = new GradientDrawable(); + circleBg.setShape(GradientDrawable.OVAL); // 圆形 + circleBg.setColor(color); // 按钮颜色 + circleBg.setStroke(dp2px(2), Color.WHITE); // 白色边框(2dp宽,区分颜色) + colorBtn.setBackground(circleBg); // 设置圆形背景 + + colorBtn.setClickable(true); + colorBtn.setFocusable(true); + + // 点击事件(逻辑不变) + colorBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - // 关键:判断非应用自身更新,才执行选择逻辑(避免循环) if (!isAppSelfUpdatingColor) { - isAppSelfUpdatingColor = true; // 标记为应用自身更新 + isAppSelfUpdatingColor = true; try { - // 更新原始基准值 + mOriginalAlpha = Color.alpha(color); + mOriginalAlphaPercent = alpha2Percent(mOriginalAlpha); mOriginalR = Color.red(color); mOriginalG = Color.green(color); mOriginalB = Color.blue(color); - mOriginalAlpha = Color.alpha(color); - // 更新实时值(原始值=实时值) + mCurrentAlpha = mOriginalAlpha; + mCurrentAlphaPercent = mOriginalAlphaPercent; mCurrentR = mOriginalR; mCurrentG = mOriginalG; mCurrentB = mOriginalB; - // 重置亮度+最终颜色 mCurrentBrightnessPercent = DEFAULT_BRIGHTNESS; mCurrentColor = color; - // 同步所有控件 updateAllViews(); - builder.create().dismiss(); // 关闭选择器 - LogUtils.d(TAG, "select system color | 选择颜色:" + String.format("#%08X", color)); + builder.create().dismiss(); + LogUtils.d(TAG, "select system color | 选择颜色:" + String.format("#%08X", color) + + " | 透明度:" + mCurrentAlphaPercent + "%"); } finally { - // 释放标记 isAppSelfUpdatingColor = false; } } } }); - colorLayout.addView(colorBtn); - } + colorLayout.addView(colorBtn); + } - builder.setView(colorLayout).setNegativeButton("取消", null).show(); - } + // 层级嵌套(滚动容器→颜色容器) + horizontalScrollView.addView(colorLayout); + builder.setView(horizontalScrollView).setNegativeButton("关闭", null).show(); + } // ====================== 点击事件实现(统一处理,逻辑清晰) ====================== @Override diff --git a/powerbell/src/main/res/drawable/btn_common.xml b/powerbell/src/main/res/drawable/btn_common.xml new file mode 100644 index 0000000..7ccb64d --- /dev/null +++ b/powerbell/src/main/res/drawable/btn_common.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/powerbell/src/main/res/layout/dialog_color_palette.xml b/powerbell/src/main/res/layout/dialog_color_palette.xml index 885d969..426ce5c 100644 --- a/powerbell/src/main/res/layout/dialog_color_palette.xml +++ b/powerbell/src/main/res/layout/dialog_color_palette.xml @@ -1,160 +1,184 @@ - + - - + - - + - + - + - + - - + - - + - - + - + - + - - + - - + - + - - + + + + + + + + + + + + + + + + + + + + +