Android - 在默认按钮上保持背景图像的宽高比

时间:2012-10-31 12:46:43

标签: android button background aspect-ratio

有什么方法可以在Button上作为背景应用时保持drawable的宽高比(不能使用ImageButton(需要Button上的文字),不能使用setCompoundDrawables(),因为这也不符合我的要求(我自己的班级支持添加背景,同时仍保留原始的Android默认按钮,另外我需要在按钮中间设置te背景,而不是留下,右,上或下))。

我尝试使用ScaleDrawable的解决方案,但要么我做错了要么行不通:

Bitmap scaled = Bitmap.createScaledBitmap(original, (int)newBmpWidth, (int)newBmpHeight, false);
BitmapDrawable bd = new BitmapDrawable(scaled);
ScaleDrawable sd = new ScaleDrawable(bd, Gravity.CENTER, a, b);
//for a and b I tried lots of different values, ranging from 0.07f to 1000
sd.setLevel(1);

然后我使用ScaleDrawable作为背景,但无论如何它都会被拉伸。

我也尝试了InsetDrawable,但是,无论是我做错了什么还是行不通,期待第一次:

BitmapDrawable mBitmapDrawable = new BitmapDrawable(mBitmap);
InsetDrawable mInsetDrawable = new InsetDrawable(mBitmapDrawable, mLeftOffset, 0, mRightOffset, 0);

然后我使用InsetDrawable作为背景,但无论如何这也会被拉伸。

有没有办法应用背景但保持宽高比Button我可以找到ImageButtons的大量答案,但遗憾的是Button没有setImageBitmap()setScaleType()方法。

1 个答案:

答案 0 :(得分:1)

我最近遇到了设置ImageView背景图片的同样问题。我提出的解决方案适用于任何View,因此它也应涵盖Button

问题在于View始终将其背景延伸到View的宽度和高度的全部范围,无论Drawable作为背景提供的缩放比例。由于您未能提供专门的Drawables的报告表明,在将图像设置为背景之前,无法通过任何缩放图像来抵消这种情况,因为View只会采用图像尺寸,无论它们是什么,并且可以独立地再次缩放图像尺寸填补View区域。

我的解决方案采用了不同的方法,因为如果我们能够提供与View相同的宽高比的背景图像,那么就不会有失真。

下面的函数scaleKeepingAspect()获取图像资源并回答包含缩放到所需宽度和高度的原始图像的BitmapDrawable。以保持原始图像的纵横比的方式执行缩放,并且用透明像素填充适合所需框的最终剩余空间。原始图像以结果图像为中心。

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)您的View在您的布局xml中由myView标识,并且(b)您的背景图片是文件res/drawable/background.png,请执行以下操作:

  1. 声明您的ActivityView.OnLayoutChangeListener接口的实现者:

    public class MyActivity extends Activity implements View.OnLayoutChangeListener {
    
        ...
    
    }
    
  2. 注册Activity作为您View的布局更改的聆听者:

    @Override public void onCreate(Bundle savedInstanceState) {
    
        ...
    
        myView = (View) findViewById(R.id.myView);
        myView.addOnLayoutChangeListener(this);
    
        ...
    
    }
    
  3. 检测布局更改处理程序中的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;
    
        }
    
    }