diff --git a/powerbell/build.properties b/powerbell/build.properties index 3f39d98..c2edd88 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Wed Dec 24 12:22:06 HKT 2025 +#Wed Dec 24 09:10:57 GMT 2025 stageCount=29 libraryProject= baseVersion=15.14 publishVersion=15.14.28 -buildCount=0 +buildCount=57 baseBetaVersion=15.14.29 diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/BackgroundPicturePreviewDialog.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/BackgroundPicturePreviewDialog.java index 1889114..442aab3 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/BackgroundPicturePreviewDialog.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/BackgroundPicturePreviewDialog.java @@ -12,6 +12,7 @@ import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.powerbell.MainActivity; import cc.winboll.studio.powerbell.R; import cc.winboll.studio.powerbell.activities.BackgroundSettingsActivity; +import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils; import cc.winboll.studio.powerbell.utils.UriUtils; import cc.winboll.studio.powerbell.views.BackgroundView; @@ -142,7 +143,8 @@ public class BackgroundPicturePreviewDialog extends Dialog { } // 加载图片到预览视图 - mBackgroundView.loadImage(szSrcImage); + int nCurrentPixelColor = BackgroundSourceUtils.getInstance(mContext).getCurrentBackgroundBean().getPixelColor(); + mBackgroundView.loadImage(nCurrentPixelColor, szSrcImage, true); LogUtils.d(TAG, "【previewRecivedPicture】图片预览完成,文件路径:" + szSrcImage); } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/NetworkBackgroundDialog.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/NetworkBackgroundDialog.java index 7703abe..b90fd56 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/NetworkBackgroundDialog.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/NetworkBackgroundDialog.java @@ -107,7 +107,9 @@ public class NetworkBackgroundDialog extends AlertDialog { // 图片加载成功,获取文件路径并设置背景 mDownloadSavedPath = (String) msg.obj; LogUtils.d(TAG, String.format("handleMessage: 图片加载成功,保存路径:%s", mDownloadSavedPath)); - mBackgroundView.loadImage(mDownloadSavedPath); + int nCurrentPixelColor = BackgroundSourceUtils.getInstance(mContext).getCurrentBackgroundBean().getPixelColor(); + + mBackgroundView.loadImage(nCurrentPixelColor, mDownloadSavedPath, true); break; case MSG_IMAGE_LOAD_FAILED: // 图片加载失败,设置默认背景 diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTest2Activity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTest2Activity.java index b6bb989..7e583d3 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTest2Activity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTest2Activity.java @@ -14,6 +14,7 @@ import cc.winboll.studio.libappbase.ToastUtils; import cc.winboll.studio.powerbell.MainActivity; import cc.winboll.studio.powerbell.R; import cc.winboll.studio.powerbell.models.BackgroundBean; +import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils; import cc.winboll.studio.powerbell.utils.FileUtils; import cc.winboll.studio.powerbell.utils.ImageCropUtils; import cc.winboll.studio.powerbell.utils.ImageUtils; @@ -104,7 +105,8 @@ public class MainUnitTest2Activity extends AppCompatActivity { mllBackgroundView = (LinearLayout) findViewById(R.id.ll_backgroundview); // 创建MemoryCachedBackgroundView单例并添加到布局 - mMemoryCachedBackgroundView = MemoryCachedBackgroundView.getInstance(this, "", false); + int nCurrentPixelColor = BackgroundSourceUtils.getInstance(this).getCurrentBackgroundBean().getPixelColor(); + mMemoryCachedBackgroundView = MemoryCachedBackgroundView.getInstance(this, nCurrentPixelColor, "", false); mllBackgroundView.addView(mMemoryCachedBackgroundView); LogUtils.d(TAG, "initViewAndEvent:内存缓存背景视图实例创建并添加完成"); @@ -217,7 +219,8 @@ public class MainUnitTest2Activity extends AppCompatActivity { LogUtils.d(TAG, String.format("handleCropResult:裁剪回调处理 | resultCode=%d", resultCode)); if (resultCode == RESULT_OK) { if (isFileValid(mPrivateCropImageFile)) { - mMemoryCachedBackgroundView.loadImage(mPrivateCropImageFile.getAbsolutePath()); + int nCurrentPixelColor = BackgroundSourceUtils.getInstance(this).getCurrentBackgroundBean().getPixelColor(); + mMemoryCachedBackgroundView.loadImage(nCurrentPixelColor, mPrivateCropImageFile.getAbsolutePath(), true); LogUtils.d(TAG, String.format("handleCropResult:裁剪成功 | 加载裁剪图=%s", mPrivateCropImageFile.getAbsolutePath())); ToastUtils.show("裁剪成功"); mPreviewBackgroundBean.setIsUseBackgroundScaledCompressFile(true); diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTestActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTestActivity.java index f32e10e..c66817f 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTestActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTestActivity.java @@ -207,25 +207,25 @@ public class MainUnitTestActivity extends AppCompatActivity { * @param resultCode 裁剪结果码 */ private void handleCropResult(int resultCode) { - LogUtils.d(TAG, String.format("handleCropResult:裁剪回调处理 | resultCode=%d", resultCode)); - if (resultCode == RESULT_OK) { - if (isFileValid(mPrivateCropImageFile)) { - mBackgroundView.loadImage(mPrivateCropImageFile.getAbsolutePath()); - LogUtils.d(TAG, String.format("handleCropResult:裁剪成功 | 加载裁剪图=%s", mPrivateCropImageFile.getAbsolutePath())); - ToastUtils.show("裁剪成功"); - mPreviewBackgroundBean.setIsUseBackgroundScaledCompressFile(true); - doubleRefreshPreview(); - } else { - LogUtils.e(TAG, "handleCropResult:裁剪成功但输出文件无效"); - ToastUtils.show("裁剪失败:输出文件无效"); - } - } else if (resultCode == RESULT_CANCELED) { - LogUtils.d(TAG, "handleCropResult:裁剪取消"); - ToastUtils.show("裁剪已取消"); - } else { - LogUtils.e(TAG, String.format("handleCropResult:裁剪失败 | resultCode异常=%d", resultCode)); - ToastUtils.show("裁剪失败"); - } +// LogUtils.d(TAG, String.format("handleCropResult:裁剪回调处理 | resultCode=%d", resultCode)); +// if (resultCode == RESULT_OK) { +// if (isFileValid(mPrivateCropImageFile)) { +// mBackgroundView.loadImage(mPrivateCropImageFile.getAbsolutePath()); +// LogUtils.d(TAG, String.format("handleCropResult:裁剪成功 | 加载裁剪图=%s", mPrivateCropImageFile.getAbsolutePath())); +// ToastUtils.show("裁剪成功"); +// mPreviewBackgroundBean.setIsUseBackgroundScaledCompressFile(true); +// doubleRefreshPreview(); +// } else { +// LogUtils.e(TAG, "handleCropResult:裁剪成功但输出文件无效"); +// ToastUtils.show("裁剪失败:输出文件无效"); +// } +// } else if (resultCode == RESULT_CANCELED) { +// LogUtils.d(TAG, "handleCropResult:裁剪取消"); +// ToastUtils.show("裁剪已取消"); +// } else { +// LogUtils.e(TAG, String.format("handleCropResult:裁剪失败 | resultCode异常=%d", resultCode)); +// ToastUtils.show("裁剪失败"); +// } } /** diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/ImageUtils.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/ImageUtils.java index 5230434..c7d9f2b 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/ImageUtils.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/ImageUtils.java @@ -4,7 +4,11 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Paint; +import android.view.ViewGroup; +import android.widget.LinearLayout; import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.powerbell.R; import java.io.File; @@ -22,7 +26,7 @@ import java.io.OutputStream; */ public class ImageUtils { // ================================== 静态常量区(置顶归类,消除魔法值)================================= - public static final String TAG = ImageUtils.class.getSimpleName(); + public static final String TAG = "ImageUtils"; private static final Bitmap.CompressFormat COMPRESS_FORMAT = Bitmap.CompressFormat.JPEG; private static final int MIN_COMPRESS_QUALITY = 0; private static final int MAX_COMPRESS_QUALITY = 100; @@ -60,6 +64,75 @@ public class ImageUtils { } } + public static Bitmap drawBitmapOnSolidBackground(final int bgColor, int originalFrameW, int originalFrameH, Bitmap fgBitmap) { + // 1. 严格参数校验 + if (fgBitmap == null || fgBitmap.isRecycled()) { + LogUtils.e(TAG, "【drawBitmapOnSolidBackground】参数异常:前景Bitmap为空或已回收"); + return null; + } + if (fgBitmap.getWidth() <= 0 || fgBitmap.getHeight() <= 0) { + LogUtils.e(TAG, "【drawBitmapOnSolidBackground】参数异常:前景Bitmap尺寸无效"); + return null; + } + if (originalFrameW <= 0 || originalFrameH <= 0) { + LogUtils.e(TAG, "【drawBitmapOnSolidBackground】参数异常:原画框尺寸无效(宽高必须大于0)"); + return null; + } + + // 计算原画框宽高比(核心:返回位图尺寸严格为originalFrameW×originalFrameH,比例自然一致) + float frameRatio = (float) originalFrameW / originalFrameH; + LogUtils.d(TAG, String.format("【drawBitmapOnSolidBackground】原画框目标尺寸=%dx%d | 画框比例=%.2f", + originalFrameW, originalFrameH, frameRatio)); + + // 3. 核心逻辑:强制画布尺寸为originalFrameW×originalFrameH(满足需求) + int extendedCanvasW = originalFrameW; + int extendedCanvasH = originalFrameH; + LogUtils.d(TAG, String.format("【drawBitmapOnSolidBackground】画布尺寸(强制目标尺寸)=%dx%d | 实际比例=%.2f(与画框一致)", + extendedCanvasW, extendedCanvasH, (float) extendedCanvasW / extendedCanvasH)); + + // 4. 创建与目标尺寸完全一致的结果Bitmap(ARGB_8888 格式支持透明通道) + Bitmap resultBitmap = Bitmap.createBitmap(extendedCanvasW, extendedCanvasH, Bitmap.Config.ARGB_8888); + if (resultBitmap == null) { + LogUtils.e(TAG, "【drawBitmapOnSolidBackground】创建结果Bitmap失败"); + return null; + } + LogUtils.d(TAG, String.format("【drawBitmapOnSolidBackground】结果Bitmap尺寸=%dx%d | 比例=%.2f", + resultBitmap.getWidth(), resultBitmap.getHeight(), (float) resultBitmap.getWidth() / resultBitmap.getHeight())); + + // 5. 画布绘制:先画满纯色背景,再画带透明的居中前景 + Canvas canvas = new Canvas(resultBitmap); + try { + // 5.1 绘制纯色背景(填满整个目标尺寸画布) + canvas.drawRect(0, 0, extendedCanvasW, extendedCanvasH, new Paint() {{ + setColor(bgColor); + setStyle(Paint.Style.FILL); + }}); + LogUtils.d(TAG, "【drawBitmapOnSolidBackground】纯色背景绘制完成(填满目标尺寸)"); + + // 5.2 计算前景在目标画布内的居中位置 + float fgX = (extendedCanvasW - fgBitmap.getWidth()) / 2f; + float fgY = (extendedCanvasH - fgBitmap.getHeight()) / 2f; + + // 5.3 绘制前景位图(开启透明度支持,保留Alpha通道) +// Paint fgPaint = new Paint(); +// fgPaint.setAlpha(0); // 保持前景自身透明度(默认255,可根据需求调整) +// fgPaint.setAntiAlias(true); // 可选:抗锯齿,让边缘更平滑 +// fgPaint.setDither(true); // 可选:抖动,提升色彩显示效果 +// canvas.drawBitmap(fgBitmap, fgX, fgY, fgPaint); +// LogUtils.d(TAG, String.format("【drawBitmapOnSolidBackground】前景位图居中完成 | 位置=(%.1f,%.1f)", +// fgX, fgY)); +// + return resultBitmap; + } catch (Exception e) { + LogUtils.e(TAG, "【drawBitmapOnSolidBackground】合成失败", e); + if (resultBitmap != null && !resultBitmap.isRecycled()) { + resultBitmap.recycle(); + } + return null; + } + } + + // ================================== 核心工具方法(图片质量压缩)================================= /** * 图片质量压缩(JPEG格式),压缩后覆盖源文件 diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/BackgroundView.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/BackgroundView.java index 939cac7..c5d20d6 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/BackgroundView.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/BackgroundView.java @@ -9,6 +9,7 @@ import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; @@ -16,6 +17,7 @@ import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.ToastUtils; import cc.winboll.studio.powerbell.App; import cc.winboll.studio.powerbell.models.BackgroundBean; +import cc.winboll.studio.powerbell.utils.ImageUtils; import java.io.File; /** @@ -39,6 +41,10 @@ public class BackgroundView extends RelativeLayout { private ImageView mIvBackground; // 图片显示控件 // 图片属性 private float mImageAspectRatio = 1.0f; // 原图宽高比(宽/高) + // 当前图片背景 + private int mbgColor = 0xFFFFFFFF; + // 当前背景画框尺寸 + ViewGroup.LayoutParams mbgLayoutParams; // ====================================== 构造器(Java7兼容) ====================================== public BackgroundView(Context context) { @@ -72,7 +78,7 @@ public class BackgroundView extends RelativeLayout { // 3. 初始化ImageView initImageView(); // 4. 初始设置透明背景 - setDefaultTransparentBackground(); + setDefaultEmptyBackground(); LogUtils.d(TAG, "=== initView 完成 ==="); } @@ -86,7 +92,7 @@ public class BackgroundView extends RelativeLayout { mLlContainer.setLayoutParams(llParams); mLlContainer.setOrientation(LinearLayout.VERTICAL); mLlContainer.setGravity(android.view.Gravity.CENTER); - mLlContainer.setBackgroundColor(0x00000000); + //mLlContainer.setBackgroundColor(0x00000000); this.addView(mLlContainer); LogUtils.d(TAG, "=== initLinearLayout 完成 ==="); } @@ -95,12 +101,12 @@ public class BackgroundView extends RelativeLayout { LogUtils.d(TAG, "=== initImageView 启动 ==="); mIvBackground = new ImageView(mContext); LinearLayout.LayoutParams ivParams = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT ); mIvBackground.setLayoutParams(ivParams); mIvBackground.setScaleType(ImageView.ScaleType.FIT_CENTER); - mIvBackground.setBackgroundColor(0x00000000); + //mIvBackground.setBackgroundColor(0x00000000); mLlContainer.addView(mIvBackground); LogUtils.d(TAG, "=== initImageView 完成 ==="); } @@ -115,13 +121,17 @@ public class BackgroundView extends RelativeLayout { // 参数校验 if (bean == null) { LogUtils.e(TAG, "loadByBackgroundBean: BackgroundBean为空"); - setDefaultTransparentBackground(); + setDefaultEmptyBackground(); return; } + + // 设置图片背景 + mbgColor = bean.getPixelColor(); + // 判断是否使用背景文件 if (!bean.isUseBackgroundFile()) { LogUtils.d(TAG, "loadByBackgroundBean: 不使用背景文件,设置透明背景"); - setDefaultTransparentBackground(); + setDefaultEmptyBackground(); return; } // 获取目标路径 @@ -135,98 +145,140 @@ public class BackgroundView extends RelativeLayout { LogUtils.e(TAG, "loadByBackgroundBean: 视图控件图片不存在:" + targetPath); return; } + loadImage(mbgColor, targetPath, isRefresh); + } + + public void loadImage(int bgColor, String imagePath, boolean isRefresh) { + // 3. 隐藏ImageView防止闪烁 + mIvBackground.setVisibility(View.GONE); + // 计算画框尺寸 + //mbgLayoutParams = adjustImageViewSize(); + mbgLayoutParams = mLlContainer.getLayoutParams(); + // 刷新逻辑:重新解码原始品质图片并更新缓存 if (isRefresh) { LogUtils.d(TAG, "loadByBackgroundBean: 刷新图片,重新解码原始品质图片并更新缓存"); - Bitmap newBitmap = decodeOriginalBitmap(targetFile); - if (newBitmap != null) { - App.sBitmapCacheUtils.cacheBitmap(targetPath, newBitmap); - App.sBitmapCacheUtils.increaseRefCount(targetPath); - LogUtils.d(TAG, "loadByBackgroundBean: 刷新缓存成功,路径=" + targetPath); + Bitmap newBitmap = decodeOriginalBitmap(new File(imagePath)); + + // ======================== 核心集成:调用drawBitmapOnSolidBackground合成 ======================== + //Bitmap combinedBitmap = ImageUtils.drawBitmapOnSolidBackground(mbgColor, mbgLayoutParams.width, mbgLayoutParams.height, newBitmap); + Bitmap combinedBitmap = ImageUtils.drawBitmapOnSolidBackground(0xFF112233, mbgLayoutParams.width, mbgLayoutParams.height, newBitmap); + if (combinedBitmap == null) { + LogUtils.e(TAG, "loadImage: 纯色背景合成失败,使用原始Bitmap"); + combinedBitmap = newBitmap; + } else { + LogUtils.d(TAG, "loadImage: 纯色背景合成成功,尺寸与原始图一致"); + // 合成成功后,回收原始Bitmap(避免重复缓存) + if (newBitmap != null && !newBitmap.isRecycled() && newBitmap != combinedBitmap) { + newBitmap.recycle(); + LogUtils.d(TAG, "loadImage: 原始Bitmap已回收"); + } + } + // ======================== 合成逻辑结束 ======================== + if (combinedBitmap != null) { + App.sBitmapCacheUtils.clearAllCache(); + App.sBitmapCacheUtils.cacheBitmap(imagePath, combinedBitmap); + App.sBitmapCacheUtils.increaseRefCount(imagePath); + mCurrentCachedPath = imagePath; + LogUtils.d(TAG, "loadByBackgroundBean: 刷新缓存成功,路径=" + imagePath); } else { - LogUtils.e(TAG, "loadByBackgroundBean: 刷新解码失败,路径=" + targetPath); + LogUtils.e(TAG, "loadByBackgroundBean: 刷新解码失败,路径=" + imagePath); } } + // 加载图片 - loadImage(targetPath); - setBackgroundColor(bean.getPixelColor()); + Bitmap cachedBitmap = App.sBitmapCacheUtils.getCachedBitmap(imagePath); +// LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mIvBackground.getLayoutParams(); +// params.width = mbgLayoutParams.width; +// params.height = mbgLayoutParams.height; +// mIvBackground.setLayoutParams(params); +// LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( +// LinearLayout.LayoutParams.MATCH_PARENT, +// LinearLayout.LayoutParams.MATCH_PARENT +// ); + //mIvBackground.setLayoutParams(params); + mIvBackground.setImageBitmap(cachedBitmap); + mIvBackground.setScaleType(ImageView.ScaleType.FIT_CENTER); + mIvBackground.setVisibility(View.VISIBLE); LogUtils.d(TAG, "=== loadByBackgroundBean 完成 ==="); - } + } /** * 改进版:强制保持缓存策略,不自动清理任何缓存,强化引用计数管理,保留图片原始品质 * @param imagePath 图片绝对路径 */ - public void loadImage(String imagePath) { - LogUtils.d(TAG, "=== loadImage 启动,路径:" + imagePath + " ==="); - // 1. 路径空校验 - if (TextUtils.isEmpty(imagePath)) { - LogUtils.e(TAG, "loadImage: 图片路径为空"); - setDefaultTransparentBackground(); - return; - } - // 2. 文件有效性校验 - File imageFile = new File(imagePath); - if (!imageFile.exists() || !imageFile.isFile()) { - LogUtils.e(TAG, "loadImage: 图片文件无效"); - setDefaultTransparentBackground(); - return; - } - // 3. 隐藏ImageView防止闪烁 - mIvBackground.setVisibility(View.GONE); +// public void loadImage2(String imagePath) { +// LogUtils.d(TAG, "=== loadImage 启动,路径:" + imagePath + ",背景色:0x%08X ===", mbgColor); +// // 1. 路径空校验 +// if (TextUtils.isEmpty(imagePath)) { +// LogUtils.e(TAG, "loadImage: 图片路径为空"); +// setDefaultEmptyBackground(); +// return; +// } +// // 2. 文件有效性校验 +// File imageFile = new File(imagePath); +// if (!imageFile.exists() || !imageFile.isFile()) { +// LogUtils.e(TAG, "loadImage: 图片文件无效"); +// setDefaultEmptyBackground(); +// return; +// } +// +// // ======================== 路径判断逻辑(强制缓存版) ======================== +// // 3.1 路径未变化:校验缓存有效性(缓存的是合成后的Bitmap) +// if (imagePath.equals(mCurrentCachedPath)) { +// Bitmap cachedBitmap = App.sBitmapCacheUtils.getCachedBitmap(imagePath); +// if (isBitmapValid(cachedBitmap)) { +// LogUtils.d(TAG, "loadImage: 路径未变,使用有效缓存Bitmap(合成后品质)"); +// mImageAspectRatio = (float) cachedBitmap.getWidth() / cachedBitmap.getHeight(); +// mIvBackground.setImageBitmap(cachedBitmap); +// mIvBackground.setVisibility(View.VISIBLE); +// LogUtils.d(TAG, "=== loadImage 完成(缓存命中) ==="); +// return; +// } else { +// LogUtils.e(TAG, "loadImage: 缓存Bitmap无效,尝试重加载并合成"); +// } +// } +// // 3.2 路径已更新:保留旧缓存,仅更新路径记录 +// if (!TextUtils.isEmpty(mCurrentCachedPath) && !mCurrentCachedPath.equals(imagePath)) { +// LogUtils.d(TAG, "loadImage: 路径已更新,保留旧缓存,原路径=" + mCurrentCachedPath + ",新路径=" + imagePath); +// } +// // ======================== 路径判断逻辑结束 ======================== +// +// // 4. 计算图片宽高比(原始图片) +// if (!calculateImageAspectRatio(imageFile)) { +// setDefaultEmptyBackground(); +// return; +// } +// +// +// // 5. 获取或解码Bitmap(原始图) +// Bitmap originalBitmap = App.sBitmapCacheUtils.getCachedBitmap(imagePath); +// if (isBitmapValid(originalBitmap)) { +// LogUtils.d(TAG, "loadImage: 从缓存获取原始Bitmap,准备合成"); +// } else { +// LogUtils.d(TAG, "loadImage: 缓存未命中,解码原始品质图片"); +// originalBitmap = decodeOriginalBitmap(imageFile); +// if (originalBitmap == null) { +// LogUtils.e(TAG, "loadImage: 图片解码失败(原始品质)"); +// ToastUtils.show("图片解码失败,无法加载"); +// setDefaultEmptyBackground(); +// return; +// } +// } +// +// // 6. 缓存合成后的Bitmap(替换原始图缓存) +//// App.sBitmapCacheUtils.cacheBitmap(imagePath, originalBitmap); +//// LogUtils.d(TAG, "loadImage: 合成后图片缓存成功,路径=" + imagePath); +//// // 7. 引用计数管理 +//// App.sBitmapCacheUtils.increaseRefCount(imagePath); +// // 8. 更新当前缓存路径 +// mCurrentCachedPath = imagePath; +// // 9. 设置图片并调整尺寸 +// //mIvBackground.setImageBitmap(originalBitmap); +// +// LogUtils.d(TAG, "=== loadImage 完成(合成后加载) ==="); +// } - // ======================== 路径判断逻辑(强制缓存版) ======================== - // 3.1 路径未变化:校验缓存有效性 - if (imagePath.equals(mCurrentCachedPath)) { - Bitmap cachedBitmap = App.sBitmapCacheUtils.getCachedBitmap(imagePath); - if (isBitmapValid(cachedBitmap)) { - LogUtils.d(TAG, "loadImage: 路径未变,使用有效缓存Bitmap(原始品质)"); - mImageAspectRatio = (float) cachedBitmap.getWidth() / cachedBitmap.getHeight(); - mIvBackground.setImageBitmap(cachedBitmap); - adjustImageViewSize(); - LogUtils.d(TAG, "=== loadImage 完成(缓存命中) ==="); - return; - } else { - LogUtils.e(TAG, "loadImage: 缓存Bitmap无效,尝试重加载原始品质图片"); - } - } - // 3.2 路径已更新:保留旧缓存,仅更新路径记录 - if (!TextUtils.isEmpty(mCurrentCachedPath) && !mCurrentCachedPath.equals(imagePath)) { - LogUtils.d(TAG, "loadImage: 路径已更新,保留旧缓存,原路径=" + mCurrentCachedPath + ",新路径=" + imagePath); - } - // ======================== 路径判断逻辑结束 ======================== - - // 4. 计算图片宽高比 - if (!calculateImageAspectRatio(imageFile)) { - setDefaultTransparentBackground(); - return; - } - // 5. 获取或解码Bitmap - Bitmap bitmap = App.sBitmapCacheUtils.getCachedBitmap(imagePath); - if (isBitmapValid(bitmap)) { - LogUtils.d(TAG, "loadImage: 从缓存获取有效Bitmap(原始品质)"); - } else { - LogUtils.d(TAG, "loadImage: 缓存未命中,解码原始品质图片"); - bitmap = decodeOriginalBitmap(imageFile); - if (bitmap == null) { - LogUtils.e(TAG, "loadImage: 图片解码失败(原始品质)"); - ToastUtils.show("图片解码失败,无法加载"); - setDefaultTransparentBackground(); - return; - } - // 缓存新图片 - App.sBitmapCacheUtils.cacheBitmap(imagePath, bitmap); - LogUtils.d(TAG, "loadImage: 新图片缓存成功,路径=" + imagePath); - } - // 6. 引用计数管理 - App.sBitmapCacheUtils.increaseRefCount(imagePath); - // 7. 更新当前缓存路径 - mCurrentCachedPath = imagePath; - // 8. 设置图片并调整尺寸 - mIvBackground.setImageBitmap(bitmap); - adjustImageViewSize(); - LogUtils.d(TAG, "=== loadImage 完成 ==="); - } // ====================================== 内部工具方法 ====================================== /** @@ -299,54 +351,55 @@ public class BackgroundView extends RelativeLayout { /** * 调整ImageView尺寸,保持原图比例 */ - private void adjustImageViewSize() { - LogUtils.d(TAG, "=== adjustImageViewSize 启动 ==="); - // 空指针校验 - if (mLlContainer == null || mIvBackground == null) { - LogUtils.e(TAG, "adjustImageViewSize: 容器或ImageView未初始化"); - return; - } - // 获取容器尺寸 - int llWidth = mLlContainer.getWidth(); - int llHeight = mLlContainer.getHeight(); - if (llWidth == 0 || llHeight == 0) { - LogUtils.w(TAG, "adjustImageViewSize: 容器尺寸未初始化,延迟调整"); - post(new Runnable() { - @Override - public void run() { - adjustImageViewSize(); - } - }); - return; - } - // 计算ImageView尺寸 - 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(ImageView.ScaleType.FIT_CENTER); - mIvBackground.setVisibility(View.VISIBLE); - LogUtils.d(TAG, "adjustImageViewSize: 尺寸调整完成,宽=" + ivWidth + ",高=" + ivHeight); - LogUtils.d(TAG, "=== adjustImageViewSize 完成 ==="); - } +// private LinearLayout.LayoutParams adjustImageViewSize() { +// LogUtils.d(TAG, "=== adjustImageViewSize 启动 ==="); +// // 空指针校验 +// if (mLlContainer == null || mIvBackground == null) { +// LogUtils.e(TAG, "adjustImageViewSize: 容器或ImageView未初始化"); +// return null; +// } +// // 获取容器尺寸 +// int llWidth = mLlContainer.getWidth(); +// int llHeight = mLlContainer.getHeight(); +// if (llWidth == 0 || llHeight == 0) { +// LogUtils.w(TAG, "adjustImageViewSize: 容器尺寸未初始化,延迟调整"); +// post(new Runnable() { +// @Override +// public void run() { +// adjustImageViewSize(); +// } +// }); +// return null; +// } +// // 计算ImageView尺寸 +// 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(ImageView.ScaleType.FIT_CENTER); +// mIvBackground.setVisibility(View.VISIBLE); +// LogUtils.d(TAG, "adjustImageViewSize: 尺寸调整完成,宽=" + ivWidth + ",高=" + ivHeight); +// LogUtils.d(TAG, "=== adjustImageViewSize 完成 ==="); +// return params; +// } /** * 设置默认透明背景,仅减少引用计数,不删除缓存 */ - private void setDefaultTransparentBackground() { + private void setDefaultEmptyBackground() { LogUtils.d(TAG, "=== setDefaultTransparentBackground 启动 ==="); // 清空ImageView mIvBackground.setImageDrawable(null); - mIvBackground.setBackgroundColor(0x00000000); + //mIvBackground.setBackgroundColor(mbgColor); mImageAspectRatio = 1.0f; // 减少引用计数,不删除缓存 if (!TextUtils.isEmpty(mCurrentCachedPath)) { @@ -401,7 +454,9 @@ public class BackgroundView extends RelativeLayout { protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); LogUtils.d(TAG, "onSizeChanged: 尺寸变化,宽=" + w + ",高=" + h + ",调整ImageView尺寸"); - adjustImageViewSize(); + //adjustImageViewSize(); +// mbgLayoutParams.width = mLlContainer.getWidth(); +// mbgLayoutParams.height = mLlContainer.getHeight(); } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MemoryCachedBackgroundView.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MemoryCachedBackgroundView.java index 0af5d7e..699c864 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MemoryCachedBackgroundView.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MemoryCachedBackgroundView.java @@ -6,6 +6,7 @@ import android.text.TextUtils; import android.util.AttributeSet; import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.powerbell.models.BackgroundBean; +import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils; /** * 单实例缓存版背景视图控件(基于Java7)- 强制缓存版 @@ -56,7 +57,7 @@ public class MemoryCachedBackgroundView extends BackgroundView { * @param isReload 是否强制重新加载图片(路径匹配时仍刷新) * @return 缓存/新创建的MemoryCachedBackgroundView实例 */ - public static MemoryCachedBackgroundView getInstance(Context context, String imagePath, boolean isReload) { + public static MemoryCachedBackgroundView getInstance(Context context, int bgColor, String imagePath, boolean isReload) { LogUtils.d(TAG, "【getInstance】调用 | 图片路径:" + imagePath + " | 是否重载:" + isReload); // 空路径校验 if (TextUtils.isEmpty(imagePath)) { @@ -69,7 +70,7 @@ public class MemoryCachedBackgroundView extends BackgroundView { LogUtils.d(TAG, "【getInstance】路径已缓存,当前缓存实例有效"); if (isReload) { LogUtils.d(TAG, "【getInstance】强制重载图片 | 路径:" + imagePath); - sCachedView.loadImage(imagePath); + sCachedView.loadImage(bgColor, imagePath, isReload); } else { LogUtils.d(TAG, "【getInstance】使用缓存实例,无需重载 | 路径:" + imagePath); } @@ -81,7 +82,7 @@ public class MemoryCachedBackgroundView extends BackgroundView { String oldPath = sCachedImagePath; sCachedView = new MemoryCachedBackgroundView(context); sCachedImagePath = imagePath; - sCachedView.loadImage(imagePath); + sCachedView.loadImage(bgColor, imagePath, isReload); LogUtils.d(TAG, "【getInstance】已更新当前缓存实例,旧实例路径:" + oldPath + "(强制保持)"); return sCachedView; } @@ -113,7 +114,8 @@ public class MemoryCachedBackgroundView extends BackgroundView { String oldPath = sCachedImagePath; sCachedView = new MemoryCachedBackgroundView(context); sCachedImagePath = lastPath; - sCachedView.loadImage(lastPath); + int nCurrentPixelColor = BackgroundSourceUtils.getInstance(context).getCurrentBackgroundBean().getPixelColor(); + sCachedView.loadImage(nCurrentPixelColor, sCachedImagePath, false); LogUtils.d(TAG, "【getLastInstance】已更新最后路径实例,旧实例路径:" + oldPath + "(强制保持)"); return sCachedView; } @@ -211,13 +213,13 @@ public class MemoryCachedBackgroundView extends BackgroundView { } // ====================================== 重写父类方法:增强日志+SP持久化(强制保持版) ====================================== - @Override - public void loadImage(String imagePath) { - LogUtils.d(TAG, "【loadImage】调用 | 图片路径:" + imagePath); - super.loadImage(imagePath); - // 保存最后加载路径到SP(强制保持,不自动删除) - saveLastLoadImagePath(getContext(), imagePath); - } +// @Override +// public void loadImage(String imagePath) { +// LogUtils.d(TAG, "【loadImage】调用 | 图片路径:" + imagePath); +// super.loadImage(imagePath); +// // 保存最后加载路径到SP(强制保持,不自动删除) +// saveLastLoadImagePath(getContext(), imagePath); +// } @Override public void loadByBackgroundBean(BackgroundBean bean) {