You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过代码设置LinearLayout背景Drawable的ScaleType为FitCenter?

Solution for FitCenter Scaling with BitmapDrawable Background

Got it, let's break this down. The key thing to realize is that BitmapDrawable doesn't have a built-in ScaleType property like ImageView does. By default, when you set a BitmapDrawable as a view's background without a tile mode, it stretches to fill the entire view (FitXY). If you set a tile mode, it repeats the original-size bitmap instead.

To get the FitCenter behavior (maintaining aspect ratio, centering the image without stretching) — either alone or combined with tiling — you'll need to manually scale your bitmap first, then create the drawable from the scaled result.

Option 1: FitCenter (No Tiling)

This gives you the centered, non-stretched background you want, without repeating the image:

// Get your original bitmap
Bitmap originalBitmap = BitmapFactory.DecodeFile(Button1ImageURI);

// Make sure the LinearLayout has been measured first (use a layout listener if needed)
int layoutWidth = MainLinearLayout.Width;
int layoutHeight = MainLinearLayout.Height;

// Calculate the scale factor to fit the bitmap without stretching
float scaleFactor = Math.Min(
    (float)layoutWidth / originalBitmap.Width,
    (float)layoutHeight / originalBitmap.Height
);
int scaledWidth = (int)(originalBitmap.Width * scaleFactor);
int scaledHeight = (int)(originalBitmap.Height * scaleFactor);

// Create the scaled bitmap
Bitmap scaledBitmap = Bitmap.CreateScaledBitmap(originalBitmap, scaledWidth, scaledHeight, true);

// Create a full-size bitmap to draw the centered image onto
Bitmap fitCenterBitmap = Bitmap.CreateBitmap(layoutWidth, layoutHeight, Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(fitCenterBitmap);

// Calculate position to center the scaled image
int leftOffset = (layoutWidth - scaledWidth) / 2;
int topOffset = (layoutHeight - scaledHeight) / 2;

// Draw the scaled bitmap into the center of the full-size bitmap
canvas.DrawBitmap(scaledBitmap, leftOffset, topOffset, null);

// Set as background
BitmapDrawable fitCenterDrawable = new BitmapDrawable(Resources, fitCenterBitmap);
MainLinearLayout.Background = fitCenterDrawable;

// Clean up unused bitmaps to avoid memory leaks
originalBitmap.Recycle();
scaledBitmap.Recycle();

Option 2: FitCenter + Tiling

If you want to repeat the scaled, aspect-ratio-preserving bitmap across the LinearLayout, skip the full-size canvas step and just use the scaled bitmap directly with tile mode:

Bitmap originalBitmap = BitmapFactory.DecodeFile(Button1ImageURI);
int layoutWidth = MainLinearLayout.Width;
int layoutHeight = MainLinearLayout.Height;

float scaleFactor = Math.Min(
    (float)layoutWidth / originalBitmap.Width,
    (float)layoutHeight / originalBitmap.Height
);
int scaledWidth = (int)(originalBitmap.Width * scaleFactor);
int scaledHeight = (int)(originalBitmap.Height * scaleFactor);

Bitmap scaledBitmap = Bitmap.CreateScaledBitmap(originalBitmap, scaledWidth, scaledHeight, true);

// Create drawable with tiling enabled
BitmapDrawable tiledFitCenterDrawable = new BitmapDrawable(Resources, scaledBitmap);
tiledFitCenterDrawable.SetTileModeXY(Shader.TileMode.Repeat, Shader.TileMode.Repeat);
MainLinearLayout.Background = tiledFitCenterDrawable;

originalBitmap.Recycle();

Important Note: Measuring the Layout

If you try to get the LinearLayout's width/height too early (before the layout is drawn), you'll get 0 values. To fix this, use a ViewTreeObserver.OnGlobalLayoutListener to run your code after the layout is fully measured:

MainLinearLayout.ViewTreeObserver.AddOnGlobalLayoutListener(new LayoutReadyListener(MainLinearLayout, Button1ImageURI, Resources));

// Custom listener class
private class LayoutReadyListener : Java.Lang.Object, ViewTreeObserver.IOnGlobalLayoutListener
{
    private readonly LinearLayout _layout;
    private readonly string _imageUri;
    private readonly Resources _resources;

    public LayoutReadyListener(LinearLayout layout, string imageUri, Resources resources)
    {
        _layout = layout;
        _imageUri = imageUri;
        _resources = resources;
    }

    public void OnGlobalLayout()
    {
        // Remove the listener to avoid repeated calls
        _layout.ViewTreeObserver.RemoveOnGlobalLayoutListener(this);

        // Run your bitmap scaling/background setup code here (use Option 1 or 2 above)
        Bitmap originalBitmap = BitmapFactory.DecodeFile(_imageUri);
        int layoutWidth = _layout.Width;
        int layoutHeight = _layout.Height;

        float scaleFactor = Math.Min((float)layoutWidth / originalBitmap.Width, (float)layoutHeight / originalBitmap.Height);
        int scaledWidth = (int)(originalBitmap.Width * scaleFactor);
        int scaledHeight = (int)(originalBitmap.Height * scaleFactor);

        Bitmap scaledBitmap = Bitmap.CreateScaledBitmap(originalBitmap, scaledWidth, scaledHeight, true);
        BitmapDrawable drawable = new BitmapDrawable(_resources, scaledBitmap);
        drawable.SetTileModeXY(Shader.TileMode.Repeat, Shader.TileMode.Repeat);
        _layout.Background = drawable;

        originalBitmap.Recycle();
    }
}

内容的提问来源于stack exchange,提问作者CDrosos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 16:37:40