Définir la taille dessinable par programme

90

Les images (icônes) ont à peu près la même taille, mais je dois les redimensionner pour que les boutons restent à la même hauteur.

Comment puis-je faire cela?

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
la source
Avez-vous trouvé le moyen de redimensionner un dessinable (Bitmap)?
Zelimir
2
Bien tard, mais vous vous demandez pourquoi vous n'appeliez pas setCompoundDrawables()? Intrinsèque fait référence à la taille de l'image d'origine à d'autres endroits dans Android, par exemple Drawable.getIntrinsicHeight().
William T.Mallard

Réponses:

159

La setBounds()méthode ne fonctionne pas pour tous les types de conteneurs (a cependant fonctionné pour certains de mes ImageView).

Essayez la méthode ci-dessous pour mettre à l'échelle le dessinable lui-même:

// 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
la source
pour moi le problème ici, c'est qu'il dessine un rectangle blanc autour de l'image
dessinable
8
Le constructeur BitmapDrawable (Bitmap) est obsolète. Utilisez: Drawable d = new BitmapDrawable (getResources (), Bitmap.createScaledBitmap (bitmap, 50, 50, true));
Andy
1
Cela créera une pixellisation lors de la mise à l'échelle des drawables. Même s'il s'agit de dessins vectoriels.
Sanket Berde
veulent probablement utiliserContextCompat.getDrawable(context, resourceid)
Pierre
En remarque, vous pouvez créer par StateListDrawableprogramme et utiliser une addStateméthode avec ce "dessinable converti" pour le faire fonctionner pour la selector's itemtaille utilisée dans setPasswordVisibilityToggleDrawable.
Fruit
31

Précisez la taille avec setBounds(), c'est-à-dire pour une utilisation au format 50x50

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

public void setBounds (int gauche, int haut, int droite, int bas)

jkhouw1
la source
2
Après SetBounds, la taille reste la même. Peut-être qu'une invalidation est nécessaire?
Kostadin le
6
En fait, setBounds fonctionne pour GradientDrawables. Cela ne fonctionne tout simplement pas pour Image Drawables.
gregm
Cela a fonctionné pour moi lorsque je mettais l'image dans un bouton, mais pas lorsque je la mettais dans une ImageView. L'OP utilisait un bouton, mais appelait également la saveur intrinsèque de la setCompoundDrawables()fonction.
William T.Mallard
@gregm Fait intéressant, vous pouvez également définir la taille d'un GradientDrawable à l'aide de setSize ().
6rchid le
12

Avant d'appliquer .setBounds (..), essayez de convertir le dessin actuel en ScaleDrawable

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

après ça

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

marchera

iBog
la source
2
Pourquoi cette étape est-elle nécessaire? Quel emballage dans un ScaleDrawableoffre une alternative au non emballage?
azizbekian
10

Je n'ai pas eu le temps de creuser la raison pour laquelle la méthode setBounds () ne fonctionne pas sur le dessin bitmap comme prévu, mais j'ai peu modifié la solution @ androbean-studio pour faire ce que setBounds devrait faire ...

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

usage:

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

résultats

avant: entrez la description de l'image ici après:entrez la description de l'image ici

ceph3us
la source
comment ajouter un rembourrage à gauche?
reegan29
8

Utiliser

textView.setCompoundDrawablesWithIntrinsicBounds()

Votre minSdkVersion doit être 17 dans build.gradle

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

Pour modifier la taille de dessin:

    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
la source
3

Utilisez la méthode post pour obtenir l'effet souhaité:

{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
la source
3

Probablement un peu tard. Mais voici la solution qui a finalement fonctionné pour moi dans chaque situation.

L'idée est de créer un dessin personnalisé avec une taille intrinique fixe et de transmettre le travail de dessin au dessin original.

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);
        }
    };
Studio Androbean
la source
qu'est-ce que mPlatform?
batsheva
@batsheva C'est juste quelque chose qu'il utilise pour la conversion de DP en px ...
Développeur Android
2

La réponse jkhouw1 est correcte, mais il manque quelques détails, voir ci-dessous:

C'est beaucoup plus facile pour au moins API> 21. Supposons que nous ayons VectorDrawable à partir des ressources (exemple de code pour le récupérer):

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

Pour ce VectorDrawable, définissez simplement la taille souhaitée:

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

Et montrer dessinable dans le bouton:

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

C'est ça. Mais notez d'utiliser setCompoundDrawables (pas la version Intrinsic)!

Ilia Petukhov
la source
0

Vous pouvez créer une sous-classe du type de vue et remplacer la méthode onSizeChanged.

Je voulais avoir des éléments de dessin composés de mise à l'échelle sur mes vues de texte qui ne m'obligeaient pas à me soucier de définir des éléments de dessin bitmap en xml, etc. et je l'ai fait de cette façon:

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

}

(Notez que j'ai utilisé w deux fois, pas h, car dans ce cas, je mettais l'icône au-dessus du texte, et donc l'icône ne devrait pas avoir la même hauteur que la vue texte)

Cela peut être appliqué aux dessins d'arrière-plan ou à tout autre élément que vous souhaitez redimensionner en fonction de la taille de votre vue. onSizeChanged () est appelé la première fois que la vue est créée, vous n'avez donc pas besoin de cas particuliers pour initialiser la taille.

Zulaxia
la source
0

Vous pouvez essayer button.requestLayout(). Lorsque la taille de l'arrière-plan est modifiée, il doit être mesuré et sa mise en page, mais cela ne le fera pas

Xiaomei
la source
0

Cela fonctionne en utilisant 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) }

Exemple:

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)
développeur android
la source
-1

Vous pouvez utiliser LayerDrawable à partir d'une seule couche et de la méthode 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);
Valery Miller
la source
-1

Cela fait un moment que la question n'a pas été posée,
mais beaucoup ne savent toujours pas comment faire cette chose simple.

C'est assez simple dans ce cas lorsque vous utilisez un Drawable comme dessin composé sur un TextView (Button).

Donc 2 choses que vous devez faire:

1. définir des limites:

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

2.Définissez le dessinable de manière appropriée (sans utiliser de limites intrinsèques):

button.setCompoundDrawablesRelative(drawable, null, null, null)
  • Pas besoin d'utiliser des Bitmaps
  • Aucune solution de contournement telle que ScaleDrawable ColorDrawableou LayerDrawable(ce qui est définitivement créé à d'autres fins)
  • Pas besoin de tirables personnalisés!
  • Aucune solution de contournement avec le post
  • C'est une solution native et simple, exactement comme Android attend de vous.
Leo Droidcoder
la source
-42
Button button = new Button(this);
Button = (Button) findViewById(R.id.button01);

Utilisez Button.setHeight()ou Button.setWeight()et définissez une valeur.

user564612
la source
9
qui définit simplement la hauteur du bouton, pas la hauteur du dessinable. Je veux définir la largeur / hauteur du dessin (surtout s'il est plus grand que la hauteur du bouton défini).
21
Vous savez que vous pouvez supprimer la réponse, n'est-ce pas?
Iharob Al Asimi