Как я могу уменьшить рисунок на кнопке?

Как я могу сделать рисование на кнопке меньше? Значок слишком большой, на самом деле выше, чем кнопка. Это код, который я использую:

    <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);

14 ответов

Решение

Вы должны использовать ImageButton и указать изображение в android:srcи установить android:scaletype в fitXY


Настройка масштабируемой отрисовки в коде

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

Я нашел очень простое и эффективное решение 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:width а также android:height свойства.

Таким образом, вы можете получить одинаковый размер для разных экранов.

Недостатком является то, что он не совсем похож на fitXY, который масштабировал бы ширину изображения, чтобы соответствовать X, и соответственно масштабировал высоту изображения.

Кнопки не меняют свои внутренние изображения.

Мое решение не требует манипулирования кодом.

Он использует макет с 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. Подсчет значков с разным разрешением может привести к непредсказуемому пользовательскому интерфейсу (значок слишком большой или слишком маленький)
  2. Текст в текстовом представлении (включая кнопки) не заполняет компонент. Это проблема Android, и я не знаю, как ее решить.
  3. Вы можете использовать его в качестве включения.

Удачи

Мой 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());
                }
            }
        }
    }
}

Используйте ScaleDrawable, как предложил Абхинав.

Проблема в том, что drawable тогда не отображается - это какая-то ошибка в 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]);

Ты можешь позвонить 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() не похоже на работу (и не возвращается ScaleDrawable) для меня.

Модифицированный код использует setBounds предоставить границы для изображения. Android вписывает изображение в эти границы.

Я делаю это, как показано ниже. Это создает изображение размером 100x100 в кнопке независимо от входного изображения.

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

Не используется ScaleDrawable или. Не используется button.setCompoundDrawablesRelativeWithIntrinsicBounds() решил мою проблему, так как кажется, что вместо внутренних границ, которые вы только что установили, используются внутренние границы (размер исходного изображения).

Если вы хотите использовать 1 изображение и отображать его в другом размере, вы можете использовать масштабируемое рисование ( http://developer.android.com/guide/topics/resources/drawable-resource.html).

Вот функция, которую я создал для масштабирования векторных отрисовок. Я использовал его для настройки составного объекта 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;
}
  • Используя функцию "BATCH DRAWABLE IMPORT", вы можете импортировать нестандартный размер в зависимости от вашего требования, например 20dp*20dp

    • Теперь после импорта используйте импортированный drawable_image в качестве drawable_source для вашей кнопки

    • Так проще введите описание изображения здесь

Вы пытались обернуть ваше изображение в ScaleDrawable и затем использовать его в своей кнопке?

Это потому что ты не setLevel, после тебя setLevel(1), это будет отображаться как вы хотите

Вы можете использовать рисованные объекты разных размеров, которые используются с различными плотностями / размерами экрана и т. Д., Чтобы ваше изображение выглядело правильно на всех устройствах.

Смотрите здесь: http://developer.android.com/guide/practices/screens_support.html

Я попробовал методы этого поста, но не нашел ни одного из них столь привлекательным. Мое решение состояло в том, чтобы использовать viewview и textview и выровнять верхнюю и нижнюю часть viewview к 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>

Я сделал пользовательский класс кнопок для достижения этой цели.

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>

Использование расширения 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.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)
}
Другие вопросы по тегам