Программно установить размер чертежа

92

Изображения (значки) имеют примерно одинаковый размер, но мне нужно изменить их размер, чтобы кнопки оставались той же высоты.

Как мне это сделать?

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().
Уильям Т. Маллард,

Ответы:

160

Этот 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"
Эрик Чен
источник
для меня проблема в том, что он рисует белый прямоугольник вокруг изображения, которое можно
рисовать
8
Конструктор BitmapDrawable (Bitmap) устарел. Использование: Drawable d = new BitmapDrawable (getResources (), Bitmap.createScaledBitmap (bitmap, 50, 50, true));
Энди
1
Это создаст пикселизацию при масштабировании чертежей. Даже если это векторные чертежи.
Sanket Berde
наверное захочу использоватьContextCompat.getDrawable(context, resourceid)
Пьер
В качестве примечания, вы можете создавать StateListDrawableпрограммно и использовать addStateметод с этим «преобразованным drawable», чтобы он работал для selector's itemразмера, используемого в setPasswordVisibilityToggleDrawable.
Fruit
31

Укажите размер с помощью setBounds(), т.е. для размера 50x50 используйте

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

public void setBounds (int слева, int сверху, int справа, int снизу)

jkhouw1
источник
2
После SetBounds размер остается прежним. Может быть нужен какой-нибудь недействительный?
Костадин
6
На самом деле setBounds работает для GradientDrawables. Это просто не работает для изображений.
gregm
У меня это сработало, когда я помещал изображение на кнопку, но не когда я помещал его в ImageView. OP использовал кнопку, но также вызывал внутреннюю разновидность setCompoundDrawables()функции.
Уильям Т. Маллард,
@gregm Интересно, что вы также можете установить размер GradientDrawable с помощью setSize ().
6rchid
12

Перед применением .setBounds (..) попробуйте преобразовать текущий Drawable в ScaleDrawable

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

после этого

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

заработает

iBog
источник
2
Зачем нужен этот шаг? Какая упаковка в a 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);

полученные результаты

до: введите описание изображения здесь после:введите описание изображения здесь

ceph3us
источник
как добавить отступ слева?
reegan29 07
8

Использовать

textView.setCompoundDrawablesWithIntrinsicBounds()

Ваш minSdkVersion должен быть 17 в build.gradle

    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);
        }
    });
OneEyeQuestion
источник
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 (не для внутренней версии)!

Илья Петухов
источник
1

Получил эту работу с помощью 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)
разработчик Android
источник
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, поскольку в этом случае я помещал значок над текстом, и, следовательно, значок не должен иметь ту же высоту, что и текстовое представление)

Это может быть применено к фоновым чертежам или чему-либо еще, что вы хотите изменить относительно размера вашего представления. onSizeChanged () вызывается при первом создании View, поэтому вам не нужны особые случаи для инициализации размера.

Зулаксия
источник
0

Можешь попробовать button.requestLayout(). Когда размер фона изменяется, его нужно повторно измерить и разметить, но он этого не сделает.

Сяомэй
источник
-1

Вы можете использовать LayerDrawable только из одного слоя и метода setLayerInset:

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 (Button).

Итак, вам нужно сделать 2 вещи:

1. Установите границы:

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

2. Установите подходящий для рисования (без использования внутренних границ):

button.setCompoundDrawablesRelative(drawable, null, null, null)
  • Нет необходимости использовать растровые изображения
  • Нет обходных путей, таких как ScaleDrawable ColorDrawableилиLayerDrawable (которые определенно созданы для других целей)
  • Нет необходимости в нестандартных чертежах!
  • Нет обходных путей с post
  • Это естественное и простое решение, именно то, что ожидает от вас Android.
Лев Дроидкодер
источник
-43
Button button = new Button(this);
Button = (Button) findViewById(R.id.button01);

Используйте Button.setHeight()или Button.setWeight()и установите значение.

user564612
источник
9
который просто устанавливает высоту кнопки, а не высоту вытягиваемого элемента. Я хочу установить ширину / высоту вытягиваемого (особенно если она больше установленной высоты кнопки).
23
Вы знаете, что можете удалить ответ, не так ли?
Iharob Al Asimi