Bir düğmenin üzerindeki çekmeceyi nasıl küçültebilirim?


87

bir düğmedeki çekmeceyi nasıl küçültebilirim? Simge çok büyük, aslında düğmeden daha yüksek. Kullandığım kod bu:

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

Üst kısım nasıl görünmesi gerektiği, şu anda nasıl göründüğü ile ilgili.

Üst kısım nasıl görünmesi gerektiği, şu anda nasıl göründüğü ile ilgili.

Bunu denedim ama hiçbir resim görüntülenmiyor. :-(

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

Ne aldığınızın ve ne yapmaya çalıştığınızın bir resmini yüklerseniz daha iyi olur. Teşekkürler.
Lalit Poptani

Çekmecelerin boyutunu belirlemek için özel düğmenizi tanımlayabilirsiniz. Cevabımı burada görün stackoverflow.com/a/31916731/2308720
Oleksandr

Bunun 2011'den olduğunu biliyorum ... ama aslında kameranın düğmenin sınırlarını
aştığı bir

Yanıtlar:


70

Bir kullanmalıdır ımagebutton ve görüntüyü belirtmek android:srcve set android:scaletypeiçinfitXY


Kodda ölçeklenmiş çekilebilirlik ayarlama

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

Çekilebilirliği kodda ayarlarsanız, düğme yüksekliğine göre yeniden boyutlandırabilir ve ardından ayarlayabilirsiniz.
Ronnie

Şimdi görüntü gösteriliyor ancak yeniden boyutlandırılmıyor! 0.1f ile 10f arasındaki değerleri denedim. Herhangi bir fikir? Yardımlarınız için teşekkürler ...
Reto

Deneyindrawable.setBounds(0, 0, drawable.getIntrinsicWidth()*0.5, drawable.getIntrinsicHeight()*0.5);
Ronnie

Bu, çekilebilir parçayı yeniden boyutlandırırsa, ölçeklenebilir çizilebilir parçayı kaldırabilir ve çekilebilir parçayı doğrudan kullanabilirsiniz.
Ronnie

2
ScaleWidth ve scaleHeight için kendi değerlerimizi belirlememiz mi gerekiyor? Onlar sadece tanımlayıcı mı?
SametSahin

90

Gerektirmeyen çok basit ve etkili bir XML çözümü buldum ImageButton

Resminiz için aşağıdaki gibi çekilebilir bir dosya yapın ve kullanın 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>

Görüntü boyutunu android:widthve android:heightözellikleriyle ayarlayabilirsiniz .

Bu şekilde en azından farklı ekranlar için aynı boyutu elde edebilirsiniz.

Bunun dezavantajı, görüntü genişliğini X'e sığacak şekilde ölçeklendirecek ve görüntü yüksekliğini buna göre ölçeklendirecek olan fitXY'ye tam olarak benzememesidir.


9
Kabul edilen cevap bu olmalıdır. Bir ImageButton istemiyorsa (örneğin, metin istedikleri için, vb.), Bu yanıt Metin artı sıfır kodlu bir Düğme içinde boyutlandırılmış görüntülere izin verir.
Recycled Steel

3
Bunun gibi yeni bir çekmece yaptım ve sonra android:drawableTopyeni çekmeceyi ekledim. Ayarladığım genişlik / yükseklik için hangi değerler olursa olsun, bana varsayılan olanı gösteriyor.
driftking9987

9
Lollipop'un altındaki Android sürümleri için çalışmıyor gibi görünüyor.
Jyotman Singh

32
yükseklik, genişlik yalnızca API seviyesi 23 ve üzerinde çalışır. Geriye doğru desteklenmez.
Palak Darji

Katılıyorum, bu açık ara en iyi çözüm
Senzo Malinga

10

Düğmeler iç görüntülerini yeniden boyutlandırmaz.

Çözümüm kod manipülasyonu gerektirmiyor.

TextView ve ImageView ile bir düzen kullanır.

Düzenin arka planı kırmızı 3 boyutlu çekilebilir olmalıdır.

Android: scaleType'ı tanımlamanız gerekebilir xml niteliğini .

Misal:

<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. Farklı çözünürlük simgelerine güvenmek, öngörülemeyen bir kullanıcı arayüzüne neden olabilir (simge çok büyük veya çok küçük)
  2. Metin görünümündeki metin (düğmeler dahil) bileşeni doldurmuyor. Bu bir Android problemi ve nasıl çözeceğimi bilmiyorum.
  3. İçerme olarak kullanabilirsiniz.

İyi şanslar


RE: TextViews, eğer görünümün olabildiğince küçük olmasını istiyorsam, onun dolgusunu sıfıra ayarlıyorum. Aksi takdirde varsayılan bir dolgusu var gibi görünüyor.
William T. Mallard

6

Bir kullan ScaleDrawable olarak Abhinav önerdi.

Sorun şu ki, çekilebilir dosya o zaman gösterilmiyor - bu, ScaleDrawables'da bir tür hata. "düzeyi" programlı olarak değiştirmeniz gerekir. Bu, her düğme için çalışmalıdır:

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

Güzel. Bunu yakın gelecekte kullanabileceğimi düşünüyorum!
Abhinav

@zeh, şimdi yukarıdaki kodu setContentView'dan önce çalıştırırsanız çalıştığını, aksi takdirde çalışmadığını öğrendim. Bunu gönderinize eklerseniz daha iyi olabilir.
Buddy

Bazı nedenlerden dolayı, yukarıdaki çözümüm tüm android sürümlerinde çalışmıyor.
Buddy

6

Mükemmel çalışan DiplayScaleHelper'ım:

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

Arayabilirsin setBoundsGörüntünün boyutunu değiştirmek için "bileşik" çekmeceleri .

Düğmenizin çekilebilirliğini otomatik boyutlandırmak için bu kodu deneyin:

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

bu işlev tarafından tanımlanmıştır:

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

Bunun onCreate()bir aktivitede çağrılmayabileceğini unutmayın , çünkü düğme yüksekliği ve genişliği orada (henüz) mevcut değildir. Bunu arayın onWindowFocusChanged()veya işlevi çağırmak için bu çözümü kullanın.

Düzenlendi:

Bu işlevin ilk enkarnasyonu düzgün çalışmadı. Görüntüyü ölçeklemek için userSeven7s kodunu kullandı, ancak geri dönüş ScaleDrawable.getDrawable() işe yaramıyor gibi görünüyor ( geri dönmüyorScaleDrawable ).

Değiştirilen kod setBounds, görüntünün sınırlarını sağlamak için kullanılır. Android, resmi bu sınırlara sığdırır.


Aramayın dediğin için teşekkür ederim onCreate().
Binaryan


1

Ben aşağıdaki gibi yapıyorum. Bu, giriş görüntüsünden bağımsız olarak düğmede 100x100 boyutunda bir görüntü oluşturur.

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

İkisini de kullanmıyorum ScaleDrawable. Sorunumu kullanmamak button.setCompoundDrawablesRelativeWithIntrinsicBounds(), belirlediğiniz sınırlar yerine içsel sınırlar (kaynak görüntü boyutu) kullanıyor gibi görünüyor.



0

Resminizi bir ScaleDrawable'a sarmayı ve ardından düğmenizde kullanmayı denediniz mi?


2
Bunu biraz önce denedim, ancak ScaleDrawable'ım görüntülenmiyor. . :-( bile değil ImageView ben örnek kod aldı ve sadece çekilebilir yerini bu işi yapmaz neden bir fikrin.?
Reto

Ben de aynı sorunu yaşadım. ScaleDrawablemükemmel olurdu ama işe yaramıyor. "Seviyeler" ile bir ilgisi var gibi görünüyor. Daha fazla bilgiyi burada bulabilirsiniz (ve mükemmel olmayan bazı geçici çözümler): stackoverflow.com/questions/5507539/…
zeh

(değiştir) bazı genel kodlarla düzeltildi! Yine de ScaleDrawables'ı kullanmanıza izin veren çözüm: stackoverflow.com/a/13706836/439026
zeh

0

Burada vektör çizimlerini ölçeklendirmek için oluşturduğum fonksiyon. TextView bileşik çekilebilirliğini ayarlamak için kullandım.

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

Çünkü sen yapmadın setLevel. senden sonra istediğin setLevel(1)gibi gösterilecek


0

Kotlin Uzantısını Kullanma

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)

Kolay yeniden kullanım için TextView ( Düğme onu genişletir ) üzerinde bir uzantı işlevi oluşturmanızı öneririm .

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

Soru TextView değil Button hakkındaydı.
Firzen

1
Cevabı okumalıydın. Bir Düğme TextView öğesini genişletir, böylece bunu her ikisi için de kullanabilirsiniz. Veya uzantıyı yalnızca bir Düğmeyi uzatacak şekilde değiştirin
Gibolt

-1

Bu yazının tekniklerini denedim ama hiçbirini bu kadar çekici bulmadım. Çözümüm, bir görüntü görünümü ve metin görünümü kullanmak ve görüntü görünümünü metin görünümünün üst ve altını hizalamaktı. Bu şekilde istenen sonucu aldım. İşte bazı kodlar:

<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

Bunu başarmak için özel bir düğme sınıfı yaptım.

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'de kullanım

<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
Onunla hiçbir şey yapmayacaksanız, neden bir Canvasgiriş oluşturup getResizedDrawableiçine çekiyorsunuz? Tüm işlev sadece olarak azaltılabilir drawable.setBounds(0, 0, mWidth, mHeight).
Antimonit
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.