添加调色板对话框,未调试。

This commit is contained in:
2025-12-16 12:11:32 +08:00
parent 70a004d9e3
commit 8e1d6ba197
14 changed files with 758 additions and 6 deletions

View File

@@ -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();
}
}

View File

@@ -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&豆包大模型<zhangsken@qq.com>
* @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;
}
}