@@ -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的BackgroundView( LinearLayout+ImageView, 保持原图比例居中平铺)
* 核心: ImageView保持原图比例, 在LinearLayout中居中平铺, 无拉伸、无裁剪
*/
public class BackgroundView extends RelativeLayout {
public static final String TAG = " BackgroundView " ; // 日志标记
public static final String TAG = " BackgroundView " ;
// 上下文对象(全局复用)
private Context mContext ;
private Relative Layout mrlM ain ;
// 背景 图片显示控件( 核心子View)
private ImageView mivBackground ;
private Linear Layout mLlCont ainer ; // 主容器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 ( ) ;
}
/**
* 构造器2: XML布局中使用时调用( 无自定义属性)
* @param context 上下文
* @param attrs 属性集
*/
public BackgroundView ( Context context , AttributeSet attrs ) {
super ( context , attrs ) ;
LogUtils . d ( TAG , " === BackgroundView 构造器2( XML无属性) 启动 === " ) ;
LogUtils . d ( TAG , " === BackgroundView 构造器2 启动 === " ) ;
this . mContext = context ;
initView ( ) ;
}
/**
* 构造器3: XML布局中使用时调用( 带自定义属性+默认样式)
* @param context 上下文
* @param attrs 属性集
* @param defStyleAttr 默认样式属性
*/
public BackgroundView ( Context context , AttributeSet attrs , int defStyleAttr ) {
super ( context , attrs , defStyleAttr ) ;
LogUtils . d ( TAG , " === BackgroundView 构造器3( XML带属性+默认样式) 启动 === " ) ;
LogUtils . d ( TAG , " === BackgroundView 构造器3 启动 === " ) ;
this . mContext = context ;
initView ( ) ;
}
/**
* 构造器4: XML布局中使用时调用( 带自定义属性+默认样式+自定义样式资源)
* @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 构造器4( XML全参数) 启动 === " ) ;
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 . l ayout. view_background , null ) ;
mrlMain . setBackgroundColor ( 0x00000000 ) ; // 全透明背景( ARGB: 透明通道+黑色,无视觉影响)
mrlM ain . setBackground ( new ColorDrawable ( 0x00000000 ) ) ; // 双重保障: 兼容Android低版本, 确保背景透明
mivBackground = mrlM ain. 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 . L ayoutParams . MATCH_PARENT
) ;
mLlCont ainer . setLayoutParams ( llParams ) ;
mLlCont ainer . 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 ) ;
// 配置ImageView: wrap_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尺寸( 按图片比例扩展到父控件, 确保不拉伸)
adjustImageViewSiz e( ) ;
// 计算原图比例
if ( ! calculateImageAspectRatio ( imageFil e) ) {
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 / i mageHeight ;
LogUtils . d ( TAG , " 【calculateImageAspectRatio】计算成功 " ) ;
mImageAspectRatio = ( float ) width / height ;
LogUtils . d ( TAG , " 原图比例: " + mI mageAspectRatio ) ;
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 压缩后的Bitmap( null表示解码失败)
*/
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 ( ) ; // 尺寸变化时 重新调整
}
}