Compare commits

...

6 Commits

6 changed files with 458 additions and 391 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Wed Dec 10 20:11:13 HKT 2025
stageCount=12
#Thu Dec 11 03:22:10 HKT 2025
stageCount=15
libraryProject=
baseVersion=15.12
publishVersion=15.12.11
publishVersion=15.12.14
buildCount=0
baseBetaVersion=15.12.12
baseBetaVersion=15.12.15

View File

@@ -2,28 +2,36 @@ package cc.winboll.studio.powerbell;
import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import cc.winboll.studio.libaes.utils.WinBoLLActivityManager;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.ToastUtils;
import cc.winboll.studio.powerbell.model.BackgroundBean;
import cc.winboll.studio.powerbell.receivers.GlobalApplicationReceiver;
import cc.winboll.studio.powerbell.utils.AppCacheUtils;
import cc.winboll.studio.powerbell.utils.AppConfigUtils;
import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils;
import cc.winboll.studio.powerbell.utils.BitmapCacheUtils;
import java.io.File;
public class App extends GlobalApplication {
public static final String TAG = "App";
public static final String COMPONENT_EN1 = "cc.winboll.studio.powerbell.MainActivityEN1";
public static final String COMPONENT_CN1 = "cc.winboll.studio.powerbell.MainActivityCN1";
public static final String COMPONENT_CN2 = "cc.winboll.studio.powerbell.MainActivityCN2";
public static final String ACTION_SWITCHTO_EN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_EN1";
public static final String ACTION_SWITCHTO_CN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN1";
public static final String ACTION_SWITCHTO_CN2 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN2";
public static final String COMPONENT_EN1 = "cc.winboll.studio.powerbell.MainActivityEN1";
public static final String COMPONENT_CN1 = "cc.winboll.studio.powerbell.MainActivityCN1";
public static final String COMPONENT_CN2 = "cc.winboll.studio.powerbell.MainActivityCN2";
public static final String ACTION_SWITCHTO_EN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_EN1";
public static final String ACTION_SWITCHTO_CN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN1";
public static final String ACTION_SWITCHTO_CN2 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN2";
// 数据配置存储工具
static AppConfigUtils _mAppConfigUtils;
static AppCacheUtils _mAppCacheUtils;
// 新增:全局 Bitmap 缓存工具(常驻内存)
public static BitmapCacheUtils _mBitmapCacheUtils;
GlobalApplicationReceiver mReceiver;
static String szTempDir = "";
@@ -34,25 +42,16 @@ public class App extends GlobalApplication {
@Override
public void onCreate() {
super.onCreate();
setIsDebugging(BuildConfig.DEBUG);
//setIsDebugging(false);
setIsDebugging(BuildConfig.DEBUG);
// 初始化活动窗口管理
WinBoLLActivityManager.init(this);
// 初始化活动窗口管理
WinBoLLActivityManager.init(this);
// 初始化 Toast 框架
ToastUtils.init(this);
// 临时文件夹方案1
// 获取Pictures文件夹路径Android 10及以上推荐使用MediaStore此处为传统方式
// 临时文件夹初始化(保持原有逻辑)
File picturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
// 定义目标文件路径在Pictures目录下创建"PowerBell"子文件夹及文件)
File powerBellDir = new File(picturesDir, "PowerBell");
// 临时文件夹方案2 <图片保存失败>
// 获取Pictures文件夹路径Android 10及以上推荐使用MediaStore此处为传统方式
//File powerBellDir = getExternalFilesDir("TempDir");
// 先创建文件夹(如果不存在)
if (!powerBellDir.exists()) {
powerBellDir.mkdirs();
}
@@ -61,11 +60,54 @@ public class App extends GlobalApplication {
// 设置数据配置存储工具
_mAppConfigUtils = getAppConfigUtils(this);
_mAppCacheUtils = getAppCacheUtils(this);
// 初始化全局 Bitmap 缓存工具关键App 启动时初始化,常驻内存)
_mBitmapCacheUtils = BitmapCacheUtils.getInstance();
mReceiver = new GlobalApplicationReceiver(this);
mReceiver.registerAction();
// ======================== 新增:异步预加载背景图 ========================
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
new Thread(new Runnable() {
@Override
public void run() {
try {
// 1. 获取背景源工具类实例
BackgroundSourceUtils bgSourceUtils = BackgroundSourceUtils.getInstance(App.this);
if (bgSourceUtils == null) {
LogUtils.e(TAG, "preloadBitmap: BackgroundSourceUtils 实例为空");
return;
}
// 2. 获取当前背景Bean
BackgroundBean bgBean = bgSourceUtils.getCurrentBackgroundBean();
if (bgBean == null || !bgBean.isUseBackgroundFile()) {
LogUtils.d(TAG, "preloadBitmap: 无有效背景文件,跳过预加载");
return;
}
// 3. 获取背景图路径(优先取压缩图路径)
String bgPath = bgBean.isUseBackgroundScaledCompressFile()
? bgBean.getBackgroundScaledCompressFilePath()
: bgBean.getBackgroundFilePath();
// 4. 预加载到全局缓存
if (_mBitmapCacheUtils != null) {
_mBitmapCacheUtils.cacheBitmap(bgPath);
LogUtils.d(TAG, "preloadBitmap: 应用启动时预加载成功 - " + bgPath);
} else {
LogUtils.e(TAG, "preloadBitmap: 全局 BitmapCacheUtils 未初始化");
}
} catch (Exception e) {
LogUtils.e(TAG, "preloadBitmap: 预加载失败 - " + e.getMessage());
}
}
}).start();
}
}, 1000); // 延迟1秒执行避免阻塞应用初始化
// ======================== 预加载逻辑结束 ========================
}
// 保持原有方法不变
public static AppConfigUtils getAppConfigUtils(Context context) {
if (_mAppConfigUtils == null) {
_mAppConfigUtils = AppConfigUtils.getInstance(context);
@@ -84,12 +126,14 @@ public class App extends GlobalApplication {
_mAppCacheUtils.clearBatteryHistory();
}
@Override
public void onTerminate() {
super.onTerminate();
ToastUtils.release();
}
@Override
public void onTerminate() {
super.onTerminate();
ToastUtils.release();
// 可选App 终止时清空 Bitmap 缓存,释放内存
if (_mBitmapCacheUtils != null) {
_mBitmapCacheUtils.clearAllCache();
}
}
}

View File

@@ -51,15 +51,14 @@ import cc.winboll.studio.powerbell.views.BatteryDrawable;
import cc.winboll.studio.powerbell.views.VerticalSeekBar;
/**
* 主活动类Java 7 兼容 | 首屏加速+窗体缓存)
* 主活动类Java 7 兼容 | 移除窗体缓存)
* 核心优化点:
* 1. ViewHolder 缓存控件 + ViewStub 延迟加载(原有)
* 2. savedInstanceState 窗体缓存(新增):缓存视图状态/数据,快速重建窗体
* 3. 资源异步加载 + 非关键任务异步化(原有)
* 1. ViewHolder 缓存控件 + ViewStub 延迟加载
* 2. 资源异步加载 + 非关键任务异步化
*/
public class MainActivity extends WinBoLLActivity {
// ======================== 静态常量(新增savedInstanceState 缓存键)========================
// ======================== 静态常量(移除缓存相关键)========================
public static final String TAG = "MainActivity";
private static final int REQUEST_WRITE_STORAGE_PERMISSION = 1001;
public static final int MSG_RELOAD_APPCONFIG = 0;
@@ -67,17 +66,7 @@ public class MainActivity extends WinBoLLActivity {
public static final int MSG_LOAD_BACKGROUND = 2;
private static final int DELAY_LOAD_NON_CRITICAL = 500;
// 缓存键(统一管理,避免键名重复)
private static final String KEY_VIEW_STATE = "key_view_state"; // 视图状态缓存键
private static final String KEY_CHARGE_REMINDER = "key_charge_reminder"; // 充电提醒值
private static final String KEY_USEGE_REMINDER = "key_usege_reminder"; // 耗电提醒值
private static final String KEY_CURRENT_VALUE = "key_current_value"; // 当前电量值
private static final String KEY_IS_SERVICE_ENABLE = "key_is_service_enable"; // 服务开关状态
private static final String KEY_IS_CHARGE_ENABLE = "key_is_charge_enable"; // 充电提醒开关
private static final String KEY_IS_USEGE_ENABLE = "key_is_usege_enable"; // 耗电提醒开关
private static final String KEY_BACKGROUND_BEAN = "key_background_bean"; // 背景配置Bean
// ======================== 成员属性(保持原有,新增缓存标识)========================
// ======================== 成员属性(移除缓存标识)========================
public static MainActivity _mMainActivity;
static MainViewFragment _mMainViewFragment;
static Handler _mHandler;
@@ -99,10 +88,6 @@ public class MainActivity extends WinBoLLActivity {
private BatteryDrawable mChargeReminderValueBatteryDrawable;
private BatteryDrawable mUsegeReminderValueBatteryDrawable;
// 新增缓存标识判断是否从savedInstanceState恢复避免重复初始化
private boolean isRestoredFromCache = false;
// ======================== 视图缓存容器ViewHolder 不变)========================
private static class ViewHolder {
BackgroundView backgroundView;
@@ -115,8 +100,7 @@ public class MainActivity extends WinBoLLActivity {
ImageView ivCurrentBattery, ivChargeReminderBattery, ivUsegeReminderBattery;
}
// ======================== 重写生命周期核心savedInstanceState 缓存/恢复)========================
// ======================== 重写生命周期(移除缓存恢复/保存逻辑)========================
@Override
public Activity getActivity() {
return this;
@@ -129,80 +113,27 @@ public class MainActivity extends WinBoLLActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
LogUtils.d(TAG, "onCreate(...) - 窗体缓存优化savedInstanceState = " + (savedInstanceState != null));
LogUtils.d(TAG, "onCreate(...) - 移除窗体缓存");
super.onCreate(savedInstanceState);
initGlobalHandler();
// 第一步优先从savedInstanceState恢复窗体核心优化
if (savedInstanceState != null) {
restoreFromCache(savedInstanceState); // 从缓存恢复视图/数据
isRestoredFromCache = true; // 标记为缓存恢复,跳过重复初始化
}
// 恢复原始初始化流程:直接加载布局+初始化
setContentView(R.layout.activity_main);
initCoreUtilsAsync();
initViewHolder();
initCriticalView();
loadNonCriticalViewDelayed();
// 第二步:无缓存时,正常初始化(保持原有逻辑,新增判断)
if (!isRestoredFromCache) {
setContentView(R.layout.activity_main); // 加载布局(仅首次/无缓存时执行)
initCoreUtilsAsync(); // 异步初始化工具类
initViewHolder(); // 绑定控件(仅首次/无缓存时执行)
initCriticalView(); // 初始化核心视图
loadNonCriticalViewDelayed(); // 延迟加载非核心视图
}
// 第三步:权限申请(无论是否缓存,都需确保权限有效)
// 权限申请
PermissionUtils.getInstance().checkAndRequestStoragePermission(this);
}
/**
* 重写 onSaveInstanceState保存视图状态/数据到 savedInstanceState(关键)
* 当Activity销毁前如旋转屏幕、后台回收自动调用此方法缓存数据
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
LogUtils.d(TAG, "onSaveInstanceState - 缓存窗体状态/数据");
// 1. 缓存控件数据(避免重建后重复读取配置)
if (mViewHolder != null && mAppConfigUtils != null) {
outState.putInt(KEY_CHARGE_REMINDER, mAppConfigUtils.getChargeReminderValue());
outState.putInt(KEY_USEGE_REMINDER, mAppConfigUtils.getUsegeReminderValue());
outState.putInt(KEY_CURRENT_VALUE, mAppConfigUtils.getCurrentValue());
outState.putBoolean(KEY_IS_SERVICE_ENABLE, mAppConfigUtils.getIsEnableService());
outState.putBoolean(KEY_IS_CHARGE_ENABLE, mViewHolder.cbIsEnableChargeReminder.isChecked());
outState.putBoolean(KEY_IS_USEGE_ENABLE, mViewHolder.cbIsEnableUsegeReminder.isChecked());
}
// 2. 缓存背景配置(避免重建后重复加载背景图)
if (mBgSourceUtils != null) {
BackgroundBean backgroundBean = mBgSourceUtils.getCurrentBackgroundBean();
if (backgroundBean != null) {
outState.putSerializable(KEY_BACKGROUND_BEAN, backgroundBean); // 需BackgroundBean实现Serializable
}
}
// 3. 缓存视图状态可选如SeekBar进度、控件可见性等
if (mViewHolder != null) {
outState.putInt(KEY_VIEW_STATE + "_charge_seek", mViewHolder.chargeReminderSeekBar.getProgress());
outState.putInt(KEY_VIEW_STATE + "_usege_seek", mViewHolder.usegeReminderSeekBar.getProgress());
}
}
/**
* 重写 onRestoreInstanceState从 savedInstanceState 恢复数据可选onCreate中已处理
* 确保在onStart后、onResume前恢复避免视图状态覆盖
*/
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null && !isRestoredFromCache) {
restoreFromCache(savedInstanceState);
isRestoredFromCache = true;
}
}
// 移除 onSaveInstanceState 方法
// 移除 onRestoreInstanceState 方法
@Override
protected void onDestroy() {
super.onDestroy();
// 释放资源(保持原有)
if (mADsBannerView != null) {
mADsBannerView.releaseAdResources();
}
@@ -211,23 +142,15 @@ public class MainActivity extends WinBoLLActivity {
if (_mHandler != null) {
_mHandler.removeCallbacksAndMessages(null);
}
// 重置缓存标识
isRestoredFromCache = false;
}
@Override
protected void onResume() {
super.onResume();
// 缓存恢复后,无需重复发送加载消息(仅首次/无缓存时执行)
if (!isRestoredFromCache) {
if (_mHandler != null) {
_mHandler.sendEmptyMessage(MSG_LOAD_BACKGROUND);
}
} else {
// 缓存恢复后,快速刷新视图(避免状态不一致)
refreshViewFromCache();
// 移除缓存恢复后的刷新逻辑,直接发送加载背景消息
if (_mHandler != null) {
_mHandler.sendEmptyMessage(MSG_LOAD_BACKGROUND);
}
// 恢复广告(保持原有)
if (mADsBannerView != null) {
mADsBannerView.resumeADs(MainActivity.this);
}
@@ -312,94 +235,10 @@ public class MainActivity extends WinBoLLActivity {
}
}
// ======================== 新增:窗体缓存核心方法(恢复+刷新)========================
/**
* 从 savedInstanceState 恢复视图和数据(核心)
* 避免重复加载布局、绑定控件、读取配置,加快窗体重建速度
*/
private void restoreFromCache(Bundle savedInstanceState) {
LogUtils.d(TAG, "restoreFromCache - 从缓存恢复窗体");
// 1. 恢复工具类(无需重新初始化,直接获取实例)
mApplication = (App) getApplication();
mAppConfigUtils = App.getAppConfigUtils(getActivity());
mBgSourceUtils = BackgroundSourceUtils.getInstance(getActivity());
// 2. 恢复ViewHolder仅绑定控件不重新inflate布局
if (mViewHolder == null) {
mViewHolder = new ViewHolder();
initViewHolder(); // 复用原有绑定逻辑,避免重复代码
}
// 3. 恢复背景配置直接设置缓存的BackgroundBean避免重复读取
BackgroundBean cachedBean = (BackgroundBean) savedInstanceState.getSerializable(KEY_BACKGROUND_BEAN);
if (cachedBean != null && mViewHolder.backgroundView != null) {
mViewHolder.backgroundView.loadBackgroundBean(cachedBean);
//mBgSourceUtils.setCurrentBackgroundBean(cachedBean); // 同步更新工具类缓存
}
// 4. 恢复控件数据从缓存读取避免重复调用AppConfigUtils
int chargeReminder = savedInstanceState.getInt(KEY_CHARGE_REMINDER, 80); // 默认值80
int usegeReminder = savedInstanceState.getInt(KEY_USEGE_REMINDER, 20); // 默认值20
int currentValue = savedInstanceState.getInt(KEY_CURRENT_VALUE, 50); // 默认值50
boolean isServiceEnable = savedInstanceState.getBoolean(KEY_IS_SERVICE_ENABLE, false);
boolean isChargeEnable = savedInstanceState.getBoolean(KEY_IS_CHARGE_ENABLE, false);
boolean isUsegeEnable = savedInstanceState.getBoolean(KEY_IS_USEGE_ENABLE, false);
// 5. 恢复电量图标(复用缓存实例,避免重新创建)
initBatteryDrawables();
mCurrentValueBatteryDrawable.setValue(currentValue);
mChargeReminderValueBatteryDrawable.setValue(chargeReminder);
mUsegeReminderValueBatteryDrawable.setValue(usegeReminder);
// 6. 恢复控件状态(直接设置,避免重复绑定数据)
if (mViewHolder != null) {
mViewHolder.cbIsEnableChargeReminder.setChecked(isChargeEnable);
mViewHolder.cbIsEnableUsegeReminder.setChecked(isUsegeEnable);
mViewHolder.swIsEnableService.setChecked(isServiceEnable);
mViewHolder.chargeReminderSeekBar.setProgress(savedInstanceState.getInt(KEY_VIEW_STATE + "_charge_seek", chargeReminder));
mViewHolder.usegeReminderSeekBar.setProgress(savedInstanceState.getInt(KEY_VIEW_STATE + "_usege_seek", usegeReminder));
mViewHolder.tvChargeReminderValue.setText(String.valueOf(chargeReminder) + "%");
mViewHolder.tvUsegeReminderValue.setText(String.valueOf(usegeReminder) + "%");
mViewHolder.tvCurrentValue.setText(String.valueOf(currentValue) + "%");
}
// 7. 恢复非核心视图(广告)
loadAdsView();
}
// ======================== 移除缓存相关核心方法restoreFromCache/refreshViewFromCache========================
/**
* 缓存恢复后,快速刷新视图(确保状态一致
*/
private void refreshViewFromCache() {
if (mViewHolder == null) return;
// 快速设置背景色从缓存Bean获取
if (mBgSourceUtils != null && mViewHolder.mainLayout != null) {
BackgroundBean cachedBean = mBgSourceUtils.getCurrentBackgroundBean();
if (cachedBean != null) {
mViewHolder.mainLayout.setBackgroundColor(cachedBean.getPixelColor());
}
}
// 快速设置电量图标(避免图标不显示)
if (mViewHolder.ivCurrentBattery != null) {
mViewHolder.ivCurrentBattery.setImageDrawable(mCurrentValueBatteryDrawable);
}
if (mViewHolder.ivChargeReminderBattery != null) {
mViewHolder.ivChargeReminderBattery.setImageDrawable(mChargeReminderValueBatteryDrawable);
}
if (mViewHolder.ivUsegeReminderBattery != null) {
mViewHolder.ivUsegeReminderBattery.setImageDrawable(mUsegeReminderValueBatteryDrawable);
}
// 重新绑定监听(确保交互正常,避免监听失效)
setViewListener();
}
/**
* 初始化电量图标(复用逻辑,避免重复代码)
* 初始化电量图标(复用逻辑
*/
private void initBatteryDrawables() {
if (mCurrentValueBatteryDrawable == null) {
@@ -413,13 +252,11 @@ public class MainActivity extends WinBoLLActivity {
}
}
// ======================== 原有核心方法(微调:新增缓存判断,避免重复执行)========================
// ======================== 原有核心方法(移除缓存判断逻辑)========================
/**
* 刷新背景(新增缓存判断,缓存恢复后无需重复执行
* 刷新背景(移除缓存判断)
*/
public void reloadBackground() {
if (isRestoredFromCache) return; // 缓存恢复后,跳过重复加载
if (mViewHolder == null || mBgSourceUtils == null || mViewHolder.backgroundView == null) {
LogUtils.e(TAG, "reloadBackground: 背景加载失败(控件/工具类未初始化)");
return;
@@ -434,10 +271,9 @@ public class MainActivity extends WinBoLLActivity {
}
/**
* 设置主页面背景颜色(新增缓存判断)
* 设置主页面背景颜色(移除缓存判断)
*/
void setBackgroundColor() {
if (isRestoredFromCache) return;
if (isFinishing() || isDestroyed() || mViewHolder == null || mBgSourceUtils == null || mViewHolder.mainLayout == null) {
return;
}
@@ -449,10 +285,9 @@ public class MainActivity extends WinBoLLActivity {
}
/**
* 设置视图数据(新增缓存判断,缓存恢复后无需重复执行
* 设置视图数据(移除缓存判断)
*/
void setViewData() {
if (isRestoredFromCache) return;
if (mViewHolder == null || mAppConfigUtils == null) return;
int nChargeReminderValue = mAppConfigUtils.getChargeReminderValue();
@@ -464,7 +299,7 @@ public class MainActivity extends WinBoLLActivity {
mViewHolder.llRightSeekBar.setBackground(mDrawableFrame);
}
initBatteryDrawables(); // 复用初始化逻辑
initBatteryDrawables();
if (mViewHolder.ivCurrentBattery != null) {
mCurrentValueBatteryDrawable.setValue(nCurrentValue);
mViewHolder.ivCurrentBattery.setImageDrawable(mCurrentValueBatteryDrawable);
@@ -478,7 +313,6 @@ public class MainActivity extends WinBoLLActivity {
mViewHolder.ivUsegeReminderBattery.setImageDrawable(mUsegeReminderValueBatteryDrawable);
}
// 控件数据绑定(保持原有)
if (mViewHolder.tvChargeReminderValue != null) {
mViewHolder.tvChargeReminderValue.setTextColor(getActivity().getColor(R.color.colorCharge));
mViewHolder.tvChargeReminderValue.setText(String.valueOf(nChargeReminderValue) + "%");
@@ -515,7 +349,6 @@ public class MainActivity extends WinBoLLActivity {
}
}
// 其他原有方法setViewListener、setCurrentValueBattery、initCoreUtilsAsync等保持不变
/**
* 设置视图监听(保持原有)
*/

View File

@@ -6,6 +6,7 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -14,6 +15,7 @@ import android.os.Handler;
import android.os.Looper;
import android.provider.MediaStore;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.FileProvider;
@@ -52,7 +54,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
private BackgroundView mBackgroundView;
private File mfTakePhoto;
volatile boolean isCommitSettings = false;
volatile boolean isPreviewBackgroundChanged = false;
volatile boolean isPreviewBackgroundChanged = false;
@Override
public Activity getActivity() {
@@ -71,49 +73,49 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
mBackgroundView = (BackgroundView) findViewById(R.id.background_view);
mBgSourceUtils = BackgroundSourceUtils.getInstance(this);
mBgSourceUtils.loadSettings();
mBgSourceUtils.loadSettings();
mPermissionUtils = PermissionUtils.getInstance();
// File tempDir = new File(App.getTempDirPath());
// if (!tempDir.exists()) {
// tempDir.mkdirs();
// }
// mfTakePhoto = new File(tempDir, "TakePhoto.jpg");
//
// File selectTempDir = new File(mBgSourceUtils.getBackgroundSourceDirPath(), "SelectTemp");
// if (!selectTempDir.exists()) {
// selectTempDir.mkdirs();
// LogUtils.d(TAG, "【选图初始化】选图临时目录创建完成:" + selectTempDir.getAbsolutePath());
// }
File tempDir = new File(App.getTempDirPath());
if (!tempDir.exists()) {
tempDir.mkdirs();
}
mfTakePhoto = new File(tempDir, "TakePhoto.jpg");
File selectTempDir = new File(mBgSourceUtils.getBackgroundSourceDirPath(), "SelectTemp");
if (!selectTempDir.exists()) {
selectTempDir.mkdirs();
LogUtils.d(TAG, "【选图初始化】选图临时目录创建完成:" + selectTempDir.getAbsolutePath());
}
initToolbar();
initClickListeners();
if (handleShareIntent()) {
ToastUtils.show("handleShareIntent");
} else {
mBgSourceUtils.setCurrentSourceToPreview();
}
ToastUtils.show("handleShareIntent");
} else {
mBgSourceUtils.setCurrentSourceToPreview();
}
Uri uriSelectedImage = UriUtil.getUriForFile(this, new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundFilePath()));
// 创建预览数据剪裁环境
mBgSourceUtils.createAndUpdatePreviewEnvironmentForCropping(mBgSourceUtils.getPreviewBackgroundBean());
doubleRefreshPreview();
Uri uriSelectedImage = UriUtil.getUriForFile(this, new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundFilePath()));
// 创建预览数据剪裁环境
mBgSourceUtils.createAndUpdatePreviewEnvironmentForCropping(mBgSourceUtils.getPreviewBackgroundBean());
doubleRefreshPreview();
LogUtils.d(TAG, "【初始化】BackgroundSettingsActivity 初始化完成");
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
doubleRefreshPreview();
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
doubleRefreshPreview();
}
private void initToolbar() {
mToolbar = findViewById(R.id.toolbar);
mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
mToolbar.setSubtitle(getTag());
mToolbar.setSubtitle(getTag());
mToolbar.setTitleTextAppearance(this, R.style.Toolbar_TitleText);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -143,10 +145,10 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
BackgroundPicturePreviewDialog dlg = new BackgroundPicturePreviewDialog(this);
dlg.show();
LogUtils.d(TAG, "【分享处理】收到分享图片意图");
return true;
return true;
}
}
return false;
return false;
}
boolean isImageType(String lowerMimeType) {
@@ -255,8 +257,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
mBackgroundView.getWidth(),
mBackgroundView.getHeight(),
false,
REQUEST_CROP_IMAGE
);
REQUEST_CROP_IMAGE);
}
};
@@ -270,8 +271,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
0,
0,
true,
REQUEST_CROP_IMAGE
);
REQUEST_CROP_IMAGE);
}
};
@@ -429,8 +429,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
mBackgroundView.getWidth(),
mBackgroundView.getHeight(),
false,
REQUEST_CROP_IMAGE
);
REQUEST_CROP_IMAGE);
LogUtils.d(TAG, "【拍照完成】已启动裁剪");
}
@@ -470,50 +469,52 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
return null;
}
private void handleSelectPictureResult(int resultCode, Intent data) {
if (resultCode != RESULT_OK || data == null) {
handleOperationCancelOrFail();
return;
}
private void handleSelectPictureResult(int resultCode, Intent data) {
if (resultCode != RESULT_OK || data == null) {
handleOperationCancelOrFail();
return;
}
Uri selectedImage = data.getData();
if (selectedImage == null) {
ToastUtils.show("图片Uri为空");
return;
}
LogUtils.d(TAG, "【选图回调】Uri : " + selectedImage.toString());
Uri selectedImage = data.getData();
if (selectedImage == null) {
ToastUtils.show("图片Uri为空");
return;
}
LogUtils.d(TAG, "【选图回调】Uri : " + selectedImage.toString());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getContentResolver().takePersistableUriPermission(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getContentResolver().takePersistableUriPermission(
selectedImage,
Intent.FLAG_GRANT_READ_URI_PERMISSION
);
LogUtils.d(TAG, "【选图权限】已添加持久化权限");
}
);
LogUtils.d(TAG, "【选图权限】已添加持久化权限");
}
LogUtils.d(TAG, "【选图同步】路径绑定完成");
// 选图后启动固定比例裁剪(调用工具类)
putUriFileToPreviewSource(selectedImage);
ImageCropUtils.startImageCrop(BackgroundSettingsActivity.this,
LogUtils.d(TAG, "【选图同步】路径绑定完成");
// 选图后启动固定比例裁剪(调用工具类)
putUriFileToPreviewSource(selectedImage);
ImageCropUtils.startImageCrop(BackgroundSettingsActivity.this,
mBgSourceUtils.getPreviewBackgroundBean(),
mBackgroundView.getWidth(),
mBackgroundView.getHeight(),
false,
REQUEST_CROP_IMAGE
);
}
REQUEST_CROP_IMAGE);
}
boolean putUriFileToPreviewSource(Uri srcUriFile) {
File srcFile = new File(UriUtil.getFilePathFromUri(this, srcUriFile));
return putUriFileToPreviewSource(srcFile);
}
boolean putUriFileToPreviewSource(Uri srcUriFile) {
File srcFile = new File(UriUtil.getFilePathFromUri(this, srcUriFile));
return putUriFileToPreviewSource(srcFile);
}
boolean putUriFileToPreviewSource(File srcFile) {
mBgSourceUtils.loadSettings();
File dstFile = new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundFilePath());
return FileUtils.copyFile(srcFile, dstFile);
}
boolean putUriFileToPreviewSource(File srcFile) {
mBgSourceUtils.loadSettings();
File dstFile = new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundFilePath());
return FileUtils.copyFile(srcFile, dstFile);
}
/**
* 核心修改:裁剪成功后调用双重刷新,确保最新图片加载
*/
private void handleCropImageResult(int requestCode, int resultCode, Intent data) {
LogUtils.d(TAG, "handleCropImageResult: 处理裁剪结果");
File cropTempFile = new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundScaledCompressFilePath());
@@ -523,9 +524,9 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
boolean isCropSuccess = (resultCode == RESULT_OK) && isFileExist && isFileReadable && fileSize > 100;
if (isCropSuccess) {
isPreviewBackgroundChanged = true;
isPreviewBackgroundChanged = true;
LogUtils.d(TAG, "handleCropImageResult: 裁剪成功");
BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
final BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
previewBean.setIsUseBackgroundFile(true);
previewBean.setIsUseBackgroundScaledCompressFile(true);
mBgSourceUtils.saveSettings();
@@ -546,15 +547,16 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
}
}
// 关键修改延迟300ms调用双重刷新确保文件写入完成
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
if (mBackgroundView != null && !isFinishing()) {
mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean());
LogUtils.d(TAG, "handleCropImageResult: 裁剪图片加载完成");
if (!isFinishing()) {
doubleRefreshPreview();
LogUtils.d(TAG, "handleCropImageResult: 触发双重刷新");
}
}
}, 50);
}, 300);
} else {
handleOperationCancelOrFail();
}
@@ -697,10 +699,42 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
return cropBitmap;
}
/**
* 核心修改:添加缓存清理 + 控件 Bitmap 清空逻辑
*/
private void doubleRefreshPreview() {
LogUtils.d(TAG, "【双重刷新】开始");
// 1. 清空缓存工具类的旧数据
if (mBgSourceUtils != null) {
BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
if (previewBean != null && previewBean.isUseBackgroundFile()) {
String bgPath = previewBean.isUseBackgroundScaledCompressFile()
? previewBean.getBackgroundScaledCompressFilePath()
: previewBean.getBackgroundFilePath();
// 强制清除缓存
App._mBitmapCacheUtils.removeCachedBitmap(bgPath);
LogUtils.d(TAG, "【双重刷新】已清空工具类缓存:" + bgPath);
}
}
// 2. 清空 BackgroundView 自身的 Bitmap 引用
// if (mBackgroundView != null) {
// // 清空 ImageView 持有的 Bitmap
// if (mBackgroundView instanceof BackgroundView) {
// ((BackgroundView) mBackgroundView).setImageBitmap(null);
// }
// // 清空背景 Drawable 引用
// Drawable drawable = mBackgroundView.getBackground();
// if (drawable != null) {
// drawable.setCallback(null);
// mBackgroundView.setBackground(null);
// }
// LogUtils.d(TAG, "【双重刷新】已清空控件 Bitmap 引用");
// }
// 3. 重新加载最新数据
if (mBackgroundView != null && !isFinishing()) {
mBgSourceUtils.loadSettings();
mBgSourceUtils.loadSettings();
mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean());
LogUtils.d(TAG, "【双重刷新】第一重完成");
} else {
@@ -708,6 +742,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
return;
}
// 4. 延长延迟到200ms确保文件完全加载
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
@@ -717,7 +752,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
LogUtils.d(TAG, "【双重刷新】第二重完成");
}
}
}, 50);
}, 200);
}
@@ -725,37 +760,16 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
mBgSourceUtils.setCurrentSourceToPreview();
LogUtils.d(TAG, "【操作回调】取消或失败");
ToastUtils.show("【操作回调】取消或失败");
doubleRefreshPreview();
doubleRefreshPreview();
}
/**
* 启动系统裁剪工具
* @param activity 上下文
* @param srcFile 裁剪原图
* @param aspectX 裁剪宽比例自由裁剪传0
* @param aspectY 裁剪高比例自由裁剪传0
* @param isFreeCrop 是否自由裁剪
* @param requestCode 裁剪请求码
*/
/**
* 启动系统裁剪工具
* @param activity 上下文
* @param srcFile 裁剪原图
* @param aspectX 裁剪宽比例自由裁剪传0
* @param aspectY 裁剪高比例自由裁剪传0
* @param isFreeCrop 是否自由裁剪
* @param requestCode 裁剪请求码
*/
/**
* 获取FileProvider Uri复用方法避免重复代码
*/
public Uri getFileProviderUri(File file) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
String FILE_PROVIDER_AUTHORITY = getPackageName() + ".fileprovider";
String FILE_PROVIDER_AUTHORITY = getPackageName() + ".fileprovider";
return FileProvider.getUriForFile(this, FILE_PROVIDER_AUTHORITY, file);
} else {
@@ -779,9 +793,9 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
if (isCommitSettings) {
super.finish();
} else {
// 如果预览背景改变过就提示是否更换背景
if (isPreviewBackgroundChanged) {
YesNoAlertDialog.show(this, "背景更换问题", "是否确定背景图片设置?", new YesNoAlertDialog.OnDialogResultListener(){
// 如果预览背景改变过就提示是否更换背景
if (isPreviewBackgroundChanged) {
YesNoAlertDialog.show(this, "背景更换问题", "是否确定背景图片设置?", new YesNoAlertDialog.OnDialogResultListener() {
@Override
public void onYes() {
mBgSourceUtils.commitPreviewSourceToCurrent();
@@ -795,11 +809,11 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
finish();
}
});
} else {
// 如果预览背景未改变就直接退出
isCommitSettings = true;
finish();
}
} else {
// 如果预览背景未改变就直接退出
isCommitSettings = true;
finish();
}
}
}
}

View File

@@ -0,0 +1,165 @@
package cc.winboll.studio.powerbell.utils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.TextUtils;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import cc.winboll.studio.libappbase.LogUtils;
/**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/12/11 01:57
* @Describe 单例 Bitmap 缓存工具类Java 7 兼容)
* 功能:内存缓存 Bitmap支持路径关联缓存、全局获取、缓存清空
* 特点1. 单例模式 2. 压缩加载避免OOM 3. 路径- Bitmap 映射 4. 线程安全
*/
public class BitmapCacheUtils {
private static final String TAG = "BitmapCacheUtils";
// 最大图片尺寸适配1080P屏幕可根据需求调整
private static final int MAX_WIDTH = 1080;
private static final int MAX_HEIGHT = 1920;
// 单例实例volatile 保证多线程可见性)
private static volatile BitmapCacheUtils sInstance;
// 路径-Bitmap 缓存容器(内存缓存)
private final Map<String, Bitmap> mBitmapCacheMap;
// 私有构造器(单例模式)
private BitmapCacheUtils() {
mBitmapCacheMap = new HashMap<>();
}
/**
* 获取单例实例(双重校验锁,线程安全)
*/
public static BitmapCacheUtils getInstance() {
if (sInstance == null) {
synchronized (BitmapCacheUtils.class) {
if (sInstance == null) {
sInstance = new BitmapCacheUtils();
}
}
}
return sInstance;
}
/**
* 核心接口:根据图片路径缓存 Bitmap 到内存
* @param imagePath 图片绝对路径
* @return 缓存成功的 Bitmap / null路径无效/文件不存在)
*/
public Bitmap cacheBitmap(String imagePath) {
if (TextUtils.isEmpty(imagePath)) {
LogUtils.e(TAG, "cacheBitmap: 图片路径为空");
return null;
}
File imageFile = new File(imagePath);
if (!imageFile.exists() || !imageFile.isFile()) {
LogUtils.e(TAG, "cacheBitmap: 图片文件不存在 - " + imagePath);
return null;
}
// 已缓存则直接返回,避免重复加载
if (mBitmapCacheMap.containsKey(imagePath)) {
LogUtils.d(TAG, "cacheBitmap: 图片已缓存,直接返回 - " + imagePath);
return mBitmapCacheMap.get(imagePath);
}
// 压缩加载 Bitmap避免OOM
Bitmap bitmap = decodeCompressedBitmap(imagePath);
if (bitmap != null) {
// 存入缓存容器
mBitmapCacheMap.put(imagePath, bitmap);
LogUtils.d(TAG, "cacheBitmap: 图片缓存成功 - " + imagePath);
} else {
LogUtils.e(TAG, "cacheBitmap: 图片解码失败 - " + imagePath);
}
return bitmap;
}
/**
* 核心接口:根据路径获取缓存的 Bitmap
* @param imagePath 图片绝对路径
* @return 缓存的 Bitmap / null
*/
public Bitmap getCachedBitmap(String imagePath) {
if (TextUtils.isEmpty(imagePath)) {
return null;
}
return mBitmapCacheMap.get(imagePath);
}
/**
* 清空所有 Bitmap 缓存(释放内存)
*/
public void clearAllCache() {
for (Bitmap bitmap : mBitmapCacheMap.values()) {
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle(); // 主动回收 Bitmap
}
}
mBitmapCacheMap.clear();
LogUtils.d(TAG, "clearAllCache: 所有 Bitmap 缓存已清空");
}
/**
* 移除指定路径的 Bitmap 缓存
* @param imagePath 图片绝对路径
*/
public void removeCachedBitmap(String imagePath) {
if (TextUtils.isEmpty(imagePath)) {
return;
}
Bitmap bitmap = mBitmapCacheMap.remove(imagePath);
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
LogUtils.d(TAG, "removeCachedBitmap: 移除并回收缓存 - " + imagePath);
}
}
/**
* 压缩解码 Bitmap按最大尺寸缩放避免OOM
*/
private Bitmap decodeCompressedBitmap(String imagePath) {
BitmapFactory.Options options = new BitmapFactory.Options();
// 第一步:只获取图片尺寸,不加载像素
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, options);
// 计算缩放比例
int sampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT);
// 第二步:加载压缩后的 Bitmap
options.inJustDecodeBounds = false;
options.inSampleSize = sampleSize;
options.inPreferredConfig = Bitmap.Config.RGB_565; // 节省内存比ARGB_8888少一半内存
options.inPurgeable = true;
options.inInputShareable = true;
return BitmapFactory.decodeFile(imagePath, options);
}
/**
* 计算 Bitmap 缩放比例
*/
private int calculateInSampleSize(BitmapFactory.Options options, int maxWidth, int maxHeight) {
int rawWidth = options.outWidth;
int rawHeight = options.outHeight;
int inSampleSize = 1;
if (rawWidth > maxWidth || rawHeight > maxHeight) {
int halfWidth = rawWidth / 2;
int halfHeight = rawHeight / 2;
while ((halfWidth / inSampleSize) >= maxWidth && (halfHeight / inSampleSize) >= maxHeight) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
}

View File

@@ -12,6 +12,8 @@ import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.ToastUtils;
import cc.winboll.studio.powerbell.App;
import cc.winboll.studio.powerbell.model.BackgroundBean;
import java.io.File;
@@ -22,6 +24,8 @@ import java.io.File;
public class BackgroundView extends RelativeLayout {
public static final String TAG = "BackgroundView";
// 新增:记录当前已缓存的图片路径
private String mCurrentCachedPath = "";
private Context mContext;
private LinearLayout mLlContainer; // 主容器LinearLayout
@@ -55,8 +59,6 @@ public class BackgroundView extends RelativeLayout {
LogUtils.d(TAG, "=== initView 启动 ===");
// 1. 配置当前控件:全屏+透明
setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
//setBackgroundColor(0x00000000);
//setBackground(new ColorDrawable(0x00000000));
// 2. 初始化主容器LinearLayout
initLinearLayout();
@@ -64,7 +66,7 @@ public class BackgroundView extends RelativeLayout {
// 3. 初始化ImageView
initImageView();
// 初始设置透明背景
// 初始设置透明背景
setDefaultTransparentBackground();
LogUtils.d(TAG, "=== initView 完成 ===");
@@ -101,22 +103,21 @@ public class BackgroundView extends RelativeLayout {
LogUtils.d(TAG, "=== initImageView 完成 ===");
}
public void loadBackgroundBean(BackgroundBean bean) {
if (!bean.isUseBackgroundFile()) {
setDefaultTransparentBackground();
return;
}
if (bean.isUseBackgroundScaledCompressFile()) {
loadImage(bean.getBackgroundScaledCompressFilePath());
} else {
loadImage(bean.getBackgroundFilePath());
}
}
public void loadBackgroundBean(BackgroundBean bean) {
if (!bean.isUseBackgroundFile()) {
setDefaultTransparentBackground();
return;
}
String targetPath = bean.isUseBackgroundScaledCompressFile()
? bean.getBackgroundScaledCompressFilePath()
: bean.getBackgroundFilePath();
// 调用带路径判断的loadImage方法
loadImage(targetPath);
}
// ====================================== 对外方法 ======================================
/**
* 加载图片保持原图比例在LinearLayout中居中平铺
* 改造后:添加路径判断,路径更新时同步更新缓存
* @param imagePath 图片绝对路径
*/
public void loadImage(String imagePath) {
@@ -132,25 +133,51 @@ public class BackgroundView extends RelativeLayout {
setDefaultTransparentBackground();
return;
}
mIvBackground.setVisibility(View.GONE);
// 计算原图比例
mIvBackground.setVisibility(View.GONE);
// ======================== 新增:路径判断逻辑 ========================
// 1. 路径未变化:直接使用缓存
if (imagePath.equals(mCurrentCachedPath)) {
//ToastUtils.show("isReload == false");
Bitmap cachedBitmap = App._mBitmapCacheUtils.getCachedBitmap(imagePath);
if (cachedBitmap != null && !cachedBitmap.isRecycled()) {
LogUtils.d(TAG, "loadImage: 路径未变,使用缓存 Bitmap");
mImageAspectRatio = (float) cachedBitmap.getWidth() / cachedBitmap.getHeight();
mIvBackground.setImageBitmap(cachedBitmap);
adjustImageViewSize();
mIvBackground.setVisibility(View.VISIBLE);
return;
}
}
// 2. 路径已更新:移除旧缓存,加载新图片并更新缓存
if (!TextUtils.isEmpty(mCurrentCachedPath)) {
App._mBitmapCacheUtils.removeCachedBitmap(mCurrentCachedPath);
LogUtils.d(TAG, "loadImage: 路径已更新,移除旧缓存 - " + mCurrentCachedPath);
}
// ======================== 路径判断逻辑结束 ========================
// 无缓存/路径更新:走原有逻辑加载图片
if (!calculateImageAspectRatio(imageFile)) {
setDefaultTransparentBackground();
return;
}
// 压缩加载Bitmap
Bitmap bitmap = decodeBitmapWithCompress(imageFile, 1080, 1920);
if (bitmap == null) {
setDefaultTransparentBackground();
return;
}
// 设置图片
// 缓存新图片,并更新当前缓存路径记录
App._mBitmapCacheUtils.cacheBitmap(imagePath);
mCurrentCachedPath = imagePath;
LogUtils.d(TAG, "loadImage: 加载新图片并更新缓存 - " + imagePath);
mIvBackground.setImageDrawable(new BitmapDrawable(mContext.getResources(), bitmap));
adjustImageViewSize(); // 调整尺寸
adjustImageViewSize();
mIvBackground.setVisibility(View.VISIBLE);
LogUtils.d(TAG, "=== loadImage 完成 ===");
}
@@ -198,56 +225,39 @@ public class BackgroundView extends RelativeLayout {
}
}
/**
* 调整ImageView尺寸保持原图比例在LinearLayout中居中平铺
*/
private void adjustImageViewSize() {
//LogUtils.d(TAG, "=== adjustImageViewSize 启动 ===");
if (mLlContainer == null || mIvBackground == null) {
//LogUtils.e(TAG, "控件为空");
return;
}
// 获取LinearLayout尺寸
int llWidth = mLlContainer.getWidth();
int llHeight = mLlContainer.getHeight();
if (llWidth == 0 || llHeight == 0) {
postDelayed(new Runnable() {
@Override
public void run() {
adjustImageViewSize();
}
}, 100);
return;
if (llWidth != 0 && llHeight != 0) {
int ivWidth, ivHeight;
if (mImageAspectRatio >= 1.0f) {
ivWidth = Math.min((int) (llHeight * mImageAspectRatio), llWidth);
ivHeight = (int) (ivWidth / mImageAspectRatio);
} else {
ivHeight = Math.min((int) (llWidth / mImageAspectRatio), llHeight);
ivWidth = (int) (ivHeight * mImageAspectRatio);
}
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mIvBackground.getLayoutParams();
params.width = ivWidth;
params.height = ivHeight;
mIvBackground.setLayoutParams(params);
mIvBackground.setScaleType(ScaleType.FIT_CENTER);
mIvBackground.setVisibility(View.VISIBLE);
}
// 计算ImageView尺寸保持比例不超出LinearLayout
int ivWidth, ivHeight;
if (mImageAspectRatio >= 1.0f) {
ivWidth = Math.min((int) (llHeight * mImageAspectRatio), llWidth);
ivHeight = (int) (ivWidth / mImageAspectRatio);
} else {
ivHeight = Math.min((int) (llWidth / mImageAspectRatio), llHeight);
ivWidth = (int) (ivHeight * mImageAspectRatio);
}
// 应用尺寸
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mIvBackground.getLayoutParams();
params.width = ivWidth;
params.height = ivHeight;
mIvBackground.setLayoutParams(params);
mIvBackground.setScaleType(ScaleType.FIT_CENTER); // 确保居中平铺
mIvBackground.setVisibility(View.VISIBLE);
//LogUtils.d(TAG, "ImageView尺寸" + ivWidth + "x" + ivHeight);
//LogUtils.d(TAG, "=== adjustImageViewSize 完成 ===");
}
private void setDefaultTransparentBackground() {
mIvBackground.setImageBitmap(null);
mIvBackground.setBackgroundColor(0x00000000);
mImageAspectRatio = 1.0f;
// 清空缓存路径记录
mCurrentCachedPath = "";
}
// ====================================== 重写方法 ======================================
@@ -257,3 +267,4 @@ public class BackgroundView extends RelativeLayout {
adjustImageViewSize(); // 尺寸变化时重新调整
}
}