如何缩小按钮上的可绘制对象?


87

如何使按钮上的绘制更小?图标太大,实际上比按钮高。这是我正在使用的代码:

    <Button
    android:background="@drawable/red_button"
    android:drawableLeft="@drawable/s_vit"
    android:id="@+id/ButtonTest"
    android:gravity="left|center_vertical" 
    android:text="S-SERIES CALCULATOR"
    android:textColor="@android:color/white"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:layout_marginLeft="25dp"
    android:layout_marginRight="25dp"
    android:drawablePadding="10dp">
    </Button>

上面是它的外观,下面是现在的外观。

上面是它的外观,下面是现在的外观。

我尝试了此操作,但没有显示图像。:-(

    Resources res = getResources();
    ScaleDrawable sd = new ScaleDrawable(res.getDrawable(R.drawable.s_vit), 0, 10f, 10f);
    Button btn = (Button) findViewById(R.id.ButtonTest);
    btn.setCompoundDrawables(sd.getDrawable(), null, null, null);

最好上传一张您正在获得的图像以及您正在尝试的图像。谢谢。
Lalit Poptani 2011年

您可以定义自定义按钮以定义可绘制对象的大小。在这里查看我的答案 stackoverflow.com/a/31916731/2308720
Oleksandr 2015年

我知道这是从2011年开始的...但是我实际上更喜欢按钮的外观,因为相机超出了按钮的范围-我本来会保留它的样子...只是
说说

Answers:


70

您应该使用ImageButton并在中指定图像android:src,然后将其设置android:scaletypefitXY


在代码中设置缩放的可绘制对象

Drawable drawable = getResources().getDrawable(R.drawable.s_vit);
drawable.setBounds(0, 0, (int)(drawable.getIntrinsicWidth()*0.5), 
                         (int)(drawable.getIntrinsicHeight()*0.5));
ScaleDrawable sd = new ScaleDrawable(drawable, 0, scaleWidth, scaleHeight);
Button btn = findViewbyId(R.id.yourbtnID);
btn.setCompoundDrawables(sd.getDrawable(), null, null, null); //set drawableLeft for example

如果在代码中设置了可绘制对象,则可以根据按钮的高度调整其大小,然后进行设置。
罗尼

现在显示了图像,但没有调整大小!我尝试了0.1f和10f之间的值。任何的想法?感谢您的帮助...
Reto

试试这个drawable.setBounds(0, 0, drawable.getIntrinsicWidth()*0.5, drawable.getIntrinsicHeight()*0.5);
Ronnie

如果这会调整绘图对象的大小,则可以删除scaledrawable零件并直接使用该绘图对象。
罗尼

2
我们是否应该为scaleWidth和scaleHeight设置自己的值?它们只是描述性的吗?
SametSahin

89

我发现了一个不需要的非常简单有效的XML解决方案 ImageButton

为图像制作一个可绘制的文件,如下所示,并将其用于 android:drawableLeft

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item
    android:id="@+id/half_overlay"
    android:drawable="@drawable/myDrawable"
    android:width="40dp"
    android:height="40dp"
    />

</layer-list>

您可以使用android:widthandroid:height属性设置图像大小。

这样,您至少可以在不同的屏幕上获得相同的尺寸。

缺点是它并不完全像fitXY,它将缩放图像宽度以适合X并相应地缩放图像高度。


9
这应该是公认的答案。如果不希望使用ImageButton(例如,因为他们想要文本等),则此答案允许在Button中使用Text加上零代码来调整图像大小。
再生钢

3
我这样制作了一个新的drawable,然后在其中android:drawableTop添加了新的drawable。无论我设置了什么宽度/高度值,它都会显示默认值。
shiftking9987 '16

9
似乎不适用于Lollipop以下的Android版本。
Jyotman Singh'7

32
height,width仅在API级别23及更高版本中起作用。不支持向后。
Palak Darji'8

我同意,这是迄今为止最好的解决办法
Senzo马林加

10

按钮不会调整其内部图像的大小。

我的解决方案不需要代码操作。

它使用TextView和ImageView的布局。

布局的背景应具有红色的3d可绘制对象。

您可能需要定义android:scaleType xml属性。

例:

<LinearLayout
    android:id="@+id/list_item"
    android:layout_width="fill_parent"
    android:layout_height="50dp"
    android:padding="2dp" >

    <ImageView
        android:layout_width="50dp"
        android:layout_height="fill_parent"
        android:src="@drawable/camera" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        android:lines="1"
        android:gravity="center_vertical"
        android:text="Hello - primary" />

</LinearLayout>

顺便说一句:

  1. 指望不同分辨率的图标可能会导致UI不可预测(图标太大或太小)
  2. textview中的文本(包括按钮中的文本)未填充该组件。这是一个Android问题,我不知道如何解决。
  3. 您可以将其用作包含。

祝好运


RE:TextViews,如果我希望视图尽可能小,请将其填充设置为零。否则,它似乎具有默认的填充。
威廉·T·马拉德

6

按照Abhinav的建议使用ScaleDrawable

问题在于,可绘制对象然后不会显示-这是ScaleDrawables中的某种错误。您需要以编程方式更改“级别”。这应该适用于每个按钮:

// Fix level of existing drawables
Drawable[] drawables = myButton.getCompoundDrawables();
for (Drawable d : drawables) if (d != null && d instanceof ScaleDrawable) d.setLevel(1);
myButton.setCompoundDrawables(drawables[0], drawables[1], drawables[2], drawables[3]);

真好 我想我可能会在不久的将来使用它!
Abhinav

@zeh,现在我发现,如果您在setContentView之前运行上述代码,它会起作用,否则它将不起作用。如果将其添加到您的帖子中可能会更好。
好友

由于某种原因,我的上述解决方案不适用于所有android版本。
好友

6

我的DiplayScaleHelper,效果很好:

import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ScaleDrawable;
import android.widget.Button;

public class DisplayHelper {

  public static void scaleButtonDrawables(Button btn, double fitFactor) {
        Drawable[] drawables = btn.getCompoundDrawables();

        for (int i = 0; i < drawables.length; i++) {
            if (drawables[i] != null) {
                if (drawables[i] instanceof ScaleDrawable) {
                    drawables[i].setLevel(1);
                }
                drawables[i].setBounds(0, 0, (int) (drawables[i].getIntrinsicWidth() * fitFactor),
                    (int) (drawables[i].getIntrinsicHeight() * fitFactor));
                ScaleDrawable sd = new ScaleDrawable(drawables[i], 0, drawables[i].getIntrinsicWidth(), drawables[i].getIntrinsicHeight());
                if(i == 0) {
                    btn.setCompoundDrawables(sd.getDrawable(), drawables[1], drawables[2], drawables[3]);
                } else if(i == 1) {
                    btn.setCompoundDrawables(drawables[0], sd.getDrawable(), drawables[2], drawables[3]);
                } else if(i == 2) {
                    btn.setCompoundDrawables(drawables[0], drawables[1], sd.getDrawable(), drawables[3]);
                } else {
                    btn.setCompoundDrawables(drawables[0], drawables[1], drawables[2], sd.getDrawable());
                }
            }
        }
    }
}

4

您可以调用setBounds“化合物”可绘制对象来修改图像的大小。

尝试使用以下代码来自动调整按钮的可绘制大小:

DroidUtils.scaleButtonDrawables((Button) findViewById(R.id.ButtonTest), 1.0);

通过此函数定义:

public final class DroidUtils {

    /** scale the Drawables of a button to "fit"
     *  For left and right drawables: height is scaled 
     *  eg. with fitFactor 1 the image has max. the height of the button.
     *  For top and bottom drawables: width is scaled: 
     *  With fitFactor 0.9 the image has max. 90% of the width of the button 
     *  */
    public static void scaleButtonDrawables(Button btn, double fitFactor) {
        Drawable[] drawables = btn.getCompoundDrawables();

        for (int i = 0; i < drawables.length; i++) {
            if (drawables[i] != null) {
                int imgWidth = drawables[i].getIntrinsicWidth();
                int imgHeight = drawables[i].getIntrinsicHeight();
                if ((imgHeight > 0) && (imgWidth > 0)) {    //might be -1
                    float scale;
                    if ((i == 0) || (i == 2)) { //left or right -> scale height
                        scale = (float) (btn.getHeight() * fitFactor) / imgHeight;
                    } else { //top or bottom -> scale width
                        scale = (float) (btn.getWidth() * fitFactor) / imgWidth;                    
                    }
                    if (scale < 1.0) {
                        Rect rect = drawables[i].getBounds();
                        int newWidth = (int)(imgWidth * scale);
                        int newHeight = (int)(imgHeight * scale);
                        rect.left = rect.left + (int)(0.5 * (imgWidth - newWidth)); 
                        rect.top = rect.top + (int)(0.5 * (imgHeight - newHeight));
                        rect.right = rect.left + newWidth;
                        rect.bottom = rect.top + newHeight;
                        drawables[i].setBounds(rect);
                    }
                }
            }
        }
    }
}

请注意,可能尚未调用onCreate()活动,因为那里的按钮高度和宽度尚不可用。调用它onWindowFocusChanged()或使用此解决方案来调用该函数。

编辑:

此功能的第一个版本无法正常工作。它使用了userSeven7s代码缩放图像,但是返回对我来说ScaleDrawable.getDrawable() 似乎不起作用(return也不起作用ScaleDrawable)。

修改后的代码用于setBounds提供图像的边界。Android使图像适合这些范围。


谢谢您说过不要致电onCreate()
Binarian '18


1

我正在做如下。这将在按钮中创建一个100x100尺寸的图像,与输入图像无关。

drawable.bounds = Rect(0,0,100,100)
button.setCompoundDrawables(drawable, null, null, null)

都不使用ScaleDrawable。不使用button.setCompoundDrawablesRelativeWithIntrinsicBounds()解决了我的问题,因为这似乎使用了固有界限(源图像大小),而不是您刚刚设置的界限。



0

您是否尝试过将图像包装在ScaleDrawable中,然后在按钮中使用它?


2
刚刚尝试过,但是我的ScaleDrawable不显示。:-(即使不在ImageView中。我也使用了示例代码,只是替换了drawable。为什么不起作用呢?
Reto

我有同样的问题。ScaleDrawable会很完美,但这根本行不通。似乎与“级别”有关。更多信息这里(和一些解决方法是不完美):stackoverflow.com/questions/5507539/...
ZEH

(编辑)用一些通用代码修复了它!这里的解决方案仍然允许您使用ScaleDrawables:stackoverflow.com/a/13706836/439026
zeh 2012年

0

这是我为缩放矢量可绘制对象创建的函数。我用它来设置TextView复合可绘制。

/**
 * Used to load vector drawable and set it's size to intrinsic values
 *
 * @param context Reference to {@link Context}
 * @param resId   Vector image resource id
 * @param tint    If not 0 - colour resource to tint the drawable with.
 * @param newWidth If not 0 then set the drawable's width to this value and scale 
 *                 height accordingly.
 * @return On success a reference to a vector drawable
 */
@Nullable
public static Drawable getVectorDrawable(@NonNull Context context,
                                         @DrawableRes int resId,
                                         @ColorRes int tint,
                                         float newWidth)
{
    VectorDrawableCompat drawableCompat =
            VectorDrawableCompat.create(context.getResources(), resId, context.getTheme());
    if (drawableCompat != null)
    {
        if (tint != 0)
        {
            drawableCompat.setTint(ResourcesCompat.getColor(context.getResources(), tint, context.getTheme()));
        }

        drawableCompat.setBounds(0, 0, drawableCompat.getIntrinsicWidth(), drawableCompat.getIntrinsicHeight());

        if (newWidth != 0.0)
        {
            float scale = newWidth / drawableCompat.getIntrinsicWidth();
            float height = scale * drawableCompat.getIntrinsicHeight();
            ScaleDrawable scaledDrawable = new ScaleDrawable(drawableCompat, Gravity.CENTER, 1.0f, 1.0f);
            scaledDrawable.setBounds(0,0, (int) newWidth, (int) height);
            scaledDrawable.setLevel(10000);
            return scaledDrawable;
        }
    }
    return drawableCompat;
}


0

这是因为你没有setLevel。在您之后setLevel(1),它将根据您的需要显示


0

使用Kotlin扩展

val drawable = ContextCompat.getDrawable(context, R.drawable.my_icon)
// or resources.getDrawable(R.drawable.my_icon, theme)
val sizePx = 25
drawable?.setBounds(0, 0, sizePx, sizePx)
//                            (left,     top,  right, bottom)
my_button.setCompoundDrawables(drawable, null, null, null)

我建议在TextView上创建扩展功能(Button对其进行扩展),以方便重用。

button.leftDrawable(R.drawable.my_icon, 25)

// Button extends TextView
fun TextView.leftDrawable(@DrawableRes id: Int = 0, @DimenRes sizeRes: Int) {
    val drawable = ContextCompat.getDrawable(context, id)
    val size = context.resources.getDimensionPixelSize(sizeRes)
    drawable?.setBounds(0, 0, size, size)
    this.setCompoundDrawables(drawable, null, null, null)
}

问题是关于Button而不是TextView。
Firzen

1
您应该已经阅读了答案。Button扩展了TextView,因此您可以同时使用它们。或更改扩展名以仅扩展Button
Gibolt

-1

我尝试了这篇文章的技巧,但没有发现其中任何一种如此吸引人。我的解决方案是使用imageview和textview并将imageview的顶部和底部与textview对齐。这样我得到了预期的结果。这是一些代码:

<RelativeLayout
    android:id="@+id/relativeLayout1"
    android:layout_width="match_parent"
    android:layout_height="48dp" >


    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignTop="@+id/textViewTitle"
        android:layout_alignBottom="@+id/textViewTitle"
        android:src="@drawable/ic_back" />

    <TextView
        android:id="@+id/textViewBack"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/textViewTitle"
        android:layout_alignBottom="@+id/textViewTitle"
        android:layout_toRightOf="@+id/imageView1"
        android:text="Back"
        android:textColor="@color/app_red"
        android:textSize="@dimen/title_size" />
</RelativeLayout>

-1

我制作了一个自定义按钮类来实现此目的。

CustomButton.java

public class CustomButton extends android.support.v7.widget.AppCompatButton {

    private Drawable mDrawable;

    public CustomButton(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CustomButton,
                0, 0);

        try {
            float mWidth = a.getDimension(R.styleable.CustomButton_drawable_width, 0);
            float mHeight = a.getDimension(R.styleable.CustomButton_drawable_width, 0);

            Drawable[] drawables = this.getCompoundDrawables();
            Drawable[] resizedDrawable = new Drawable[4];

            for (int i = 0; i < drawables.length; i++) {
                if (drawables[i] != null) {
                    mDrawable = drawables[i];
                }
                resizedDrawable[i] = getResizedDrawable(drawables[i], mWidth, mHeight);
            }

            this.setCompoundDrawables(resizedDrawable[0], resizedDrawable[1], resizedDrawable[2], resizedDrawable[3]);
        } finally {
            a.recycle();
        }
    }

    public Drawable getmDrawable() {
        return mDrawable;
    }

    private Drawable getResizedDrawable(Drawable drawable, float mWidth, float mHeight) {
        if (drawable == null) {
            return null;
        }

        try {
            Bitmap bitmap;

            bitmap = Bitmap.createBitmap((int)mWidth, (int)mHeight, Bitmap.Config.ARGB_8888);

            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
            return drawable;
        } catch (OutOfMemoryError e) {
            // Handle the error
            return null;
        }
    }
}

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomButton">
        <attr name="drawable_width" format="dimension" />
        <attr name="drawable_height" format="dimension" />
    </declare-styleable>
</resources>

xml中的用法

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.MainActivity">

     <com.example.CustomButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableTop="@drawable/ic_hero"
            android:text="Avenger"
            custom:drawable_height="10dp"
            custom:drawable_width="10dp" />

</RelativeLayout>

1
如果您不打算对其进行任何处理,为什么要创建一个CanvasingetResizedDrawable并吸引它呢?整个功能可以简化为drawable.setBounds(0, 0, mWidth, mHeight)
Antimonit
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.