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

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"

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)


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


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


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

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

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

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.


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


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


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)

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

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

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


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