在 Android 中调整可绘制对象的大小

发布于 2024-11-28 18:41:03 字数 933 浏览 1 评论 0原文

我正在为进度对话框(pbarDialog)设置一个可绘制对象,但我的问题是我想每次调整可绘制对象的大小,但不知道如何操作。

这是一些代码:

Handler progressHandler = new Handler() {

    public void handleMessage(Message msg) {
        switch (msg.what) {
            // some more code
            case UPDATE_PBAR:
                pbarDialog.setIcon(mAppIcon);
                pbarDialog.setMessage(mPbarMsg);
                pbarDialog.incrementProgressBy(mIncrement+1);
                break;
        }
    }
};

pbarDialog.show();

Thread myThread = new Thread(new Runnable() {

    public void run() {
        // some code
        for (int i = 0; i < mApps.size(); i++) {
            mAppIcon = mAdapter.getIcons().get(mApps.get(i).getPackageName());
            // need to resize drawable here
            progressHandler.sendEmptyMessage(UPDATE_PBAR);
        }
        handler.sendEmptyMessage(DISMISS_PBAR);
    }

});

myThread.start();

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 some code:

Handler progressHandler = new Handler() {

    public void handleMessage(Message msg) {
        switch (msg.what) {
            // some more code
            case UPDATE_PBAR:
                pbarDialog.setIcon(mAppIcon);
                pbarDialog.setMessage(mPbarMsg);
                pbarDialog.incrementProgressBy(mIncrement+1);
                break;
        }
    }
};

pbarDialog.show();

Thread myThread = new Thread(new Runnable() {

    public void run() {
        // some code
        for (int i = 0; i < mApps.size(); i++) {
            mAppIcon = mAdapter.getIcons().get(mApps.get(i).getPackageName());
            // need to resize drawable here
            progressHandler.sendEmptyMessage(UPDATE_PBAR);
        }
        handler.sendEmptyMessage(DISMISS_PBAR);
    }

});

myThread.start();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

已下线请稍等 2024-12-05 18:41:03

以下对我有用:

private Drawable resize(Drawable image) {
    Bitmap b = ((BitmapDrawable)image).getBitmap();
    Bitmap bitmapResized = Bitmap.createScaledBitmap(b, 50, 50, false);
    return new BitmapDrawable(getResources(), bitmapResized);
}

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);
}
美男兮 2024-12-05 18:41:03

这就是我的结局,部分感谢萨阿德的回答:

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;

}

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;

}
饮惑 2024-12-05 18:41:03

对于调整大小,这很好而且很短(上面的代码对我不起作用),找到 此处

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

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);
暗恋未遂 2024-12-05 18:41:03

这是上述答案的组合作为 Kotlin 扩展

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

用法:

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

val scaled = context.scaledDrawable(R.drawable.ic_whatever, 100, 50)
imageView.setImageDrawable(scaled)

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)
疯到世界奔溃 2024-12-05 18:41:03

也许我的解决方案没有完全涵盖这个问题,但我需要类似“CustomDrawable”的东西。

换句话说,我想在圆形前面设置一个徽标。因此,我创建了一个带有背景(只是一个彩色圆圈)的 FrameLayout,并在这个圆形形状的前面显示了徽标。

要调整徽标大小,我通过缩放缩小徽标 - 这是一些代码:

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

这是 FrameLayout,它显示 ListView 行内的图标:

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

将此解决方案视为选项/想法。

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.

断肠人 2024-12-05 18:41:03

如果源 Drawable 不是 BitmapDrawable 的实例,则投票最多的答案将不起作用,这可能是使用矢量、颜色可绘制等的情况...

最合适的解决方案可能是将 Drawable 绘制到具有设置位图的 Canvas 中,如下所示:

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

奖励:要计算要应用的比例(例如,将 Drawable 缩放到视图时):

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

注意:始终在工作线程中执行此操作!

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!

爱冒险 2024-12-05 18:41:03

Kotlin 方式

最终对我有用的是这个简单的解决方案

fun resizeDrawable(width:Int, height:Int): Drawable {
        val drawable = ResourceUtils.getDrawable(R.drawable.ic_info)
        val bitmap = drawable.toBitmap(width, height) //here width and height are in px
        return bitmap.toDrawable(getResources())
    }

Kotlin way

What it ended up working for me was this simple solution

fun resizeDrawable(width:Int, height:Int): Drawable {
        val drawable = ResourceUtils.getDrawable(R.drawable.ic_info)
        val bitmap = drawable.toBitmap(width, height) //here width and height are in px
        return bitmap.toDrawable(getResources())
    }
飞烟轻若梦 2024-12-05 18:41:03

对于仍在解决这个问题的任何人来说,请记住,这里评价最高的答案并不是正确的选择。如果您拥有的 Drawable 不是从 BitmapDrawable 扩展的,则将任何 Drawable 转换为 BitmapDrawable 是行不通的,您将得到一个 ClassCastException 。

这是我最终用于调整可绘制对象大小的代码,它适用于各种可绘制对象:

Kotlin

fun Context.getResizedDrawable(
    @DrawableRes drawableId: Int,
    @DimenRes size: Int,
): Drawable? {
    val dimen = resources.getDimensionPixelSize(size)

    return ContextCompat.getDrawable(this, drawableId)?.let { drawable ->
        val bitmap = Bitmap.createBitmap(dimen, dimen, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)

        drawable.setBounds(0, 0, canvas.width, canvas.height)
        drawable.draw(canvas)

        BitmapDrawable(this.resources, bitmap)
    }
}

Java

@Nullable
public Drawable getResizedDrawable(
    Context context,
    @DrawableRes int drawableId,
    @DimenRes int size
) {
    int dimen = context.getResources().getDimensionPixelSize(size);
    Drawable drawable = ContextCompat.getDrawable(context, drawableId);
    Bitmap bitmap = Bitmap.createBitmap(dimen, dimen, Bitmap.Config.ARGB_8888);

    if (drawable != null) {
        Canvas canvas = new Canvas(bitmap);
        
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return new BitmapDrawable(context.getResources(), bitmap);
    } else {
        return null;
    }
}

For anyone still struggling with this issue, have in mind that the top rated answers here are not the way to go. Casting any Drawable to BitmapDrawable is not gonna work if the Drawable you have does not extend from BitmapDrawable, you'll get a ClassCastException instead.

This is the code I ended up using for resizing a Drawable which works for every kind of Drawable:

Kotlin

fun Context.getResizedDrawable(
    @DrawableRes drawableId: Int,
    @DimenRes size: Int,
): Drawable? {
    val dimen = resources.getDimensionPixelSize(size)

    return ContextCompat.getDrawable(this, drawableId)?.let { drawable ->
        val bitmap = Bitmap.createBitmap(dimen, dimen, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)

        drawable.setBounds(0, 0, canvas.width, canvas.height)
        drawable.draw(canvas)

        BitmapDrawable(this.resources, bitmap)
    }
}

Java

@Nullable
public Drawable getResizedDrawable(
    Context context,
    @DrawableRes int drawableId,
    @DimenRes int size
) {
    int dimen = context.getResources().getDimensionPixelSize(size);
    Drawable drawable = ContextCompat.getDrawable(context, drawableId);
    Bitmap bitmap = Bitmap.createBitmap(dimen, dimen, Bitmap.Config.ARGB_8888);

    if (drawable != null) {
        Canvas canvas = new Canvas(bitmap);
        
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return new BitmapDrawable(context.getResources(), bitmap);
    } else {
        return null;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文