Bagaimana cara mengecilkan drawable pada sebuah tombol?

87

bagaimana cara membuat drawable pada tombol lebih kecil? Ikonnya terlalu besar, sebenarnya lebih tinggi dari tombolnya. Ini adalah kode yang saya gunakan:

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

Bagian atas adalah bagaimana seharusnya terlihat, semakin rendah tampilannya sekarang.

Bagian atas adalah bagaimana seharusnya terlihat, semakin rendah tampilannya sekarang.

Saya mencoba ini tetapi tidak ada gambar yang ditampilkan. :-(

    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);
Reto
sumber
Akan lebih baik jika Anda mengunggah gambar tentang apa yang Anda dapatkan dan apa yang Anda coba lakukan. Terima kasih.
Lalit Poptani
Anda dapat menentukan tombol kustom Anda untuk menentukan ukuran drawable. Lihat jawaban saya di sini stackoverflow.com/a/31916731/2308720
Oleksandr
Saya tahu ini dari tahun 2011 ... tetapi saya sebenarnya lebih suka tampilan tombol dengan kamera yang melampaui batas tombol - Saya akan membiarkannya seperti itu ... katakan saja :)
killercowuk

Jawaban:

70

Anda harus menggunakan ImageButton dan menentukan gambar dalam android:src, dan setel android:scaletypekefitXY


Menyetel kode drawable berskala

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
Ronnie
sumber
Jika Anda menyetel kode drawable, Anda dapat mengubah ukurannya berdasarkan tinggi tombol, lalu menyetelnya.
Ronnie
Sekarang gambar ditampilkan tetapi ukurannya tidak diubah! Saya mencoba nilai antara 0.1f dan 10f. Ada ide? Terima kasih atas bantuan Anda ...
Reto
Coba inidrawable.setBounds(0, 0, drawable.getIntrinsicWidth()*0.5, drawable.getIntrinsicHeight()*0.5);
Ronnie
Jika ini mengubah ukuran drawable, Anda dapat menghapus bagian yang dapat digambar berskala dan menggunakan drawable secara langsung.
Ronnie
2
Apakah kita seharusnya menetapkan nilai kita sendiri untuk scaleWidth dan scaleHeight? Apakah mereka hanya deskriptif?
SametSahin
90

Saya telah menemukan solusi XML yang sangat sederhana dan efektif yang tidak memerlukan ImageButton

Buat file drawable untuk gambar Anda seperti di bawah ini dan gunakan untuk 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>

Anda dapat mengatur ukuran gambar dengan properti android:widthdan android:height.

Dengan cara ini Anda setidaknya bisa mendapatkan ukuran yang sama untuk layar yang berbeda.

Kekurangannya adalah tidak persis seperti fitXY yang akan menskalakan lebar gambar agar pas dengan X dan menskalakan tinggi gambar yang sesuai.

Sobat
sumber
9
Ini harus menjadi jawaban yang diterima. Jika seseorang tidak menginginkan ImageButton (misalnya karena mereka menginginkan teks, dll) maka jawaban ini memungkinkan untuk gambar berukuran dalam sebuah Tombol dengan Teks ditambah kode nol.
Baja Daur Ulang
3
Saya membuat drawable baru seperti ini dan kemudian android:drawableTopsaya menambahkan drawable baru. Tidak peduli berapa nilai untuk lebar / tinggi yang saya tetapkan, ini menunjukkan kepada saya nilai default.
driftking9987
9
Sepertinya tidak berfungsi untuk versi Android di bawah Lollipop.
Jyotman Singh
32
tinggi, lebar hanya berfungsi di API level 23 dan lebih tinggi. Tidak didukung mundur.
Palak Darji
Saya setuju, sejauh ini ini adalah solusi terbaik
Senzo Malinga
10

Tombol tidak mengubah ukuran gambar dalamnya.

Solusi saya tidak memerlukan manipulasi kode.

Ini menggunakan tata letak dengan TextView dan ImageView.

Latar belakang tata letak harus memiliki 3d drawable berwarna merah.

Anda mungkin perlu menentukan atribut android: scaleType xml.

Contoh:

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

BTW:

  1. Mengandalkan ikon resolusi yang berbeda dapat menghasilkan UI yang tidak dapat diprediksi (ikon terlalu besar atau terlalu kecil)
  2. Teks dalam tampilan teks (termasuk dalam tombol) tidak mengisi komponen. Ini adalah masalah Android dan saya tidak tahu bagaimana menyelesaikannya.
  3. Anda dapat menggunakannya sebagai tambahan.

Semoga berhasil

AlikElzin-kilaka
sumber
RE: TextView, jika saya ingin tampilan menjadi sekecil mungkin, saya menyetel paddingnya ke nol. Tampaknya memiliki padding default sebaliknya.
William T. Mallard
6

Gunakan ScaleDrawable seperti yang disarankan Abhinav .

Masalahnya adalah drawable tidak muncul saat itu - ini semacam bug di ScaleDrawables. Anda harus mengubah "level" secara terprogram. Ini harus berfungsi untuk setiap tombol:

// 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]);
zeh
sumber
Bagus. Saya pikir saya mungkin akan menggunakan ini dalam waktu dekat!
Abhinav
@zeh, sekarang saya menemukan bahwa itu berfungsi jika Anda menjalankan kode di atas sebelum setContentView, jika tidak maka tidak akan berfungsi. Akan lebih baik jika Anda menambahkan ini ke posting Anda.
Buddy
Untuk beberapa alasan, solusi saya di atas tidak berfungsi pada semua versi Android.
Buddy
6

My DiplayScaleHelper, yang berfungsi dengan sempurna:

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());
                }
            }
        }
    }
}
Владимир Фишер
sumber
4

Anda bisa menelepon setBounds drawable "gabungan" untuk mengubah ukuran gambar.

Coba kode ini untuk mengubah ukuran drawable tombol Anda secara otomatis:

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

didefinisikan oleh fungsi ini:

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

Ketahuilah, bahwa ini mungkin tidak dipanggil dalam onCreate()suatu aktivitas, karena tinggi dan lebar tombol belum (belum) tersedia di sana. Panggil ini onWindowFocusChanged()atau gunakan solusi ini untuk memanggil fungsi.

Diedit:

Inkarnasi pertama dari fungsi ini tidak bekerja dengan benar. Itu menggunakan kode userSeven7s untuk menskalakan gambar, tetapi mengembalikan ScaleDrawable.getDrawable() tampaknya tidak berfungsi (juga tidak mengembalikanScaleDrawable ) untuk saya.

Kode yang dimodifikasi digunakan setBoundsuntuk memberikan batasan pada gambar. Android menyesuaikan gambar ke dalam batasan ini.

yonojoy
sumber
Terima kasih karena Anda mengatakan untuk tidak memanggilnya onCreate().
Binarian
1

Saya melakukannya seperti di bawah ini. Ini membuat gambar berukuran 100x100 pada tombol yang tidak bergantung pada gambar masukan.

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

Tidak menggunakan ScaleDrawablekeduanya. Tidak menggunakan button.setCompoundDrawablesRelativeWithIntrinsicBounds()memecahkan masalah saya, karena tampaknya menggunakan batas intrinsik (ukuran gambar sumber) bukan batas yang baru saja Anda tetapkan.

LP
sumber
0

Anda dapat menggunakan drawable dengan ukuran berbeda yang digunakan dengan kepadatan / ukuran layar berbeda, dll., Sehingga gambar Anda terlihat benar di semua perangkat.

Lihat di sini: http://developer.android.com/guide/practices/screens_support.html#support

HXCaine
sumber
Saya menggunakan gambar yang sama di tempat yang berbeda. Inilah mengapa saya tidak dapat mengubah ukurannya, itu harus ditampilkan dalam ukuran yang saya inginkan.
Reto
0

Apakah Anda mencoba membungkus gambar Anda dalam ScaleDrawable dan kemudian menggunakannya di tombol Anda?

Abhinav
sumber
2
Baru saja mencoba ini, namun ScaleDrawable saya tidak ditampilkan. :-( Bahkan tidak dalam ImageView. Saya mengambil kode sampel dan baru saja mengganti drawable. Adakah yang tahu mengapa ini tidak berhasil?
Reto
Saya memiliki masalah yang sama. ScaleDrawableakan sempurna, tetapi tidak berhasil. Sepertinya ada hubungannya dengan "level". Informasi selengkapnya di sini (dan beberapa solusi yang kurang sempurna): stackoverflow.com/questions/5507539/…
zeh
(edit) perbaiki dengan beberapa kode umum! Solusi di sini yang masih memungkinkan Anda menggunakan ScaleDrawables: stackoverflow.com/a/13706836/439026
zeh
0

Di sini fungsi yang saya buat untuk menskalakan vector drawable. Saya menggunakannya untuk mengatur drawable gabungan 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;
}
zmicer
sumber
0
  • Menggunakan fitur "BATCH DRAWABLE IMPORT", Anda dapat mengimpor ukuran khusus tergantung pada contoh kebutuhan Anda 20dp * 20dp

    • Sekarang setelah mengimpor gunakan drawable_image yang diimpor sebagai drawable_source untuk tombol Anda

    • Ini lebih sederhana masukkan deskripsi gambar di sini

Santhosh PR
sumber
Bagaimana Anda bisa sampai di sana?
Pengembang android
Ini adalah plugin yang menurut saya. plugins.jetbrains.com/plugin/7658-android-drawable-importer
GeoMint
0

Itu karena kamu tidak melakukannya setLevel. setelah Anda setLevel(1), itu akan ditampilkan sesuai keinginan Anda

Songtao Lou
sumber
0

Menggunakan Ekstensi 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)

Saya sarankan membuat fungsi ekstensi pada TextView ( Tombol memperluasnya ) agar mudah digunakan kembali.

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)
}
Gibolt
sumber
Pertanyaannya adalah tentang Button, bukan TextView.
Firzen
1
Anda seharusnya sudah membaca jawabannya. Tombol A memperluas TextView, jadi Anda bisa menggunakan ini untuk keduanya. Atau ubah ekstensi untuk hanya memperpanjang Tombol
Gibolt
-1

Saya mencoba teknik posting ini tetapi tidak menemukan satupun dari mereka yang begitu menarik. Solusi saya adalah menggunakan imageview dan textview dan menyelaraskan imageview atas dan bawah ke textview. Dengan cara ini saya mendapatkan hasil yang diinginkan. Berikut beberapa kode:

<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>
Argumen Ilegal
sumber
-1

Saya membuat kelas tombol kustom untuk mencapai ini.

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>

Penggunaan dalam 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>
Jeffy Lee
sumber
1
Mengapa Anda membuat Canvasdi getResizedDrawabledan menarik ke dalamnya jika Anda tidak akan melakukan apa-apa dengan itu? Seluruh fungsi bisa direduksi hanya sampai drawable.setBounds(0, 0, mWidth, mHeight).
Antimonit