Imposta le dimensioni disegnabili a livello di codice


90

Le immagini (icone) hanno all'incirca le stesse dimensioni, ma ho bisogno di ridimensionarle in modo che i pulsanti rimangano alla stessa altezza.

Come faccio a fare questo?

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

Hai trovato il modo per ridimensionare il disegnabile (Bitmap)?
Zelimir

2
Molto tardi, ma ti chiedi perché non stavi chiamando setCompoundDrawables()? Intrinsic si riferisce alla dimensione dell'immagine originale in altri luoghi all'interno di Android, ad es Drawable.getIntrinsicHeight().
William T. Mallard

Risposte:


159

Il setBounds()metodo non funziona per ogni tipo di contenitore (tuttavia ha funzionato per alcuni dei miei ImageView).

Prova il metodo seguente per ridimensionare il disegno stesso:

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

per me il problema qui, è che disegna un rettangolo bianco attorno all'immagine disegnabile
noloman

8
Il costruttore BitmapDrawable (Bitmap) è deprecato. Usa: Drawable d = new BitmapDrawable (getResources (), Bitmap.createScaledBitmap (bitmap, 50, 50, true));
Andy

1
Questo creerà pixel quando si ridimensionano i drawable. Anche se sono disegnabili con vettori.
Sanket Berde

probabilmente vorrebbe usareContextCompat.getDrawable(context, resourceid)
Pierre

Come nota a margine, puoi creare StateListDrawableprogrammaticamente e usare il addStatemetodo con quel "disegnabile convertito" per farlo funzionare per le selector's itemdimensioni utilizzate in setPasswordVisibilityToggleDrawable.
Frutta

31

Specificare la dimensione con setBounds(), ad esempio per un utilizzo di dimensioni 50x50

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

public void setBounds (int a sinistra, int in alto, int a destra, int in basso)


2
Dopo SetBounds la dimensione rimane la stessa. Potrebbe essere necessario qualche invalidamento?
Kostadin

6
In realtà, setBounds funziona per GradientDrawables. Semplicemente non funziona per Image Drawables.
gregm

Ha funzionato per me quando stavo inserendo l'immagine in un pulsante, ma non quando l'ho inserita in un ImageView. L'OP utilizzava un pulsante, ma richiamava anche il sapore intrinseco della setCompoundDrawables()funzione.
William T. Mallard,

@gregm È interessante notare che puoi anche impostare la dimensione per un GradientDrawable usando setSize ().
6rchid

12

Prima di applicare .setBounds (..) prova a convertire Drawable corrente in ScaleDrawable

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

dopo di che

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

funzionerà


2
Perché è necessario questo passaggio? Quale avvolgimento in un ScaleDrawabledà alternativa al non avvolgimento?
azizbekian

10

Non ho avuto il tempo di scavare perché il metodo setBounds () non funziona su bitmap disegnabili come previsto, ma ho una soluzione @ androbean-studio poco ottimizzata per fare ciò che setBounds dovrebbe fare ...

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

utilizzo:

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

risultati

prima: inserisci qui la descrizione dell'immagine dopo:inserisci qui la descrizione dell'immagine


come aggiungere il riempimento a sinistra?
reegan29

8

Usare

textView.setCompoundDrawablesWithIntrinsicBounds()

La tua minSdkVersion dovrebbe essere 17 in build.gradle

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

Per modificare la dimensione del disegno:

    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

Usa il metodo post per ottenere l'effetto desiderato:

{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

Probabilmente un po 'tardi. Ma ecco la soluzione che finalmente ha funzionato per me in ogni situazione.

L'idea è di creare un disegno personalizzato con dimensioni intrinseche fisse e trasferire il lavoro di disegno al disegno originale.

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

cos'è mPlatform?
Batsheva

@batsheva È solo qualcosa che usa per la conversione da dp a px ...
sviluppatore Android

2

La risposta di jkhouw1 è quella corretta, ma manca di alcuni dettagli, vedi sotto:

È molto più semplice per almeno API> 21. Supponiamo di avere VectorDrawable dalle risorse (codice di esempio per recuperarlo):

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

Per quel VectorDrawable basta impostare la dimensione desiderata:

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

E mostra disegnabile nel pulsante:

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

Questo è tutto. Ma nota di usare setCompoundDrawables (non la versione Intrinsic)!


0

È possibile creare una sottoclasse del tipo di visualizzazione e sovrascrivere il metodo onSizeChanged.

Volevo avere drawables composti di ridimensionamento sulle mie visualizzazioni di testo che non richiedessero di scherzare con la definizione di drawables bitmap in xml, ecc. E l'ho fatto in questo modo:

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

}

(Nota che ho usato w due volte, non h, poiché in questo caso stavo mettendo l'icona sopra il testo, e quindi l'icona non dovrebbe avere la stessa altezza della vista del testo)

Questo può essere applicato ai drawable di sfondo o qualsiasi altra cosa tu voglia ridimensionare rispetto alla dimensione della tua vista. onSizeChanged () viene chiamato la prima volta che viene creata la vista, quindi non è necessario alcun caso speciale per inizializzare la dimensione.


0

Puoi provare button.requestLayout(). Quando la dimensione dello sfondo viene modificata, è necessario rimisurare e layout, ma non lo farà


0

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

Esempio:

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

Puoi utilizzare LayerDrawable da un solo livello e il metodo setLayerInset:

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

È passato un po 'di tempo da quando è stata posta la domanda,
ma per molti non è ancora chiaro come fare questa semplice cosa.

È piuttosto semplice in questo caso quando si utilizza un Drawable come un composto disegnabile su un TextView (Button).

Quindi 2 cose che devi fare:

1.Impostare i limiti:

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

2.Impostare il disegnabile in modo appropriato (senza utilizzare limiti intrinseci):

button.setCompoundDrawablesRelative(drawable, null, null, null)
  • Non è necessario utilizzare Bitmap
  • Nessuna soluzione alternativa come ScaleDrawable ColorDrawableo LayerDrawable(cosa viene sicuramente creato per altri scopi)
  • Non c'è bisogno di drawables personalizzati!
  • Nessuna soluzione alternativa con post
  • È una soluzione nativa e semplice, proprio come Android si aspetta che tu faccia.

-42
Button button = new Button(this);
Button = (Button) findViewById(R.id.button01);

Usa Button.setHeight()o Button.setWeight()e imposta un valore.


9
che imposta solo l'altezza del pulsante, non l'altezza del drawable. voglio impostare la larghezza / altezza del drawable (specialmente se è maggiore dell'altezza del pulsante impostato).

21
Sai che puoi cancellare la risposta, vero?
Iharob Al Asimi
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.