From 8e1d6ba197908e011c10c93450655278fe85d9bf Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Tue, 16 Dec 2025 12:11:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=B0=83=E8=89=B2=E6=9D=BF?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D=E6=A1=86=EF=BC=8C=E6=9C=AA=E8=B0=83=E8=AF=95?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- powerbell/build.properties | 4 +- .../BackgroundSettingsActivity.java | 19 +- .../powerbell/dialogs/ColorPaletteDialog.java | 356 ++++++++++++++++++ .../src/main/res/drawable/btn_bg_gray.xml | 7 + .../src/main/res/drawable/btn_bg_primary.xml | 7 + .../main/res/drawable/dialog_bg_radius.xml | 17 + .../src/main/res/drawable/edittext_bg.xml | 10 + .../main/res/drawable/seekbar_progress.xml | 20 + .../src/main/res/drawable/seekbar_thumb.xml | 15 + .../layout/activity_background_settings.xml | 9 + .../main/res/layout/dialog_color_palette.xml | 207 ++++++++++ .../src/main/res/layout/layout_color_grid.xml | 9 + powerbell/src/main/res/values/colors.xml | 70 +++- powerbell/src/main/res/values/styles.xml | 14 + 14 files changed, 758 insertions(+), 6 deletions(-) create mode 100644 powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/ColorPaletteDialog.java create mode 100644 powerbell/src/main/res/drawable/btn_bg_gray.xml create mode 100644 powerbell/src/main/res/drawable/btn_bg_primary.xml create mode 100644 powerbell/src/main/res/drawable/dialog_bg_radius.xml create mode 100644 powerbell/src/main/res/drawable/edittext_bg.xml create mode 100644 powerbell/src/main/res/drawable/seekbar_progress.xml create mode 100644 powerbell/src/main/res/drawable/seekbar_thumb.xml create mode 100644 powerbell/src/main/res/layout/dialog_color_palette.xml create mode 100644 powerbell/src/main/res/layout/layout_color_grid.xml diff --git a/powerbell/build.properties b/powerbell/build.properties index 71e67f5..c0f6b00 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Sun Dec 14 19:58:14 HKT 2025 +#Tue Dec 16 04:10:23 GMT 2025 stageCount=7 libraryProject= baseVersion=15.14 publishVersion=15.14.6 -buildCount=0 +buildCount=1 baseBetaVersion=15.14.7 diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundSettingsActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundSettingsActivity.java index ab3c74d..f909d1b 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundSettingsActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundSettingsActivity.java @@ -15,7 +15,6 @@ import android.os.Looper; import android.provider.MediaStore; import android.text.TextUtils; import android.view.View; -import android.widget.LinearLayout; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; import androidx.core.content.FileProvider; @@ -24,6 +23,7 @@ import cc.winboll.studio.libappbase.ToastUtils; import cc.winboll.studio.powerbell.App; import cc.winboll.studio.powerbell.R; import cc.winboll.studio.powerbell.dialogs.BackgroundPicturePreviewDialog; +import cc.winboll.studio.powerbell.dialogs.ColorPaletteDialog; import cc.winboll.studio.powerbell.dialogs.YesNoAlertDialog; import cc.winboll.studio.powerbell.models.BackgroundBean; import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils; @@ -864,5 +864,22 @@ public class BackgroundSettingsActivity extends WinBoLLActivity { doubleRefreshPreview(); isPreviewBackgroundChanged = true; } + + public void onColorPaletteDialog(View view) { + // 初始颜色(白色,含透明度) + //int initialColor = 0xFFFFFFFF; + int initialColor = mBgSourceUtils.getPreviewBackgroundBean().getPixelColor(); + // 显示对话框 + ColorPaletteDialog dialog = new ColorPaletteDialog(this, initialColor, new ColorPaletteDialog.OnColorSelectedListener() { + @Override + public void onColorSelected(int color) { + // 回调返回 0xAARRGGBB 格式颜色,直接使用 + mBgSourceUtils.getPreviewBackgroundBean().setPixelColor(color); + doubleRefreshPreview(); + LogUtils.d("选择颜色", String.format("#%08X", color)); + } + }); + dialog.show(); + } } 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 new file mode 100644 index 0000000..80eb110 --- /dev/null +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/ColorPaletteDialog.java @@ -0,0 +1,356 @@ +package cc.winboll.studio.powerbell.dialogs; + +import android.app.Dialog; +import android.content.Context; +import android.graphics.Color; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.EditText; +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; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/12/16 11:47 + * @Describe 调色板对话框(支持颜色拾取、RGB输入、透明度/色阶调节,兼容 API29-30+ 小米机型) + */ +public class ColorPaletteDialog extends Dialog implements View.OnClickListener { + // ====================== 常量/成员变量 ====================== + private static final String TAG = "ColorPaletteDialog"; + private static final int MAX_PROGRESS = 255; // 透明度/色阶最大值(0-255) + private OnColorSelectedListener mListener; // 颜色选择回调接口 + private int mInitialColor; // 初始颜色(含透明度,默认白色0xFFFFFFFF) + private int mCurrentColor; // 当前选择的颜色 + + // 控件引用 + private ImageView ivColorPicker; // 颜色拾取框(点击选色) + private EditText etR, etG, etB; // RGB 颜色输入框 + private EditText etColorValue; // 颜色值输入框(如 #FFFFFF) + private SeekBar sbAlpha; // 透明度进度条(0=全透明,255=不透明) + private SeekBar sbBrightness; // 色阶进度条(调节亮度,0=最暗,255=最亮) + private TextView tvConfirm; // 确认按钮 + private TextView tvCancel; // 取消按钮 + + + // ====================== 回调接口 ====================== + /** + * 颜色选择完成回调接口 + */ + public interface OnColorSelectedListener { + void onColorSelected(int color); // 返回 0xAARRGGBB 格式颜色 + } + + + // ====================== 构造方法 ====================== + public ColorPaletteDialog(Context context, int initialColor, OnColorSelectedListener listener) { + super(context, R.style.CustomDialogStyle); + this.mInitialColor = initialColor; + this.mCurrentColor = initialColor; + this.mListener = listener; + if (mListener == null) { + throw new IllegalArgumentException("OnColorSelectedListener 不能为 null!"); + } + } + + + // ====================== 生命周期 ====================== + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_color_palette, null); + setContentView(view); + initView(view); + initData(); + adjustDialogSize(); + } + + + // ====================== 初始化方法 ====================== + private void initView(View view) { + // 颜色拾取框 + ivColorPicker = view.findViewById(R.id.iv_color_picker); + ivColorPicker.setOnClickListener(this); + // RGB 输入框 + etR = view.findViewById(R.id.et_r); + etG = view.findViewById(R.id.et_g); + etB = view.findViewById(R.id.et_b); + setEditTextWatcher(etR); + setEditTextWatcher(etG); + setEditTextWatcher(etB); + // 颜色值输入框 + etColorValue = view.findViewById(R.id.et_color_value); + etColorValue.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) {} + @Override + public void afterTextChanged(Editable s) { + parseColorFromStr(s.toString().trim()); + } + }); + // 透明度进度条 + sbAlpha = view.findViewById(R.id.sb_alpha); + sbAlpha.setMax(MAX_PROGRESS); + sbAlpha.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) updateColorByAlpha(progress); + } + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} + }); + // 色阶进度条 + sbBrightness = view.findViewById(R.id.sb_brightness); + sbBrightness.setMax(MAX_PROGRESS); + sbBrightness.setProgress(128); + sbBrightness.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) updateColorByBrightness(progress); + } + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} + }); + // 按钮 + tvConfirm = view.findViewById(R.id.tv_confirm); + tvCancel = view.findViewById(R.id.tv_cancel); + tvConfirm.setOnClickListener(this); + tvCancel.setOnClickListener(this); + } + + private void initData() { + ivColorPicker.setBackgroundColor(mInitialColor); + int alpha = Color.alpha(mInitialColor); + int r = Color.red(mInitialColor); + int g = Color.green(mInitialColor); + int b = Color.blue(mInitialColor); + etR.setText(String.valueOf(r)); + etG.setText(String.valueOf(g)); + etB.setText(String.valueOf(b)); + etColorValue.setText(String.format("#%08X", mInitialColor)); + sbAlpha.setProgress(alpha); + } + + private void adjustDialogSize() { + Window window = getWindow(); + if (window != null) { + WindowManager.LayoutParams lp = window.getAttributes(); + lp.width = (int) (getContext().getResources().getDisplayMetrics().widthPixels * 0.8); + lp.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(lp); + window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + } + } + + + // ====================== 颜色逻辑处理 ====================== + private void parseColorFromStr(String colorStr) { + if (TextUtils.isEmpty(colorStr)) return; + try { + if (!colorStr.startsWith("#")) colorStr = "#" + colorStr; + int color = Color.parseColor(colorStr); + if (colorStr.length() == 7) { // #RRGGBB 补全透明度 + color = Color.argb(Color.alpha(mCurrentColor), Color.red(color), Color.green(color), Color.blue(color)); + } + updateCurrentColor(color, true); + } catch (IllegalArgumentException e) { + LogUtils.e(TAG, "颜色格式错误:" + colorStr, e); + } + } + + private void updateColorByRGB() { + try { + int r = parseInputValue(etR.getText().toString(), 0, MAX_PROGRESS); + int g = parseInputValue(etG.getText().toString(), 0, MAX_PROGRESS); + int b = parseInputValue(etB.getText().toString(), 0, MAX_PROGRESS); + int alpha = Color.alpha(mCurrentColor); + int newColor = Color.argb(alpha, r, g, b); + updateCurrentColor(newColor, true); + } catch (Exception e) { + LogUtils.e(TAG, "RGB 更新失败", e); + } + } + + private void updateColorByAlpha(int alpha) { + int r = Color.red(mCurrentColor); + int g = Color.green(mCurrentColor); + int b = Color.blue(mCurrentColor); + updateCurrentColor(Color.argb(alpha, r, g, b), true); + } + + private void updateColorByBrightness(int brightness) { + float factor = brightness / 128f; + int alpha = Color.alpha(mCurrentColor); + int r = adjustBrightness(Color.red(mCurrentColor), factor); + int g = adjustBrightness(Color.green(mCurrentColor), factor); + int b = adjustBrightness(Color.blue(mCurrentColor), factor); + updateCurrentColor(Color.argb(alpha, r, g, b), false); + } + + private int adjustBrightness(int colorComponent, float factor) { + int newComponent = (int) (colorComponent * factor); + return Math.min(Math.max(newComponent, 0), MAX_PROGRESS); + } + + private void updateCurrentColor(int newColor, boolean updateBrightness) { + mCurrentColor = newColor; + // 更新拾取框 + ivColorPicker.setBackgroundColor(newColor); + // 更新 RGB 输入框 + etR.setText(String.valueOf(Color.red(newColor))); + etG.setText(String.valueOf(Color.green(newColor))); + etB.setText(String.valueOf(Color.blue(newColor))); + // 更新颜色值输入框 + etColorValue.setText(String.format("#%08X", newColor)); + // 更新透明度进度条(避免循环) + sbAlpha.setOnSeekBarChangeListener(null); + sbAlpha.setProgress(Color.alpha(newColor)); + sbAlpha.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) updateColorByAlpha(progress); + } + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} + }); + // 更新色阶进度条 + if (updateBrightness) { + sbBrightness.setOnSeekBarChangeListener(null); + sbBrightness.setProgress(128); + sbBrightness.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) updateColorByBrightness(progress); + } + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} + }); + } + } + + private int parseInputValue(String input, int min, int max) { + if (TextUtils.isEmpty(input)) return min; + try { + int value = Integer.parseInt(input); + return Math.min(Math.max(value, min), max); + } catch (NumberFormatException e) { + return min; + } + } + + + // ====================== 控件监听 ====================== + private void setEditTextWatcher(EditText editText) { + editText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) {} + @Override + public void afterTextChanged(Editable s) { + updateColorByRGB(); + } + }); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.iv_color_picker) { + showSystemColorPicker(); + } else if (id == R.id.tv_confirm) { + if (mListener != null) mListener.onColorSelected(mCurrentColor); + dismiss(); + } else if (id == R.id.tv_cancel) { + dismiss(); + } + } + + /** + * 修正后:系统颜色选择器(无 API29+ 方法,全版本兼容) + */ + private void showSystemColorPicker() { + final android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(getContext()); + builder.setTitle("选择颜色"); + final int[] systemColors = { + 0xFFFFFFFF, 0xFF000000, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, + 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 0xFF888888, 0xFFAAAAAA + }; + // 横向布局存放颜色按钮 + LinearLayout colorView = new LinearLayout(getContext()); + colorView.setOrientation(LinearLayout.HORIZONTAL); + colorView.setGravity(Gravity.CENTER); + colorView.setPadding(dp2px(10), dp2px(10), dp2px(10), dp2px(10)); + // 循环添加颜色按钮(用 LayoutParams 设置边距) + for (int i = 0; i < systemColors.length; i++) { + ImageView iv = new ImageView(getContext()); + LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( + dp2px(40), dp2px(40) + ); + // 非最后一个按钮设置右侧边距 10dp + if (i != systemColors.length - 1) { + lp.setMargins(0, 0, dp2px(10), 0); + } + iv.setLayoutParams(lp); + iv.setBackgroundColor(systemColors[i]); + iv.setClickable(true); + iv.setFocusable(true); + // 点击选择颜色 + final int finalI = i; + iv.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + int selectedColor = systemColors[finalI]; + int newColor = Color.argb( + Color.alpha(mCurrentColor), + Color.red(selectedColor), + Color.green(selectedColor), + Color.blue(selectedColor) + ); + updateCurrentColor(newColor, true); + builder.create().dismiss(); + } + }); + colorView.addView(iv); + } + builder.setView(colorView) + .setNegativeButton("取消", null) + .show(); + } + + + // ====================== 工具方法 ====================== + private int dp2px(float dp) { + return (int) (dp * getContext().getResources().getDisplayMetrics().density + 0.5f); + } + + + // ====================== 内存优化 ====================== + @Override + public void dismiss() { + super.dismiss(); + mListener = null; + } +} + diff --git a/powerbell/src/main/res/drawable/btn_bg_gray.xml b/powerbell/src/main/res/drawable/btn_bg_gray.xml new file mode 100644 index 0000000..ba883b9 --- /dev/null +++ b/powerbell/src/main/res/drawable/btn_bg_gray.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/powerbell/src/main/res/drawable/btn_bg_primary.xml b/powerbell/src/main/res/drawable/btn_bg_primary.xml new file mode 100644 index 0000000..6f78e61 --- /dev/null +++ b/powerbell/src/main/res/drawable/btn_bg_primary.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/powerbell/src/main/res/drawable/dialog_bg_radius.xml b/powerbell/src/main/res/drawable/dialog_bg_radius.xml new file mode 100644 index 0000000..773dcd8 --- /dev/null +++ b/powerbell/src/main/res/drawable/dialog_bg_radius.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/powerbell/src/main/res/drawable/edittext_bg.xml b/powerbell/src/main/res/drawable/edittext_bg.xml new file mode 100644 index 0000000..8b48b87 --- /dev/null +++ b/powerbell/src/main/res/drawable/edittext_bg.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/powerbell/src/main/res/drawable/seekbar_progress.xml b/powerbell/src/main/res/drawable/seekbar_progress.xml new file mode 100644 index 0000000..4e27cf9 --- /dev/null +++ b/powerbell/src/main/res/drawable/seekbar_progress.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/powerbell/src/main/res/drawable/seekbar_thumb.xml b/powerbell/src/main/res/drawable/seekbar_thumb.xml new file mode 100644 index 0000000..fb9e7b5 --- /dev/null +++ b/powerbell/src/main/res/drawable/seekbar_thumb.xml @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/powerbell/src/main/res/layout/activity_background_settings.xml b/powerbell/src/main/res/layout/activity_background_settings.xml index d06279c..e8096d1 100644 --- a/powerbell/src/main/res/layout/activity_background_settings.xml +++ b/powerbell/src/main/res/layout/activity_background_settings.xml @@ -117,6 +117,15 @@ android:layout_margin="5dp" android:id="@+id/activitybackgroundpictureAButton7"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbell/src/main/res/layout/layout_color_grid.xml b/powerbell/src/main/res/layout/layout_color_grid.xml new file mode 100644 index 0000000..6c0f8fd --- /dev/null +++ b/powerbell/src/main/res/layout/layout_color_grid.xml @@ -0,0 +1,9 @@ + + + + diff --git a/powerbell/src/main/res/values/colors.xml b/powerbell/src/main/res/values/colors.xml index a81deb7..f08fbe8 100644 --- a/powerbell/src/main/res/values/colors.xml +++ b/powerbell/src/main/res/values/colors.xml @@ -58,9 +58,73 @@ @color/colorRed @color/colorBlue @color/colorYellow - + #FFFFFFFF - - + + + #FFFFFF + #000000 + + + + #4A90E2 + #2196F3 + #1976D2 + + #66BB6A + #4CAF50 + #388E3C + + #EF5350 + #F44336 + #D32F2F + + #FFF59D + #FFC107 + #FFA000 + + #FF9800 + + #9C27B0 + + + #00000000 + #80000000 + + + + + #F5F5F5 + #EEEEEE + #E0E0E0 + #BDBDBD + #9E9E9E + #757575 + #616161 + #424242 + #212121 + + + #4D9E9E9E + #809E9E9E + #B39E9E9E + + #EEE + #999 + #666 + #333 + + + #809E9E9E + + #4D424242 + + + #9E9E9E + + #757575 + + #E0E0E0 + diff --git a/powerbell/src/main/res/values/styles.xml b/powerbell/src/main/res/values/styles.xml index 6509201..4e1d231 100644 --- a/powerbell/src/main/res/values/styles.xml +++ b/powerbell/src/main/res/values/styles.xml @@ -26,4 +26,18 @@ @dimen/text_subtitle_size + + +