From 35d210c378e7fbbc8b91d48a85752fda0753f740 Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Sat, 20 Dec 2025 19:26:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=BB=9A=E5=8A=A8=E6=9D=A1?= =?UTF-8?q?=E6=8B=89=E5=8A=A8=E6=97=B6=EF=BC=8C=E5=AE=9E=E6=97=B6=E9=A2=84?= =?UTF-8?q?=E8=A7=88=E6=95=B0=E5=80=BC=E7=9A=84=E5=8A=9F=E8=83=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- powerbell/build.properties | 4 +- .../studio/powerbell/MainActivity.java | 121 ++---- .../powerbell/views/MainContentView.java | 376 +++++++++++------- .../powerbell/views/VerticalSeekBar.java | 215 ++++++---- 4 files changed, 411 insertions(+), 305 deletions(-) diff --git a/powerbell/build.properties b/powerbell/build.properties index 1d9044e..7086acd 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Sat Dec 20 18:45:13 HKT 2025 +#Sat Dec 20 11:24:15 GMT 2025 stageCount=11 libraryProject= baseVersion=15.14 publishVersion=15.14.10 -buildCount=0 +buildCount=2 baseBetaVersion=15.14.11 diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java index 5841b82..10d1103 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java @@ -41,14 +41,11 @@ import cc.winboll.studio.powerbell.views.MainContentView; * 适配:Java7 | API30 | 内存泄漏防护 | UI与服务状态实时同步 */ public class MainActivity extends WinBoLLActivity implements MainContentView.OnViewActionListener { - // ======================== 静态常量(置顶统一,抽离魔法值,便于维护)======================== - public static final String TAG = "MainActivity"; - // 请求码常量 + // ======================== 静态常量(置顶统一,抽离魔法值)======================== + public static final String TAG = "MainActivity"; private static final int REQUEST_READ_MEDIA_IMAGES = 1001; - // 延迟加载常量(非核心视图延迟加载时长) private static final long DELAY_LOAD_NON_CRITICAL = 500L; - // Handler消息标识(按业务优先级排序) public static final int MSG_RELOAD_APPCONFIG = 0; public static final int MSG_CURRENTVALUEBATTERY = 1; public static final int MSG_LOAD_BACKGROUND = 2; @@ -75,7 +72,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV private Drawable mFrameDrawable; private Menu mMenu; - // ======================== 生命周期方法(按系统调用顺序排列,逻辑闭环)======================== + // ======================== 生命周期方法(按系统调用顺序排列)======================== @Override public Activity getActivity() { return this; @@ -88,12 +85,10 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV @Override protected void onCreate(Bundle savedInstanceState) { - LogUtils.d(TAG, "onCreate: 页面启动,开始初始化流程 | savedInstanceState=" + savedInstanceState); super.onCreate(savedInstanceState); + LogUtils.d(TAG, "onCreate() | savedInstanceState=" + savedInstanceState); - // 优先初始化全局Handler,避免消息丢失 initGlobalHandler(); - // 布局与核心流程初始化 setContentView(R.layout.activity_main); initPermissionUtils(); initMainContentView(); @@ -105,62 +100,56 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); - LogUtils.d(TAG, "onPostCreate: 发起权限申请"); + LogUtils.d(TAG, "onPostCreate() | savedInstanceState=" + savedInstanceState); mPermissionUtils.startPermissionRequest(this); + LogUtils.d(TAG, "onPostCreate: 发起权限申请"); } @Override protected void onResume() { super.onResume(); - LogUtils.d(TAG, "onResume: 恢复页面状态"); - // 恢复背景与服务开关UI + LogUtils.d(TAG, "onResume()"); if (sGlobalHandler != null) { sGlobalHandler.sendEmptyMessage(MSG_LOAD_BACKGROUND); sGlobalHandler.sendEmptyMessage(MSG_UPDATE_SERVICE_SWITCH); - LogUtils.d(TAG, "onResume: 发送背景加载与服务开关更新消息"); } - // 恢复广告 if (mADsBannerView != null) { mADsBannerView.resumeADs(this); - LogUtils.d(TAG, "onResume: 广告视图恢复展示"); } } @Override protected void onPause() { super.onPause(); - LogUtils.d(TAG, "onPause: 页面暂停"); + LogUtils.d(TAG, "onPause()"); } @Override protected void onDestroy() { super.onDestroy(); - LogUtils.d(TAG, "onDestroy: 开始释放资源"); + LogUtils.d(TAG, "onDestroy()"); + // 释放广告资源 if (mADsBannerView != null) { mADsBannerView.releaseAdResources(); mADsBannerView = null; - LogUtils.d(TAG, "onDestroy: 广告资源已释放"); } // 释放核心视图 if (mMainContentView != null) { mMainContentView.releaseResources(); mMainContentView = null; - LogUtils.d(TAG, "onDestroy: 核心视图资源已释放"); } // 销毁Handler,防止内存泄漏 if (sGlobalHandler != null) { sGlobalHandler.removeCallbacksAndMessages(null); sGlobalHandler = null; - LogUtils.d(TAG, "onDestroy: 全局Handler已销毁"); } - // 释放Drawable,清空回调 + // 释放Drawable if (mFrameDrawable != null) { mFrameDrawable.setCallback(null); mFrameDrawable = null; - LogUtils.d(TAG, "onDestroy: 框架背景Drawable已释放"); } - // 置空所有引用,帮助GC回收 + // 置空所有引用 sMainActivity = null; mPermissionUtils = null; mAppConfigUtils = null; @@ -170,31 +159,27 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV mApplication = null; mToolbar = null; mAdsViewStub = null; - LogUtils.d(TAG, "onDestroy: 所有资源释放完成"); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - LogUtils.d(TAG, "onActivityResult: requestCode=" + requestCode + " | resultCode=" + resultCode + " | data=" + data); + LogUtils.d(TAG, "onActivityResult() | requestCode=" + requestCode + " | resultCode=" + resultCode + " | data=" + data); mPermissionUtils.handlePermissionRequest(this, requestCode, resultCode, data); - // 背景设置完成后重新加载 if (requestCode == REQUEST_READ_MEDIA_IMAGES && sGlobalHandler != null) { sGlobalHandler.sendEmptyMessage(MSG_LOAD_BACKGROUND); - LogUtils.d(TAG, "onActivityResult: 背景设置完成,发送重新加载消息"); } } // ======================== 菜单与导航方法 ======================== @Override public boolean onCreateOptionsMenu(Menu menu) { - LogUtils.d(TAG, "onCreateOptionsMenu: 初始化菜单"); + LogUtils.d(TAG, "onCreateOptionsMenu() | menu=" + menu); mMenu = menu; AESThemeUtil.inflateMenu(this, menu); if (App.isDebugging()) { DevelopUtils.inflateMenu(this, menu); getMenuInflater().inflate(R.menu.toolbar_unittest, mMenu); - LogUtils.d(TAG, "onCreateOptionsMenu: 调试模式,加载单元测试菜单"); } getMenuInflater().inflate(R.menu.toolbar_main, mMenu); return true; @@ -202,7 +187,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV @Override public boolean onOptionsItemSelected(MenuItem item) { - LogUtils.d(TAG, "onOptionsItemSelected: 菜单点击 | itemId=" + item.getItemId()); + LogUtils.d(TAG, "onOptionsItemSelected() | itemId=" + item.getItemId()); if (AESThemeUtil.onAppThemeItemSelected(this, item)) { recreate(); return true; @@ -213,27 +198,21 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV switch (item.getItemId()) { case R.id.action_settings: startActivity(new Intent(this, SettingsActivity.class)); - LogUtils.d(TAG, "onOptionsItemSelected: 跳转设置页面"); break; case R.id.action_battery_report: startActivity(new Intent(this, BatteryReportActivity.class)); - LogUtils.d(TAG, "onOptionsItemSelected: 跳转电池报告页面"); break; case R.id.action_clearrecord: startActivity(new Intent(this, ClearRecordActivity.class)); - LogUtils.d(TAG, "onOptionsItemSelected: 跳转记录清理页面"); break; case R.id.action_changepicture: startActivityForResult(new Intent(this, BackgroundSettingsActivity.class), REQUEST_READ_MEDIA_IMAGES); - LogUtils.d(TAG, "onOptionsItemSelected: 跳转背景设置页面 | requestCode=" + REQUEST_READ_MEDIA_IMAGES); break; case R.id.action_unittestactivity: startActivity(new Intent(this, MainUnitTestActivity.class)); - LogUtils.d(TAG, "onOptionsItemSelected: 跳转单元测试页面"); break; case R.id.action_about: startAboutActivity(); - LogUtils.d(TAG, "onOptionsItemSelected: 跳转关于页面"); break; default: return super.onOptionsItemSelected(item); @@ -244,41 +223,41 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV @Override public void setupToolbar() { super.setupToolbar(); + LogUtils.d(TAG, "setupToolbar()"); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(false); - LogUtils.d(TAG, "setupToolbar: 隐藏返回按钮"); } } @Override public void onBackPressed() { + LogUtils.d(TAG, "onBackPressed()"); moveTaskToBack(true); - LogUtils.d(TAG, "onBackPressed: 应用退至后台"); } @Override public boolean dispatchKeyEvent(KeyEvent event) { + LogUtils.d(TAG, "dispatchKeyEvent() | event=" + event); return super.dispatchKeyEvent(event); } // ======================== 核心初始化方法 ======================== private void initPermissionUtils() { - LogUtils.d(TAG, "initPermissionUtils: 初始化权限工具类"); + LogUtils.d(TAG, "initPermissionUtils()"); mPermissionUtils = PermissionUtils.getInstance(); } private void initGlobalHandler() { - LogUtils.d(TAG, "initGlobalHandler: 初始化全局Handler"); + LogUtils.d(TAG, "initGlobalHandler()"); if (sGlobalHandler == null) { sGlobalHandler = new Handler() { @Override public void handleMessage(Message msg) { - // 校验Activity状态,避免销毁后操作UI if (sMainActivity == null || sMainActivity.isFinishing() || sMainActivity.isDestroyed()) { LogUtils.w(TAG, "handleMessage: Activity已销毁,跳过消息 | what=" + msg.what); return; } - LogUtils.d(TAG, "handleMessage: 处理消息 | what=" + msg.what); + LogUtils.d(TAG, "handleMessage() | what=" + msg.what); switch (msg.what) { case MSG_RELOAD_APPCONFIG: sMainActivity.updateViewData(); @@ -299,30 +278,28 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV } } }; - LogUtils.d(TAG, "initGlobalHandler: 全局Handler创建成功"); } } private void initMainContentView() { - LogUtils.d(TAG, "initMainContentView: 初始化核心视图"); + LogUtils.d(TAG, "initMainContentView()"); View rootView = findViewById(android.R.id.content); mMainContentView = new MainContentView(this, rootView, this); } private void initCriticalView() { - LogUtils.d(TAG, "initCriticalView: 初始化关键视图组件"); + LogUtils.d(TAG, "initCriticalView()"); sMainActivity = this; mToolbar = findViewById(R.id.toolbar); setSupportActionBar(mToolbar); if (mToolbar != null) { mToolbar.setTitleTextAppearance(this, R.style.Toolbar_TitleText); - LogUtils.d(TAG, "initCriticalView: Toolbar样式设置完成"); } mAdsViewStub = findViewById(R.id.stub_ads_banner); } private void initCoreUtilsAsync() { - LogUtils.d(TAG, "initCoreUtilsAsync: 异步初始化核心工具类"); + LogUtils.d(TAG, "initCoreUtilsAsync()"); new Thread(new Runnable() { @Override public void run() { @@ -336,7 +313,6 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV if (mServiceControlBean == null) { mServiceControlBean = new ControlCenterServiceBean(false); ControlCenterServiceBean.saveBean(getApplicationContext(), mServiceControlBean); - LogUtils.d(TAG, "initCoreUtilsAsync: 本地无配置,创建默认禁用配置"); } // 根据配置启停服务 @@ -348,7 +324,6 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV @Override public void run() { ControlCenterService.startControlCenterService(getApplicationContext()); - LogUtils.d(TAG, "initCoreUtilsAsync: 配置启用服务,启动服务"); } }); } else if (!isServiceEnable && isServiceAlive) { @@ -356,7 +331,6 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV @Override public void run() { ControlCenterService.stopControlCenterService(getApplicationContext()); - LogUtils.d(TAG, "initCoreUtilsAsync: 配置禁用服务,停止服务"); } }); } @@ -380,13 +354,12 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV sGlobalHandler.sendEmptyMessage(MSG_UPDATE_SERVICE_SWITCH); } }); - LogUtils.d(TAG, "initCoreUtilsAsync: 异步线程执行完成"); } }).start(); } private void loadNonCriticalViewDelayed() { - LogUtils.d(TAG, "loadNonCriticalViewDelayed: 延迟加载非核心视图 | 延迟时长=" + DELAY_LOAD_NON_CRITICAL + "ms"); + LogUtils.d(TAG, "loadNonCriticalViewDelayed() | 延迟时长=" + DELAY_LOAD_NON_CRITICAL + "ms"); new Handler().postDelayed(new Runnable() { @Override public void run() { @@ -401,7 +374,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV // ======================== 视图操作方法 ======================== private void loadAdsView() { - LogUtils.d(TAG, "loadAdsView: 加载广告视图"); + LogUtils.d(TAG, "loadAdsView()"); if (mAdsViewStub == null) { LogUtils.e(TAG, "loadAdsView: 广告ViewStub为空,加载失败"); return; @@ -409,22 +382,20 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV if (mADsBannerView == null) { View adsView = mAdsViewStub.inflate(); mADsBannerView = adsView.findViewById(R.id.adsbanner); - LogUtils.d(TAG, "loadAdsView: 广告视图创建成功"); } } private void updateViewData() { - LogUtils.d(TAG, "updateViewData: 更新视图数据"); + LogUtils.d(TAG, "updateViewData()"); if (mMainContentView == null || mFrameDrawable == null) { LogUtils.e(TAG, "updateViewData: 核心视图或框架背景为空,更新失败"); return; } mMainContentView.updateViewData(mFrameDrawable); - LogUtils.d(TAG, "updateViewData: 视图数据更新完成"); } private void reloadBackground() { - LogUtils.d(TAG, "reloadBackground: 重新加载背景"); + LogUtils.d(TAG, "reloadBackground()"); if (mMainContentView == null || mBgSourceUtils == null) { LogUtils.e(TAG, "reloadBackground: 核心视图或背景工具类为空,加载失败"); return; @@ -432,15 +403,13 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV BackgroundBean currentBgBean = mBgSourceUtils.getCurrentBackgroundBean(); if (currentBgBean != null) { mMainContentView.backgroundView.loadBackgroundBean(currentBgBean); - LogUtils.d(TAG, "reloadBackground: 加载自定义背景成功"); } else { mMainContentView.backgroundView.setBackgroundResource(R.drawable.default_background); - LogUtils.w(TAG, "reloadBackground: 无自定义背景,使用默认背景"); } } private void setMainLayoutBackgroundColor() { - LogUtils.d(TAG, "setMainLayoutBackgroundColor: 设置主布局背景色"); + LogUtils.d(TAG, "setMainLayoutBackgroundColor()"); if (isFinishing() || isDestroyed() || mMainContentView == null || mBgSourceUtils == null) { LogUtils.e(TAG, "setMainLayoutBackgroundColor: 上下文无效,设置失败"); return; @@ -453,41 +422,34 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV } private void updateServiceSwitchUI() { - LogUtils.d(TAG, "updateServiceSwitchUI: 更新服务开关UI状态"); + LogUtils.d(TAG, "updateServiceSwitchUI()"); if (mMainContentView == null || mServiceControlBean == null) { LogUtils.e(TAG, "updateServiceSwitchUI: 核心视图或服务配置为空,更新失败"); return; } boolean configEnabled = mServiceControlBean.isEnableService(); - LogUtils.d(TAG, "updateServiceSwitchUI: 服务配置启用状态=" + configEnabled); mMainContentView.setServiceSwitchEnabled(false); mMainContentView.setServiceSwitchChecked(configEnabled); mMainContentView.setServiceSwitchEnabled(true); - LogUtils.d(TAG, "updateServiceSwitchUI: 服务开关UI状态更新完成"); } // ======================== 服务与线程管理方法 ======================== private void toggleServiceEnableState(boolean isEnable) { - LogUtils.d(TAG, "toggleServiceEnableState: 切换服务状态 | 目标状态=" + isEnable); + LogUtils.d(TAG, "toggleServiceEnableState() | 目标状态=" + isEnable); if (mServiceControlBean == null) { LogUtils.e(TAG, "toggleServiceEnableState: 服务配置为空,切换失败"); return; } mServiceControlBean.setIsEnableService(isEnable); ControlCenterServiceBean.saveBean(getApplicationContext(), mServiceControlBean); - LogUtils.d(TAG, "toggleServiceEnableState: 服务配置已保存"); // UI开关联动服务启停 if (isEnable) { - // 开启:启动服务 if (!ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName())) { ControlCenterService.startControlCenterService(getApplicationContext()); - LogUtils.d(TAG, "toggleServiceEnableState: 服务已启动"); } } else { - // 关闭:停止服务 ControlCenterService.stopControlCenterService(getApplicationContext()); - LogUtils.d(TAG, "toggleServiceEnableState: 服务已停止"); } sGlobalHandler.sendEmptyMessage(MSG_UPDATE_SERVICE_SWITCH); @@ -495,7 +457,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV // ======================== 页面跳转方法 ======================== private void startAboutActivity() { - LogUtils.d(TAG, "startAboutActivity: 启动关于页面"); + LogUtils.d(TAG, "startAboutActivity()"); Intent aboutIntent = new Intent(getApplicationContext(), AboutActivity.class); APPInfo appInfo = genDefaultAppInfo(); aboutIntent.putExtra(AboutActivity.EXTRA_APPINFO, appInfo); @@ -504,14 +466,13 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV // ======================== 消息发送方法 ======================== private void notifyServiceAppConfigChange() { - LogUtils.d(TAG, "notifyServiceAppConfigChange: 通知服务配置变更"); + LogUtils.d(TAG, "notifyServiceAppConfigChange()"); ControlCenterService.sendAppConfigStatusUpdateMessage(this); reloadAppConfig(); } - // ======================== 静态工具方法 ======================== public static void reloadAppConfig() { - LogUtils.d(TAG, "reloadAppConfig: 发送配置重载消息"); + LogUtils.d(TAG, "reloadAppConfig()"); if (sGlobalHandler != null) { sGlobalHandler.sendEmptyMessage(MSG_RELOAD_APPCONFIG); } else { @@ -520,7 +481,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV } public static void sendCurrentBatteryValueMessage(int value) { - LogUtils.d(TAG, "sendCurrentBatteryValueMessage: 发送当前电量消息 | 电量=" + value); + LogUtils.d(TAG, "sendCurrentBatteryValueMessage() | 电量=" + value); if (sGlobalHandler != null) { Message msg = sGlobalHandler.obtainMessage(MSG_CURRENTVALUEBATTERY); msg.arg1 = value; @@ -532,7 +493,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV // ======================== 辅助工具方法 ======================== private APPInfo genDefaultAppInfo() { - LogUtils.d(TAG, "genDefaultAppInfo: 生成默认应用信息"); + LogUtils.d(TAG, "genDefaultAppInfo()"); String branchName = "powerbell"; APPInfo appInfo = new APPInfo(); appInfo.setAppName(getString(R.string.app_name)); @@ -551,31 +512,31 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV // ======================== MainContentView 事件回调 ======================== @Override public void onChargeReminderSwitchChanged(boolean isChecked) { - LogUtils.d(TAG, "onChargeReminderSwitchChanged: 充电提醒开关状态变更 | isChecked=" + isChecked); + LogUtils.d(TAG, "onChargeReminderSwitchChanged() | isChecked=" + isChecked); notifyServiceAppConfigChange(); } @Override public void onUsageReminderSwitchChanged(boolean isChecked) { - LogUtils.d(TAG, "onUsageReminderSwitchChanged: 耗电提醒开关状态变更 | isChecked=" + isChecked); + LogUtils.d(TAG, "onUsageReminderSwitchChanged() | isChecked=" + isChecked); notifyServiceAppConfigChange(); } @Override public void onServiceSwitchChanged(boolean isChecked) { - LogUtils.d(TAG, "onServiceSwitchChanged: 服务总开关状态变更 | isChecked=" + isChecked); + LogUtils.d(TAG, "onServiceSwitchChanged() | isChecked=" + isChecked); toggleServiceEnableState(isChecked); } @Override public void onChargeReminderProgressChanged(int progress) { - LogUtils.d(TAG, "onChargeReminderProgressChanged: 充电提醒阈值变更 | progress=" + progress); + LogUtils.d(TAG, "onChargeReminderProgressChanged() | progress=" + progress); notifyServiceAppConfigChange(); } @Override public void onUsageReminderProgressChanged(int progress) { - LogUtils.d(TAG, "onUsageReminderProgressChanged: 耗电提醒阈值变更 | progress=" + progress); + LogUtils.d(TAG, "onUsageReminderProgressChanged() | progress=" + progress); notifyServiceAppConfigChange(); } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MainContentView.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MainContentView.java index 69ca29a..94a38d8 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MainContentView.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MainContentView.java @@ -24,12 +24,55 @@ import cc.winboll.studio.powerbell.utils.AppConfigUtils; * @Date 2025/12/17 13:14 * @Describe 主页面核心视图封装类:统一管理视图绑定、数据更新、事件监听,解耦 Activity 逻辑 * 适配:Java7 | API30 | 小米手机,优化性能与资源回收,杜绝内存泄漏,配置变更确认对话框 + * 新增:拖动进度条时实时预览 sbUsageReminder 与 sbChargeReminder 比值 */ public class MainContentView { // ======================== 静态常量(置顶,唯一标识)======================== public static final String TAG = "MainContentView"; - // ======================== 核心成员变量(按「依赖→视图→内部资源→对话框」排序)======================== + // 变更类型常量(区分不同控件,精准处理逻辑) + private static final int CHANGE_TYPE_CHARGE_SWITCH = 1; + private static final int CHANGE_TYPE_USAGE_SWITCH = 2; + private static final int CHANGE_TYPE_SERVICE_SWITCH = 3; + private static final int CHANGE_TYPE_CHARGE_SEEKBAR = 4; + private static final int CHANGE_TYPE_USAGE_SEEKBAR = 5; + + // ======================== 内部静态类(临时数据载体,避免外部依赖)======================== + /** + * 临时配置数据实体(缓存变更信息,取消时恢复) + */ + private static class TempConfigData { + int changeType; + boolean originalBooleanValue; + int originalIntValue; + boolean newBooleanValue; + int newIntValue; + + // 构造方法(开关类型) + TempConfigData(int changeType, boolean originalValue, boolean newValue) { + this.changeType = changeType; + this.originalBooleanValue = originalValue; + this.newBooleanValue = newValue; + } + + // 构造方法(进度条类型) + TempConfigData(int changeType, int originalValue, int newValue) { + this.changeType = changeType; + this.originalIntValue = originalValue; + this.newIntValue = newValue; + } + } + + // ======================== 事件回调接口(解耦视图与业务,提升扩展性)======================== + public interface OnViewActionListener { + void onChargeReminderSwitchChanged(boolean isChecked); + void onUsageReminderSwitchChanged(boolean isChecked); + void onServiceSwitchChanged(boolean isChecked); + void onChargeReminderProgressChanged(int progress); + void onUsageReminderProgressChanged(int progress); + } + + // ======================== 成员变量(按功能分类,避免混乱)======================== // 外部依赖实例(生命周期关联,优先声明) private Context mContext; private AppConfigUtils mAppConfigUtils; @@ -59,6 +102,10 @@ public class MainContentView { public ImageView ivChargeReminderBattery; public ImageView ivUsageReminderBattery; + // 进度缓存(用于实时计算比值,避免频繁调用 getProgress()) + private int mCurrentChargeProgress; + private int mCurrentUsageProgress; + // 内部复用资源(避免重复创建,优化性能) private BatteryDrawable mCurrentBatteryDrawable; private BatteryDrawable mChargeReminderBatteryDrawable; @@ -66,62 +113,27 @@ public class MainContentView { // 配置变更确认对话框(单例复用,避免重复创建) private AlertDialog mConfigConfirmDialog; - // 对话框 Builder(核心新增:解决 setMessage 不生效问题) private AlertDialog.Builder mDialogBuilder; // 临时存储变更数据(对话框确认前缓存,取消时恢复) private TempConfigData mTempConfigData; // 对话框状态锁(避免快速点击重复弹窗) private boolean isDialogShowing = false; - // ======================== 临时配置数据实体(缓存变更信息,取消时恢复)======================== - private static class TempConfigData { - // 变更类型(区分开关/进度条,避免混淆) - int changeType; - // 原始值(取消时恢复用) - boolean originalBooleanValue; - int originalIntValue; - // 变更后的值(确认时保存用) - boolean newBooleanValue; - int newIntValue; - - // 构造方法(开关类型) - TempConfigData(int changeType, boolean originalValue, boolean newValue) { - this.changeType = changeType; - this.originalBooleanValue = originalValue; - this.newBooleanValue = newValue; - } - - // 构造方法(进度条类型) - TempConfigData(int changeType, int originalValue, int newValue) { - this.changeType = changeType; - this.originalIntValue = originalValue; - this.newIntValue = newValue; - } - } - - // 变更类型常量(区分不同控件,精准处理逻辑) - private static final int CHANGE_TYPE_CHARGE_SWITCH = 1; - private static final int CHANGE_TYPE_USAGE_SWITCH = 2; - private static final int CHANGE_TYPE_SERVICE_SWITCH = 3; - private static final int CHANGE_TYPE_CHARGE_SEEKBAR = 4; - private static final int CHANGE_TYPE_USAGE_SEEKBAR = 5; - // ======================== 构造方法(初始化入口,逻辑闭环)======================== public MainContentView(Context context, View rootView, OnViewActionListener actionListener) { - LogUtils.d(TAG, "constructor: 开始初始化"); + LogUtils.d(TAG, "MainContentView() | context=" + context + " | rootView=" + rootView + " | actionListener=" + actionListener); // 初始化外部依赖 this.mContext = context; this.mActionListener = actionListener; this.mAppConfigUtils = AppConfigUtils.getInstance(context.getApplicationContext()); - LogUtils.d(TAG, "constructor: 外部依赖初始化完成"); // 执行核心初始化流程(按顺序执行,避免依赖空指针) bindViews(rootView); initBatteryDrawables(); - initConfirmDialog(); // 先初始化对话框,再绑定监听 + initConfirmDialog(); bindViewListeners(); - LogUtils.d(TAG, "constructor: 整体初始化完成"); + LogUtils.d(TAG, "MainContentView 初始化完成"); } // ======================== 私有初始化方法(封装内部逻辑,仅暴露入口)======================== @@ -129,7 +141,7 @@ public class MainContentView { * 绑定视图控件(显式强转适配 Java7,适配 API30 视图加载机制) */ private void bindViews(View rootView) { - LogUtils.d(TAG, "bindViews: 开始绑定视图"); + LogUtils.d(TAG, "bindViews() | rootView=" + rootView); // 基础布局绑定 mainLayout = (RelativeLayout) rootView.findViewById(R.id.activitymainRelativeLayout1); backgroundView = (BackgroundView) rootView.findViewById(R.id.fragmentmainviewBackgroundView1); @@ -153,17 +165,20 @@ public class MainContentView { ivChargeReminderBattery = (ImageView) rootView.findViewById(R.id.fragmentandroidviewImageView3); ivUsageReminderBattery = (ImageView) rootView.findViewById(R.id.fragmentandroidviewImageView2); + // 初始化进度缓存(从配置读取初始值) + mCurrentChargeProgress = mAppConfigUtils.getChargeReminderValue(); + mCurrentUsageProgress = mAppConfigUtils.getUsageReminderValue(); + // 关键视图绑定校验(仅保留核心控件错误日志,精简冗余) - if (mainLayout == null) LogUtils.e(TAG, "bindViews: mainLayout 绑定失败"); - if (backgroundView == null) LogUtils.e(TAG, "bindViews: backgroundView 绑定失败"); - LogUtils.d(TAG, "bindViews: 视图绑定完成"); + if (mainLayout == null) LogUtils.e(TAG, "mainLayout 绑定失败"); + if (backgroundView == null) LogUtils.e(TAG, "backgroundView 绑定失败"); } /** * 初始化电池 Drawable(集成 BatteryDrawable,默认能量风格,适配小米机型渲染) */ private void initBatteryDrawables() { - LogUtils.d(TAG, "initBatteryDrawables: 开始初始化电池 Drawable"); + LogUtils.d(TAG, "initBatteryDrawables()"); // 当前电量 Drawable(颜色从资源读取,适配 API30 主题) int colorCurrent = getResourceColor(R.color.colorCurrent); mCurrentBatteryDrawable = new BatteryDrawable(colorCurrent); @@ -173,17 +188,15 @@ public class MainContentView { // 耗电提醒 Drawable int colorUsage = getResourceColor(R.color.colorUsege); mUsageReminderBatteryDrawable = new BatteryDrawable(colorUsage); - - LogUtils.d(TAG, "initBatteryDrawables: 电池 Drawable 初始化完成"); } /** * 初始化配置变更确认对话框(核心优化:保存 Builder 实例,解决消息不生效问题) */ private void initConfirmDialog() { - LogUtils.d(TAG, "initConfirmDialog: 开始初始化确认对话框"); + LogUtils.d(TAG, "initConfirmDialog()"); if (mContext == null) { - LogUtils.e(TAG, "initConfirmDialog: Context 为空,初始化失败"); + LogUtils.e(TAG, "Context 为空,初始化失败"); return; } @@ -196,7 +209,7 @@ public class MainContentView { mDialogBuilder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - confirmConfigChange(); // 确认变更,保存配置 + confirmConfigChange(); dialog.dismiss(); } }); @@ -205,7 +218,7 @@ public class MainContentView { mDialogBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - cancelConfigChange(); // 取消变更,恢复原始值 + cancelConfigChange(); dialog.dismiss(); } }); @@ -214,7 +227,7 @@ public class MainContentView { mDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { - cancelConfigChange(); // 取消变更,恢复原始值 + cancelConfigChange(); dialog.dismiss(); } }); @@ -223,22 +236,22 @@ public class MainContentView { mConfigConfirmDialog = mDialogBuilder.create(); mConfigConfirmDialog.setCancelable(true); mConfigConfirmDialog.setCanceledOnTouchOutside(true); - LogUtils.d(TAG, "initConfirmDialog: 确认对话框初始化完成"); } /** * 绑定视图事件监听(Java7 显式实现接口,适配 API30 事件分发,修复进度条弹窗失效) */ private void bindViewListeners() { - LogUtils.d(TAG, "bindViewListeners: 开始绑定事件监听"); + LogUtils.d(TAG, "bindViewListeners()"); // 依赖校验,避免空指针 if (mAppConfigUtils == null || mActionListener == null || mConfigConfirmDialog == null) { - LogUtils.e(TAG, "bindViewListeners: 依赖实例为空,跳过监听绑定"); + LogUtils.e(TAG, "依赖实例为空,跳过监听绑定"); return; } // 充电提醒进度条监听(使用 VerticalSeekBar 专属接口,确保弹窗100%触发) if (sbChargeReminder != null) { + // 原有:触摸抬起/取消监听(用于配置确认) sbChargeReminder.setOnVerticalSeekBarTouchListener(new VerticalSeekBar.OnVerticalSeekBarTouchListener() { @Override public void onTouchUp(VerticalSeekBar seekBar, int progress) { @@ -250,9 +263,9 @@ public class MainContentView { } // 缓存变更数据,显示确认对话框 mTempConfigData = new TempConfigData(CHANGE_TYPE_CHARGE_SEEKBAR, originalValue, progress); - updateDialogMessageByChangeType(); // 更新提示语 + updateDialogMessageByChangeType(); showConfigConfirmDialog(); - LogUtils.d(TAG, "ChargeReminderSeekBar: 触摸抬起触发变更,原始值=" + originalValue + ", 新进度=" + progress); + LogUtils.d(TAG, "ChargeReminderSeekBar触摸抬起 | 原始值=" + originalValue + " | 新进度=" + progress); } @Override @@ -265,10 +278,34 @@ public class MainContentView { tvChargeReminderValue.setText(originalValue + "%"); } seekBar.setProgress(originalValue); - LogUtils.d(TAG, "ChargeReminderSeekBar: 触摸取消,进度回滚至=" + originalValue); + // 恢复进度缓存 + mCurrentChargeProgress = originalValue; + LogUtils.d(TAG, "ChargeReminderSeekBar触摸取消 | 进度回滚至=" + originalValue); } }); - LogUtils.d(TAG, "bindViewListeners: 充电提醒进度条专属监听绑定完成"); + + // 新增:实时进度变化监听(用于比值预览) + sbChargeReminder.setOnVerticalSeekBarChangeListener(new VerticalSeekBar.OnVerticalSeekBarChangeListener() { + @Override + public void onProgressChanged(VerticalSeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + mCurrentChargeProgress = progress; + // 同步更新进度文本和电池图标(保持UI一致性) + if (tvChargeReminderValue != null && mChargeReminderBatteryDrawable != null && ivChargeReminderBattery != null) { + mChargeReminderBatteryDrawable.setBatteryValue(progress); + ivChargeReminderBattery.setImageDrawable(mChargeReminderBatteryDrawable); + tvChargeReminderValue.setText(progress + "%"); + } + } + } + + @Override + public void onStartTrackingTouch(VerticalSeekBar seekBar) {} + + @Override + public void onStopTrackingTouch(VerticalSeekBar seekBar) {} + }); + LogUtils.d(TAG, "充电提醒进度条专属监听绑定完成"); } // 充电提醒开关监听 @@ -282,16 +319,17 @@ public class MainContentView { if (originalValue == newValue) return; // 缓存变更数据,显示确认对话框 mTempConfigData = new TempConfigData(CHANGE_TYPE_CHARGE_SWITCH, originalValue, newValue); - updateDialogMessageByChangeType(); // 更新提示语 + updateDialogMessageByChangeType(); showConfigConfirmDialog(); - LogUtils.d(TAG, "cbEnableChargeReminder: 触发变更,原始值=" + originalValue + ", 变更后=" + newValue); + LogUtils.d(TAG, "cbEnableChargeReminder点击 | 原始值=" + originalValue + " | 变更后=" + newValue); } }); - LogUtils.d(TAG, "bindViewListeners: 充电提醒开关监听绑定完成"); + LogUtils.d(TAG, "充电提醒开关监听绑定完成"); } // 耗电提醒进度条监听(使用 VerticalSeekBar 专属接口,确保弹窗100%触发) if (sbUsageReminder != null) { + // 原有:触摸抬起/取消监听(用于配置确认) sbUsageReminder.setOnVerticalSeekBarTouchListener(new VerticalSeekBar.OnVerticalSeekBarTouchListener() { @Override public void onTouchUp(VerticalSeekBar seekBar, int progress) { @@ -303,9 +341,9 @@ public class MainContentView { } // 缓存变更数据,显示确认对话框 mTempConfigData = new TempConfigData(CHANGE_TYPE_USAGE_SEEKBAR, originalValue, progress); - updateDialogMessageByChangeType(); // 更新提示语 + updateDialogMessageByChangeType(); showConfigConfirmDialog(); - LogUtils.d(TAG, "UsageReminderSeekBar: 触摸抬起触发变更,原始值=" + originalValue + ", 新进度=" + progress); + LogUtils.d(TAG, "UsageReminderSeekBar触摸抬起 | 原始值=" + originalValue + " | 新进度=" + progress); } @Override @@ -318,10 +356,34 @@ public class MainContentView { tvUsageReminderValue.setText(originalValue + "%"); } seekBar.setProgress(originalValue); - LogUtils.d(TAG, "UsageReminderSeekBar: 触摸取消,进度回滚至=" + originalValue); + // 恢复进度缓存 + mCurrentUsageProgress = originalValue; + LogUtils.d(TAG, "UsageReminderSeekBar触摸取消 | 进度回滚至=" + originalValue); } }); - LogUtils.d(TAG, "bindViewListeners: 耗电提醒进度条专属监听绑定完成"); + + // 新增:实时进度变化监听(用于比值预览) + sbUsageReminder.setOnVerticalSeekBarChangeListener(new VerticalSeekBar.OnVerticalSeekBarChangeListener() { + @Override + public void onProgressChanged(VerticalSeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + mCurrentUsageProgress = progress; + // 同步更新进度文本和电池图标(保持UI一致性) + if (tvUsageReminderValue != null && mUsageReminderBatteryDrawable != null && ivUsageReminderBattery != null) { + mUsageReminderBatteryDrawable.setBatteryValue(progress); + ivUsageReminderBattery.setImageDrawable(mUsageReminderBatteryDrawable); + tvUsageReminderValue.setText(progress + "%"); + } + } + } + + @Override + public void onStartTrackingTouch(VerticalSeekBar seekBar) {} + + @Override + public void onStopTrackingTouch(VerticalSeekBar seekBar) {} + }); + LogUtils.d(TAG, "耗电提醒进度条专属监听绑定完成"); } // 耗电提醒开关监听 @@ -335,12 +397,12 @@ public class MainContentView { if (originalValue == newValue) return; // 缓存变更数据,显示确认对话框 mTempConfigData = new TempConfigData(CHANGE_TYPE_USAGE_SWITCH, originalValue, newValue); - updateDialogMessageByChangeType(); // 更新提示语 + updateDialogMessageByChangeType(); showConfigConfirmDialog(); - LogUtils.d(TAG, "cbEnableUsageReminder: 触发变更,原始值=" + originalValue + ", 变更后=" + newValue); + LogUtils.d(TAG, "cbEnableUsageReminder点击 | 原始值=" + originalValue + " | 变更后=" + newValue); } }); - LogUtils.d(TAG, "bindViewListeners: 耗电提醒开关监听绑定完成"); + LogUtils.d(TAG, "耗电提醒开关监听绑定完成"); } // 服务总开关监听(核心优化:逻辑与其他控件完全对齐) @@ -359,13 +421,13 @@ public class MainContentView { updateDialogMessageByChangeType(); // 显示确认对话框 showConfigConfirmDialog(); - LogUtils.d(TAG, "swEnableService: 触发变更,原始值=" + originalValue + ", 变更后=" + newValue); + LogUtils.d(TAG, "swEnableService点击 | 原始值=" + originalValue + " | 变更后=" + newValue); } }); - LogUtils.d(TAG, "bindViewListeners: 服务总开关监听绑定完成"); + LogUtils.d(TAG, "服务总开关监听绑定完成"); } - LogUtils.d(TAG, "bindViewListeners: 所有事件监听绑定完成"); + LogUtils.d(TAG, "所有事件监听绑定完成"); } // ======================== 对外暴露核心方法(业务入口,精简参数,明确职责)======================== @@ -374,9 +436,9 @@ public class MainContentView { * @param frameDrawable 进度条背景 Drawable(外部传入,适配主题切换) */ public void updateViewData(Drawable frameDrawable) { - LogUtils.d(TAG, "updateViewData: 开始更新视图数据"); + LogUtils.d(TAG, "updateViewData() | frameDrawable=" + frameDrawable); if (mAppConfigUtils == null) { - LogUtils.e(TAG, "updateViewData: AppConfigUtils 为空,跳过更新"); + LogUtils.e(TAG, "AppConfigUtils 为空,跳过更新"); return; } @@ -388,13 +450,15 @@ public class MainContentView { boolean usageEnable = mAppConfigUtils.isUsageReminderEnabled(); // 从服务控制Bean读取状态,确保UI与实际一致 boolean serviceEnable = getServiceEnableState(); - LogUtils.d(TAG, "updateViewData: 配置数据读取完成,charge=" + chargeVal + ", usage=" + usageVal + ", current=" + currentVal + ", serviceEnable=" + serviceEnable); + // 更新进度缓存 + mCurrentChargeProgress = chargeVal; + mCurrentUsageProgress = usageVal; + LogUtils.d(TAG, "配置数据读取完成 | charge=" + chargeVal + " | usage=" + usageVal + " | current=" + currentVal + " | serviceEnable=" + serviceEnable); // 进度条背景更新 if (frameDrawable != null) { if (llLeftSeekBar != null) llLeftSeekBar.setBackground(frameDrawable); if (llRightSeekBar != null) llRightSeekBar.setBackground(frameDrawable); - LogUtils.d(TAG, "updateViewData: 进度条背景更新完成"); } // 当前电量更新(联动 BatteryDrawable,实时刷新图标) @@ -406,7 +470,6 @@ public class MainContentView { tvCurrentBatteryValue.setTextColor(getResourceColor(R.color.colorCurrent)); tvCurrentBatteryValue.setText(currentVal + "%"); } - LogUtils.d(TAG, "updateViewData: 当前电量视图更新完成"); // 充电提醒视图更新 if (ivChargeReminderBattery != null && mChargeReminderBatteryDrawable != null) { @@ -419,7 +482,6 @@ public class MainContentView { } if (sbChargeReminder != null) sbChargeReminder.setProgress(chargeVal); if (cbEnableChargeReminder != null) cbEnableChargeReminder.setChecked(chargeEnable); - LogUtils.d(TAG, "updateViewData: 充电提醒视图更新完成"); // 耗电提醒视图更新 if (ivUsageReminderBattery != null && mUsageReminderBatteryDrawable != null) { @@ -432,7 +494,6 @@ public class MainContentView { } if (sbUsageReminder != null) sbUsageReminder.setProgress(usageVal); if (cbEnableUsageReminder != null) cbEnableUsageReminder.setChecked(usageEnable); - LogUtils.d(TAG, "updateViewData: 耗电提醒视图更新完成"); // 服务开关+提示文本更新(确保状态准确) if (swEnableService != null) { @@ -440,9 +501,8 @@ public class MainContentView { swEnableService.setText(mContext.getString(R.string.txt_aboveswitch)); } if (tvTips != null) tvTips.setText(mContext.getString(R.string.txt_aboveswitchtips)); - LogUtils.d(TAG, "updateViewData: 服务开关及提示文本更新完成"); - LogUtils.d(TAG, "updateViewData: 所有视图数据更新完成"); + LogUtils.d(TAG, "所有视图数据更新完成"); } /** @@ -450,10 +510,10 @@ public class MainContentView { * @param value 电量值(自动校准 0-100,避免异常值) */ public void updateCurrentBattery(int value) { - LogUtils.d(TAG, "updateCurrentBattery: 开始更新,原始值=" + value); + LogUtils.d(TAG, "updateCurrentBattery() | 原始值=" + value); // 核心依赖校验 if (tvCurrentBatteryValue == null || mCurrentBatteryDrawable == null || ivCurrentBattery == null) { - LogUtils.e(TAG, "updateCurrentBattery: 视图/Drawable 为空,跳过更新"); + LogUtils.e(TAG, "视图/Drawable 为空,跳过更新"); return; } @@ -464,14 +524,14 @@ public class MainContentView { ivCurrentBattery.setImageDrawable(mCurrentBatteryDrawable); tvCurrentBatteryValue.setText(validValue + "%"); - LogUtils.d(TAG, "updateCurrentBattery: 更新完成,校准后值=" + validValue); + LogUtils.d(TAG, "更新完成 | 校准后值=" + validValue); } /** * 释放资源(主动回收,适配 API30 资源管控机制,优化小米手机内存占用) */ public void releaseResources() { - LogUtils.d(TAG, "releaseResources: 开始释放资源"); + LogUtils.d(TAG, "releaseResources()"); // 释放对话框资源(安全销毁,避免内存泄漏) if (mConfigConfirmDialog != null) { if (mConfigConfirmDialog.isShowing()) { @@ -514,7 +574,7 @@ public class MainContentView { mAppConfigUtils = null; mActionListener = null; - LogUtils.d(TAG, "releaseResources: 所有资源释放完成"); + LogUtils.d(TAG, "所有资源释放完成"); } /** @@ -522,9 +582,9 @@ public class MainContentView { * @param enabled 服务启用状态 */ public void setServiceSwitchChecked(boolean enabled) { + LogUtils.d(TAG, "setServiceSwitchChecked() | enabled=" + enabled); if (swEnableService != null) { swEnableService.setChecked(enabled); - LogUtils.d(TAG, "setServiceSwitchChecked: 服务开关UI更新为=" + enabled); } } @@ -533,9 +593,9 @@ public class MainContentView { * @param enabled 是否允许点击 */ public void setServiceSwitchEnabled(boolean enabled) { + LogUtils.d(TAG, "setServiceSwitchEnabled() | enabled=" + enabled); if (swEnableService != null) { swEnableService.setEnabled(enabled); - LogUtils.d(TAG, "setServiceSwitchEnabled: 服务开关点击状态更新为=" + enabled); } } @@ -544,21 +604,22 @@ public class MainContentView { * 显示配置变更确认对话框(确保 Activity 处于前台,避免异常,防止重复弹窗) */ private void showConfigConfirmDialog() { + LogUtils.d(TAG, "showConfigConfirmDialog() | isDialogShowing=" + isDialogShowing); // 对话框状态锁:正在显示则跳过,避免重复触发 if (isDialogShowing) { - LogUtils.d(TAG, "showConfigConfirmDialog: 对话框已显示,跳过重复调用"); + LogUtils.d(TAG, "对话框已显示,跳过重复调用"); return; } // 基础校验:对话框/上下文/Builder 为空 if (mDialogBuilder == null || mContext == null) { - LogUtils.e(TAG, "showConfigConfirmDialog: 对话框Builder/上下文异常,无法显示"); + LogUtils.e(TAG, "对话框Builder/上下文异常,无法显示"); if (mTempConfigData != null) cancelConfigChange(); return; } // Activity 状态校验:避免销毁后弹窗崩溃(适配 API30) Activity activity = (Activity) mContext; if (activity.isFinishing() || activity.isDestroyed()) { - LogUtils.e(TAG, "showConfigConfirmDialog: Activity 已销毁,无法显示对话框"); + LogUtils.e(TAG, "Activity 已销毁,无法显示对话框"); if (mTempConfigData != null) cancelConfigChange(); return; } @@ -575,15 +636,16 @@ public class MainContentView { mConfigConfirmDialog.setOnDismissListener(null); } }); - LogUtils.d(TAG, "showConfigConfirmDialog: 确认对话框显示成功"); + LogUtils.d(TAG, "确认对话框显示成功"); } /** * 确认配置变更(保存数据+回调监听+更新视图) */ private void confirmConfigChange() { + LogUtils.d(TAG, "confirmConfigChange() | mTempConfigData=" + mTempConfigData); if (mTempConfigData == null || mAppConfigUtils == null || mActionListener == null) { - LogUtils.e(TAG, "confirmConfigChange: 依赖数据为空,确认失败"); + LogUtils.e(TAG, "依赖数据为空,确认失败"); return; } @@ -592,40 +654,40 @@ public class MainContentView { case CHANGE_TYPE_CHARGE_SWITCH: mAppConfigUtils.setChargeReminderEnabled(mTempConfigData.newBooleanValue); mActionListener.onChargeReminderSwitchChanged(mTempConfigData.newBooleanValue); - LogUtils.d(TAG, "confirmConfigChange: 充电提醒开关确认,值=" + mTempConfigData.newBooleanValue); + LogUtils.d(TAG, "充电提醒开关确认 | 值=" + mTempConfigData.newBooleanValue); break; // 耗电提醒开关 case CHANGE_TYPE_USAGE_SWITCH: mAppConfigUtils.setUsageReminderEnabled(mTempConfigData.newBooleanValue); mActionListener.onUsageReminderSwitchChanged(mTempConfigData.newBooleanValue); - LogUtils.d(TAG, "confirmConfigChange: 耗电提醒开关确认,值=" + mTempConfigData.newBooleanValue); + LogUtils.d(TAG, "耗电提醒开关确认 | 值=" + mTempConfigData.newBooleanValue); break; // 服务总开关(核心:持久化配置+触发 Activity 回调) case CHANGE_TYPE_SERVICE_SWITCH: // 1. 设置服务启停 - if (mTempConfigData.newBooleanValue) { - ControlCenterService.startControlCenterService(mContext); - } else { - ControlCenterService.stopControlCenterService(mContext); - } + if (mTempConfigData.newBooleanValue) { + ControlCenterService.startControlCenterService(mContext); + } else { + ControlCenterService.stopControlCenterService(mContext); + } // 2. 强制触发 Activity 回调,执行服务启停逻辑 mActionListener.onServiceSwitchChanged(mTempConfigData.newBooleanValue); - LogUtils.d(TAG, "confirmConfigChange: 服务开关确认,值=" + mTempConfigData.newBooleanValue + ",已持久化配置"); + LogUtils.d(TAG, "服务开关确认 | 值=" + mTempConfigData.newBooleanValue + ",已持久化配置"); break; // 充电提醒进度条 case CHANGE_TYPE_CHARGE_SEEKBAR: mAppConfigUtils.setChargeReminderValue(mTempConfigData.newIntValue); mActionListener.onChargeReminderProgressChanged(mTempConfigData.newIntValue); - LogUtils.d(TAG, "confirmConfigChange: 充电提醒进度确认,值=" + mTempConfigData.newIntValue); + LogUtils.d(TAG, "充电提醒进度确认 | 值=" + mTempConfigData.newIntValue); break; // 耗电提醒进度条 case CHANGE_TYPE_USAGE_SEEKBAR: mAppConfigUtils.setUsageReminderValue(mTempConfigData.newIntValue); mActionListener.onUsageReminderProgressChanged(mTempConfigData.newIntValue); - LogUtils.d(TAG, "confirmConfigChange: 耗电提醒进度确认,值=" + mTempConfigData.newIntValue); + LogUtils.d(TAG, "耗电提醒进度确认 | 值=" + mTempConfigData.newIntValue); break; default: - LogUtils.w(TAG, "confirmConfigChange: 未知变更类型,跳过"); + LogUtils.w(TAG, "未知变更类型,跳过"); break; } @@ -637,8 +699,9 @@ public class MainContentView { * 取消配置变更(恢复原始值+刷新视图,确保 UI 与配置一致) */ private void cancelConfigChange() { + LogUtils.d(TAG, "cancelConfigChange() | mTempConfigData=" + mTempConfigData); if (mTempConfigData == null || mAppConfigUtils == null) { - LogUtils.e(TAG, "cancelConfigChange: 依赖数据为空,取消失败"); + LogUtils.e(TAG, "依赖数据为空,取消失败"); return; } @@ -647,19 +710,19 @@ public class MainContentView { if (cbEnableChargeReminder != null) { cbEnableChargeReminder.setChecked(mTempConfigData.originalBooleanValue); } - LogUtils.d(TAG, "cancelConfigChange: 充电提醒开关取消,恢复值=" + mTempConfigData.originalBooleanValue); + LogUtils.d(TAG, "充电提醒开关取消 | 恢复值=" + mTempConfigData.originalBooleanValue); break; case CHANGE_TYPE_USAGE_SWITCH: if (cbEnableUsageReminder != null) { cbEnableUsageReminder.setChecked(mTempConfigData.originalBooleanValue); } - LogUtils.d(TAG, "cancelConfigChange: 耗电提醒开关取消,恢复值=" + mTempConfigData.originalBooleanValue); + LogUtils.d(TAG, "耗电提醒开关取消 | 恢复值=" + mTempConfigData.originalBooleanValue); break; case CHANGE_TYPE_SERVICE_SWITCH: if (swEnableService != null) { swEnableService.setChecked(mTempConfigData.originalBooleanValue); } - LogUtils.d(TAG, "cancelConfigChange: 服务开关取消,恢复值=" + mTempConfigData.originalBooleanValue); + LogUtils.d(TAG, "服务开关取消 | 恢复值=" + mTempConfigData.originalBooleanValue); break; case CHANGE_TYPE_CHARGE_SEEKBAR: if (sbChargeReminder != null) { @@ -670,7 +733,7 @@ public class MainContentView { ivChargeReminderBattery.setImageDrawable(mChargeReminderBatteryDrawable); tvChargeReminderValue.setText(mTempConfigData.originalIntValue + "%"); } - LogUtils.d(TAG, "cancelConfigChange: 充电提醒进度取消,恢复值=" + mTempConfigData.originalIntValue); + LogUtils.d(TAG, "充电提醒进度取消 | 恢复值=" + mTempConfigData.originalIntValue); break; case CHANGE_TYPE_USAGE_SEEKBAR: if (sbUsageReminder != null) { @@ -681,10 +744,10 @@ public class MainContentView { ivUsageReminderBattery.setImageDrawable(mUsageReminderBatteryDrawable); tvUsageReminderValue.setText(mTempConfigData.originalIntValue + "%"); } - LogUtils.d(TAG, "cancelConfigChange: 耗电提醒进度取消,恢复值=" + mTempConfigData.originalIntValue); + LogUtils.d(TAG, "耗电提醒进度取消 | 恢复值=" + mTempConfigData.originalIntValue); break; default: - LogUtils.w(TAG, "cancelConfigChange: 未知变更类型,跳过"); + LogUtils.w(TAG, "未知变更类型,跳过"); break; } @@ -692,40 +755,11 @@ public class MainContentView { mTempConfigData = null; } - // ======================== 内部工具方法(封装重复逻辑,提升复用性)======================== - /** - * 获取资源颜色(适配 API30 主题颜色读取机制,兼容低版本,优化小米机型颜色显示,防御空指针) - * @param colorResId 颜色资源 ID - * @return 校准后的颜色值 - */ - private int getResourceColor(int colorResId) { - // 空指针防御:Context 为空返回默认黑色 - if (mContext == null) { - LogUtils.e(TAG, "getResourceColor: Context 为空,返回默认黑色"); - return 0xFF000000; - } - // 适配 API30 主题颜色读取 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - return mContext.getResources().getColor(colorResId, mContext.getTheme()); - } else { - return mContext.getResources().getColor(colorResId); - } - } - - /** - * 获取服务启用状态(统一从服务控制Bean读取,确保全链路状态一致) - * @return 服务启用状态(true=启用,false=禁用) - */ - private boolean getServiceEnableState() { - ControlCenterServiceBean serviceBean = ControlCenterServiceBean.loadBean(mContext, ControlCenterServiceBean.class); - // 本地无配置时,默认禁用服务(与服务初始化逻辑对齐) - return serviceBean != null && serviceBean.isEnableService(); - } - /** * 根据变更类型更新对话框提示语(核心优化:通过 Builder 更新,确保生效) */ private void updateDialogMessageByChangeType() { + LogUtils.d(TAG, "updateDialogMessageByChangeType() | mTempConfigData=" + mTempConfigData); if (mDialogBuilder == null || mTempConfigData == null) return; String message; if (mTempConfigData.changeType == CHANGE_TYPE_SERVICE_SWITCH) { @@ -741,13 +775,61 @@ public class MainContentView { mDialogBuilder.setMessage(message); } - // ======================== 事件回调接口(解耦视图与业务,提升扩展性)======================== - public interface OnViewActionListener { - void onChargeReminderSwitchChanged(boolean isChecked); - void onUsageReminderSwitchChanged(boolean isChecked); - void onServiceSwitchChanged(boolean isChecked); - void onChargeReminderProgressChanged(int progress); - void onUsageReminderProgressChanged(int progress); + // ======================== 内部工具方法(封装重复逻辑,提升复用性)======================== + /** + * 实时计算并更新比值预览(sbUsageReminder / sbChargeReminder) + * 处理除数为0的情况,避免崩溃 + */ +// private void updateRatioPreview() { +// if (mTvRatioPreview == null) return; +// float ratio; +// // 处理除数为0:充电进度为0时显示0(可根据需求改为“--”) +// if (mCurrentChargeProgress == 0) { +// ratio = 0.0f; +// } else { +// ratio = (float) mCurrentUsageProgress / mCurrentChargeProgress; +// } +// // 格式化比值:保留1位小数,适配本地化(解决小米手机小数分隔符问题) +// String ratioText = String.format(Locale.getDefault(), "比值:%.1f", ratio); +// mTvRatioPreview.setText(ratioText); +// // 触发比值变化回调 +// if (mActionListener != null) { +// mActionListener.onRatioChanged(ratio); +// } +// LogUtils.d(TAG, "比值预览更新 | usage=" + mCurrentUsageProgress + " | charge=" + mCurrentChargeProgress + " | ratio=" + ratio); +// } + + /** + * 获取资源颜色(适配 API30 主题颜色读取机制,兼容低版本,优化小米机型颜色显示,防御空指针) + * @param colorResId 颜色资源 ID + * @return 校准后的颜色值 + */ + private int getResourceColor(int colorResId) { + LogUtils.d(TAG, "getResourceColor() | colorResId=" + colorResId); + // 空指针防御:Context 为空返回默认黑色 + if (mContext == null) { + LogUtils.e(TAG, "Context 为空,返回默认黑色"); + return 0xFF000000; + } + // 适配 API30 主题颜色读取 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return mContext.getResources().getColor(colorResId, mContext.getTheme()); + } else { + return mContext.getResources().getColor(colorResId); + } + } + + /** + * 获取服务启用状态(统一从服务控制Bean读取,确保全链路状态一致) + * @return 服务启用状态(true=启用,false=禁用) + */ + private boolean getServiceEnableState() { + LogUtils.d(TAG, "getServiceEnableState()"); + ControlCenterServiceBean serviceBean = ControlCenterServiceBean.loadBean(mContext, ControlCenterServiceBean.class); + // 本地无配置时,默认禁用服务(与服务初始化逻辑对齐) + boolean state = serviceBean != null && serviceBean.isEnableService(); + LogUtils.d(TAG, "服务启用状态获取完成 | state=" + state); + return state; } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/VerticalSeekBar.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/VerticalSeekBar.java index b4eae36..d5343f3 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/VerticalSeekBar.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/VerticalSeekBar.java @@ -5,49 +5,19 @@ import android.graphics.Canvas; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.SeekBar; - import cc.winboll.studio.libappbase.LogUtils; /** * @Author ZhanGSKen&豆包大模型 * @Date 2025/12/17 14:11 * @Describe 垂直进度条控件,适配 API30,支持逆时针旋转(0在下,100在上),修复滑块同步+弹窗触发bug + * 新增:实时进度变化监听接口,支持拖动时实时回调进度 */ public class VerticalSeekBar extends SeekBar { // ======================== 静态常量 ========================= private static final String TAG = VerticalSeekBar.class.getSimpleName(); - // ======================== 成员变量 ========================= - private volatile int mProgress = -1; // 当前进度缓存,修复滑块同步问题 - private OnVerticalSeekBarTouchListener mTouchListener; // 触摸事件回调接口(核心新增) - - // ======================== 构造方法 ========================= - public VerticalSeekBar(Context context) { - super(context); - initView(); - LogUtils.d(TAG, "VerticalSeekBar: 单参数构造方法初始化完成"); - } - - public VerticalSeekBar(Context context, AttributeSet attrs) { - super(context, attrs); - initView(); - LogUtils.d(TAG, "VerticalSeekBar: 双参数构造方法初始化完成"); - } - - public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - initView(); - LogUtils.d(TAG, "VerticalSeekBar: 三参数构造方法初始化完成"); - } - - // ======================== 初始化方法 ========================= - private void initView() { - // 移除水平默认阴影,优化垂直显示效果,减少 API30 不必要的绘制开销 - setBackgroundDrawable(null); - LogUtils.d(TAG, "initView: 视图初始化完成,移除默认背景阴影"); - } - - // ======================== 核心接口(新增,用于弹窗触发回调)======================== + // ======================== 接口定义(前置,便于外部调用)======================== /** * 垂直进度条触摸事件回调接口,解决原生 OnSeekBarChangeListener 回调失效问题 * 直接在触摸抬起时回调,确保配置变更对话框100%触发 @@ -68,6 +38,67 @@ public class VerticalSeekBar extends SeekBar { void onTouchCancel(VerticalSeekBar seekBar, int progress); } + /** + * 垂直进度条实时进度变化监听接口 + * 支持拖动过程中实时回调进度,用于比值预览等实时UI更新场景 + */ + public interface OnVerticalSeekBarChangeListener { + /** + * 进度变化时回调 + * @param seekBar 当前垂直进度条实例 + * @param progress 当前进度(0~100) + * @param fromUser 是否是用户触摸导致的进度变化 + */ + void onProgressChanged(VerticalSeekBar seekBar, int progress, boolean fromUser); + + /** + * 开始触摸进度条时回调 + * @param seekBar 当前垂直进度条实例 + */ + void onStartTrackingTouch(VerticalSeekBar seekBar); + + /** + * 停止触摸进度条时回调 + * @param seekBar 当前垂直进度条实例 + */ + void onStopTrackingTouch(VerticalSeekBar seekBar); + } + + // ======================== 成员变量 ========================= + // 核心状态:当前进度缓存,修复滑块同步问题(volatile 保证多线程可见性) + private volatile int mProgress = -1; + // 监听接口:触摸事件回调(原有,用于弹窗触发) + private OnVerticalSeekBarTouchListener mTouchListener; + // 监听接口:实时进度变化回调(新增,用于比值计算) + private OnVerticalSeekBarChangeListener mProgressChangeListener; + + // ======================== 构造方法 ========================= + public VerticalSeekBar(Context context) { + super(context); + initView(); + LogUtils.d(TAG, "VerticalSeekBar(Context) 初始化"); + } + + public VerticalSeekBar(Context context, AttributeSet attrs) { + super(context, attrs); + initView(); + LogUtils.d(TAG, "VerticalSeekBar(Context, AttributeSet) 初始化"); + } + + public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initView(); + LogUtils.d(TAG, "VerticalSeekBar(Context, AttributeSet, int) 初始化"); + } + + // ======================== 初始化方法 ========================= + private void initView() { + // 移除水平默认阴影,优化垂直显示效果,减少 API30 不必要的绘制开销 + setBackgroundDrawable(null); + LogUtils.d(TAG, "initView: 移除默认背景阴影,完成视图初始化"); + } + + // ======================== 对外设置方法(监听接口绑定)======================== /** * 设置触摸事件监听器(给外部调用,如 MainContentView 绑定) * @param listener 触摸事件回调实例 @@ -77,7 +108,16 @@ public class VerticalSeekBar extends SeekBar { LogUtils.d(TAG, "setOnVerticalSeekBarTouchListener: 触摸监听器绑定完成"); } - // ======================== 重写测量/布局/绘制方法 ========================= + /** + * 设置实时进度变化监听器(给外部调用,如 MainContentView 绑定) + * @param listener 实时进度变化回调实例 + */ + public void setOnVerticalSeekBarChangeListener(OnVerticalSeekBarChangeListener listener) { + this.mProgressChangeListener = listener; + LogUtils.d(TAG, "setOnVerticalSeekBarChangeListener: 实时进度监听器绑定完成"); + } + + // ======================== 重写系统方法(测量/布局/绘制)======================== @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(heightMeasureSpec, widthMeasureSpec); @@ -97,51 +137,13 @@ public class VerticalSeekBar extends SeekBar { canvas.rotate(-90); canvas.translate(-getHeight(), 0); super.onDraw(canvas); - LogUtils.v(TAG, "onDraw: 垂直绘制完成,旋转角度=-90°"); + LogUtils.v(TAG, "onDraw: 完成垂直绘制,旋转角度=-90°"); } - // ======================== 重写触摸事件(优化事件透传,新增接口回调)======================== - @Override - public boolean onTouchEvent(MotionEvent event) { - // 先调用父类方法,保留原生监听器兼容性,同时强制透传事件 - super.onTouchEvent(event); - boolean handled = true; // 强制消费事件,避免事件被拦截导致回调丢失 - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - LogUtils.d(TAG, "onTouchEvent: 触摸按下,坐标Y=" + event.getY()); - break; - - case MotionEvent.ACTION_MOVE: - calculateProgress(event.getY()); - setProgress(mProgress); - LogUtils.v(TAG, "onTouchEvent: 触摸滑动,进度更新为=" + mProgress); - break; - - case MotionEvent.ACTION_UP: - calculateProgress(event.getY()); - setProgress(mProgress); - LogUtils.d(TAG, "onTouchEvent: 触摸抬起,触发弹窗回调,进度=" + mProgress); - // 核心:调用新增接口,直接通知外部触发配置变更对话框 - if (mTouchListener != null) { - mTouchListener.onTouchUp(this, mProgress); - } - break; - - case MotionEvent.ACTION_CANCEL: - LogUtils.d(TAG, "onTouchEvent: 触摸取消,进度保持=" + getProgress()); - // 可选:触摸取消时回调,外部可做进度回滚处理 - if (mTouchListener != null) { - mTouchListener.onTouchCancel(this, getProgress()); - } - break; - } - return handled; - } - - // ======================== 重写进度设置方法 ========================= + // ======================== 重写进度设置方法(修复滑块同步+新增实时回调)======================== /** * 重写进度设置,调用尺寸变化方法强制刷新,解决 setProgress 滑块不跟随问题 + * 新增:支持外部调用 setProgress 时触发实时进度回调 */ @Override public synchronized void setProgress(int progress) { @@ -149,7 +151,68 @@ public class VerticalSeekBar extends SeekBar { // 强制触发尺寸变化,同步刷新滑块位置(核心bug修复逻辑) onSizeChanged(getWidth(), getHeight(), 0, 0); mProgress = progress; - LogUtils.d(TAG, "setProgress: 进度设置完成,进度=" + progress + ", 滑块同步刷新"); + LogUtils.d(TAG, "setProgress: 进度设置为" + progress + ",滑块同步刷新"); + // 触发实时进度监听(外部调用 setProgress 时 fromUser 为 false) + if (mProgressChangeListener != null) { + mProgressChangeListener.onProgressChanged(this, progress, false); + } + } + + // ======================== 重写触摸事件(优化事件透传+实时进度回调)======================== + @Override + public boolean onTouchEvent(MotionEvent event) { + // 先调用父类方法,保留原生监听器兼容性,同时强制透传事件 + super.onTouchEvent(event); + boolean handled = true; // 强制消费事件,避免事件被拦截导致回调丢失 + boolean fromUser = true; // 标记是否是用户触摸导致的进度变化 + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + LogUtils.d(TAG, "onTouchEvent: 触摸按下,Y坐标=" + event.getY()); + // 触发实时进度监听:开始触摸 + if (mProgressChangeListener != null) { + mProgressChangeListener.onStartTrackingTouch(this); + } + break; + + case MotionEvent.ACTION_MOVE: + calculateProgress(event.getY()); + setProgress(mProgress); + LogUtils.v(TAG, "onTouchEvent: 触摸滑动,进度更新为" + mProgress); + // 触发实时进度监听:进度变化 + if (mProgressChangeListener != null) { + mProgressChangeListener.onProgressChanged(this, mProgress, fromUser); + } + break; + + case MotionEvent.ACTION_UP: + calculateProgress(event.getY()); + setProgress(mProgress); + LogUtils.d(TAG, "onTouchEvent: 触摸抬起,进度=" + mProgress + ",触发弹窗回调"); + // 触发实时进度监听:停止触摸 + if (mProgressChangeListener != null) { + mProgressChangeListener.onProgressChanged(this, mProgress, fromUser); + mProgressChangeListener.onStopTrackingTouch(this); + } + // 核心:调用原有触摸接口,通知外部触发配置变更对话框 + if (mTouchListener != null) { + mTouchListener.onTouchUp(this, mProgress); + } + break; + + case MotionEvent.ACTION_CANCEL: + LogUtils.d(TAG, "onTouchEvent: 触摸取消,当前进度=" + getProgress()); + // 触发实时进度监听:停止触摸 + if (mProgressChangeListener != null) { + mProgressChangeListener.onStopTrackingTouch(this); + } + // 可选:触摸取消时回调,外部可做进度回滚处理 + if (mTouchListener != null) { + mTouchListener.onTouchCancel(this, getProgress()); + } + break; + } + return handled; } // ======================== 内部工具方法 ========================= @@ -162,7 +225,7 @@ public class VerticalSeekBar extends SeekBar { mProgress = getMax() - (int) (getMax() * touchY / getHeight()); // 校准进度范围,防止超出 0~100(兼容 API30 进度边界校验) mProgress = Math.max(0, Math.min(mProgress, getMax())); - LogUtils.v(TAG, "calculateProgress: 进度计算完成,触摸Y=" + touchY + ", 计算进度=" + mProgress); + LogUtils.v(TAG, "calculateProgress: 触摸Y=" + touchY + ",计算进度=" + mProgress); } }