Resize Drawable in Android

前端 未结 6 1994
梦如初夏
梦如初夏 2020-12-02 17:12

I am setting a drawable for a progress dialog (pbarDialog) but my issue is I want to resize the drawable each time but can\'t figure out how.

Here is so

相关标签:
6条回答
  • 2020-12-02 17:34

    Here's where I ended up, thanks in part to Saad's answer:

    public Drawable scaleImage (Drawable image, float scaleFactor) {
    
        if ((image == null) || !(image instanceof BitmapDrawable)) {
            return image;
        }
    
        Bitmap b = ((BitmapDrawable)image).getBitmap();
    
        int sizeX = Math.round(image.getIntrinsicWidth() * scaleFactor);
        int sizeY = Math.round(image.getIntrinsicHeight() * scaleFactor);
    
        Bitmap bitmapResized = Bitmap.createScaledBitmap(b, sizeX, sizeY, false);
    
        image = new BitmapDrawable(getResources(), bitmapResized);
    
        return image;
    
    }
    
    0 讨论(0)
  • 2020-12-02 17:36

    The following worked for me:

    private Drawable resize(Drawable image) {
        Bitmap b = ((BitmapDrawable)image).getBitmap();
        Bitmap bitmapResized = Bitmap.createScaledBitmap(b, 50, 50, false);
        return new BitmapDrawable(getResources(), bitmapResized);
    }
    
    0 讨论(0)
  • 2020-12-02 17:36

    Maybe my solution covers the question not completely, but I needed something like a "CustomDrawable".

    In other words, I want to set a logo in front of a circle shape. So I created a FrameLayout with a background (just a colored circle) and in front of this round shape I show the logo.

    To resize the logo I shrink the logo by scaling - here is some code:

    iv = new ImageView(mContext);
    
    iv.setScaleX(0.75f); // <- resized by scaling 
    iv.setScaleY(0.75f);
    
    // loading the drawable from a getter (replace this with any drawable)
    Drawable drawable = ML.loadIcon(mContext, Integer.parseInt(icon));
    
    iv.setImageDrawable(drawable);
    
    // icon get's shown inside a ListView
    viewHolder.mIvIcon.addView(iv);
    

    Here is the FrameLayout which shows the icon inside ListView's row:

    <FrameLayout
        android:id="@+id/iv_card_icon"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:src="@drawable/circle"
        android:layout_marginStart="16dp"
        />
    

    See this solution as an option / idea.

    0 讨论(0)
  • 2020-12-02 17:41

    Here is a combination of the above answers as a Kotlin extension

    fun Context.scaledDrawableResources(@DrawableRes id: Int, @DimenRes width: Int, @DimenRes height: Int): Drawable {
        val w = resources.getDimension(width).toInt()
        val h = resources.getDimension(height).toInt()
        return scaledDrawable(id, w, h)
    }
    
    fun Context.scaledDrawable(@DrawableRes id: Int, width: Int, height: Int): Drawable {
        val bmp = BitmapFactory.decodeResource(resources, id)
        val bmpScaled = Bitmap.createScaledBitmap(bmp, width, height, false)
        return BitmapDrawable(resources, bmpScaled)
    }
    

    Usage:

    val scaled = context.scaledDrawableResources(R.drawable.ic_whatever, R.dimen.width, R.dimen.height)
    imageView.setImageDrawable(scaled)
    

    or

    val scaled = context.scaledDrawable(R.drawable.ic_whatever, 100, 50)
    imageView.setImageDrawable(scaled)
    
    0 讨论(0)
  • 2020-12-02 17:48

    The most voted answer wont work if the source Drawable is not instanceof BitmapDrawable which can be the case of using vector, color drawables, etc...

    The most appropriate solution could be to draw the Drawable into a Canvas with set bitmap, as following:

    @NonNull final Drawable drawable = yourSourceDrawable;
    
    // Define the Canvas and Bitmap the drawable will be drawn against
    final Canvas c = new Canvas();
    c.setBitmap(bitmap);
    
    // Draw the scaled drawable into the final bitmap
    if (yourSourceDrawable!= null) {
        yourSourceDrawable.setBounds(0, 0, newWidth, newHeight);
        yourSourceDrawable.draw(c);
    }
    

    BONUS: To calculate the scale to be applied (e.g. when scaling the Drawable to a view):

    if (drawable != null && drawable.getIntrinsicWidth() > 0 && drawable.getIntrinsicHeight() > 0) {
        // the intrinsic dimensions can be -1 in some cases such as ColorDrawables which aim to fill 
        // the whole View
        previewWidth = drawable.getIntrinsicWidth();
        previewHeight = drawable.getIntrinsicHeight();
    }
    
    final float widthScale = mViewWidth / (float) (previewWidth);
    if (widthScale != 1f)
        newWidth = Math.max((int)(widthScale * previewWidth), 1);
    
    final float heightScale = mViewHeight / (float) (previewHeight);
    if (heightScale != 1f)
        newHeight = Math.max((int)(heightScale * previewHeight), 1);
    

    NOTE: ALWAYS do this in a worker thread!

    0 讨论(0)
  • 2020-12-02 17:55

    For the resizing, this is nice and short (the code above wasn't working for me), found here:

      ImageView iv = (ImageView) findViewById(R.id.imageView);
      Bitmap bMap = BitmapFactory.decodeResource(getResources(), R.drawable.picture);
      Bitmap bMapScaled = Bitmap.createScaledBitmap(bMap, newWidth, newHeight, true);
      iv.setImageBitmap(bMapScaled);
    
    0 讨论(0)
提交回复
热议问题