如何通过代码设置LinearLayout背景Drawable的ScaleType为FitCenter?
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

