Zeichnungsgröße programmgesteuert einstellen

88

Die Bilder (Symbole) haben ungefähr die gleiche Größe, aber ich muss ihre Größe ändern, damit die Schaltflächen dieselbe Höhe haben.

Wie mache ich das?

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
quelle
Haben Sie herausgefunden, wie Sie die Größe von Drawable (Bitmap) ändern können?
Zelimir
2
Viel zu spät, aber Sie fragen sich, warum Sie nicht angerufen haben setCompoundDrawables()? Intrinsic bezieht sich auf die ursprüngliche Bildgröße an anderen Stellen in Android, z Drawable.getIntrinsicHeight().
William T. Mallard

Antworten:

158

Die setBounds()Methode funktioniert nicht für jeden Containertyp (hat jedoch für einige meiner Container funktioniert ImageView).

Versuchen Sie die folgende Methode, um das Zeichen selbst zu skalieren:

// 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
quelle
Für mich ist das Problem hier, dass es ein weißes Rechteck um das zeichnbare Bild
zeichnet
8
Der BitmapDrawable-Konstruktor (Bitmap) ist veraltet. Verwendung: Drawable d = new BitmapDrawable (getResources (), Bitmap.createScaledBitmap (Bitmap, 50, 50, true));
Andy
1
Dies erzeugt eine Pixelierung beim Skalieren von Drawables. Auch wenn es sich um Vektorzeichnungen handelt.
Sanket Berde
wahrscheinlich wollenContextCompat.getDrawable(context, resourceid)
Pierre
Als Randnotiz können Sie StateListDrawableprogrammgesteuert erstellen und die addStateMethode mit diesem "konvertierten Zeichen" verwenden, damit es für selector's itemdie in verwendete Größe funktioniert setPasswordVisibilityToggleDrawable.
Obst
31

Geben Sie die Größe mit an setBounds(), dh für eine Verwendung im Format 50 x 50

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

public void setBounds (int links, int oben, int rechts, int unten)

jkhouw1
quelle
2
Nach SetBounds bleibt die Größe gleich. Möglicherweise wird eine Ungültigmachung benötigt?
Kostadin
6
Tatsächlich funktioniert setBounds für GradientDrawables. Es funktioniert einfach nicht für Image Drawables.
Gregm
Es hat bei mir funktioniert, als ich das Bild in eine Schaltfläche eingefügt habe, aber nicht, als ich es in eine ImageView eingefügt habe. Das OP benutzte eine Taste, rief aber auch den eigentlichen Geschmack der setCompoundDrawables()Funktion auf.
William T. Mallard
@gregm Interessanterweise können Sie die Größe für ein GradientDrawable auch mit setSize () festlegen.
6.
12

Versuchen Sie vor dem Anwenden von .setBounds (..), das aktuelle Drawable in ScaleDrawable zu konvertieren

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

nachdem

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

wird funktionieren

iBog
quelle
2
Warum ist dieser Schritt erforderlich? Welche Verpackung in a ScaleDrawablebietet eine Alternative zur Nichtverpackung?
Azizbekian
10

Ich hatte keine Zeit zu graben, warum die setBounds () -Methode nicht wie erwartet mit Bitmap Drawable funktioniert, aber ich habe eine kleine optimierte @ androbean-Studio-Lösung, um das zu tun, was setBounds tun sollte ...

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

Verwendung:

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

Ergebnisse

vorher: Geben Sie hier die Bildbeschreibung ein nachher:Geben Sie hier die Bildbeschreibung ein

ceph3us
quelle
Wie füge ich noch Polster hinzu?
reegan29
7

Benutzen

textView.setCompoundDrawablesWithIntrinsicBounds()

Ihre minSdkVersion sollte 17 in build.gradle sein

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

So ändern Sie die Zeichengröße:

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

Verwenden Sie die Post-Methode, um den gewünschten Effekt zu erzielen:

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

Wahrscheinlich etwas spät. Aber hier ist die Lösung, die endlich in jeder Situation für mich funktioniert hat.

Die Idee ist, ein benutzerdefiniertes Zeichenobjekt mit fester innerer Größe zu erstellen und den Zeichenauftrag an das ursprüngliche Zeichenelement weiterzugeben.

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);
        }
    };
Androbean Studio
quelle
Was ist mPlatform?
Batsheva
@batsheva Es ist nur etwas, das er für die Konvertierung von dp zu px verwendet ...
Android-Entwickler
0

Sie können eine Unterklasse des Ansichtstyps erstellen und die onSizeChanged-Methode überschreiben.

Ich wollte in meinen Textansichten zusammengesetzte Drawables skalieren, ohne dass ich mit dem Definieren von Bitmap-Drawables in XML usw. herumspielen musste, und tat dies folgendermaßen:

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

}

(Beachten Sie, dass ich w zweimal verwendet habe, nicht h, da ich in diesem Fall das Symbol über dem Text platziert habe und das Symbol daher nicht die gleiche Höhe wie die Textansicht haben sollte.)

Dies kann auf Hintergrundzeichnungen oder auf alles andere angewendet werden, dessen Größe Sie relativ zu Ihrer Ansichtsgröße ändern möchten. onSizeChanged () wird beim ersten Erstellen der Ansicht aufgerufen, sodass Sie keine Sonderfälle zum Initialisieren der Größe benötigen.

Zulaxia
quelle
0

Die Antwort von jkhouw1 ist richtig, aber es fehlen einige Details, siehe unten:

Zumindest für API> 21 ist dies viel einfacher. Angenommen, wir haben VectorDrawable aus Ressourcen (Beispielcode zum Abrufen):

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

Für dieses VectorDrawable stellen Sie einfach die gewünschte Größe ein:

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

Und zeige zeichnbar in Knopf:

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

Das ist es. Beachten Sie jedoch, dass Sie setCompoundDrawables verwenden (keine intrinsische Version)!

Ilia Petukhov
quelle
0

Sie können es versuchen button.requestLayout(). Wenn die Hintergrundgröße geändert wird, muss sie neu gemessen und angeordnet werden, dies wird jedoch nicht durchgeführt

Xiaomei
quelle
0

Das funktioniert mit 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) }

Beispiel:

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-Entwickler
quelle
-1

Sie können LayerDrawable nur von einer Ebene und der setLayerInset-Methode aus verwenden:

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

Es ist schon eine Weile her, dass die Frage gestellt wurde,
aber für viele ist immer noch unklar, wie man diese einfache Sache macht.

In diesem Fall ist es ziemlich einfach, wenn Sie ein Drawable als zusammengesetztes Drawable in einer TextView (Schaltfläche) verwenden.

Also 2 Dinge, die Sie tun müssen:

1. Grenzen setzen:

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

2.Stellen Sie das Zeichen entsprechend ein (ohne Verwendung von Eigengrenzen):

button.setCompoundDrawablesRelative(drawable, null, null, null)
  • Bitmaps müssen nicht verwendet werden
  • Keine Problemumgehungen wie ScaleDrawable ColorDrawableoder LayerDrawable(was definitiv für andere Zwecke erstellt wurde)
  • Keine Notwendigkeit in benutzerdefinierten Zeichen!
  • Keine Problemumgehungen mit dem post
  • Es ist eine native und einfache Lösung, genau wie Android es von Ihnen erwartet.
Leo Droidcoder
quelle
-43
Button button = new Button(this);
Button = (Button) findViewById(R.id.button01);

Verwenden Sie Button.setHeight()oder Button.setWeight()und legen Sie einen Wert fest.

user564612
quelle
9
Dadurch wird nur die Tastenhöhe festgelegt, nicht die Höhe des Zeichens. Ich möchte die Breite / Höhe des Zeichens einstellen (insbesondere wenn es größer als die eingestellte Tastenhöhe ist).
21
Sie wissen, dass Sie die Antwort löschen können, nicht wahr?
Iharob Al Asimi