我正在为进度对话框设置一个可绘制对象(
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();
以下对我有用:
private Drawable resize(Drawable image) {
Bitmap b = ((BitmapDrawable)image).getBitmap();
Bitmap bitmapResized = Bitmap.createScaledBitmap(b, 50, 50, false);
return new BitmapDrawable(getResources(), bitmapResized);
}
这就是我的结局,部分感谢萨阿德的回答:
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:
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);
这里是上述答案的组合作为 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)
也许我的解决方案没有完全涵盖问题,但我需要类似“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"
/>
将此解决方案视为一种选择/想法。
如果源 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);
注意:始终在工作线程中执行此操作!
最终对我有用的是这个简单的解决方案
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())
}
对于仍在解决此问题的任何人,请记住,这里评价最高的答案并不是正确的选择。如果您拥有的 Drawable 不是从 BitmapDrawable 扩展的,则将任何 Drawable 转换为 BitmapDrawable 是行不通的,您将得到一个 ClassCastException 。
这是我最终用于调整可绘制对象大小的代码,它适用于各种可绘制对象:
科特林
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);
Canvas canvas = new Canvas(bitmap);
if (drawable != null) {
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return new BitmapDrawable(context.getResources(), bitmap);
} else {
return null;
}
}