Setel ukuran drawable secara terprogram

91

Gambar (ikon) memiliki ukuran yang kurang lebih sama, tetapi saya perlu mengubah ukurannya agar tombol-tombolnya tetap memiliki tinggi yang sama.

Bagaimana saya melakukan ini?

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);
weston
sumber
Sudahkah Anda menemukan cara mengubah ukuran drawable (Bitmap)?
Zelimir
2
Terlambat, tapi bertanya-tanya mengapa Anda tidak menelepon setCompoundDrawables()? Intrinsik mengacu pada ukuran gambar asli di tempat lain dalam Android, mis Drawable.getIntrinsicHeight().
William T. Mallard

Jawaban:

159

The setBounds()Metode tidak bekerja untuk setiap jenis kontainer (melakukan pekerjaan untuk beberapa saya ImageView's, namun).

Coba metode di bawah ini untuk menskalakan drawable itu sendiri:

// 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"
Eric Chen
sumber
bagi saya masalahnya di sini, adalah menggambar persegi panjang putih di sekitar gambar yang dapat
digambar
8
Konstruktor BitmapDrawable (Bitmap) tidak digunakan lagi. Gunakan: Drawable d = new BitmapDrawable (getResources (), Bitmap.createScaledBitmap (bitmap, 50, 50, true));
Andy
1
Ini akan membuat pikselasi saat menskalakan drawable. Meskipun merupakan vector drawable.
Sanket Berde
mungkin ingin menggunakanContextCompat.getDrawable(context, resourceid)
Pierre
Sebagai catatan tambahan, Anda dapat membuat secara StateListDrawableterprogram dan menggunakan addStatemetode dengan "drawable yang dikonversi" untuk membuatnya berfungsi untuk selector's itemukuran yang digunakan di setPasswordVisibilityToggleDrawable.
Buah
31

Tentukan ukuran dengan setBounds(), yaitu untuk penggunaan ukuran 50x50

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

public void setBounds (int kiri, int atas, int kanan, int bawah)

jkhouw1.dll
sumber
2
Setelah ukuran SetBounds tetap sama. Mungkin diperlukan beberapa pembatalan?
Kostadin
6
Sebenarnya, setBounds berfungsi untuk GradientDrawables. Itu tidak berfungsi untuk Image Drawables.
gregm
Ini berhasil bagi saya ketika saya meletakkan gambar di sebuah tombol, tetapi tidak ketika saya meletakkannya di ImageView. OP menggunakan sebuah tombol, tetapi juga memanggil rasa intrinsik dari setCompoundDrawables()fungsi tersebut.
William T. Mallard
@gregm Menariknya, Anda juga bisa menyetel ukuran untuk GradientDrawable menggunakan setSize ().
6rchid
12

Sebelum menerapkan .setBounds (..) cobalah untuk mengubah Drawable saat ini menjadi ScaleDrawable

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

setelah itu

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

akan bekerja

iBog
sumber
2
Mengapa langkah ini diperlukan? Wrapping in a ScaleDrawablememberikan alternatif selain non wrapping?
azizbekian
10

saya tidak punya waktu untuk menggali mengapa metode setBounds () tidak berfungsi pada bitmap drawable seperti yang diharapkan tetapi saya memiliki sedikit solusi @ androbean-studio tweak untuk melakukan apa yang harus dilakukan 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;
    }
}

pemakaian:

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

hasil

sebelum: masukkan deskripsi gambar di sini setelah:masukkan deskripsi gambar di sini

ceph3us
sumber
bagaimana cara menambahkan padding kiri?
dimulai kembali 29
8

Menggunakan

textView.setCompoundDrawablesWithIntrinsicBounds()

MinSdkVersion Anda harus 17 dalam build.gradle

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

Untuk mengubah ukuran drawable:

    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);
Semih Fatih
sumber
3

Gunakan metode posting untuk mencapai efek yang diinginkan:

{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
sumber
3

Mungkin agak terlambat. Tetapi inilah solusi yang akhirnya berhasil untuk saya dalam setiap situasi.

Idenya adalah membuat drawable khusus dengan ukuran intrinic tetap dan meneruskan pekerjaan menggambar ke drawable asli.

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);
        }
    };
Studio Androbean
sumber
apa itu mPlatform?
batsheva
@batsheva Itu hanya sesuatu yang dia gunakan untuk konversi dari dp ke px ...
pengembang android
2

Jawaban jkhouw1 benar, tetapi kurang detail, lihat di bawah:

Jauh lebih mudah untuk setidaknya API> 21. Asumsikan bahwa kita memiliki VectorDrawable dari sumber daya (contoh kode untuk mengambilnya):

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

Untuk itu VectorDrawable cukup setel ukuran yang diinginkan:

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

Dan tunjukkan tombol drawable in:

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

Itu dia. Tetapi perhatikan untuk menggunakan setCompoundDrawables (bukan versi Intrinsik)!

Ilia Petukhov
sumber
0

Anda bisa membuat subclass dari tipe tampilan, dan mengganti metode onSizeChanged.

Saya ingin memiliki penskalaan majemuk yang dapat digambar pada tampilan teks saya yang tidak mengharuskan saya untuk dipusingkan dengan mendefinisikan sumber daya dapat digambar bitmap dalam xml, dll. Dan melakukannya dengan cara ini:

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

}

(Perhatikan bahwa saya menggunakan w dua kali, bukan h, karena dalam kasus ini saya meletakkan ikon di atas teks, dan dengan demikian ikon tidak boleh memiliki ketinggian yang sama dengan tampilan teks)

Ini bisa diterapkan ke drawable latar belakang, atau apa pun yang ingin Anda ubah ukurannya sesuai dengan ukuran tampilan Anda. onSizeChanged () dipanggil saat pertama kali Tampilan dibuat, jadi Anda tidak memerlukan kasus khusus untuk menginisialisasi ukuran.

Zulaksia
sumber
0

Kamu bisa mencoba button.requestLayout(). Ketika ukuran latar belakang diubah, itu perlu mengukur ulang dan tata letak, tetapi itu tidak akan melakukannya

Xiaomei
sumber
0

Membuat ini berfungsi menggunakan 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) }

Contoh:

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)
pengembang android
sumber
-1

Anda dapat menggunakan LayerDrawable hanya dari satu lapisan dan metode 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);
Valery Miller
sumber
-1

Sudah lama sejak pertanyaan itu diajukan
tetapi masih belum jelas bagi banyak orang bagaimana melakukan hal sederhana ini.

Ini cukup sederhana dalam kasus itu ketika Anda menggunakan Drawable sebagai drawable gabungan pada TextView (Button).

Jadi 2 hal yang harus Anda lakukan:

1. Tetapkan batas:

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

2. Atur drawable dengan tepat (tanpa menggunakan batas intrinsik):

button.setCompoundDrawablesRelative(drawable, null, null, null)
  • Tidak perlu menggunakan Bitmap
  • Tidak ada solusi seperti ScaleDrawable ColorDrawableatauLayerDrawable (apa yang pasti dibuat untuk tujuan lain)
  • Tidak perlu drawable khusus!
  • Tidak ada solusi dengan post
  • Ini adalah solusi asli dan sederhana, seperti yang diharapkan Android dari Anda.
Leo Droidcoder
sumber
-42
Button button = new Button(this);
Button = (Button) findViewById(R.id.button01);

Gunakan Button.setHeight()atau Button.setWeight()dan tetapkan nilai.

pengguna564612
sumber
9
yang hanya menyetel tinggi tombol, bukan tinggi drawable. saya ingin mengatur lebar / tinggi drawable (terutama jika lebih besar dari tinggi tombol set).
21
Anda tahu Anda bisa menghapus jawabannya, bukan?
Iharob Al Asimi