缩放图像在手机上无法正常工作

问题描述 投票:0回答:2

我正在尝试绘制背面设计的纸牌。我有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)
    }

这是平板电脑上的外观:tablet

vs是手机上的样子:phone

注意:我不确定为什么图像太大,或者如何在此处缩放它们。

android kotlin bitmap scale
2个回答
1
投票

您用于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,然后执行操作


0
投票

我找到了一种使之起作用的方法,部分感谢@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)
    }

[进行了大量的实验以找出需要转换的内容,以及以哪种方式进行转换,但我知道了:-)

© www.soinside.com 2019 - 2024. All rights reserved.