From ed660aa4efb589ec42f475fd38d0e9ec3ef929a6 Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Mon, 1 Dec 2025 17:46:43 +0800 Subject: [PATCH] 20251201_174639_788 --- powerbell/build.properties | 4 +- .../powerbell/views/BackgroundView.java | 156 +++++++++--------- 2 files changed, 83 insertions(+), 77 deletions(-) diff --git a/powerbell/build.properties b/powerbell/build.properties index aea26bbb..f361f4eb 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Mon Dec 01 09:33:34 GMT 2025 +#Mon Dec 01 09:45:38 GMT 2025 stageCount=13 libraryProject= baseVersion=15.11 publishVersion=15.11.12 -buildCount=59 +buildCount=60 baseBetaVersion=15.11.13 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 f7503d5b..05c03a52 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 @@ -20,7 +20,7 @@ import androidx.annotation.Nullable; /** * @Author ZhanGSKen&豆包大模型 * @Date 2025/11/19 18:01 - * @Describe 背景图片视图控件(全透明背景 + 不拉伸居中平铺 + 完全填充父视图 + 预览/正式模式切换) + * @Describe 背景图片视图控件(全透明背景 + 保持比例扩展 + 完全填充父视图 + 预览/正式模式切换) */ public class BackgroundView extends RelativeLayout { @@ -30,7 +30,7 @@ public class BackgroundView extends RelativeLayout { private ImageView ivBackground; private BackgroundSourceUtils backgroundSourceUtils; // 工具类实例(避免重复创建) - private float imageAspectRatio = 1.0f; // 图片原始宽高比(控制不拉伸) + private float imageAspectRatio = 1.0f; // 图片原始宽高比(控制不拉伸的核心) // 标记当前是否处于预览模式(用于区分加载预览/正式背景) private boolean isPreviewMode = false; @@ -72,7 +72,7 @@ public class BackgroundView extends RelativeLayout { // 初始化工具类(单例,全局唯一) backgroundSourceUtils = BackgroundSourceUtils.getInstance(mContext); - // 2. 初始化内部ImageView(核心:不拉伸+居中平铺+全透明) + // 2. 初始化内部ImageView(核心:保持比例+居中+全透明) initBackgroundImageView(); // 3. 初始加载:默认加载正式背景 @@ -91,7 +91,7 @@ public class BackgroundView extends RelativeLayout { layoutParams.setMargins(0, 0, 0, 0); // 取消边距(避免ImageView与控件间缝隙) ivBackground.setLayoutParams(layoutParams); - // 关键配置:缩放模式FIT_CENTER(不拉伸,按原始比例显示) + // 关键配置:缩放模式FIT_CENTER(保持比例,完整显示图片),与正式模式统一 ivBackground.setScaleType(ImageView.ScaleType.FIT_CENTER); ivBackground.setPadding(0, 0, 0, 0); // 取消内部padding(避免图片与ImageView间缝隙) ivBackground.setBackgroundColor(0x00000000); // ImageView背景全透明 @@ -113,16 +113,16 @@ public class BackgroundView extends RelativeLayout { isPreviewMode = false; // 标记为正式模式 // 从工具类获取最新正式背景路径(确保路径同步) String backgroundPath = backgroundSourceUtils.getCurrentBackgroundFilePath(); - // 加载并显示图片 + // 加载并显示图片(复用正式模式的比例计算逻辑) loadAndSetImageViewBackground(backgroundPath); } /** - * 重新加载预览背景(修复:强制读取预览Bean最新路径+多重有效性校验) + * 重新加载预览背景(修复:复用比例计算逻辑+保持图片原始比例) * 作用:控件加载图片时,优先用压缩图路径,失败则用原图路径,均失败则显示默认图 */ public void reloadPreviewBackground() { - LogUtils.d(TAG, "=== 开始加载预览背景(路径校验版)==="); + LogUtils.d(TAG, "=== 开始加载预览背景(比例适配版)==="); // 关键:直接从工具类获取预览Bean最新路径(避免使用缓存路径) BackgroundSourceUtils bgSourceUtils = BackgroundSourceUtils.getInstance(getContext()); BackgroundBean previewBean = bgSourceUtils.getPreviewBackgroundBean(); @@ -136,7 +136,8 @@ public class BackgroundView extends RelativeLayout { String compressPath = previewBean.getBackgroundScaledCompressFilePath(); File compressFile = checkFileValidity(compressPath); // 校验文件有效性 if (compressFile != null) { - loadBitmapAndDisplay(compressPath, "压缩图"); + // 修复:调用带文件的加载方法(复用比例计算逻辑) + loadPreviewImageByFile(compressFile, "压缩图"); return; } @@ -145,7 +146,7 @@ public class BackgroundView extends RelativeLayout { String originalPath = previewBean.getBackgroundFilePath(); File originalFile = checkFileValidity(originalPath); if (originalFile != null) { - loadBitmapAndDisplay(originalPath, "原图"); + loadPreviewImageByFile(originalFile, "原图"); return; } @@ -154,6 +155,40 @@ public class BackgroundView extends RelativeLayout { setDefaultBackground(); } + /** + * 新增:预览模式加载图片(按文件加载,复用比例计算逻辑) + * 核心:计算图片原始宽高比,确保ImageView按比例扩展到父控件 + */ + private void loadPreviewImageByFile(File imageFile, String imageType) { + LogUtils.d(TAG, "【" + imageType + "加载】开始加载:" + imageFile.getAbsolutePath()); + isPreviewMode = true; // 标记为预览模式 + + // 1. 计算图片原始宽高比(核心:保持比例的关键) + if (!calculateImageAspectRatio(imageFile)) { + LogUtils.e(TAG, "【" + imageType + "加载失败】图片尺寸无效"); + setDefaultBackground(); + return; + } + + // 2. 压缩加载Bitmap(避免OOM,保持原始比例) + Bitmap bitmap = decodeBitmapWithCompress(imageFile, 1080, 1920); + if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) { + LogUtils.e(TAG, "【" + imageType + "加载失败】Bitmap无效(空/宽高为0)"); + setDefaultBackground(); + return; + } + + // 2. 配置ImageView(保持比例,与正式模式一致) + ivBackground.setScaleType(ScaleType.FIT_CENTER); // 修复:取消CENTER_CROP,用FIT_CENTER保持比例 + ivBackground.setBackgroundColor(0x00000000); // 确保背景透明,不覆盖图片 + ivBackground.setImageBitmap(bitmap); // 设置图片 + + // 3. 调整ImageView尺寸(按原始比例扩展到父控件) + adjustImageViewSize(); + + LogUtils.d(TAG, "【" + imageType + "加载成功】宽高:" + bitmap.getWidth() + "x" + bitmap.getHeight() + ",宽高比:" + imageAspectRatio); + } + /** * 新增:校验文件有效性(路径非空+文件存在+是文件+大小>100bytes) * @param filePath 待校验的图片路径 @@ -183,61 +218,18 @@ public class BackgroundView extends RelativeLayout { } /** - * 新增:加载Bitmap并显示(统一处理Bitmap有效性) - * @param imagePath 图片路径 - * @param imageType 图片类型(压缩图/原图,用于日志区分) - */ - private void loadBitmapAndDisplay(String imagePath, String imageType) { - Bitmap bitmap = BitmapFactory.decodeFile(imagePath); - // 校验Bitmap有效性(避免宽高为0的无效Bitmap) - if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) { - LogUtils.e(TAG, "【" + imageType + "加载失败】Bitmap无效(空/宽高为0)"); - setDefaultBackground(); - return; - } - - // 强制设置ScaleType(避免因缩放导致图片显示异常) - ivBackground.setScaleType(ScaleType.CENTER_CROP); - // 移除默认背景色(避免白色覆盖图片) - setBackgroundColor(getResources().getColor(android.R.color.transparent)); - // 显示图片并调整尺寸(复用原有调整逻辑) - ivBackground.setImageBitmap(bitmap); - adjustImageViewSize(bitmap); // 复用项目中原有尺寸调整方法 - LogUtils.d(TAG, "【" + imageType + "加载成功】宽高:" + bitmap.getWidth() + "x" + bitmap.getHeight()); - } - - /** - * 兜底:无默认图片时,用代码生成透明/纯色背景(避免报错) + * 兜底:无默认图片时,用代码生成透明背景(避免白色/拉伸) */ private void setDefaultBackground() { - ivBackground.setScaleType(ScaleType.CENTER_CROP); - // 方案1:生成透明背景(推荐,避免白色) - ivBackground.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - // 或 方案2:生成白色背景(根据界面需求选择) - // ivBackground.setBackgroundColor(getResources().getColor(android.R.color.white)); - // 或 方案3:生成灰色背景(更友好,避免纯白/纯黑突兀) - // ivBackground.setBackgroundColor(getResources().getColor(android.R.color.darker_gray)); - - // 可选:设置一个空的Bitmap,避免ImageView显示空白 - Bitmap emptyBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); - ivBackground.setImageBitmap(emptyBitmap); - LogUtils.d(TAG, "【默认背景】使用代码生成透明背景(无图片资源)"); + isPreviewMode = true; + ivBackground.setScaleType(ScaleType.FIT_CENTER); + ivBackground.setBackgroundColor(0x00000000); // 全透明背景 + ivBackground.setImageBitmap(null); // 清空图片,避免残留 + imageAspectRatio = 1.0f; // 重置宽高比 + adjustImageViewSize(); // 调整尺寸,确保居中 + LogUtils.d(TAG, "【默认背景】使用透明背景(无图片资源)"); } -// 复用原有尺寸调整方法(若项目中已存在,无需重复添加) - private void adjustImageViewSize(Bitmap bitmap) { - // 此处保留项目中原有逻辑(如根据控件尺寸缩放图片等) - // 示例逻辑(仅供参考): - int viewWidth = getWidth(); - int viewHeight = getHeight(); - if (viewWidth > 0 && viewHeight > 0 && bitmap != null) { - // 计算缩放比例,适配控件尺寸 - float scale = Math.min((float) viewWidth / bitmap.getWidth(), (float) viewHeight / bitmap.getHeight()); - // 后续尺寸调整逻辑... - } - } - - /** * 【对外提供】预览指定路径的临时图片(直接传入路径,不依赖Bean) * 用于:临时预览本地图片、测试图片等场景 @@ -246,7 +238,7 @@ public class BackgroundView extends RelativeLayout { public void previewBackgroundImage(String previewImagePath) { LogUtils.d(TAG, "=== 开始预览指定路径图片 ==="); isPreviewMode = true; // 标记为预览模式 - // 加载并显示指定路径图片 + // 加载并显示指定路径图片(复用正式模式的比例计算逻辑) loadAndSetImageViewBackground(previewImagePath); } @@ -293,7 +285,7 @@ public class BackgroundView extends RelativeLayout { ivBackground.setBackgroundDrawable(backgroundDrawable); } - // 6. 调整ImageView尺寸(居中平铺,适配控件大小) + // 6. 调整ImageView尺寸(按比例扩展到父控件,居中平铺) adjustImageViewSize(); LogUtils.d(TAG, "图片加载成功(" + (isPreviewMode ? "预览模式" : "正式模式") + ")"); @@ -336,8 +328,9 @@ public class BackgroundView extends RelativeLayout { return false; } - // 保存原始宽高比 + // 保存原始宽高比(预览/正式模式共用) imageAspectRatio = (float) imageWidth / imageHeight; + LogUtils.d(TAG, "图片宽高比计算完成:" + imageAspectRatio + "(宽:" + imageWidth + ",高:" + imageHeight + ")"); return true; } catch (Exception e) { LogUtils.e(TAG, "计算图片宽高比失败:" + e.getMessage(), e); @@ -346,8 +339,8 @@ public class BackgroundView extends RelativeLayout { } /** - * 调整ImageView尺寸(核心:不拉伸,居中平铺,适配控件大小) - * 效果:ImageView按图片比例缩放,最大尺寸不超过控件,同时在控件中居中 + * 调整ImageView尺寸(核心修复:按原始比例扩展到父控件,不拉伸、不裁剪) + * 效果:ImageView按图片比例缩放,最大尺寸填满父控件,同时保持居中 */ private void adjustImageViewSize() { int parentWidth = getWidth(); // 控件宽度(已完全填充父视图) @@ -361,18 +354,28 @@ public class BackgroundView extends RelativeLayout { adjustImageViewSize(); } }); - //LogUtils.d(TAG, "父容器未测量完成,延迟调整ImageView尺寸"); + LogUtils.d(TAG, "父容器未测量完成,延迟调整ImageView尺寸"); return; } int imageViewWidth, imageViewHeight; - // 按图片原始比例,计算ImageView最大可行尺寸(不超过控件,不拉伸) - if (imageAspectRatio >= 1.0f) { // 横图(宽 ≥ 高):优先适配控件宽度 - imageViewWidth = Math.min(parentWidth, (int) (parentHeight * imageAspectRatio)); - imageViewHeight = (int) (imageViewWidth / imageAspectRatio); - } else { // 竖图(宽 < 高):优先适配控件高度 - imageViewHeight = Math.min(parentHeight, (int) (parentWidth / imageAspectRatio)); - imageViewWidth = (int) (imageViewHeight * imageAspectRatio); + // 核心逻辑:按图片原始比例,计算ImageView最大尺寸(填满父控件,不拉伸) + if (imageAspectRatio >= 1.0f) { // 横图(宽 ≥ 高):优先填满父控件宽度,高度按比例计算 + imageViewWidth = parentWidth; // 宽度=父控件宽度(填满) + imageViewHeight = Math.round(imageViewWidth / imageAspectRatio); // 高度按比例计算 + // 若高度超过父控件,按父控件高度重新计算(确保完全显示在父控件内) + if (imageViewHeight > parentHeight) { + imageViewHeight = parentHeight; + imageViewWidth = Math.round(imageViewHeight * imageAspectRatio); + } + } else { // 竖图(宽 < 高):优先填满父控件高度,宽度按比例计算 + imageViewHeight = parentHeight; // 高度=父控件高度(填满) + imageViewWidth = Math.round(imageViewHeight * imageAspectRatio); // 宽度按比例计算 + // 若宽度超过父控件,按父控件宽度重新计算 + if (imageViewWidth > parentWidth) { + imageViewWidth = parentWidth; + imageViewHeight = Math.round(imageViewWidth / imageAspectRatio); + } } // 应用尺寸到ImageView(更新布局参数) @@ -381,7 +384,9 @@ public class BackgroundView extends RelativeLayout { layoutParams.height = imageViewHeight; ivBackground.setLayoutParams(layoutParams); - LogUtils.d(TAG, "ImageView尺寸调整完成:宽=" + imageViewWidth + ", 高=" + imageViewHeight + "(控件尺寸:" + parentWidth + "x" + parentHeight + ")"); + LogUtils.d(TAG, "ImageView尺寸调整完成(" + (isPreviewMode ? "预览模式" : "正式模式") + "):"); + LogUtils.d(TAG, "→ 控件尺寸:" + parentWidth + "x" + parentHeight); + LogUtils.d(TAG, "→ ImageView尺寸:" + imageViewWidth + "x" + imageViewHeight + "(宽高比:" + imageAspectRatio + ")"); } /** @@ -422,6 +427,7 @@ public class BackgroundView extends RelativeLayout { */ private void setDefaultTransparentBackground() { ivBackground.setBackground(new ColorDrawable(0x00000000)); // 全透明背景 + ivBackground.setImageBitmap(null); // 清空图片 imageAspectRatio = 1.0f; // 重置宽高比(避免影响下次加载) adjustImageViewSize(); // 调整尺寸(确保ImageView居中且不占位异常) LogUtils.d(TAG, "已设置默认透明背景"); @@ -429,7 +435,7 @@ public class BackgroundView extends RelativeLayout { /** * 父容器尺寸变化时(如屏幕旋转),重新调整ImageView尺寸 - * 确保:控件尺寸变化后,图片仍保持不拉伸+居中平铺 + * 确保:控件尺寸变化后,图片仍保持比例+填满父控件 */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {