以编程方式设置可绘制尺寸


90

图像(图标)的大小大致相同,但是我需要调整它们的大小,以使按钮保持相同的高度。

我该怎么做呢?

Button button = new Button(this);
button.setText(apiEventObject.getTitle());
button.setOnClickListener(listener);

/*
 * set clickable id of button to actual event id
 */
int id = Integer.parseInt(apiEventObject.getId());
button.setId(id);

button.setLayoutParams(new LayoutParams(
        android.view.ViewGroup.LayoutParams.FILL_PARENT,
        android.view.ViewGroup.LayoutParams.WRAP_CONTENT));

Drawable drawable = LoadImageFromWebOperations(apiSizeObject.getSmall());
//?resize drawable here? drawable.setBounds(50, 50, 50, 50);
button.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);

您是否找到了如何调整可绘制(位图)大小的方法?
Zelimir

2
很晚了,但是想知道为什么你不打电话setCompoundDrawables()吗?本征是指Android中其他位置的原始图片大小,例如Drawable.getIntrinsicHeight()
威廉·T·马拉德

Answers:


159

setBounds()方法不适用于每种类型的容器(但是对我ImageView的某些容器却有效)。

请尝试以下方法来缩放可绘制对象本身:

// Read your drawable from somewhere
Drawable dr = getResources().getDrawable(R.drawable.somedrawable);
Bitmap bitmap = ((BitmapDrawable) dr).getBitmap();
// Scale it to 50 x 50
Drawable d = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap, 50, 50, true));
// Set your new, scaled drawable "d"

对我来说,这里的问题是,它在可绘制图像周围绘制了一个白色矩形
noloman 2012年

8
不推荐使用BitmapDrawable(Bitmap)构造函数。使用:Drawable d = new BitmapDrawable(getResources(),Bitmap.createScaledBitmap(bitmap,50,50,true));
安迪

1
放大可绘制对象时,这将创建像素化。即使它们是矢量可绘制对象。
Sanket Berde

可能要使用ContextCompat.getDrawable(context, resourceid)
Pierre

附带说明,您可以通过StateListDrawable编程addState方式创建并使用带有“转换后的可绘制对象”的方法,以使其适用于中selector's item使用的大小setPasswordVisibilityToggleDrawable
水果

31

用指定尺寸setBounds(),即用于50x50尺寸

drawable.setBounds(0, 0, 50, 50);

public void setBounds(左向左,顶部向内,右侧向右,底部向内)


2
在SetBounds之后,大小保持不变。可能需要一些失效吗?
Kostadin

6
实际上,setBounds可用于GradientDrawables。它只是不适用于图像可绘制对象。
gregm 2012年

当我将图像放入按钮时,它对我有用,但是当我将其放入ImageView时,它却对我不起作用。OP在使用按钮的同时,还调用了函数的固有风格setCompoundDrawables()
威廉·T·马拉德

@gregm有趣的是,您还可以使用setSize()设置GradientDrawable的大小。
6rchid

12

在应用.setBounds(..)之前,尝试将当前Drawable转换为ScaleDrawable

drawable = new ScaleDrawable(drawable, 0, width, height).getDrawable();

之后

drawable.setBounds(0, 0, width, height);

将工作


2
为什么需要此步骤?什么包装可以ScaleDrawable代替非包装?
阿齐兹别克人

10

我没有时间去挖掘为什么setBounds()方法不能按预期在可绘制位图上工作,但是我几乎没有调整@ androbean-studio解决方案来执行setBounds应该做的事情...

/**
 * Created by ceph3us on 23.05.17.
 * file belong to pl.ceph3us.base.android.drawables
 * this class wraps drawable and forwards draw canvas
 * on it wrapped instance by using its defined bounds
 */
public class WrappedDrawable extends Drawable {

    private final Drawable _drawable;
    protected Drawable getDrawable() {
        return _drawable;
    }

    public WrappedDrawable(Drawable drawable) {
        super();
        _drawable = drawable;
    }

    @Override
    public void setBounds(int left, int top, int right, int bottom) {
        //update bounds to get correctly
        super.setBounds(left, top, right, bottom);
        Drawable drawable = getDrawable();
        if (drawable != null) {
            drawable.setBounds(left, top, right, bottom);
        }
    }

    @Override
    public void setAlpha(int alpha) {
        Drawable drawable = getDrawable();
        if (drawable != null) {
            drawable.setAlpha(alpha);
        }
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        Drawable drawable = getDrawable();
        if (drawable != null) {
            drawable.setColorFilter(colorFilter);
        }
    }

    @Override
    public int getOpacity() {
        Drawable drawable = getDrawable();
        return drawable != null
                ? drawable.getOpacity()
                : PixelFormat.UNKNOWN;
    }

    @Override
    public void draw(Canvas canvas) {
        Drawable drawable = getDrawable();
        if (drawable != null) {
            drawable.draw(canvas);
        }
    }

    @Override
    public int getIntrinsicWidth() {
        Drawable drawable = getDrawable();
        return drawable != null
                ? drawable.getBounds().width()
                : 0;
    }

    @Override
    public int getIntrinsicHeight() {
        Drawable drawable = getDrawable();
        return drawable != null ?
                drawable.getBounds().height()
                : 0;
    }
}

用法:

// get huge drawable 
final Drawable drawable = resources.getDrawable(R.drawable.g_logo);
// create our wrapper           
WrappedDrawable wrappedDrawable = new WrappedDrawable(drawable);
// set bounds on wrapper 
wrappedDrawable.setBounds(0,0,32,32); 
// use wrapped drawable 
Button.setCompoundDrawablesWithIntrinsicBounds(wrappedDrawable ,null, null, null);

结果

之前:在此处输入图片说明 之后:在此处输入图片说明


如何向左添加填充?
reegan29

8

使用

textView.setCompoundDrawablesWithIntrinsicBounds()

您的minSdkVersion在build.gradle中应该为17

    defaultConfig {
    applicationId "com.example..."
    minSdkVersion 17
    targetSdkVersion 25
    versionCode 1
    versionName "1.0"
}

更改可绘制尺寸:

    TextView v = (TextView)findViewById(email);
    Drawable dr = getResources().getDrawable(R.drawable.signup_mail);
    Bitmap bitmap = ((BitmapDrawable) dr).getBitmap();
    Drawable d = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap, 80, 80, true));

    //setCompoundDrawablesWithIntrinsicBounds (image to left, top, right, bottom)
    v.setCompoundDrawablesWithIntrinsicBounds(d,null,null,null);

3

使用post方法可以达到预期的效果:

{your view}.post(new Runnable()
    {
        @Override
        public void run()
        {
            Drawable image = context.getResources().getDrawable({drawable image resource id});
            image.setBounds(0, 0, {width amount in pixels}, {height amount in pixels});
            {your view}.setCompoundDrawables(image, null, null, null);
        }
    });

3

大概有点晚了。但是,这是最终在每种情况下都对我有用的解决方案。

这个想法是创建一个具有固定内部尺寸的自定义可绘制对象,并将绘制作业传递给原始可绘制对象。

Drawable icon = new ColorDrawable(){
        Drawable iconOrig = resolveInfo.loadIcon(packageManager);

        @Override
        public void setBounds(int left, int top, int right, int bottom){
            super.setBounds(left, top, right, bottom);//This is needed so that getBounds on this class would work correctly.
            iconOrig.setBounds(left, top, right, bottom);
        }

        @Override
        public void draw(Canvas canvas){
            iconOrig.draw(canvas);
        }

        @Override
        public int getIntrinsicWidth(){
            return  mPlatform.dp2px(30);
        }

        @Override
        public int getIntrinsicHeight(){
            return  mPlatform.dp2px(30);
        }
    };

什么是mPlatform?
batsheva

@batsheva这只是他用于从dp转换为px的东西...
Android开发人员

2

jkhouw1答案是正确的,但是缺少一些细节,请参见下文:

至少对于API> 21,它要容易得多。假设我们从资源中有VectorDrawable(检索它的示例代码):

val iconResource = context.resources.getIdentifier(name, "drawable", context.packageName)
val drawable = context.resources.getDrawable(iconResource, null)

对于该VectorDrawable,只需设置所需的大小即可:

drawable.setBounds(0, 0, size, size)

并在按钮中显示可绘制:

button.setCompoundDrawables(null, drawable, null, null)

而已。但是请注意使用setCompoundDrawables(非内部版本)!


0

您可以创建视图类型的子类,并覆盖onSizeChanged方法。

我想在文本视图上缩放比例可绘制对象,而无需在xml等中定义位图可绘制对象,并且这样做:

public class StatIcon extends TextView {

    private Bitmap mIcon;

    public void setIcon(int drawableId) {
    mIcon = BitmapFactory.decodeResource(RIApplication.appResources,
            drawableId);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        if ((w > 0) && (mIcon != null))
            this.setCompoundDrawablesWithIntrinsicBounds(
                null,
                new BitmapDrawable(Bitmap.createScaledBitmap(mIcon, w, w,
                        true)), null, null);

        super.onSizeChanged(w, h, oldw, oldh);
    }

}

(请注意,我使用了两次w,而不是h,因为在这种情况下,我将图标放在文本上方,因此图标的高度不应与文本视图的高度相同)。

可以将其应用于背景可绘制对象,或要相对于视图大小调整大小的任何其他对象。第一次创建View时会调用onSizeChanged(),因此不需要任何特殊情况即可初始化大小。


0

你可以试试看button.requestLayout()。更改背景大小时,需要重新测量和布局,但不会这样做


0

使用LayerDrawable进行以下工作:

fun getResizedDrawable(drawable: Drawable, scale: Float) =
    LayerDrawable(arrayOf(drawable)).also { it.setLayerSize(0, (drawable.intrinsicWidth * scale).toInt(), (drawable.intrinsicHeight * scale).toInt()) }

fun getResizedDrawable(drawable: Drawable, scalex: Float, scaleY: Float) =
    LayerDrawable(arrayOf(drawable)).also { it.setLayerSize(0, (drawable.intrinsicWidth * scalex).toInt(), (drawable.intrinsicHeight * scaleY).toInt()) }

fun getResizedDrawableUsingSpecificSize(drawable: Drawable, newWidth: Int, newHeight: Int) =
    LayerDrawable(arrayOf(drawable)).also { it.setLayerSize(0, newWidth, newHeight) }

例:

val drawable = AppCompatResources.getDrawable(this, android.R.drawable.sym_def_app_icon)!!
val resizedDrawable = getResizedDrawable(drawable, 3f)
textView.setCompoundDrawablesWithIntrinsicBounds(resizedDrawable, null, null, null)
imageView.setImageDrawable(resizedDrawable)

-1

您只能在一层和setLayerInset方法中使用LayerDrawable:

Drawable[] layers = new Drawable[1];
layers[0] = application.getResources().getDrawable(R.drawable.you_drawable);

LayerDrawable layerDrawable = new LayerDrawable(layers);
layerDrawable.setLayerInset(0, 10, 10, 10, 10);

-1

自问这个问题以来已经有一段时间了,
但是对于许多人如何做这个简单的事情仍然不清楚。

在这种情况下,当您将Drawable用作TextView(按钮)上的复合可绘制对象时,这非常简单。

因此,您必须做两件事:

1,设定范围

drawable.setBounds(left, top, right, bottom)

2.适当设置drawable(不使用内部边界):

button.setCompoundDrawablesRelative(drawable, null, null, null)
  • 无需使用位图
  • 没有解决方法,例如ScaleDrawable ColorDrawableLayerDrawable(肯定是为其他目的而创建的)
  • 无需自定义可绘制对象!
  • 没有解决方法 post
  • 这是一个本机且简单的解决方案,正是Android希望您做到的。

-42
Button button = new Button(this);
Button = (Button) findViewById(R.id.button01);

使用Button.setHeight()Button.setWeight()设置一个值。


9
只是设置按钮的高度,而不是绘制对象的高度。我想设置可绘制对象的宽度/高度(特别是如果它大于设置的按钮高度)。

21
您知道您可以删除答案,不是吗?
Iharob Al Asimi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.