20251204_051841_861

This commit is contained in:
2025-12-04 05:18:46 +08:00
parent 8a16728609
commit c930308425
6 changed files with 175 additions and 279 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Wed Dec 03 18:54:44 GMT 2025
#Wed Dec 03 21:14:37 GMT 2025
stageCount=13
libraryProject=
baseVersion=15.11
publishVersion=15.11.12
buildCount=178
buildCount=180
baseBetaVersion=15.11.13

View File

@@ -794,7 +794,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
previewBean.setIsUseBackgroundFile(true);
previewBean.setIsUseBackgroundScaledCompressFile(true);
mBgSourceUtils.saveSettings();
mBackgroundView.loadBackground(previewBean);
mBackgroundView.loadBackgroundBean(previewBean);
LogUtils.d(TAG, "isCropSuccess == true && mBackgroundView.loadBackground");
} else {
// 其他失败场景
@@ -889,7 +889,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
// 1. 立即刷新(第一重:优先加载最新图片)
if (mBackgroundView != null && !isFinishing()) {
mBackgroundView.loadBackground(mBgSourceUtils.getPreviewBackgroundBean());
mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean());
LogUtils.d(TAG, "【双重刷新】第一重刷新完成(立即执行)");
} else {
LogUtils.w(TAG, "【双重刷新】第一重刷新跳过:预览控件为空或页面即将销毁");
@@ -902,7 +902,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
public void run() {
// 校验:页面未销毁+控件有效,才执行二次刷新
if (mBackgroundView != null && !isFinishing()) {
mBackgroundView.loadBackground(mBgSourceUtils.getPreviewBackgroundBean());
mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean());
LogUtils.d(TAG, "【双重刷新】第二重刷新完成延迟50ms执行");
} else {
LogUtils.w(TAG, "【双重刷新】第二重刷新跳过:页面已销毁或控件无效");

View File

@@ -207,7 +207,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
mPreviewFilePath = previewFilePath;
BackgroundSourceUtils utils = BackgroundSourceUtils.getInstance(mContext);
utils.saveFileToPreviewBean(new File(mPreviewFilePath), mPreviewFileUrl);
mBackgroundView.loadBackground(utils.getPreviewBackgroundBean());
mBackgroundView.loadBackgroundBean(utils.getPreviewBackgroundBean());
} catch (Exception e) {
e.printStackTrace();
mBackgroundView.setBackgroundResource(R.drawable.ic_launcher);

View File

@@ -150,7 +150,7 @@ public class MainViewFragment extends Fragment {
void loadBackground() {
BackgroundBean bean = mBgSourceUtils.getCurrentBackgroundBean();
mBackgroundView.loadBackground(bean);
mBackgroundView.loadBackgroundBean(bean);
}
@Override
@@ -324,7 +324,7 @@ public class MainViewFragment extends Fragment {
BackgroundSourceUtils utils = BackgroundSourceUtils.getInstance(getActivity());
mBgSourceUtils.loadSettings();
BackgroundBean bean = utils.getCurrentBackgroundBean();
mBackgroundView.loadBackground(bean);
mBackgroundView.loadBackgroundBean(bean);
}
Handler mHandler = new Handler(){

View File

@@ -60,8 +60,6 @@ public class BackgroundViewTestFragment extends Fragment {
void loadBackground() {
mBgSourceUtils.loadSettings();
BackgroundBean bean = mBgSourceUtils.getCurrentBackgroundBean();
mBackgroundView.loadBackground(bean);
mBackgroundView.loadImage("/storage/emulated/0/Pictures/Gallery/owner/素材/1626915857361.png");
}
}

View File

@@ -5,352 +5,250 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.powerbell.model.BackgroundBean;
import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils;
import java.io.File;
import android.widget.ImageView.ScaleType;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import cc.winboll.studio.powerbell.R;
import android.widget.LinearLayout;
/**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/11/19 18:01
* @Describe 背景图片视图控件(全透明背景 + 保持比例扩展 + 完全填充父视图 + 预览/正式模式切换)
* 核心功能统一处理背景图片的加载、比例适配、模式切换适配多布局场景和低版本Android系统
* 基于Java7的BackgroundViewLinearLayout+ImageView保持原图比例居中平铺
* 核心ImageView保持原图比例在LinearLayout中居中平铺无拉伸、无裁剪
*/
public class BackgroundView extends RelativeLayout {
public static final String TAG = "BackgroundView"; // 日志标记
public static final String TAG = "BackgroundView";
// 上下文对象(全局复用)
private Context mContext;
private RelativeLayout mrlMain;
// 背景图片显示控件核心子View
private ImageView mivBackground;
private LinearLayout mLlContainer; // 主容器LinearLayout
private ImageView mIvBackground; // 图片显示控件
private float mImageAspectRatio = 1.0f; // 原图宽高比(宽/高)
// 图片原始宽高比(控制图片不拉伸的核心参数,宽/高)
private float mnImageAspectRatio = 1.0f;
// ====================================== 构造器(兼容所有布局场景)======================================
/**
* 构造器1代码创建控件时调用
* @param context 上下文
*/
// ====================================== 构造器Java7兼容 ======================================
public BackgroundView(Context context) {
super(context);
LogUtils.d(TAG, "=== BackgroundView 构造器1(代码创建)启动 ===");
LogUtils.d(TAG, "=== BackgroundView 构造器1 启动 ===");
this.mContext = context;
initView();
}
/**
* 构造器2XML布局中使用时调用无自定义属性
* @param context 上下文
* @param attrs 属性集
*/
public BackgroundView(Context context, AttributeSet attrs) {
super(context, attrs);
LogUtils.d(TAG, "=== BackgroundView 构造器2XML无属性启动 ===");
LogUtils.d(TAG, "=== BackgroundView 构造器2 启动 ===");
this.mContext = context;
initView();
}
/**
* 构造器3XML布局中使用时调用带自定义属性+默认样式)
* @param context 上下文
* @param attrs 属性集
* @param defStyleAttr 默认样式属性
*/
public BackgroundView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
LogUtils.d(TAG, "=== BackgroundView 构造器3XML带属性+默认样式)启动 ===");
LogUtils.d(TAG, "=== BackgroundView 构造器3 启动 ===");
this.mContext = context;
initView();
}
/**
* 构造器4XML布局中使用时调用带自定义属性+默认样式+自定义样式资源)
* @param context 上下文
* @param attrs 属性集
* @param defStyleAttr 默认样式属性
* @param defStyleRes 自定义样式资源
*/
public BackgroundView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
LogUtils.d(TAG, "=== BackgroundView 构造器4XML全参数启动 ===");
this.mContext = context;
initView();
}
// ====================================== 初始化相关方法 ======================================
/**
* 初始化视图(控件本身配置 + 子View初始化 + 初始背景加载)
* 所有构造器统一调用此方法,避免重复代码
*/
// ====================================== 初始化 ======================================
private void initView() {
LogUtils.d(TAG, "=== initView(视图初始化)启动 ===");
// 1. 配置当前控件:完全填充父视图 + 全透明背景 + 无内边距
LogUtils.d(TAG, "=== initView 启动 ===");
// 1. 配置当前控件:全屏+透明
setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
setPadding(0, 0, 0, 0); // 取消自身内边距,避免父容器与控件间出现缝隙
setBackgroundColor(0x00000000); // 全透明背景ARGB透明通道+黑色,无视觉影响)
setBackground(new ColorDrawable(0x00000000)); // 双重保障兼容Android低版本确保背景透明
setBackgroundColor(0x00000000);
setBackground(new ColorDrawable(0x00000000));
initBackgroundImageView();
// 2. 初始化主容器LinearLayout
initLinearLayout();
// 4. 初始加载:默认加载正式模式背景
// 3. 初始化ImageView
initImageView();
// 4. 初始设置透明背景
setDefaultTransparentBackground();
LogUtils.d(TAG, "=== initView(视图初始化)完成 ===");
LogUtils.d(TAG, "=== initView 完成 ===");
}
/**
* 初始化内部ImageView配置尺寸、缩放模式、背景等基础属性
* 单独抽离方法,提高代码可读性
*/
private void initBackgroundImageView() {
LogUtils.d(TAG, "=== initBackgroundImageView内部ImageView初始化启动 ===");
mrlMain = (RelativeLayout)inflate(mContext, R.layout.view_background, null);
mrlMain.setBackgroundColor(0x00000000); // 全透明背景ARGB透明通道+黑色,无视觉影响)
mrlMain.setBackground(new ColorDrawable(0x00000000)); // 双重保障兼容Android低版本确保背景透明
mivBackground = mrlMain.findViewById(R.id.bg_imageview);
// 将ImageView添加到当前控件父容器
this.addView(mrlMain);
LogUtils.d(TAG, "=== initBackgroundImageView内部ImageView初始化完成 ===");
private void initLinearLayout() {
LogUtils.d(TAG, "=== initLinearLayout 启动 ===");
mLlContainer = new LinearLayout(mContext);
// 配置LinearLayout全屏+垂直方向+居中
LinearLayout.LayoutParams llParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
);
mLlContainer.setLayoutParams(llParams);
mLlContainer.setOrientation(LinearLayout.VERTICAL);
mLlContainer.setGravity(android.view.Gravity.CENTER); // 子View居中
mLlContainer.setBackgroundColor(0x00000000);
this.addView(mLlContainer);
LogUtils.d(TAG, "=== initLinearLayout 完成 ===");
}
/**
* 【对外提供】重新加载预览模式背景图片
* 逻辑:优先加载压缩图(省内存)→ 压缩图无效则加载原图 → 均无效则显示默认透明背景
*/
public void loadBackground(BackgroundBean backgroundBean) {
LogUtils.d(TAG, "=== loadBackground加载预览背景启动 ===");
// 校验预览Bean是否为空为空则直接显示默认背景
if (backgroundBean == null || !backgroundBean.isUseBackgroundFile()) {
LogUtils.e(TAG, "【loadBackground】预览Bean为空正在加载默认图片");
setDefaultTransparentBackground();
return;
}
// 加载背景图片路径
String szBackgroundPath = backgroundBean.isUseBackgroundScaledCompressFile() ? backgroundBean.getBackgroundScaledCompressFilePath() : backgroundBean.getBackgroundFilePath();
loadAndSetImageViewBackground(szBackgroundPath);
private void initImageView() {
LogUtils.d(TAG, "=== initImageView 启动 ===");
mIvBackground = new ImageView(mContext);
// 配置ImageViewwrap_content+居中+透明背景
LinearLayout.LayoutParams ivParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
mIvBackground.setLayoutParams(ivParams);
mIvBackground.setScaleType(ScaleType.FIT_CENTER); // 保持比例+居中平铺
mIvBackground.setBackgroundColor(0x00000000);
mLlContainer.addView(mIvBackground);
LogUtils.d(TAG, "=== initImageView 完成 ===");
}
/**
* 核心逻辑加载图片并设置到ImageView正式/预览模式通用,统一处理逻辑)
* 负责:路径校验→文件校验→宽高比计算→压缩加载→尺寸调整→显示图片
* @param imagePath 图片绝对路径(可为空)
*/
private void loadAndSetImageViewBackground(String imagePath) {
LogUtils.d(TAG, "=== loadAndSetImageViewBackground加载并设置图片启动 ===");
LogUtils.d(TAG, String.format("imagePath %s", imagePath));
// 1. 路径校验:路径为空/空字符串,直接显示默认透明背景
if (imagePath == null || imagePath.isEmpty()) {
LogUtils.e(TAG, "【loadAndSetImageViewBackground】加载失败图片路径为空");
setDefaultTransparentBackground();
return;
}
// 2. 文件校验:文件不存在/不是文件,直接显示默认透明背景
File backgroundFile = new File(imagePath);
if (!backgroundFile.exists() || !backgroundFile.isFile()) {
LogUtils.e(TAG, "【loadAndSetImageViewBackground】加载失败文件不存在或无效路径" + imagePath);
setDefaultTransparentBackground();
return;
}
// 3. 计算图片原始宽高比:计算失败则显示默认透明背景
if (!calculateImageAspectRatio(backgroundFile)) {
LogUtils.e(TAG, "【loadAndSetImageViewBackground】加载失败图片宽高比计算失败路径" + imagePath);
setDefaultTransparentBackground();
return;
}
// 4. 压缩加载Bitmap避免OOM加载失败则显示默认透明背景
Bitmap bitmap = decodeBitmapWithCompress(backgroundFile, 1080, 1920);
if (bitmap == null) {
LogUtils.e(TAG, "【loadAndSetImageViewBackground】加载失败图片压缩加载失败路径" + imagePath);
setDefaultTransparentBackground();
public void loadBackgroundBean(BackgroundBean bean) {
if(!bean.isUseBackgroundFile()) {
setDefaultTransparentBackground();
return;
}
if(bean.isUseBackgroundScaledCompressFile()) {
loadImage(bean.getBackgroundScaledCompressFilePath());
} else {
loadImage(bean.getBackgroundFilePath());
}
}
// ====================================== 对外方法 ======================================
/**
* 加载图片保持原图比例在LinearLayout中居中平铺
* @param imagePath 图片绝对路径
*/
public void loadImage(String imagePath) {
LogUtils.d(TAG, "=== loadImage 启动,路径:" + imagePath + " ===");
if (TextUtils.isEmpty(imagePath)) {
setDefaultTransparentBackground();
return;
}
// 5. 设置图片到ImageView兼容低版本系统
Drawable backgroundDrawable = new BitmapDrawable(mContext.getResources(), bitmap);
mivBackground.setImageDrawable(backgroundDrawable);
File imageFile = new File(imagePath);
if (!imageFile.exists() || !imageFile.isFile()) {
LogUtils.e(TAG, "图片文件无效");
setDefaultTransparentBackground();
return;
}
// 6. 调整ImageView尺寸按图片比例扩展到父控件确保不拉伸
adjustImageViewSize();
// 计算原图比例
if (!calculateImageAspectRatio(imageFile)) {
setDefaultTransparentBackground();
return;
}
LogUtils.d(TAG, "【loadAndSetImageViewBackground】图片加载成功");
LogUtils.d(TAG, "→ 图片路径:" + imagePath);
LogUtils.d(TAG, "→ 图片宽高比:" + mnImageAspectRatio);
LogUtils.d(TAG, "=== loadAndSetImageViewBackground加载并设置图片完成加载成功===");
// 压缩加载Bitmap
Bitmap bitmap = decodeBitmapWithCompress(imageFile, 1080, 1920);
if (bitmap == null) {
setDefaultTransparentBackground();
return;
}
// 设置图片
mIvBackground.setImageDrawable(new BitmapDrawable(mContext.getResources(), bitmap));
adjustImageViewSize(); // 调整尺寸
LogUtils.d(TAG, "=== loadImage 完成 ===");
}
/**
* 计算图片原始宽高比(宽/高)→ 控制图片不拉伸的核心方法
* 仅获取图片尺寸,不加载完整图片到内存(节省内存)
* @param file 图片文件(已校验非空)
* @return 计算成功true计算失败false
*/
// ====================================== 内部工具方法 ======================================
private boolean calculateImageAspectRatio(File file) {
LogUtils.d(TAG, "=== calculateImageAspectRatio计算图片宽高比启动 ===");
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 仅获取图片尺寸,不加载图片到内存(关键配置)
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file.getAbsolutePath(), options);
// 获取图片原始宽高
int imageWidth = options.outWidth;
int imageHeight = options.outHeight;
// 校验宽高有效性(宽/高必须大于0否则视为无效图片
if (imageWidth <= 0 || imageHeight <= 0) {
LogUtils.e(TAG, "【calculateImageAspectRatio】计算失败图片尺寸无效" + imageWidth + ",高:" + imageHeight);
return false;
int width = options.outWidth;
int height = options.outHeight;
if (width <= 0 || height <= 0) {
LogUtils.e(TAG, "图片尺寸无效");
return false;
}
// 计算并保存图片原始宽高比(宽/高)
mnImageAspectRatio = (float) imageWidth / imageHeight;
LogUtils.d(TAG, "【calculateImageAspectRatio】计算成功");
mImageAspectRatio = (float) width / height;
LogUtils.d(TAG, "原图比例:" + mImageAspectRatio);
return true;
} catch (Exception e) {
LogUtils.d(TAG, "=== calculateImageAspectRatio计算图片宽高比完成发生异常===");
LogUtils.e(TAG, "计算比例失败:" + e.getMessage());
return false;
}
}
/**
* 调整ImageView尺寸核心方法
* 逻辑按图片原始宽高比计算ImageView最大尺寸填满父控件且不拉伸并保持居中
* 适配场景:控件初始化、图片加载后、父容器尺寸变化(如屏幕旋转)
*/
private void adjustImageViewSize() {
// 2. 获取根容器bg_main尺寸以bg_main为基准实现居中平铺
int parentWidth = mrlMain.getWidth();
int parentHeight = mrlMain.getHeight();
// 3. bg_main未测量完成宽/高为0延迟调整避免尺寸计算错误
if (parentWidth == 0 || parentHeight == 0) {
postDelayed(new Runnable() {
@Override
public void run() {
adjustImageViewSize(); // 延迟后重新调整
}
}, 10); // 10ms延迟平衡响应速度与测量稳定性
return;
}
// 4. 初始化ImageView目标宽高核心严格保持原图宽高比适配bg_main居中平铺
int imageViewWidth, imageViewHeight;
float imageRatio = mnImageAspectRatio; // 原图宽高比(宽/高,确保比例不变)
float parentRatio = (float) parentWidth / parentHeight; // bg_main容器宽高比宽/高)
// 关键逻辑按比例计算ImageView最大尺寸完整显示图片+适配bg_main+无拉伸)
if (imageRatio >= parentRatio) {
// 情况1原图比bg_main更宽横图→ 按bg_main宽度缩放高度按原图比例适配横向填满纵向不超出
imageViewWidth = parentWidth; // 宽度=bg_main宽度横向平铺填满
imageViewHeight = Math.round(imageViewWidth / imageRatio); // 高度按原图比例计算
} else {
// 情况2原图比bg_main更高竖图→ 按bg_main高度缩放宽度按原图比例适配纵向填满横向不超出
imageViewHeight = parentHeight; // 高度=bg_main高度纵向平铺填满
imageViewWidth = Math.round(imageViewHeight * imageRatio); // 宽度按原图比例计算
}
// 5. 应用尺寸到ImageView匹配xml布局参数确保居中
// 适配xml中RelativeLayout的LayoutParams与布局文件根容器一致
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mivBackground.getLayoutParams();
layoutParams.width = imageViewWidth; // 按比例计算的宽度适配bg_main
layoutParams.height = imageViewHeight; // 按比例计算的高度适配bg_main
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT); // 强制居中匹配需求图片在bg_main中居中
mivBackground.setLayoutParams(layoutParams);
// 6. 关键设置缩放模式匹配xml布局+保持比例+居中平铺)
mivBackground.setScaleType(ImageView.ScaleType.MATRIX);
// 确保ImageView背景透明避免遮挡适配布局视觉效果
mivBackground.setBackgroundColor(0x00000000);
}
/**
* 带压缩的Bitmap解码通用方法
* 逻辑仅缩小图片不放大保持原始比例降低内存占用避免OOM
* @param file 图片文件
* @param maxWidth 最大宽度1080px适配主流手机屏幕
* @param maxHeight 最大高度1920px适配主流手机屏幕
* @return 压缩后的Bitmapnull表示解码失败
*/
private Bitmap decodeBitmapWithCompress(File file, int maxWidth, int maxHeight) {
LogUtils.d(TAG, "=== decodeBitmapWithCompress压缩解码Bitmap启动 ===");
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 先获取图片尺寸,不加载完整图片
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file.getAbsolutePath(), options);
// 计算压缩比例(仅缩小,不放大,取宽高压缩比例的最大值)
int scaleX = options.outWidth / maxWidth; // 宽度方向压缩比例
int scaleY = options.outHeight / maxHeight; // 高度方向压缩比例
int inSampleSize = Math.max(scaleX, scaleY); // 最终压缩比例(取最大值,确保不超过最大尺寸)
if (inSampleSize <= 0) {
inSampleSize = 1; // 压缩比例最小为1不压缩
}
int scaleX = options.outWidth / maxWidth;
int scaleY = options.outHeight / maxHeight;
int inSampleSize = Math.max(scaleX, scaleY);
if (inSampleSize <= 0) inSampleSize = 1;
// 正式解码图片(配置压缩参数+省内存参数)
options.inJustDecodeBounds = false; // 允许加载完整图片
options.inSampleSize = inSampleSize; // 设置压缩比例
options.inPreferredConfig = Bitmap.Config.RGB_565; // 内存优化比ARGB_8888省一半内存
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
if (bitmap != null) {
LogUtils.d(TAG, "【decodeBitmapWithCompress】压缩解码成功");
LogUtils.d(TAG, "→ 压缩比例:" + inSampleSize);
LogUtils.d(TAG, "→ 解码后Bitmap尺寸" + bitmap.getWidth() + "x" + bitmap.getHeight());
} else {
LogUtils.e(TAG, "【decodeBitmapWithCompress】压缩解码失败Bitmap为空");
}
LogUtils.d(TAG, "=== decodeBitmapWithCompress压缩解码Bitmap完成 ===");
return bitmap;
options.inJustDecodeBounds = false;
options.inSampleSize = inSampleSize;
options.inPreferredConfig = Bitmap.Config.RGB_565;
return BitmapFactory.decodeFile(file.getAbsolutePath(), options);
} catch (Exception e) {
LogUtils.e(TAG, "【decodeBitmapWithCompress】压缩解码失败:" + e.getMessage(), e);
LogUtils.d(TAG, "=== decodeBitmapWithCompress压缩解码Bitmap完成发生异常===");
LogUtils.e(TAG, "压缩解码失败:" + e.getMessage());
return null;
}
}
/**
* 通用兜底:设置默认透明背景(图片加载失败/路径无效时使用
* 确保:无有效图片时,控件完全透明,不遮挡下层视图
* 调整ImageView尺寸保持原图比例在LinearLayout中居中平铺
*/
private void setDefaultTransparentBackground() {
LogUtils.d(TAG, "=== setDefaultTransparentBackground设置通用默认透明背景启动 ===");
mivBackground.setBackground(new ColorDrawable(0x00000000)); // ImageView背景全透明
mivBackground.setImageBitmap(null); // 清空ImageView的图片
mnImageAspectRatio = 1.0f; // 重置宽高比(避免影响下次图片加载)
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();
}
}, 10);
return;
}
// 计算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); // 确保居中平铺
LogUtils.d(TAG, "ImageView尺寸" + ivWidth + "x" + ivHeight);
LogUtils.d(TAG, "=== adjustImageViewSize 完成 ===");
}
// ====================================== 重写父类方法 ======================================
/**
* 重写父类方法:父容器尺寸变化时调用(如屏幕旋转、窗口大小调整)
* 作用:确保控件尺寸变化后,图片仍保持比例+填满父控件
* @param w 新宽度
* @param h 新高度
* @param oldw 旧宽度
* @param oldh 旧高度
*/
private void setDefaultTransparentBackground() {
mIvBackground.setImageBitmap(null);
mIvBackground.setBackgroundColor(0x00000000);
mImageAspectRatio = 1.0f;
}
// ====================================== 重写方法 ======================================
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
adjustImageViewSize(); // 重新调整ImageView尺寸适配新的控件尺寸
}
adjustImageViewSize(); // 尺寸变化时重新调整
}
}