Programowo ustaw rozmiar do rysowania


90

Obrazy (ikony) mają mniej więcej ten sam rozmiar, ale muszę je zmienić, aby przyciski miały tę samą wysokość.

Jak mam to zrobic?

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

Czy znalazłeś sposób, jak zmienić rozmiar do rysowania (mapa bitowa)?
Zelimir

2
Dużo późno, ale zastanawiasz się, dlaczego nie dzwoniłeś setCompoundDrawables()? Wewnętrzny odnosi się do oryginalnego rozmiaru obrazu w innych miejscach w systemie Android, np Drawable.getIntrinsicHeight().
William T. Mallard

Odpowiedzi:


159

Ta setBounds()metoda nie działa dla każdego typu kontenera (działała jednak dla niektórych moich ImageView).

Wypróbuj poniższą metodę, aby wyskalować sam rysunek:

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

dla mnie problem polega na tym, że rysuje biały prostokąt wokół rysowanego obrazu
noloman

8
Konstruktor BitmapDrawable (Bitmap) jest przestarzały. Użyj: Drawable d = new BitmapDrawable (getResources (), Bitmap.createScaledBitmap (bitmap, 50, 50, true));
Andy

1
Spowoduje to utworzenie pikselizacji podczas skalowania w górę rysunków. Nawet jeśli są to rysunki wektorowe.
Sanket Berde

prawdopodobnie chcesz użyćContextCompat.getDrawable(context, resourceid)
Pierre

Na marginesie, możesz tworzyć StateListDrawableprogramowo i używać addStatemetody z tym „konwertowanym do rysowania”, aby działała ona dla selector's itemrozmiaru używanego w programie setPasswordVisibilityToggleDrawable.
Owoce

31

Określ rozmiar za pomocą setBounds(), np. Aby użyć rozmiaru 50x50

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

public void setBounds (int left, int top, int right, int bottom)


2
Po SetBounds rozmiar pozostaje taki sam. Może być potrzebny jakiś unieważniony?
Kostadin,

6
Właściwie setBounds działa dla GradientDrawables. Po prostu nie działa w przypadku rysunków graficznych.
gregm

U mnie zadziałało, kiedy umieszczałem obraz w przycisku, ale nie wtedy, gdy umieszczałem go w ImageView. OP używał przycisku, ale także wywoływał wewnętrzny smak setCompoundDrawables()funkcji.
William T. Mallard

@gregm Co ciekawe, możesz również ustawić rozmiar GradientDrawable za pomocą setSize ().
6rchid

12

Przed zastosowaniem .setBounds (..) spróbuj przekonwertować bieżący Drawable na ScaleDrawable

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

po tym

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

będzie działać


2
Dlaczego ten krok jest potrzebny? Jakie opakowanie ScaleDrawablestanowi alternatywę dla niezawijania?
azizbekian

10

Nie miałem czasu, aby dowiedzieć się, dlaczego metoda setBounds () nie działa na bitmapach do rysowania zgodnie z oczekiwaniami, ale mam trochę zmodyfikowane rozwiązanie @ androbean-studio, aby zrobić to, co powinno zrobić setBounds ...

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

stosowanie:

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

wyniki

before: wprowadź opis obrazu tutaj after:wprowadź opis obrazu tutaj


jak dodać dopełnienie w lewo?
reegan 29

8

Używać

textView.setCompoundDrawablesWithIntrinsicBounds()

Twoja minSdkVersion powinna mieć 17 w build.gradle

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

Aby zmienić rozmiar do rysowania:

    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

Użyj metody postu, aby osiągnąć pożądany efekt:

{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

Prawdopodobnie trochę późno. Ale oto rozwiązanie, które w końcu zadziałało dla mnie w każdej sytuacji.

Chodzi o to, aby stworzyć niestandardowy element do rysowania ze stałym wewnętrznym rozmiarem i przekazać zadanie rysowania do oryginalnego rysunku.

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

co to jest mPlatform?
batsheva

@batsheva To po prostu coś, czego używa do konwersji z dp na px ...
programista Androida

2

Odpowiedź jkhouw1 jest poprawna, ale brakuje jej niektórych szczegółów, patrz poniżej:

Jest to o wiele łatwiejsze dla przynajmniej API> 21. Załóżmy, że mamy VectorDrawable z zasobów (przykładowy kod do pobrania):

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

Dla tego VectorDrawable ustaw żądany rozmiar:

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

I pokaż do rysowania w przycisku:

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

Otóż ​​to. Ale uwaga, aby używać setCompoundDrawables (nie w wersji Intrinsic)!


0

Można utworzyć podklasę typu widoku i nadpisać metodę onSizeChanged.

Chciałem mieć skalowane złożone rysunki w moich widokach tekstu, które nie wymagałyby majstrowania przy definiowaniu rysunków bitmapowych w XML itp. I zrobiłem to w ten sposób:

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

}

(Zwróć uwagę, że dwukrotnie użyłem w, a nie h, ponieważ w tym przypadku umieszczałem ikonę nad tekstem, a zatem ikona nie powinna mieć tej samej wysokości co widok tekstu)

Można to zastosować do rysunków w tle lub czegokolwiek innego, co chcesz zmienić w stosunku do rozmiaru widoku. onSizeChanged () jest wywoływana przy pierwszym utworzeniu widoku, więc nie potrzebujesz żadnych specjalnych przypadków do inicjalizacji rozmiaru.


0

Możesz spróbować button.requestLayout(). Gdy rozmiar tła zostanie zmieniony, należy ponownie zmierzyć i rozmieścić, ale nie zrobi tego


0

To działa przy użyciu 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) }

Przykład:

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

Możesz użyć LayerDrawable tylko z jednej warstwy i metody 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

Minęło trochę czasu, odkąd zadano to pytanie,
ale dla wielu nadal nie jest jasne, jak zrobić tę prostą rzecz.

Jest to całkiem proste w tym przypadku, gdy używasz Drawable jako złożonego do rysowania w TextView (Button).

Więc dwie rzeczy, które musisz zrobić:

1. ustaw granice:

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

2. Ustaw odpowiednio wyciąganą (bez wewnętrznych granic):

button.setCompoundDrawablesRelative(drawable, null, null, null)
  • Nie ma potrzeby używania map bitowych
  • Brak obejść, takich jak ScaleDrawable ColorDrawablelubLayerDrawable (co zdecydowanie zostało utworzone do innych celów)
  • Nie ma potrzeby niestandardowych rysunków!
  • Brak obejść dla post
  • To natywne i proste rozwiązanie, dokładnie takie, jakiego oczekuje od Ciebie Android.

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

Użyj Button.setHeight()lub Button.setWeight()i ustaw wartość.


9
która tylko ustawia wysokość przycisku, a nie wysokość elementu do rysowania. Chcę ustawić szerokość / wysokość elementu do rysowania (zwłaszcza jeśli jest większy niż ustawiona wysokość przycisku).

21
Wiesz, że możesz usunąć odpowiedź, prawda?
Iharob Al Asimi
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.