Wie kann ich das Zeichenobjekt auf einem Knopf verkleinern?


86

Wie kann ich das Zeichen auf einem Knopf verkleinern? Das Symbol ist zu groß, tatsächlich höher als die Schaltfläche. Dies ist der Code, den ich verwende:

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

Das obere ist, wie es aussehen sollte, das untere, wie es jetzt aussieht.

Das obere ist, wie es aussehen sollte, das untere, wie es jetzt aussieht.

Ich habe es versucht, aber es wird kein Bild angezeigt. :-(

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

Es wäre besser, wenn Sie ein Bild hochladen, das zeigt, was Sie erhalten und was Sie versuchen zu tun. Vielen Dank.
Lalit Poptani

Sie können Ihre benutzerdefinierte Schaltfläche definieren, um die Größe der Zeichen zu definieren. Siehe meine Antwort hier stackoverflow.com/a/31916731/2308720
Oleksandr

Ich weiß, dass dies aus dem Jahr 2011 stammt ... aber ich bevorzuge eigentlich das Aussehen des Knopfes mit einer Kamera, die aus den Grenzen des Knopfes herausbricht - ich hätte es so belassen, wie es war ... sag es einfach :)
killercowuk

Antworten:


69

Sie sollten ein verwenden Image und das Bild angeben android:src, und Satz android:scaletypezufitXY


Einstellung skalierbar im Code zeichnbar

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

Wenn Sie das Zeichenelement im Code festlegen, können Sie die Größe basierend auf der Schaltflächenhöhe ändern und dann festlegen.
Ronnie

Jetzt wird das Bild angezeigt, aber die Größe wird nicht geändert! Ich habe Werte zwischen 0.1f und 10f ausprobiert. Irgendeine Idee? Vielen Dank für Ihre Hilfe ...
Reto

Versuchen Sie diesdrawable.setBounds(0, 0, drawable.getIntrinsicWidth()*0.5, drawable.getIntrinsicHeight()*0.5);
Ronnie

Wenn dadurch die Größe des Zeichens geändert wird, können Sie das skalierbare Teil entfernen und das Zeichen direkt verwenden.
Ronnie

2
Sollen wir unsere eigenen Werte für scaleWidth und scaleHeight festlegen? Sind sie nur beschreibend?
SametSahin

87

Ich habe eine sehr einfache und effektive XML-Lösung gefunden, die nicht erforderlich ist ImageButton

Erstellen Sie eine zeichnbare Datei für Ihr Bild wie unten und verwenden Sie sie für 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>

Sie können die Bildgröße mit android:widthund android:heightEigenschaften einstellen .

Auf diese Weise können Sie mindestens die gleiche Größe für verschiedene Bildschirme erhalten.

Der Nachteil ist, dass es nicht genau wie fitXY ist, das die Bildbreite auf X skaliert und die Bildhöhe entsprechend skaliert.


9
Dies sollte die akzeptierte Antwort sein. Wenn Sie keinen ImageButton möchten (z. B. weil sie Text usw. möchten), ermöglicht diese Antwort die Größe von Bildern innerhalb eines Buttons mit Text plus Nullcode.
Recycelter Stahl

3
Ich habe ein neues Zeichen wie dieses erstellt und dann android:drawableTopdas neue Zeichen hinzugefügt. Egal welche Werte für die Breite / Höhe ich eingestellt habe, es zeigt mir den Standardwert.
Driftking9987

9
Scheint nicht für Android-Versionen unter Lollipop zu funktionieren.
Jyotman Singh

32
Höhe, Breite funktionieren nur in API-Level 23 und höher. Nicht rückwärts unterstützt.
Palak Darji

Ich stimme zu, dies ist bei weitem die beste Lösung
Senzo Malinga

10

Schaltflächen ändern nicht die Größe ihrer inneren Bilder.

Meine Lösung erfordert keine Code-Manipulation.

Es verwendet ein Layout mit TextView und ImageView.

Der Hintergrund des Layouts sollte die rote 3D-Zeichnung haben.

Möglicherweise müssen Sie das XML-Attribut android: scaleType definieren .

Beispiel:

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

Übrigens:

  1. Das Zählen auf Symbole mit unterschiedlicher Auflösung kann zu einer nicht vorhersehbaren Benutzeroberfläche führen (Symbol zu groß oder zu klein).
  2. Text in der Textansicht (einschließlich in Schaltflächen) füllt die Komponente nicht aus. Dies ist ein Android-Problem und ich weiß nicht, wie ich es lösen soll.
  3. Sie können es als Include verwenden.

Viel Glück


RE: TextViews, wenn ich möchte, dass die Ansicht so klein wie möglich ist, setze ich den Abstand dafür auf Null. Ansonsten scheint es eine Standardauffüllung zu geben.
William T. Mallard

6

Verwenden Sie ein ScaleDrawable, wie von Abhinav vorgeschlagen.

Das Problem ist, dass das Drawable dann nicht angezeigt wird - es ist eine Art Fehler in ScaleDrawables. Sie müssen das "Level" programmgesteuert ändern. Dies sollte für jede Schaltfläche funktionieren:

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

Nett. Ich denke, ich könnte dies in naher Zukunft nutzen!
Abhinav

@zeh, jetzt habe ich festgestellt, dass es funktioniert, wenn Sie den obigen Code vor setContentView ausführen, sonst funktioniert es nicht. Es könnte besser sein, wenn Sie dies zu Ihrem Beitrag hinzufügen.
Buddy

Aus irgendeinem Grund funktioniert meine obige Lösung nicht auf allen Android-Versionen.
Buddy

6

Mein DiplayScaleHelper, das funktioniert perfekt:

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

Sie können setBoundsdie "zusammengesetzten" Zeichen aufrufen, um die Größe des Bildes zu ändern.

Versuchen Sie diesen Code, um die Zeichnungsgröße Ihrer Schaltfläche automatisch zu ändern:

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

definiert durch diese Funktion:

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

Beachten Sie, dass dies möglicherweise nicht onCreate()für eine Aktivität aufgerufen wird , da Höhe und Breite der Schaltflächen dort (noch) nicht verfügbar sind. Rufen Sie dies auf onWindowFocusChanged()oder verwenden Sie diese Lösung , um die Funktion aufzurufen.

Bearbeitet:

Die erste Inkarnation dieser Funktion funktionierte nicht richtig. Es wurde userSeven7s Code verwendet, um das Bild zu skalieren, aber die Rückgabe ScaleDrawable.getDrawable() scheintScaleDrawable für mich nicht zu funktionieren (und auch nicht ).

Der geänderte Code verwendet setBounds, um die Grenzen für das Bild bereitzustellen. Android passt das Bild in diese Grenzen.


Vielen Dank, dass Sie gesagt haben, Sie sollen es nicht anrufen onCreate().
Binarian


1

Ich mache es wie unten. Dadurch wird unabhängig vom Eingabebild ein Bild mit einer Größe von 100 x 100 in der Schaltfläche erstellt.

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

Auch nicht verwenden ScaleDrawable. Nicht verwendet hat button.setCompoundDrawablesRelativeWithIntrinsicBounds()mein Problem gelöst, da dies anscheinend intrinsische Grenzen (Quellbildgröße) anstelle der gerade festgelegten Grenzen verwendet.


0

Sie können Zeichenelemente unterschiedlicher Größe verwenden, die mit unterschiedlichen Bildschirmdichten / -größen usw. verwendet werden, damit Ihr Bild auf allen Geräten richtig aussieht.

Siehe hier: http://developer.android.com/guide/practices/screens_support.html#support


Ich benutze das gleiche Bild an verschiedenen Orten. Aus diesem Grund kann ich die Größe nicht ändern. Es sollte in der gewünschten Größe angezeigt werden.
Reto

0

Haben Sie versucht, Ihr Bild in ein ScaleDrawable zu verpacken und es dann in Ihrer Schaltfläche zu verwenden?


2
Ich habe es gerade versucht, aber mein ScaleDrawable wird nicht angezeigt. :-( Auch nicht in einer ImageView. Ich habe den Beispielcode genommen und nur den Drawable ersetzt. Irgendeine Idee, warum dies nicht funktioniert?
Reto

Ich hatte das gleiche Problem. ScaleDrawablewäre perfekt, aber es funktioniert einfach nicht. Es scheint etwas mit "Levels" zu tun zu haben. Weitere Informationen hier (und einige Problemumgehungen, die nicht perfekt sind): stackoverflow.com/questions/5507539/…
zeh

(bearbeiten) behoben mit einem generischen Code! Lösung hier, die es Ihnen weiterhin ermöglicht, ScaleDrawables zu verwenden: stackoverflow.com/a/13706836/439026
zeh

0

Hier die Funktion, die ich zum Skalieren von Vektorzeichnungen erstellt habe. Ich habe es zum Festlegen der zusammensetzbaren TextView-Verbindung verwendet.

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

Es ist, weil du es nicht getan hast setLevel. Nach Ihnen setLevel(1)wird es angezeigt, wie Sie möchten


0

Kotlin-Erweiterung verwenden

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)

Ich schlage vor, eine Erweiterungsfunktion in TextView zu erstellen ( Button erweitert sie ), um sie einfach wiederverwenden zu können.

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

Die Frage betraf Button, nicht TextView.
Firzen

1
Du hättest die Antwort lesen sollen. Eine Schaltfläche erweitert TextView, sodass Sie diese für beide verwenden können. Oder ändern Sie die Erweiterung, um nur einen Button
Gibolt zu erweitern.

-1

Ich habe die Techniken dieses Beitrags ausprobiert, fand aber keine davon so attraktiv. Meine Lösung bestand darin, eine Bildansicht und eine Textansicht zu verwenden und die Bildansicht oben und unten an der Textansicht auszurichten. Auf diese Weise habe ich das gewünschte Ergebnis erzielt. Hier ist ein Code:

<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

Ich habe eine benutzerdefinierte Schaltflächenklasse erstellt, um dies zu erreichen.

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>

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

1
Warum erstellen Sie ein CanvasIn getResizedDrawableund zeichnen es ein, wenn Sie nichts damit anfangen wollen? Die ganze Funktion könnte nur auf reduziert werden drawable.setBounds(0, 0, mWidth, mHeight).
Antimonit
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.