我最近在设置背景图像时遇到了同样的问题ImageView
。我提出的解决方案适用于 any View
,因此它也应该涵盖Button
。
问题在于,无论作为背景提供的 Drawable 的缩放比例如何,它View
总是将其背景拉伸到 ' 的宽度和高度的全部范围。View
正如您关于未能提供专门的 Drawables 的报告所暗示的那样,这不能通过在将图像设置为背景之前缩放图像的任何方式来抵消,因为它View
只会获取图像尺寸,无论它们是什么,然后再次独立缩放它们以View
填充区域。
我的解决方案基于以下事实采用不同的方法:如果我们可以提供与View
's 具有相同纵横比的背景图像,则不会出现失真。
下面的函数scaleKeepingAspect()
采用图像资源并回答BitmapDrawable
包含缩放到所需宽度和高度的原始图像的 a。缩放以保持原始图像的纵横比的方式执行,并且最终剩余的空间以适合所需的框被透明像素填充。原始图像在结果图像中居中。
private BitmapDrawable scaleKeepingAspect(Resources res, int id, int dstWidth, int dstHeight) {
Bitmap b = (new BitmapFactory()).decodeResource(res, id);
float scaleX = (float) dstWidth / b.getWidth();
float scaleY = (float) dstHeight / b.getHeight();
float scale = scaleX < scaleY ? scaleX : scaleY;
int sclWidth = Math.round(scale * b.getWidth());
int sclHeight = Math.round(scale * b.getHeight());
b = Bitmap.createScaledBitmap(b, sclWidth, sclHeight, false);
int[] pixels = new int[sclWidth * sclHeight];
b.getPixels(pixels, 0, sclWidth, 0, 0, sclWidth, sclHeight);
b = Bitmap.createBitmap(dstWidth, dstHeight, b.getConfig());
b.setPixels(pixels, 0, sclWidth, (dstWidth - sclWidth) / 2, (dstHeight - sclHeight) / 2, sclWidth, sclHeight);
return new BitmapDrawable(res, Bitmap.createBitmap(b));
}
scaleKeepingAspect()
设置背景的适当位置是在布局更改事件期间,因此当由于布局处理View
而更改的边界时,背景会正确更新。View
为此,假设 (a) 您在布局 xml 中View
被标识为myView
,并且 (b) 您的背景图像是 file res/drawable/background.png
,请执行以下操作:
将您声明Activity
为View.OnLayoutChangeListener
接口的实现者:
public class MyActivity extends Activity implements View.OnLayoutChangeListener {
...
}
将您注册Activity
为侦听器以了解您的布局更改View
:
@Override public void onCreate(Bundle savedInstanceState) {
...
myView = (View) findViewById(R.id.myView);
myView.addOnLayoutChangeListener(this);
...
}
在布局更改处理程序中检测View
布局更新,并在需要时更新其背景:
@Override public void onLayoutChange (View v,
int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (left == right || top == bottom || (
left == oldLeft && top == oldTop &&
right == oldRight && bottom == oldBottom))
return;
switch (v.getId()) {
case R.id.myView:
v.setBackground(
scaleKeepingAspect(
getResources(),
R.drawable.background,
v.getWidth(),
v.getHeight()));
break;
}
}