@@ -4,6 +4,7 @@ import android.content.Context;
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.util.AttributeSet ;
import android.widget.ImageView ;
@@ -17,7 +18,7 @@ import java.io.FileOutputStream;
/**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/11/19 18:01
* @Describe 背景图片视图控件(支持预览临时图片 + 外部刷新 )
* @Describe 背景图片视图控件(全透明背景 + 不拉伸居中平铺 + 完全填充父视图 )
*/
public class BackgroundView extends RelativeLayout {
@@ -30,8 +31,8 @@ public class BackgroundView extends RelativeLayout {
private static String BACKGROUND_IMAGE_FILENAME = " current.data " ;
private static String BACKGROUND_IMAGE_PREVIEW_FILENAME = " current_preview.data " ;
private static String backgroundSourceFilePath ;
private float imageAspectRatio = 1 . 0f ; // 默认 1:1
// 标记当前是否处于预览状态
private float imageAspectRatio = 1 . 0f ; // 图片原始宽高比(控制不拉伸)
// 标记当前是否处于预览模式
private boolean isPreviewMode = false ;
public BackgroundView ( Context context ) {
@@ -59,18 +60,32 @@ public class BackgroundView extends RelativeLayout {
}
void initView ( ) {
initBackgroundImageView ( ) ;
// 1. 控件本身:完全填充父视图 + 全透明背景 + 无内边距
setLayoutParams ( new LayoutParams ( LayoutParams . MATCH_PARENT , LayoutParams . MATCH_PARENT ) ) ;
setPadding ( 0 , 0 , 0 , 0 ) ; // 取消自身内边距
setBackgroundColor ( 0x00000000 ) ; // 全透明背景(#00000000)
setBackground ( new ColorDrawable ( 0x00000000 ) ) ; // 双重保障: 同时设置Background为透明( 兼容低版本)
initBackgroundImageView ( ) ; // 初始化内部ImageView( 全透明 + 不拉伸居中平铺)
initBackgroundImagePath ( ) ;
loadAndSetImageViewBackground ( ) ;
}
private void initBackgroundImageView ( ) {
ivBackground = new ImageView ( mContext ) ;
// 2. ImageView: 初始宽高WRAP_CONTENT + 居中 + 无内边距 + 全透明背景
RelativeLayout . LayoutParams layoutParams = new RelativeLayout . LayoutParams (
LayoutParams . WRAP_CONTENT , LayoutParams . WRAP_CONTENT ) ;
layoutParams . addRule ( RelativeLayout . CENTER_IN_PARENT ) ;
layoutParams . addRule ( RelativeLayout . CENTER_IN_PARENT ) ; // 居中显示
layoutParams . setMargins ( 0 , 0 , 0 , 0 ) ; // 取消边距
ivBackground . setLayoutParams ( layoutParams ) ;
// 3. 缩放模式: FIT_CENTER( 不拉伸, 按比例显示)
ivBackground . setScaleType ( ImageView . ScaleType . FIT_CENTER ) ;
ivBackground . setPadding ( 0 , 0 , 0 , 0 ) ; // 取消内部padding
ivBackground . setBackgroundColor ( 0x00000000 ) ; // ImageView背景全透明
ivBackground . setBackground ( new ColorDrawable ( 0x00000000 ) ) ; // 双重保障(兼容低版本)
this . addView ( ivBackground ) ;
}
@@ -160,35 +175,39 @@ public class BackgroundView extends RelativeLayout {
}
/**
* 【新增公共函数】预览临时图片(不修改正式背景文件 )
* 预览临时图片(全透明背景 + 不拉伸居中平铺 )
* @param previewImagePath 临时预览图片的路径
*/
public void previewBackgroundImage ( String previewImagePath ) {
if ( previewImagePath = = null | | previewImagePath . isEmpty ( ) ) {
LogUtils . e ( TAG , " 预览图片路径为空 " ) ;
setDefaultImageViewBackground ( ) ;
return ;
}
File previewFile = new File ( previewImagePath ) ;
if ( ! previewFile . exists ( ) | | ! previewFile . isFile ( ) ) {
LogUtils . e ( TAG , " 预览图片不存在或不是文件: " + previewImagePath ) ;
setDefaultImageViewBackground ( ) ;
return ;
}
// 计算预览 图片宽高比
// 计算图片原始 宽高比
if ( ! calculateImageAspectRatio ( previewFile ) ) {
LogUtils . e ( TAG , " 预览图片尺寸无效,无法预览 " ) ;
setDefaultImageViewBackground ( ) ;
return ;
}
// 压缩加载预览图片
// 压缩加载预览图片(保持比例)
Bitmap previewBitmap = decodeBitmapWithCompress ( previewFile , 1080 , 1920 ) ;
if ( previewBitmap = = null ) {
LogUtils . e ( TAG , " 预览图片加载失败 " ) ;
setDefaultImageViewBackground ( ) ;
return ;
}
// 设置预览图片到 ImageView
// 设置预览图片(保持 ImageView透明背景)
Drawable previewDrawable = new BitmapDrawable ( mContext . getResources ( ) , previewBitmap ) ;
if ( android . os . Build . VERSION . SDK_INT > = android . os . Build . VERSION_CODES . JELLY_BEAN ) {
ivBackground . setBackground ( previewDrawable ) ;
@@ -196,14 +215,14 @@ public class BackgroundView extends RelativeLayout {
ivBackground . setBackgroundDrawable ( previewDrawable ) ;
}
// 调整 ImageView 尺寸以匹配预览图片宽高比
// 调整ImageView尺寸(居中平铺,不拉伸)
adjustImageViewSize ( ) ;
isPreviewMode = true ;
LogUtils . d ( TAG , " 进入预览模式,预览图片路径: " + previewImagePath ) ;
LogUtils . d ( TAG , " 进入预览模式,预览图片路径: " + previewImagePath + " ,宽高比: " + imageAspectRatio ) ;
}
/**
* 【新增公共函数】 退出预览模式,恢复显示正式背景图片
* 退出预览模式,恢复显示正式背景图片
*/
public void exitPreviewMode ( ) {
if ( isPreviewMode ) {
@@ -227,7 +246,7 @@ public class BackgroundView extends RelativeLayout {
}
/**
* 加载正式背景图片并设置到 ImageView
* 加载正式背景图片并设置到 ImageView(全透明背景 + 不拉伸居中平铺)
*/
private void loadAndSetImageViewBackground ( ) {
if ( backgroundSourceFilePath = = null ) {
@@ -242,11 +261,13 @@ public class BackgroundView extends RelativeLayout {
return ;
}
// 计算图片原始宽高比
if ( ! calculateImageAspectRatio ( backgroundFile ) ) {
setDefaultImageViewBackground ( ) ;
return ;
}
// 压缩加载 Bitmap( 保持比例)
Bitmap bitmap = decodeBitmapWithCompress ( backgroundFile , 1080 , 1920 ) ;
if ( bitmap = = null ) {
LogUtils . e ( TAG , " 图片加载失败,无法解析为 Bitmap " ) ;
@@ -254,6 +275,7 @@ public class BackgroundView extends RelativeLayout {
return ;
}
// 设置图片( 保持ImageView透明背景)
Drawable backgroundDrawable = new BitmapDrawable ( mContext . getResources ( ) , bitmap ) ;
if ( android . os . Build . VERSION . SDK_INT > = android . os . Build . VERSION_CODES . JELLY_BEAN ) {
ivBackground . setBackground ( backgroundDrawable ) ;
@@ -261,12 +283,13 @@ public class BackgroundView extends RelativeLayout {
ivBackground . setBackgroundDrawable ( backgroundDrawable ) ;
}
// 调整ImageView尺寸( 居中平铺, 不拉伸)
adjustImageViewSize ( ) ;
LogUtils . d ( TAG , " ImageView 背景加载成功,宽高比: " + imageAspectRatio ) ;
LogUtils . d ( TAG , " ImageView 背景加载成功(全透明+不拉伸) ,宽高比: " + imageAspectRatio ) ;
}
/**
* 计算图片宽高比(宽/高)
* 计算图片原始 宽高比(宽/高)
*/
private boolean calculateImageAspectRatio ( File file ) {
try {
@@ -291,11 +314,11 @@ public class BackgroundView extends RelativeLayout {
}
/**
* 动态 调整 ImageView 尺寸以匹配图片宽高比
* 调整ImageView尺寸(不拉伸,居中平铺)
*/
private void adjustImageViewSize ( ) {
int parentWidth = getWidth ( ) ;
int parentHeight = getHeight ( ) ;
int parentWidth = getWidth ( ) ; // 控件宽度(已填充父视图)
int parentHeight = getHeight ( ) ; // 控件高度(已填充父视图)
if ( parentWidth = = 0 | | parentHeight = = 0 ) {
post ( new Runnable ( ) {
@@ -316,14 +339,17 @@ public class BackgroundView extends RelativeLayout {
imageViewWidth = ( int ) ( imageViewHeight * imageAspectRatio ) ;
}
// 应用尺寸
RelativeLayout . LayoutParams layoutParams = ( RelativeLayout . LayoutParams ) ivBackground . getLayoutParams ( ) ;
layoutParams . width = imageViewWidth ;
layoutParams . height = imageViewHeight ;
ivBackground . setLayoutParams ( layoutParams ) ;
LogUtils . d ( TAG , " ImageView 尺寸调整完成:宽= " + imageViewWidth + " , 高= " + imageViewHeight ) ;
}
/**
* 带压缩的 Bitmap 解码(避免 OOM)
* 带压缩的 Bitmap 解码(保持比例, 避免 OOM)
*/
private Bitmap decodeBitmapWithCompress ( File file , int maxWidth , int maxHeight ) {
try {
@@ -349,13 +375,14 @@ public class BackgroundView extends RelativeLayout {
}
/**
* 设置默认背景(图片加载失败时兜底 )
* 设置默认背景(全透明兜底,避免空白 )
*/
private void setDefaultImageViewBackground ( ) {
ivBackground . setBackgroundResource ( R . drawable . default_background ) ;
// 关键:默认背景设为全透明(而非默认图,避免遮挡下层视图)
ivBackground . setBackground ( new ColorDrawable ( 0x00000000 ) ) ; // 全透明背景
imageAspectRatio = 1 . 0f ;
adjustImageViewSize ( ) ;
LogUtils . d ( TAG , " 已设置 ImageView 默认背景 " ) ;
LogUtils . d ( TAG , " 已设置默认透明 背景 " ) ;
}
@Override