Đặt kích thước có thể vẽ theo lập trình


90

Các hình ảnh (biểu tượng) có cùng kích thước, nhưng tôi cần thay đổi kích thước của chúng để các nút vẫn giữ nguyên chiều cao.

Làm thế nào để tôi làm điều này?

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

Bạn đã tìm ra cách thay đổi kích thước có thể vẽ được (Bitmap) chưa?
Zelimir

2
Đã muộn, nhưng tự hỏi tại sao bạn không gọi setCompoundDrawables()? Nội tại đề cập đến kích thước hình ảnh gốc ở những nơi khác trong Android, ví dụ Drawable.getIntrinsicHeight().
William T. Mallard

Câu trả lời:


159

Các setBounds()phương pháp không làm việc cho tất cả các loại container (đã làm việc cho một số của tôi ImageView's, tuy nhiên).

Hãy thử phương pháp dưới đây để chia tỷ lệ bản thân có thể vẽ:

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

đối với tôi vấn đề ở đây là nó vẽ một hình chữ nhật màu trắng xung quanh hình ảnh có thể vẽ được
noloman

8
Phương thức tạo BitmapDrawable (Bitmap) không được dùng nữa. Sử dụng: Drawable d = new BitmapDrawable (getResources (), Bitmap.createScaledBitmap (bitmap, 50, 50, true));
Andy

1
Điều này sẽ tạo ra pixelation khi mở rộng các tệp có thể vẽ. Ngay cả khi chúng là vật có thể vẽ được vector.
Sanket Berde

có thể muốn sử dụngContextCompat.getDrawable(context, resourceid)
Pierre

Lưu ý thêm, bạn có thể tạo theo StateListDrawablechương trình và sử dụng addStatephương thức với "có thể kéo được chuyển đổi" đó để làm cho nó hoạt động với selector's itemkích thước được sử dụng setPasswordVisibilityToggleDrawable.
Trái cây

31

Chỉ định kích thước với setBounds(), tức là để sử dụng kích thước 50x50

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

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


2
Sau khi SetBounds kích thước vẫn giữ nguyên. Có thể là một số vô hiệu cần thiết?
Kostadin

6
Trên thực tế, setBounds hoạt động cho GradientDrawables. Nó chỉ không hoạt động đối với Image Drawables.
gregm,

Nó hoạt động với tôi khi tôi đặt hình ảnh vào một nút, nhưng không hiệu quả khi tôi đặt nó vào ImageView. OP đang sử dụng một nút, nhưng cũng gọi hương vị nội tại của setCompoundDrawables()chức năng.
William T. Mallard

@gregm Thật thú vị, bạn cũng có thể đặt kích thước cho GradientDrawable bằng cách sử dụng setSize ().
6rchid

12

Trước khi áp dụng .setBounds (..) hãy thử chuyển đổi Drawable hiện tại thành ScaleDrawable

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

sau đó

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

sẽ làm việc


2
Tại sao lại cần đến bước này? Điều gì gói trong một ScaleDrawablethay thế cho không gói?
azizbekian

10

Tôi không có thời gian để tìm hiểu lý do tại sao phương thức setBounds () không hoạt động trên bitmap drawable như mong đợi nhưng tôi có một chút giải pháp @ androbean-studio được tinh chỉnh để thực hiện những gì setBounds nên làm ...

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

sử dụng:

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

các kết quả

before: nhập mô tả hình ảnh ở đây after:nhập mô tả hình ảnh ở đây


làm thế nào để thêm phần đệm bên trái?
reegan29

8

Để sử dụng

textView.setCompoundDrawablesWithIntrinsicBounds()

MinSdkVersion của bạn phải là 17 trong build.gradle

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

Để thay đổi kích thước có thể vẽ:

    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

Sử dụng phương pháp đăng bài để đạt được hiệu quả mong muốn:

{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

Có lẽ là hơi muộn. Nhưng đây là giải pháp cuối cùng đã làm việc cho tôi trong mọi tình huống.

Ý tưởng là tạo ra một bản vẽ có thể tùy chỉnh với kích thước nội dung cố định và chuyển công việc vẽ sang bản vẽ ban đầu.

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

mPlatform là gì?
batsheva

@batsheva Nó chỉ là thứ mà anh ấy sử dụng để chuyển đổi từ dp sang px ...
nhà phát triển android

2

Câu trả lời jkhouw1 là một câu trả lời đúng, nhưng nó thiếu một số chi tiết, hãy xem bên dưới:

Sẽ dễ dàng hơn nhiều đối với ít nhất API> 21. Giả sử rằng chúng ta có VectorDrawable từ các tài nguyên (mã ví dụ để truy xuất nó):

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

Đối với VectorDrawable đó, chỉ cần đặt kích thước mong muốn:

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

Và hiển thị nút có thể vẽ trong:

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

Đó là nó. Nhưng lưu ý sử dụng setCompoundDrawables (không phải phiên bản Nội tại)!


0

Bạn có thể tạo một lớp con của kiểu xem và ghi đè phương thức onSizeChanged.

Tôi muốn có các bảng vẽ phức hợp mở rộng tỷ lệ trên các chế độ xem văn bản của mình mà không yêu cầu tôi phải loay hoay với việc xác định các bảng vẽ bitmap trong xml, v.v. và đã làm theo cách này:

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

}

(Lưu ý rằng tôi đã sử dụng w hai lần, không phải h, vì trong trường hợp này tôi đang đặt biểu tượng phía trên văn bản và do đó biểu tượng không được có cùng chiều cao với chế độ xem văn bản)

Điều này có thể được áp dụng cho các bảng có thể vẽ trong nền hoặc bất kỳ thứ gì khác mà bạn muốn thay đổi kích thước liên quan đến kích thước chế độ xem của mình. onSizeChanged () được gọi là lần đầu tiên Chế độ xem được tạo, vì vậy bạn không cần bất kỳ trường hợp đặc biệt nào để khởi tạo kích thước.


0

Bạn có thể thử button.requestLayout(). Khi kích thước nền bị thay đổi, nó cần phải đo lại và bố trí, nhưng nó sẽ không làm được


0

Làm việc này bằng cách sử dụng 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) }

Thí dụ:

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

Bạn có thể sử dụng LayerDrawable chỉ từ một lớp và phương thức 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

Đã được một thời gian kể từ khi câu hỏi được đặt ra
nhưng vẫn chưa rõ ràng đối với nhiều người về cách thực hiện điều đơn giản này.

Trong trường hợp đó, khá đơn giản khi bạn sử dụng Drawable như một phức hợp có thể vẽ được trên TextView (Button).

Vì vậy, 2 điều bạn phải làm:

1. đặt giới hạn:

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

2. Đặt có thể vẽ một cách thích hợp (không sử dụng giới hạn nội tại):

button.setCompoundDrawablesRelative(drawable, null, null, null)
  • Không cần sử dụng Bitmap
  • Không có cách giải quyết nào như ScaleDrawable ColorDrawablehoặc LayerDrawable(những gì chắc chắn được tạo ra cho các mục đích khác)
  • Không cần trong tủ có thể kéo tùy chỉnh!
  • Không có giải pháp thay thế với post
  • Đó là một giải pháp nguyên bản và đơn giản, giống như cách Android mong đợi bạn làm.

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

Sử dụng Button.setHeight()hoặc Button.setWeight()và đặt một giá trị.


9
chỉ đặt chiều cao của nút, không phải chiều cao của ngăn kéo. tôi muốn đặt chiều rộng / chiều cao của có thể kéo (đặc biệt nếu nó lớn hơn chiều cao của nút đặt).

21
Bạn biết bạn có thể xóa câu trả lời, phải không?
Iharob Al Asimi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.