我正在尝试绘制背面设计的纸牌。我有1个大小可绘制对象,并以编程方式缩放这些可绘制对象。
它在平板电脑(运行Android 8.1的Pixel C上完美运行,但是卡背面的设计在手机(运行Android 10的Pixel 3a)上无法正确缩放。)在Pixel 3a上,图像为比预期的要大得多,并且不在卡的背面居中。此外,卡本身似乎可以正确缩放,但不能缩放其顶部的设计。
编辑:这似乎是操作系统级别的问题。我有一个模拟的Pixel 3a,具有API 29(Android 10,与我的物理电话相同),其外观与下面的我的物理电话的屏幕截图相同。但是,当我使用API 27(Android 8.1)创建Pixel 3a模拟器时,看起来就像在运行相同操作系统的平板电脑上一样。任何想法为什么?似乎是操作系统级别的错误,但我不确定哪个功能包含该问题,或如何精确地再现该问题。
编辑2:API 27似乎是最后一个显示我期望看到的内容。我尝试了使用API 28、29和R的仿真器,所有这些仿真器都显示了比我期望的要大得多的图像。
这是我正在运行的代码:
private fun createImageInImageCenter(context: Context, backgroundBitmap: Bitmap, bitmapToDrawInTheCenter : Bitmap) : Drawable {
// Figure out width / height
val resultBitmap = Bitmap.createBitmap(
backgroundBitmap.width,
backgroundBitmap.height,
backgroundBitmap.config
)
val scaledCenter = scaleImage(bitmapToDrawInTheCenter, backgroundBitmap.height /2,
backgroundBitmap.width / 2)
val canvas = Canvas(resultBitmap)
// Draw background
canvas.drawBitmap(backgroundBitmap, Matrix(), Paint())
// Draw design centered on top
canvas.drawBitmap(
scaledCenter,
((backgroundBitmap.width - scaledCenter.width) / 2).toFloat(), // left
((backgroundBitmap.height - scaledCenter.height) / 2).toFloat(), // top
Paint()
)
return BitmapDrawable(context.resources, resultBitmap)
}
private fun scaleImage (image: Bitmap, maxHeight: Int, maxWidth: Int = -1) : Bitmap {
var ratio = 1f
if(maxWidth > 0 && image.width > maxWidth)
ratio = maxWidth.toFloat() / image.width
if(maxHeight > 0 && (image.height * ratio).roundToInt() > maxHeight)
ratio = maxHeight.toFloat() / image.height
val sizeX = (image.width * ratio).roundToInt()
val sizeY = (image.height * ratio).roundToInt()
return Bitmap.createScaledBitmap(image, sizeX, sizeY, false)
}
fun drawCard() {
// Resize the card itself
val cardHeight = context.resources.getDimension(R.dimen.card_max_height)
val back = scaleImage(context.getDrawable(R.drawable.card_black)!!, cardHeight.toInt())
// Resize the design on the card
val image = scaleImage(context.getDrawable(R.drawable.triforce)!!, back.height / 2, back.width / 2)
pic = createImageInImageCenter(context, back, image)
}
注意:我不确定为什么图像太大,或者如何在此处缩放它们。
您用于R.dimen.card_max_height的单位是什么?
是dp还是px?这很重要,因为如果使用px,则可以在具有不同分辨率的不同屏幕上给您带来非常不同的结果。如果您使用dp,则最好使用这样的东西
int px = Math.round(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 14,r.getDisplayMetrics()));
(对不起,Java版本)
您不能不考虑不同的屏幕尺寸和分辨率而将其转换为int。
还有...我注意到你用过
context.getDrawable(R.drawable.triforce)!!
我认为在Kotlin中不建议这样做。它击败了科特林据说已经摆脱了nullpointerexception,您应该检查它是否不返回null,然后执行操作
我找到了一种使之起作用的方法,部分感谢@mmmcho的回答,也感谢我在其他地方都使用了这两种转换功能的另一个答案。
fun convertDpToPixel(context: Context, dp: Float): Float {
return dp * (context.resources
.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}
fun convertPixelsToDp(context: Context, px: Float): Float {
return px / (context.resources
.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}
private fun createImageInImageCenter(context: Context, background: Drawable, bitmapToDrawInTheCenter : Drawable) : Drawable {
val backgroundBitmap = background.toBitmap()
// Figure out width / height
val resultBitmap = Bitmap.createBitmap(
backgroundBitmap.width,
backgroundBitmap.height,
backgroundBitmap.config
)
val canvas = Canvas(resultBitmap)
// Draw background
canvas.drawBitmap(backgroundBitmap, Matrix(), Paint())
val scaledCenter = scaleImage(context, bitmapToDrawInTheCenter, resultBitmap.height / 2,
resultBitmap.width / 2)
// Do conversion from DP to Pixel for API 28+
if(Build.VERSION.SDK_INT >= 28) {
// Draw design on top
canvas.drawBitmap(
scaledCenter,
(backgroundBitmap.width.toFloat() /2) - convertDpToPixel(context, scaledCenter.width.toFloat() / 2),
(backgroundBitmap.height.toFloat() /2) - convertDpToPixel(context, scaledCenter.height.toFloat() / 2),
Paint()
)
}
else {
// Draw design on top
canvas.drawBitmap(
scaledCenter,
((backgroundBitmap.width - scaledCenter.width) / 2).toFloat(), // left
((backgroundBitmap.height - scaledCenter.height) / 2).toFloat(), // top
Paint()
)
}
return BitmapDrawable(context.resources, resultBitmap)
}
private fun scaleImage (context : Context, image: Bitmap, maxHeight: Int, maxWidth: Int = -1) : Bitmap {
var ratio = 1f
// Do conversion from pixels to DP for API 28+
if(Build.VERSION.SDK_INT >= 28)
{
if(maxWidth > 0 && image.width > maxWidth)
ratio = convertPixelsToDp(context, maxWidth.toFloat()) / image.width
if(maxHeight > 0 && (image.height * ratio).roundToInt() > maxHeight)
ratio = convertPixelsToDp(context, maxHeight.toFloat()) / image.height
}
else {
if (maxWidth > 0 && image.width > maxWidth)
ratio = maxWidth.toFloat() / image.width
if (maxHeight > 0 && (image.height * ratio).roundToInt() > maxHeight)
ratio = maxHeight.toFloat() / image.height
}
val sizeX = (image.width * ratio).roundToInt()
val sizeY = (image.height * ratio).roundToInt()
return Bitmap.createScaledBitmap(image, sizeX, sizeY, false)
}
fun drawCard() {
val back = context.getDrawable(R.drawable.card_black)!!
// Image to draw on the back
val image = context.getDrawable(R.drawable.triforce)!!
pic = createImageInImageCenter(context, back, image)
}
[进行了大量的实验以找出需要转换的内容,以及以哪种方式进行转换,但我知道了:-)