20251216_154557_434
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Tue Dec 16 06:10:34 GMT 2025
|
#Tue Dec 16 07:33:42 GMT 2025
|
||||||
stageCount=7
|
stageCount=7
|
||||||
libraryProject=
|
libraryProject=
|
||||||
baseVersion=15.14
|
baseVersion=15.14
|
||||||
publishVersion=15.14.6
|
publishVersion=15.14.6
|
||||||
buildCount=30
|
buildCount=39
|
||||||
baseBetaVersion=15.14.7
|
baseBetaVersion=15.14.7
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import android.view.WindowManager;
|
|||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.SeekBar;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
import cc.winboll.studio.powerbell.R;
|
import cc.winboll.studio.powerbell.R;
|
||||||
@@ -23,171 +22,197 @@ import cc.winboll.studio.powerbell.R;
|
|||||||
/**
|
/**
|
||||||
* @Author ZhanGSKen<zhangsken@qq.com>
|
* @Author ZhanGSKen<zhangsken@qq.com>
|
||||||
* @Date 2025/12/16 11:47
|
* @Date 2025/12/16 11:47
|
||||||
* @Describe 调色板对话框(支持颜色拾取、RGB输入、透明度/色阶调节,兼容 API29-30+ 小米机型)
|
* @Describe 调色板对话框(支持颜色拾取、RGB输入、透明度/亮度调节,兼容 API29-30+ 小米机型)
|
||||||
*/
|
*/
|
||||||
public class ColorPaletteDialog extends Dialog implements View.OnClickListener {
|
public class ColorPaletteDialog extends Dialog implements View.OnClickListener {
|
||||||
// ====================== 常量定义(首屏可见,统一管理) ======================
|
// ====================== 常量定义(首屏可见,统一管理) ======================
|
||||||
public static final String TAG = "ColorPaletteDialog";
|
public static final String TAG = "ColorPaletteDialog";
|
||||||
private static final int MAX_PROGRESS = 255; // 透明度/色阶最大值(0-255)
|
private static final int MAX_RGB_VALUE = 255; // RGB分量最大值(0-255)
|
||||||
private static final int DEFAULT_BRIGHTNESS = 128; // 默认亮度系数(1.0倍)
|
private static final int DEFAULT_BRIGHTNESS = 100; // 默认亮度百分比(100%,无调节)
|
||||||
private static final int NO_TARGET_ID = -1; // 无目标控件标记
|
private static final int BRIGHTNESS_STEP = 5; // 亮度调节步长(每次±5%,精准流畅)
|
||||||
|
private static final int MIN_BRIGHTNESS = 10; // 亮度最小值(10%,避免全黑看不见)
|
||||||
|
private static final int MAX_BRIGHTNESS = 200; // 亮度最大值(200%,避免过曝失真)
|
||||||
|
|
||||||
// ====================== 回调接口(紧跟常量,逻辑关联) ======================
|
// ====================== 回调接口(紧跟常量,逻辑关联) ======================
|
||||||
public interface OnColorSelectedListener {
|
public interface OnColorSelectedListener {
|
||||||
void onColorSelected(int color); // 返回0xAARRGGBB格式颜色
|
void onColorSelected(int color); // 返回0xAARRGGBB格式颜色(含透明度)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================== 成员变量(按优先级排序:核心数据→控件引用) ======================
|
// ====================== 成员变量(按优先级排序:核心数据→控件引用) ======================
|
||||||
// 核心数据
|
// 核心数据:原始基准值(用户输入/选择颜色时更新)+ 实时调节值(亮度变化时更新)
|
||||||
private OnColorSelectedListener mListener; // 颜色选择回调
|
private OnColorSelectedListener mListener; // 颜色选择回调(非空校验)
|
||||||
private int mInitialColor; // 初始颜色(0xAARRGGBB)
|
private int mInitialColor; // 初始颜色(传入的默认颜色)
|
||||||
private int mCurrentColor; // 当前选择颜色
|
private int mCurrentColor; // 当前最终颜色(含亮度调节)
|
||||||
|
private int mCurrentBrightnessPercent; // 当前亮度百分比(10%-200%)
|
||||||
|
private int mOriginalAlpha; // 原始透明度(固定,亮度不影响透明度)
|
||||||
|
private int mOriginalR; // 原始R分量(基准值,用户输入/选色时更新)
|
||||||
|
private int mOriginalG; // 原始G分量(基准值,用户输入/选色时更新)
|
||||||
|
private int mOriginalB; // 原始B分量(基准值,用户输入/选色时更新)
|
||||||
|
private int mCurrentR; // 实时R分量(亮度调节后,同步输入框显示)
|
||||||
|
private int mCurrentG; // 实时G分量(亮度调节后,同步输入框显示)
|
||||||
|
private int mCurrentB; // 实时B分量(亮度调节后,同步输入框显示)
|
||||||
|
// 并发控制标记:是否是应用程序自身在更新颜色(避免循环回调/重复触发)
|
||||||
|
private static volatile boolean isAppSelfUpdatingColor = false;
|
||||||
|
|
||||||
// 控件引用
|
// 控件引用(亮度改为「减号+数值+加号」底部布局)
|
||||||
private ImageView ivColorPicker; // 颜色拾取预览
|
private ImageView ivColorPicker; // 颜色预览拾取框
|
||||||
private EditText etR; // R分量输入框
|
private EditText etR; // R分量输入框(显示实时调节值)
|
||||||
private EditText etG; // G分量输入框
|
private EditText etG; // G分量输入框(显示实时调节值)
|
||||||
private EditText etB; // B分量输入框
|
private EditText etB; // B分量输入框(显示实时调节值)
|
||||||
private EditText etColorValue; // 颜色值输入框(#AARRGGBB)
|
private EditText etColorValue; // 颜色值输入框(#AARRGGBB,显示最终值)
|
||||||
private SeekBar sbAlpha; // 透明度调节进度条
|
private TextView tvBrightnessMinus;// 亮度减少按钮(-)
|
||||||
private SeekBar sbBrightness; // 亮度调节进度条
|
private TextView tvBrightnessValue;// 亮度数值显示(X%,直观易懂)
|
||||||
|
private TextView tvBrightnessPlus; // 亮度增加按钮(+)
|
||||||
private TextView tvConfirm; // 确认按钮
|
private TextView tvConfirm; // 确认按钮
|
||||||
private TextView tvCancel; // 取消按钮
|
private TextView tvCancel; // 取消按钮
|
||||||
|
|
||||||
// ====================== 构造方法(初始化核心数据,参数校验) ======================
|
// ====================== 构造方法(初始化核心数据,严格校验) ======================
|
||||||
public ColorPaletteDialog(Context context, int initialColor, OnColorSelectedListener listener) {
|
public ColorPaletteDialog(Context context, int initialColor, OnColorSelectedListener listener) {
|
||||||
super(context, R.style.CustomDialogStyle);
|
super(context, R.style.CustomDialogStyle);
|
||||||
this.mInitialColor = initialColor;
|
this.mInitialColor = initialColor;
|
||||||
this.mCurrentColor = initialColor;
|
|
||||||
this.mListener = listener;
|
this.mListener = listener;
|
||||||
|
|
||||||
// 强制回调非空,避免后续空指针
|
// 1. 强制回调非空,避免后续空指针(容错)
|
||||||
if (mListener == null) {
|
if (mListener == null) {
|
||||||
throw new IllegalArgumentException("OnColorSelectedListener can not be null!");
|
throw new IllegalArgumentException("OnColorSelectedListener can not be null!");
|
||||||
}
|
}
|
||||||
LogUtils.d(TAG, "init dialog, initial color: " + String.format("#%08X", initialColor));
|
|
||||||
|
// 2. 解析初始颜色:原始基准值 = 实时值(初始无亮度调节)
|
||||||
|
this.mOriginalAlpha = Color.alpha(initialColor);
|
||||||
|
this.mOriginalR = Color.red(initialColor);
|
||||||
|
this.mOriginalG = Color.green(initialColor);
|
||||||
|
this.mOriginalB = Color.blue(initialColor);
|
||||||
|
this.mCurrentR = mOriginalR;
|
||||||
|
this.mCurrentG = mOriginalG;
|
||||||
|
this.mCurrentB = mOriginalB;
|
||||||
|
|
||||||
|
// 3. 初始化当前状态(默认亮度100%,当前颜色=初始颜色)
|
||||||
|
this.mCurrentBrightnessPercent = DEFAULT_BRIGHTNESS;
|
||||||
|
this.mCurrentColor = initialColor;
|
||||||
|
|
||||||
|
LogUtils.d(TAG, "init dialog success | 初始颜色:" + String.format("#%08X", initialColor)
|
||||||
|
+ " | 原始RGB:" + mOriginalR + "," + mOriginalG + "," + mOriginalB
|
||||||
|
+ " | 初始亮度:" + mCurrentBrightnessPercent + "%");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================== 生命周期方法(按执行顺序排列) ======================
|
// ====================== 生命周期方法(按执行顺序排列,逻辑清晰) ======================
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
requestWindowFeature(Window.FEATURE_NO_TITLE); // 隐藏标题栏
|
||||||
View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_color_palette, null);
|
View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_color_palette, null);
|
||||||
setContentView(view);
|
setContentView(view);
|
||||||
|
|
||||||
// 初始化流程:控件绑定→数据赋值→监听设置→尺寸适配
|
// 初始化流程:控件绑定→数据赋值→监听设置→尺寸适配(小米机型优先适配)
|
||||||
initViewBind(view);
|
initViewBind(view);
|
||||||
initData();
|
initData();
|
||||||
initListener();
|
initListener();
|
||||||
adjustDialogSize();
|
adjustDialogSize();
|
||||||
LogUtils.d(TAG, "dialog create complete, adapt Xiaomi API29-30");
|
LogUtils.d(TAG, "dialog create complete | 适配小米API29-30机型");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dismiss() {
|
public void dismiss() {
|
||||||
super.dismiss();
|
super.dismiss();
|
||||||
// 释放回调引用,避免内存泄漏
|
// 释放资源,避免内存泄漏(回调引用置空)
|
||||||
mListener = null;
|
mListener = null;
|
||||||
LogUtils.d(TAG, "dialog dismiss, release resource");
|
LogUtils.d(TAG, "dialog dismiss | 释放资源完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================== 初始化核心方法(控件+数据+监听,职责单一) ======================
|
// ====================== 初始化核心方法(职责单一,便于维护) ======================
|
||||||
/**
|
/**
|
||||||
* 控件绑定(仅ID绑定,无任何业务逻辑)
|
* 控件绑定(仅做ID绑定,无任何业务逻辑,避免初始化混乱)
|
||||||
*/
|
*/
|
||||||
private void initViewBind(View view) {
|
private void initViewBind(View view) {
|
||||||
ivColorPicker = (ImageView) view.findViewById(R.id.iv_color_picker);
|
ivColorPicker = view.findViewById(R.id.iv_color_picker);
|
||||||
etR = (EditText) view.findViewById(R.id.et_r);
|
etR = view.findViewById(R.id.et_r);
|
||||||
etG = (EditText) view.findViewById(R.id.et_g);
|
etG = view.findViewById(R.id.et_g);
|
||||||
etB = (EditText) view.findViewById(R.id.et_b);
|
etB = view.findViewById(R.id.et_b);
|
||||||
etColorValue = (EditText) view.findViewById(R.id.et_color_value);
|
etColorValue = view.findViewById(R.id.et_color_value);
|
||||||
sbAlpha = (SeekBar) view.findViewById(R.id.sb_alpha);
|
tvBrightnessMinus = view.findViewById(R.id.tv_brightness_minus);
|
||||||
sbBrightness = (SeekBar) view.findViewById(R.id.sb_brightness);
|
tvBrightnessValue = view.findViewById(R.id.tv_brightness_value);
|
||||||
tvConfirm = (TextView) view.findViewById(R.id.tv_confirm);
|
tvBrightnessPlus = view.findViewById(R.id.tv_brightness_plus);
|
||||||
tvCancel = (TextView) view.findViewById(R.id.tv_cancel);
|
tvConfirm = view.findViewById(R.id.tv_confirm);
|
||||||
|
tvCancel = view.findViewById(R.id.tv_cancel);
|
||||||
|
|
||||||
// 控件非空校验,绑定失败直接关闭(小米低版本容错)
|
// 控件非空校验(小米低版本容错,绑定失败直接关闭对话框)
|
||||||
if (ivColorPicker == null || etR == null || etG == null || etB == null || etColorValue == null
|
if (ivColorPicker == null || etR == null || etG == null || etB == null || etColorValue == null
|
||||||
|| sbAlpha == null || sbBrightness == null || tvConfirm == null || tvCancel == null) {
|
|| tvBrightnessMinus == null || tvBrightnessValue == null || tvBrightnessPlus == null
|
||||||
LogUtils.e(TAG, "view bind failed, check layout ID!");
|
|| tvConfirm == null || tvCancel == null) {
|
||||||
|
LogUtils.e(TAG, "view bind failed | 请检查布局ID是否正确!");
|
||||||
dismiss();
|
dismiss();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LogUtils.d(TAG, "view bind complete");
|
LogUtils.d(TAG, "view bind complete | 所有控件绑定成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据初始化(无监听状态下赋值,避免循环回调)
|
* 数据初始化(无监听状态下赋值,避免循环回调)
|
||||||
*/
|
*/
|
||||||
private void initData() {
|
private void initData() {
|
||||||
// 解析初始颜色分量
|
// 1. 颜色预览(显示当前最终颜色,初始=原始颜色)
|
||||||
int alpha = Color.alpha(mInitialColor);
|
ivColorPicker.setBackgroundColor(mCurrentColor);
|
||||||
int r = Color.red(mInitialColor);
|
|
||||||
int g = Color.green(mInitialColor);
|
|
||||||
int b = Color.blue(mInitialColor);
|
|
||||||
|
|
||||||
// 赋值控件
|
// 2. RGB输入框(显示「实时分量」,初始=原始值)
|
||||||
ivColorPicker.setBackgroundColor(mInitialColor);
|
etR.setText(String.valueOf(mCurrentR));
|
||||||
etR.setText(String.valueOf(r));
|
etG.setText(String.valueOf(mCurrentG));
|
||||||
etG.setText(String.valueOf(g));
|
etB.setText(String.valueOf(mCurrentB));
|
||||||
etB.setText(String.valueOf(b));
|
|
||||||
etColorValue.setText(String.format("#%08X", mInitialColor));
|
|
||||||
|
|
||||||
// 进度条初始化
|
// 3. 颜色值输入框(显示当前最终颜色,格式#AARRGGBB,大写更规范)
|
||||||
sbAlpha.setMax(MAX_PROGRESS);
|
etColorValue.setText(String.format("#%08X", mCurrentColor));
|
||||||
sbBrightness.setMax(MAX_PROGRESS);
|
|
||||||
sbAlpha.setProgress(alpha);
|
|
||||||
sbBrightness.setProgress(DEFAULT_BRIGHTNESS);
|
|
||||||
|
|
||||||
LogUtils.d(TAG, "init data complete, A:" + alpha + ", R:" + r + ", G:" + g + ", B:" + b);
|
// 4. 亮度控件(显示默认100%,初始化按钮状态)
|
||||||
|
tvBrightnessValue.setText(mCurrentBrightnessPercent + "%");
|
||||||
|
updateBrightnessBtnStatus(); // 禁用边界值按钮(初始100%,都可用)
|
||||||
|
|
||||||
|
LogUtils.d(TAG, "init data complete | 原始透明度:" + mOriginalAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监听初始化(统一管理所有监听,延迟绑定避免初始化循环)
|
* 监听初始化(统一管理所有监听,延迟绑定避免初始化循环)
|
||||||
*/
|
*/
|
||||||
private void initListener() {
|
private void initListener() {
|
||||||
initClickListener();
|
// 点击监听(按钮+颜色拾取框)
|
||||||
|
ivColorPicker.setOnClickListener(this);
|
||||||
|
tvConfirm.setOnClickListener(this);
|
||||||
|
tvCancel.setOnClickListener(this);
|
||||||
|
tvBrightnessMinus.setOnClickListener(this);
|
||||||
|
tvBrightnessPlus.setOnClickListener(this);
|
||||||
|
|
||||||
|
// 输入框监听(RGB+颜色值,避免循环同步)
|
||||||
initTextWatcherListener();
|
initTextWatcherListener();
|
||||||
initSeekBarListener();
|
LogUtils.d(TAG, "all listener init complete | 监听绑定成功");
|
||||||
LogUtils.d(TAG, "all listener init complete");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对话框尺寸适配(小米全面屏+软键盘优化)
|
* 对话框尺寸适配(小米全面屏+软键盘优化,避免输入框被遮挡)
|
||||||
*/
|
*/
|
||||||
private void adjustDialogSize() {
|
private void adjustDialogSize() {
|
||||||
Window window = getWindow();
|
Window window = getWindow();
|
||||||
if (window != null) {
|
if (window != null) {
|
||||||
WindowManager.LayoutParams lp = window.getAttributes();
|
WindowManager.LayoutParams lp = window.getAttributes();
|
||||||
// 宽度占屏幕80%,高度自适应
|
// 宽度占屏幕80%,高度自适应(适配不同屏幕尺寸)
|
||||||
lp.width = (int) (getContext().getResources().getDisplayMetrics().widthPixels * 0.8);
|
lp.width = (int) (getContext().getResources().getDisplayMetrics().widthPixels * 0.8);
|
||||||
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||||
// 软键盘适配:避免输入框被遮挡(小米虚拟导航栏兼容)
|
// 软键盘适配:小米虚拟导航栏兼容,避免输入框被遮挡
|
||||||
window.setAttributes(lp);
|
window.setAttributes(lp);
|
||||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
|
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN
|
||||||
LogUtils.d(TAG, "dialog size adjust complete, adapt Xiaomi full screen");
|
| WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
|
||||||
|
LogUtils.d(TAG, "dialog size adjust complete | 适配全面屏+软键盘");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================== 监听子方法(细分类型,便于维护) ======================
|
// ====================== 监听子方法(细分类型,逻辑清晰) ======================
|
||||||
/**
|
/**
|
||||||
* 点击事件监听(按钮+颜色拾取框)
|
* 输入框文本监听(RGB+颜色值,传入触发ID避免循环同步)
|
||||||
*/
|
|
||||||
private void initClickListener() {
|
|
||||||
ivColorPicker.setOnClickListener(this);
|
|
||||||
tvConfirm.setOnClickListener(this);
|
|
||||||
tvCancel.setOnClickListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输入框文本监听(RGB+颜色值,传入触发控件ID避免循环)
|
|
||||||
*/
|
*/
|
||||||
private void initTextWatcherListener() {
|
private void initTextWatcherListener() {
|
||||||
|
// RGB输入框监听(复用方法,减少冗余)
|
||||||
setEditTextWatcher(etR, R.id.et_r);
|
setEditTextWatcher(etR, R.id.et_r);
|
||||||
setEditTextWatcher(etG, R.id.et_g);
|
setEditTextWatcher(etG, R.id.et_g);
|
||||||
setEditTextWatcher(etB, R.id.et_b);
|
setEditTextWatcher(etB, R.id.et_b);
|
||||||
|
|
||||||
|
// 颜色值输入框监听(支持#RRGGBB/#AARRGGBB格式)
|
||||||
etColorValue.addTextChangedListener(new TextWatcher() {
|
etColorValue.addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
@@ -197,202 +222,218 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable s) {
|
public void afterTextChanged(Editable s) {
|
||||||
parseColorFromStr(s.toString().trim(), R.id.et_color_value);
|
// 关键:判断非应用自身更新,才执行解析(避免循环回调)
|
||||||
|
if (!isAppSelfUpdatingColor) {
|
||||||
|
parseColorFromStr(s.toString().trim(), R.id.et_color_value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====================== 颜色核心逻辑(按触发场景分类,重点修复RGB同步) ======================
|
||||||
/**
|
/**
|
||||||
* 进度条滑动监听(透明度+亮度,仅响应手动操作)
|
* 核心计算:基于原始RGB+当前亮度,计算实时RGB+最终颜色(确保三个分量同时调节)
|
||||||
|
* 逻辑:亮度百分比→调节系数→原始RGB×系数→限制0-255→更新实时RGB+最终颜色
|
||||||
*/
|
*/
|
||||||
private void initSeekBarListener() {
|
private void calculateBrightnessAndUpdate() {
|
||||||
// 透明度进度条
|
// 亮度百分比转调节系数(10%→0.1,100%→1.0,200%→2.0)
|
||||||
sbAlpha.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
float brightnessFactor = mCurrentBrightnessPercent / 100.0f;
|
||||||
@Override
|
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
|
||||||
if (fromUser) {
|
|
||||||
updateColorByAlpha(progress, NO_TARGET_ID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
// RGB三个分量同时调节(基于原始基准值,避免叠加失真),限制0-255
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {}
|
mCurrentR = Math.min(Math.max(Math.round(mOriginalR * brightnessFactor), 0), MAX_RGB_VALUE);
|
||||||
|
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);
|
||||||
|
|
||||||
@Override
|
// 拼接透明度+实时RGB,得到最终颜色(0xAARRGGBB)
|
||||||
public void onStopTrackingTouch(SeekBar seekBar) {}
|
mCurrentColor = Color.argb(mOriginalAlpha, mCurrentR, mCurrentG, mCurrentB);
|
||||||
});
|
|
||||||
|
|
||||||
// 亮度进度条
|
|
||||||
sbBrightness.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
|
||||||
if (fromUser) {
|
|
||||||
updateColorByBrightness(progress, NO_TARGET_ID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStopTrackingTouch(SeekBar seekBar) {}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================== 颜色核心逻辑(按触发场景分类) ======================
|
|
||||||
/**
|
/**
|
||||||
* 解析颜色字符串(支持#RRGGBB/#AARRGGBB,容错处理)
|
* 亮度减少(每次减5%,最低10%,防止过暗)
|
||||||
|
*/
|
||||||
|
private void decreaseBrightness() {
|
||||||
|
changeBrightness(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 亮度增加(每次加5%,最高200%,防止过曝)
|
||||||
|
*/
|
||||||
|
private void increaseBrightness() {
|
||||||
|
changeBrightness(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 亮度调节核心方法(统一逻辑,加并发控制,同步RGB输入框)
|
||||||
|
*/
|
||||||
|
private synchronized void changeBrightness(boolean isIncrease) {
|
||||||
|
// 关键:判断非应用自身更新,才执行调节(避免重复触发/循环)
|
||||||
|
if (!isAppSelfUpdatingColor) {
|
||||||
|
isAppSelfUpdatingColor = true; // 标记为应用自身更新
|
||||||
|
try {
|
||||||
|
if (isIncrease) {
|
||||||
|
if (mCurrentBrightnessPercent >= MAX_BRIGHTNESS) return; // 达到最大值,不处理
|
||||||
|
mCurrentBrightnessPercent += BRIGHTNESS_STEP; // 增加步长
|
||||||
|
} else {
|
||||||
|
if (mCurrentBrightnessPercent <= MIN_BRIGHTNESS) return; // 达到最小值,不处理
|
||||||
|
mCurrentBrightnessPercent -= BRIGHTNESS_STEP; // 减少步长
|
||||||
|
}
|
||||||
|
// 计算亮度调节后的实时RGB+最终颜色
|
||||||
|
calculateBrightnessAndUpdate();
|
||||||
|
// 同步所有控件(重点:RGB输入框显示实时值)
|
||||||
|
updateAllViews();
|
||||||
|
LogUtils.d(TAG, (isIncrease ? "increase" : "decrease") + " brightness | "
|
||||||
|
+ "亮度:" + mCurrentBrightnessPercent + "% | 实时RGB:" + mCurrentR + "," + mCurrentG + "," + mCurrentB);
|
||||||
|
} finally {
|
||||||
|
// 直接释放标记,避免卡顿
|
||||||
|
isAppSelfUpdatingColor = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析颜色字符串(支持#RRGGBB/#AARRGGBB,容错处理,更新原始基准值+实时值)
|
||||||
*/
|
*/
|
||||||
private void parseColorFromStr(String colorStr, int triggerViewId) {
|
private void parseColorFromStr(String colorStr, int triggerViewId) {
|
||||||
if (TextUtils.isEmpty(colorStr)) {
|
// 关键:判断非应用自身更新,才执行解析(避免循环回调)
|
||||||
return;
|
if (!isAppSelfUpdatingColor) {
|
||||||
}
|
isAppSelfUpdatingColor = true; // 标记为应用自身更新
|
||||||
|
try {
|
||||||
|
if (TextUtils.isEmpty(colorStr)) return;
|
||||||
|
|
||||||
try {
|
// 补全#前缀(兼容用户输入习惯,如直接输AARRGGBB)
|
||||||
// 补全#前缀,兼容用户输入习惯
|
if (!colorStr.startsWith("#")) {
|
||||||
if (!colorStr.startsWith("#")) {
|
colorStr = "#" + colorStr;
|
||||||
colorStr = "#" + colorStr;
|
}
|
||||||
}
|
|
||||||
// 格式校验:仅支持6位(RRGGBB)/8位(AARRGGBB)
|
|
||||||
if (colorStr.length() != 7 && colorStr.length() != 9) {
|
|
||||||
LogUtils.e(TAG, "color format error, length must be 6 or 8");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int color = Color.parseColor(colorStr);
|
// 格式校验(仅支持6位RRGGBB/8位AARRGGBB,避免非法格式)
|
||||||
// 6位颜色保留当前透明度,避免用户输入丢失
|
if (colorStr.length() != 7 && colorStr.length() != 9) {
|
||||||
if (colorStr.length() == 7) {
|
LogUtils.e(TAG, "parse color failed | 格式错误(需#RRGGBB/#AARRGGBB),输入:" + colorStr);
|
||||||
color = Color.argb(Color.alpha(mCurrentColor), Color.red(color), Color.green(color), Color.blue(color));
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析颜色(系统API,安全可靠)
|
||||||
|
int parsedColor = Color.parseColor(colorStr);
|
||||||
|
|
||||||
|
// 更新原始基准值(用户输入颜色,重置基准)
|
||||||
|
mOriginalAlpha = Color.alpha(parsedColor);
|
||||||
|
mOriginalR = Color.red(parsedColor);
|
||||||
|
mOriginalG = Color.green(parsedColor);
|
||||||
|
mOriginalB = Color.blue(parsedColor);
|
||||||
|
// 更新实时值(原始值=实时值,无亮度调节)
|
||||||
|
mCurrentR = mOriginalR;
|
||||||
|
mCurrentG = mOriginalG;
|
||||||
|
mCurrentB = mOriginalB;
|
||||||
|
// 重置亮度为100%
|
||||||
|
mCurrentBrightnessPercent = DEFAULT_BRIGHTNESS;
|
||||||
|
mCurrentColor = parsedColor;
|
||||||
|
|
||||||
|
// 同步所有控件
|
||||||
|
updateAllViews();
|
||||||
|
LogUtils.d(TAG, "parse color success | 解析颜色:" + String.format("#%08X", parsedColor)
|
||||||
|
+ " | 重置亮度:" + DEFAULT_BRIGHTNESS + "%");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
LogUtils.e(TAG, "parse color failed | 非法颜色格式,输入:" + colorStr, e);
|
||||||
|
} finally {
|
||||||
|
// 直接释放标记,避免卡顿
|
||||||
|
isAppSelfUpdatingColor = false;
|
||||||
}
|
}
|
||||||
updateCurrentColor(color, triggerViewId, true);
|
|
||||||
LogUtils.d(TAG, "parse color success: " + String.format("#%08X", color));
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
LogUtils.e(TAG, "parse color failed, input: " + colorStr, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过RGB输入框更新颜色(传入触发ID,避免循环同步)
|
* 通过RGB输入框更新颜色(用户输入后,更新原始基准值+实时值,重置亮度为100%)
|
||||||
*/
|
*/
|
||||||
private static volatile boolean isUpdatingColorByRGB = false;
|
|
||||||
private synchronized void updateColorByRGB(int triggerViewId) {
|
private synchronized void updateColorByRGB(int triggerViewId) {
|
||||||
if (isUpdatingColorByRGB == false) {
|
// 关键:判断非应用自身更新,才执行更新(避免循环回调)
|
||||||
isUpdatingColorByRGB = true;
|
if (!isAppSelfUpdatingColor) {
|
||||||
try {
|
isAppSelfUpdatingColor = true; // 标记为应用自身更新
|
||||||
int r = parseInputValue(etR.getText().toString());
|
try {
|
||||||
int g = parseInputValue(etG.getText().toString());
|
// 解析用户输入的RGB值(限制0-255,非法输入设为0)
|
||||||
int b = parseInputValue(etB.getText().toString());
|
int inputR = parseInputValue(etR.getText().toString());
|
||||||
int alpha = Color.alpha(mCurrentColor);
|
int inputG = parseInputValue(etG.getText().toString());
|
||||||
int newColor = Color.argb(alpha, r, g, b);
|
int inputB = parseInputValue(etB.getText().toString());
|
||||||
|
|
||||||
updateCurrentColor(newColor, triggerViewId, true);
|
// 更新原始基准值(用户手动输入,作为新的调节基准)
|
||||||
LogUtils.d(TAG, "update color by RGB: R=" + r + ", G=" + g + ", B=" + b);
|
mOriginalR = inputR;
|
||||||
} catch (Exception e) {
|
mOriginalG = inputG;
|
||||||
LogUtils.e(TAG, "update color by RGB failed", e);
|
mOriginalB = inputB;
|
||||||
}
|
// 更新实时值(输入值=实时值,无亮度调节)
|
||||||
try {
|
mCurrentR = inputR;
|
||||||
Thread.sleep(200);
|
mCurrentG = inputG;
|
||||||
isUpdatingColorByRGB = false;
|
mCurrentB = inputB;
|
||||||
} catch (InterruptedException e) {
|
// 重置亮度为100%
|
||||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
mCurrentBrightnessPercent = DEFAULT_BRIGHTNESS;
|
||||||
}
|
// 计算最终颜色(无亮度调节,直接拼接)
|
||||||
}
|
mCurrentColor = Color.argb(mOriginalAlpha, mCurrentR, mCurrentG, mCurrentB);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// 同步所有控件
|
||||||
* 通过透明度进度条更新颜色
|
updateAllViews();
|
||||||
*/
|
LogUtils.d(TAG, "update color by RGB | 新原始RGB:" + mOriginalR + "," + mOriginalG + "," + mOriginalB
|
||||||
private void updateColorByAlpha(int alpha, int triggerViewId) {
|
+ " | 重置亮度:" + DEFAULT_BRIGHTNESS + "%");
|
||||||
int r = Color.red(mCurrentColor);
|
} catch (Exception e) {
|
||||||
int g = Color.green(mCurrentColor);
|
LogUtils.e(TAG, "update color by RGB failed", e);
|
||||||
int b = Color.blue(mCurrentColor);
|
} finally {
|
||||||
int newColor = Color.argb(alpha, r, g, b);
|
// 直接释放标记,避免卡顿
|
||||||
|
isAppSelfUpdatingColor = false;
|
||||||
updateCurrentColor(newColor, triggerViewId, true);
|
}
|
||||||
LogUtils.d(TAG, "update color by alpha: " + alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过亮度进度条更新颜色(系数0.0-2.0,精准调节)
|
|
||||||
*/
|
|
||||||
private void updateColorByBrightness(int brightness, int triggerViewId) {
|
|
||||||
float factor = brightness * 1.0f / DEFAULT_BRIGHTNESS;
|
|
||||||
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);
|
|
||||||
int newColor = Color.argb(alpha, r, g, b);
|
|
||||||
|
|
||||||
updateCurrentColor(newColor, triggerViewId, false);
|
|
||||||
LogUtils.d(TAG, "update color by brightness: factor=" + String.format("%.2f", factor));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 亮度调节(限制0-255,避免颜色分量溢出)
|
|
||||||
*/
|
|
||||||
private int adjustBrightness(int colorComponent, float factor) {
|
|
||||||
int newComponent = Math.round(colorComponent * factor);
|
|
||||||
return Math.min(Math.max(newComponent, 0), MAX_PROGRESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 核心同步方法:更新颜色+同步控件(跳过触发源,杜绝循环)
|
|
||||||
*/
|
|
||||||
private void updateCurrentColor(int newColor, int triggerViewId, boolean updateBrightness) {
|
|
||||||
mCurrentColor = newColor;
|
|
||||||
int red = Color.red(newColor);
|
|
||||||
int green = Color.green(newColor);
|
|
||||||
int blue = Color.blue(newColor);
|
|
||||||
int alpha = Color.alpha(newColor);
|
|
||||||
|
|
||||||
// 1. 同步颜色预览(始终同步)
|
|
||||||
ivColorPicker.setBackgroundColor(newColor);
|
|
||||||
|
|
||||||
// 2. 同步RGB输入框(跳过触发控件)
|
|
||||||
if (triggerViewId != R.id.et_r) etR.setText(String.valueOf(red));
|
|
||||||
if (triggerViewId != R.id.et_g) etG.setText(String.valueOf(green));
|
|
||||||
if (triggerViewId != R.id.et_b) etB.setText(String.valueOf(blue));
|
|
||||||
|
|
||||||
// 3. 同步颜色值输入框(跳过触发控件)
|
|
||||||
if (triggerViewId != R.id.et_color_value) {
|
|
||||||
etColorValue.setText(String.format("#%08X", newColor));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 同步进度条(取消监听避免循环,同步后重新绑定)
|
|
||||||
// 透明度进度条
|
|
||||||
sbAlpha.setOnSeekBarChangeListener(null);
|
|
||||||
if (triggerViewId != R.id.sb_alpha) sbAlpha.setProgress(alpha);
|
|
||||||
initSeekBarListener();
|
|
||||||
|
|
||||||
// 亮度进度条(按需重置)
|
|
||||||
sbBrightness.setOnSeekBarChangeListener(null);
|
|
||||||
if (updateBrightness && triggerViewId != R.id.sb_brightness) {
|
|
||||||
sbBrightness.setProgress(DEFAULT_BRIGHTNESS);
|
|
||||||
}
|
|
||||||
initSeekBarListener();
|
|
||||||
|
|
||||||
LogUtils.d(TAG, "sync view complete, current color: " + String.format("#%08X", newColor));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================== 工具方法(通用能力,下沉到底部) ======================
|
|
||||||
/**
|
/**
|
||||||
* 解析输入值(限制0-255,非法输入返回0)
|
* 核心同步:更新所有控件显示(统一方法,避免冗余,确保RGB输入框实时同步)
|
||||||
|
*/
|
||||||
|
private void updateAllViews() {
|
||||||
|
// 1. 同步颜色预览(显示最终颜色)
|
||||||
|
ivColorPicker.setBackgroundColor(mCurrentColor);
|
||||||
|
|
||||||
|
// 2. 同步RGB输入框(显示实时调节值,关键修复:亮度变化时更新)
|
||||||
|
etR.setText(String.valueOf(mCurrentR));
|
||||||
|
etG.setText(String.valueOf(mCurrentG));
|
||||||
|
etB.setText(String.valueOf(mCurrentB));
|
||||||
|
|
||||||
|
// 3. 同步颜色值输入框(显示最终颜色,含亮度调节)
|
||||||
|
etColorValue.setText(String.format("#%08X", mCurrentColor));
|
||||||
|
|
||||||
|
// 4. 同步亮度控件(数值+按钮状态)
|
||||||
|
tvBrightnessValue.setText(mCurrentBrightnessPercent + "%");
|
||||||
|
updateBrightnessBtnStatus();
|
||||||
|
|
||||||
|
LogUtils.d(TAG, "sync all views complete | 最终颜色:" + String.format("#%08X", mCurrentColor)
|
||||||
|
+ " | 实时RGB:" + mCurrentR + "," + mCurrentG + "," + mCurrentB
|
||||||
|
+ " | 亮度:" + mCurrentBrightnessPercent + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新亮度按钮状态(边界值禁用,提升交互体验)
|
||||||
|
*/
|
||||||
|
private void updateBrightnessBtnStatus() {
|
||||||
|
// 亮度≤10%:禁用减号(文字变浅灰);≥200%:禁用加号(文字变浅灰)
|
||||||
|
boolean canMinus = mCurrentBrightnessPercent > MIN_BRIGHTNESS;
|
||||||
|
boolean canPlus = mCurrentBrightnessPercent < MAX_BRIGHTNESS;
|
||||||
|
|
||||||
|
tvBrightnessMinus.setEnabled(canMinus);
|
||||||
|
tvBrightnessPlus.setEnabled(canPlus);
|
||||||
|
tvBrightnessMinus.setTextColor(canMinus ? Color.BLACK : Color.parseColor("#CCCCCC"));
|
||||||
|
tvBrightnessPlus.setTextColor(canPlus ? Color.BLACK : Color.parseColor("#CCCCCC"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================== 工具方法(通用能力,下沉到底部,复用性强) ======================
|
||||||
|
/**
|
||||||
|
* 解析输入值(限制0-255,非法输入返回0,容错处理)
|
||||||
*/
|
*/
|
||||||
private int parseInputValue(String input) {
|
private int parseInputValue(String input) {
|
||||||
if (TextUtils.isEmpty(input)) {
|
if (TextUtils.isEmpty(input)) return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
int value = Integer.parseInt(input);
|
int value = Integer.parseInt(input);
|
||||||
return Math.min(Math.max(value, 0), MAX_PROGRESS);
|
return Math.min(Math.max(value, 0), MAX_RGB_VALUE); // 限制范围,避免溢出
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
LogUtils.e(TAG, "parse input failed: " + input, e);
|
LogUtils.e(TAG, "parse input failed | 非法数字,输入:" + input, e);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RGB输入框监听复用(传入控件ID,统一回调)
|
* RGB输入框监听复用(减少冗余代码,统一逻辑)
|
||||||
*/
|
*/
|
||||||
private void setEditTextWatcher(EditText editText, final int viewId) {
|
private void setEditTextWatcher(EditText editText, final int viewId) {
|
||||||
editText.addTextChangedListener(new TextWatcher() {
|
editText.addTextChangedListener(new TextWatcher() {
|
||||||
@@ -404,86 +445,111 @@ public class ColorPaletteDialog extends Dialog implements View.OnClickListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable s) {
|
public void afterTextChanged(Editable s) {
|
||||||
updateColorByRGB(viewId);
|
// 关键:判断非应用自身更新,才执行更新(避免循环回调)
|
||||||
|
if (!isAppSelfUpdatingColor) {
|
||||||
|
updateColorByRGB(viewId); // 输入变化后更新颜色
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dp转px(适配小米不同分辨率,避免尺寸错乱)
|
* dp转px(适配小米不同分辨率,避免尺寸错乱,通用工具)
|
||||||
*/
|
*/
|
||||||
private int dp2px(float dp) {
|
private int dp2px(float dp) {
|
||||||
return (int) (dp * getContext().getResources().getDisplayMetrics().density + 0.5f);
|
return (int) (dp * getContext().getResources().getDisplayMetrics().density + 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示系统颜色选择器(兼容API29-30,无高版本依赖)
|
* 显示系统颜色选择器(兼容API29-30,无高版本依赖,小米机型适配)
|
||||||
*/
|
*/
|
||||||
private void showSystemColorPicker() {
|
private void showSystemColorPicker() {
|
||||||
LogUtils.d(TAG, "show system color picker");
|
LogUtils.d(TAG, "show system color picker | 兼容小米API29-30");
|
||||||
final android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(getContext());
|
final android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(getContext());
|
||||||
builder.setTitle("选择颜色");
|
builder.setTitle("选择基础颜色");
|
||||||
|
|
||||||
// 常用基础色(小米机型显示适配)
|
// 常用基础色(10种,覆盖主流需求,可按需增减)
|
||||||
final int[] systemColors = {
|
final int[] systemColors = {
|
||||||
0xFFFFFFFF, 0xFF000000, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF,
|
0xFFFFFFFF, 0xFF000000, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF,
|
||||||
0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 0xFF888888, 0xFFAAAAAA
|
0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 0xFF888888, 0xFFAAAAAA
|
||||||
};
|
};
|
||||||
|
|
||||||
// 动态创建颜色选择布局(横向排列,适配小米屏幕)
|
// 动态创建颜色选择布局(横向排列,适配小米屏幕)
|
||||||
LinearLayout colorView = new LinearLayout(getContext());
|
LinearLayout colorLayout = new LinearLayout(getContext());
|
||||||
colorView.setOrientation(LinearLayout.HORIZONTAL);
|
colorLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||||
colorView.setGravity(Gravity.CENTER);
|
colorLayout.setGravity(Gravity.CENTER);
|
||||||
colorView.setPadding(dp2px(10), dp2px(10), dp2px(10), dp2px(10));
|
colorLayout.setPadding(dp2px(10), dp2px(10), dp2px(10), dp2px(10));
|
||||||
|
|
||||||
|
// 循环添加颜色按钮(圆形,点击选择)
|
||||||
for (int i = 0; i < systemColors.length; i++) {
|
for (int i = 0; i < systemColors.length; i++) {
|
||||||
ImageView iv = new ImageView(getContext());
|
final int color = systemColors[i];
|
||||||
|
ImageView colorBtn = new ImageView(getContext());
|
||||||
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(dp2px(40), dp2px(40));
|
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(dp2px(40), dp2px(40));
|
||||||
// 低版本兼容:用setMargins替代setMarginEnd(适配API29-30)
|
|
||||||
if (i != systemColors.length - 1) {
|
if (i != systemColors.length - 1) {
|
||||||
lp.setMargins(0, 0, dp2px(10), 0);
|
lp.setMargins(0, 0, dp2px(10), 0); // 低版本兼容setMargins(API29-30)
|
||||||
}
|
}
|
||||||
iv.setLayoutParams(lp);
|
colorBtn.setLayoutParams(lp);
|
||||||
iv.setBackgroundColor(systemColors[i]);
|
colorBtn.setBackgroundColor(color);
|
||||||
iv.setClickable(true);
|
colorBtn.setClickable(true);
|
||||||
iv.setFocusable(true);
|
colorBtn.setFocusable(true);
|
||||||
|
|
||||||
final int finalI = i;
|
// 点击选择颜色:更新原始基准值+实时值,重置亮度为100%
|
||||||
iv.setOnClickListener(new View.OnClickListener() {
|
colorBtn.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
int selectedColor = systemColors[finalI];
|
// 关键:判断非应用自身更新,才执行选择逻辑(避免循环)
|
||||||
// 保留当前透明度,仅更新RGB
|
if (!isAppSelfUpdatingColor) {
|
||||||
int newColor = Color.argb(
|
isAppSelfUpdatingColor = true; // 标记为应用自身更新
|
||||||
Color.alpha(mCurrentColor),
|
try {
|
||||||
Color.red(selectedColor),
|
// 更新原始基准值
|
||||||
Color.green(selectedColor),
|
mOriginalR = Color.red(color);
|
||||||
Color.blue(selectedColor)
|
mOriginalG = Color.green(color);
|
||||||
);
|
mOriginalB = Color.blue(color);
|
||||||
updateCurrentColor(newColor, NO_TARGET_ID, true);
|
mOriginalAlpha = Color.alpha(color);
|
||||||
builder.create().dismiss();
|
// 更新实时值(原始值=实时值)
|
||||||
LogUtils.d(TAG, "select system color: " + String.format("#%08X", selectedColor));
|
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));
|
||||||
|
} finally {
|
||||||
|
// 释放标记
|
||||||
|
isAppSelfUpdatingColor = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
colorView.addView(iv);
|
colorLayout.addView(colorBtn);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.setView(colorView).setNegativeButton("取消", null).show();
|
builder.setView(colorLayout).setNegativeButton("取消", null).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================== 点击事件实现(统一处理按钮交互) ======================
|
// ====================== 点击事件实现(统一处理,逻辑清晰) ======================
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
int id = v.getId();
|
int id = v.getId();
|
||||||
if (id == R.id.iv_color_picker) {
|
// 关键:所有点击事件均加判断(避免并发冲突/重复触发)
|
||||||
showSystemColorPicker();
|
if (!isAppSelfUpdatingColor) {
|
||||||
} else if (id == R.id.tv_confirm) {
|
if (id == R.id.iv_color_picker) {
|
||||||
mListener.onColorSelected(mCurrentColor);
|
showSystemColorPicker(); // 打开系统颜色选择器
|
||||||
LogUtils.d(TAG, "confirm color, callback: " + String.format("#%08X", mCurrentColor));
|
} else if (id == R.id.tv_confirm) {
|
||||||
dismiss();
|
mListener.onColorSelected(mCurrentColor); // 确认选择,回调颜色
|
||||||
} else if (id == R.id.tv_cancel) {
|
LogUtils.d(TAG, "confirm color | 回调颜色:" + String.format("#%08X", mCurrentColor));
|
||||||
dismiss();
|
dismiss();
|
||||||
LogUtils.d(TAG, "cancel color, dismiss dialog");
|
} else if (id == R.id.tv_cancel) {
|
||||||
|
dismiss(); // 取消,关闭对话框
|
||||||
|
LogUtils.d(TAG, "cancel color | 取消选择,关闭对话框");
|
||||||
|
} else if (id == R.id.tv_brightness_minus) {
|
||||||
|
decreaseBrightness(); // 减少亮度
|
||||||
|
} else if (id == R.id.tv_brightness_plus) {
|
||||||
|
increaseBrightness(); // 增加亮度
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
powerbell/src/main/res/drawable/btn_brightness_bg.xml
Normal file
20
powerbell/src/main/res/drawable/btn_brightness_bg.xml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- 按压状态:浅灰色背景 -->
|
||||||
|
<item android:state_pressed="true">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#E0E0E0" /> <!-- 按压深色 -->
|
||||||
|
<corners android:radius="8dp" /> <!-- 圆角适配小米UI风格 -->
|
||||||
|
<stroke android:width="1dp" android:color="#CCCCCC" /> <!-- 边框 -->
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<!-- 正常状态:白色背景 -->
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#FFFFFF" /> <!-- 正常白色 -->
|
||||||
|
<corners android:radius="8dp" />
|
||||||
|
<stroke android:width="1dp" android:color="#CCCCCC" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
|
|
||||||
18
powerbell/src/main/res/drawable/btn_cancel_bg.xml
Normal file
18
powerbell/src/main/res/drawable/btn_cancel_bg.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- 按压状态:深灰色背景 -->
|
||||||
|
<item android:state_pressed="true">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#D0D0D0" />
|
||||||
|
<corners android:radius="8dp" /> <!-- 与亮度按钮圆角一致,统一风格 -->
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<!-- 正常状态:浅灰色背景 -->
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#F0F0F0" />
|
||||||
|
<corners android:radius="8dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
|
|
||||||
18
powerbell/src/main/res/drawable/btn_confirm_bg.xml
Normal file
18
powerbell/src/main/res/drawable/btn_confirm_bg.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- 按压状态:加深深色背景 -->
|
||||||
|
<item android:state_pressed="true">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#2D7CFF" /> <!-- 按压深蓝 -->
|
||||||
|
<corners android:radius="8dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<!-- 正常状态:主色背景(可改为项目主题色) -->
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#4096FF" /> <!-- 正常浅蓝,适配小米系统UI -->
|
||||||
|
<corners android:radius="8dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
|
|
||||||
@@ -4,203 +4,156 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="20dp"
|
android:padding="20dp"
|
||||||
android:background="@drawable/dialog_bg_radius">
|
android:background="@android:color/white"
|
||||||
|
android:radius="12dp">
|
||||||
|
|
||||||
<!-- 标题 -->
|
<!-- 颜色预览 -->
|
||||||
<TextView
|
<ImageView
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/iv_color_picker"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="100dp"
|
||||||
android:text="调色板"
|
android:layout_height="100dp"
|
||||||
android:textSize="18sp"
|
android:layout_gravity="center_horizontal"
|
||||||
android:textColor="@color/black"
|
android:layout_marginBottom="20dp"
|
||||||
android:textStyle="bold"
|
android:background="@color/black"
|
||||||
android:layout_marginBottom="20dp"/>
|
android:clickable="true"
|
||||||
|
android:focusable="true" />
|
||||||
|
|
||||||
<!-- 颜色拾取框 -->
|
<!-- RGB输入区 -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:gravity="center_vertical"
|
android:layout_marginBottom="15dp"
|
||||||
android:layout_marginBottom="15dp">
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="颜色拾取:"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:textColor="@color/gray_700"
|
|
||||||
android:layout_marginRight="10dp"/>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/iv_color_picker"
|
|
||||||
android:layout_width="50dp"
|
|
||||||
android:layout_height="50dp"
|
|
||||||
android:background="@color/white"
|
|
||||||
android:scaleType="fitXY"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:padding="2dp"
|
|
||||||
android:backgroundTint="@color/gray_200"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<!-- RGB 输入框 -->
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:layout_marginBottom="15dp">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="RGB:"
|
android:text="RGB:"
|
||||||
android:textSize="14sp"
|
android:textSize="16sp"
|
||||||
android:textColor="@color/gray_700"
|
android:textColor="@android:color/black" />
|
||||||
android:layout_marginRight="10dp"/>
|
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/et_r"
|
android:id="@+id/et_r"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
android:hint="R"
|
android:hint="R"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
android:maxLength="3"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textSize="14sp"
|
android:maxLength="3"
|
||||||
android:background="@drawable/edittext_bg"
|
android:textSize="14sp" />
|
||||||
android:padding="5dp"
|
|
||||||
android:layout_marginRight="10dp"/>
|
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/et_g"
|
android:id="@+id/et_g"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
android:hint="G"
|
android:hint="G"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
android:maxLength="3"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textSize="14sp"
|
android:maxLength="3"
|
||||||
android:background="@drawable/edittext_bg"
|
android:textSize="14sp" />
|
||||||
android:padding="5dp"
|
|
||||||
android:layout_marginRight="10dp"/>
|
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/et_b"
|
android:id="@+id/et_b"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
android:hint="B"
|
android:hint="B"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
|
android:gravity="center"
|
||||||
android:maxLength="3"
|
android:maxLength="3"
|
||||||
android:gravity="center"
|
android:textSize="14sp" />
|
||||||
android:textSize="14sp"
|
|
||||||
android:background="@drawable/edittext_bg"
|
|
||||||
android:padding="5dp"/>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- 颜色值输入框 -->
|
<!-- 颜色值输入区 -->
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/et_color_value"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="45dp"
|
||||||
|
android:layout_marginBottom="15dp"
|
||||||
|
android:hint="#AARRGGBB"
|
||||||
|
android:inputType="text"
|
||||||
|
android:paddingLeft="15dp"
|
||||||
|
android:paddingRight="15dp"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:background="@drawable/edittext_bg" />
|
||||||
|
|
||||||
|
<!-- 亮度调节区(底部:左-减号,中-数值,右-加号) -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:gravity="center_vertical"
|
android:layout_marginBottom="20dp"
|
||||||
android:layout_marginBottom="15dp">
|
android:gravity="center_horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/tv_brightness_minus"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="40dp"
|
||||||
android:text="颜色值:"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:textColor="@color/gray_700"
|
|
||||||
android:layout_marginRight="10dp"/>
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/et_color_value"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:hint="#AARRGGBB"
|
|
||||||
android:inputType="text"
|
|
||||||
android:maxLength="9"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textSize="14sp"
|
android:text="-"
|
||||||
android:background="@drawable/edittext_bg"
|
android:textSize="20sp"
|
||||||
android:padding="5dp"/>
|
android:textColor="@android:color/black"
|
||||||
</LinearLayout>
|
android:background="@drawable/btn_brightness_bg"
|
||||||
|
android:clickable="true"
|
||||||
<!-- 透明度进度条 -->
|
android:focusable="true" />
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_marginBottom="15dp">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/tv_brightness_value"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="透明度(0-255)"
|
android:layout_marginLeft="20dp"
|
||||||
android:textSize="14sp"
|
android:layout_marginRight="20dp"
|
||||||
android:textColor="@color/gray_700"
|
android:text="100%"
|
||||||
android:layout_marginBottom="5dp"/>
|
android:textSize="16sp"
|
||||||
|
android:textColor="@android:color/black" />
|
||||||
<SeekBar
|
|
||||||
android:id="@+id/sb_alpha"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:progressDrawable="@drawable/seekbar_progress"
|
|
||||||
android:thumb="@drawable/seekbar_thumb"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<!-- 色阶进度条 -->
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_marginBottom="20dp">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/tv_brightness_plus"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="40dp"
|
||||||
android:text="色阶(亮度)"
|
android:layout_height="40dp"
|
||||||
android:textSize="14sp"
|
android:gravity="center"
|
||||||
android:textColor="@color/gray_700"
|
android:text="+"
|
||||||
android:layout_marginBottom="5dp"/>
|
android:textSize="20sp"
|
||||||
|
android:textColor="@android:color/black"
|
||||||
<SeekBar
|
android:background="@drawable/btn_brightness_bg"
|
||||||
android:id="@+id/sb_brightness"
|
android:clickable="true"
|
||||||
android:layout_width="match_parent"
|
android:focusable="true" />
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:progressDrawable="@drawable/seekbar_progress"
|
|
||||||
android:thumb="@drawable/seekbar_thumb"/>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- 按钮区域 -->
|
<!-- 底部按钮区 -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:gravity="end">
|
android:gravity="center_horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_cancel"
|
android:id="@+id/tv_cancel"
|
||||||
android:layout_width="80dp"
|
android:layout_width="120dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="45dp"
|
||||||
android:text="取消"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textSize="14sp"
|
android:text="取消"
|
||||||
android:textColor="@color/gray_700"
|
android:textSize="16sp"
|
||||||
android:background="@drawable/btn_bg_gray"
|
android:textColor="@android:color/black"
|
||||||
android:layout_marginRight="10dp"/>
|
android:background="@drawable/btn_cancel_bg"
|
||||||
|
android:layout_marginRight="20dp"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_confirm"
|
android:id="@+id/tv_confirm"
|
||||||
android:layout_width="80dp"
|
android:layout_width="120dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="45dp"
|
||||||
android:text="确认"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textSize="14sp"
|
android:text="确认"
|
||||||
android:textColor="@color/white"
|
android:textSize="16sp"
|
||||||
android:background="@drawable/btn_bg_primary"/>
|
android:textColor="@android:color/white"
|
||||||
|
android:background="@drawable/btn_confirm_bg"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
Reference in New Issue
Block a user