Android 是否支持使用位图工厂选项的多个屏幕?

Android 是否支持使用位图工厂选项的多个屏幕?,android,android-emulator,module,screen,bitmapfactory,Android,Android Emulator,Module,Screen,Bitmapfactory,编辑一个: 根据Joseph的回答所做的更改: 在bytesToDrawablebyte[]imageBytes中: 更改了以下内容:使用BitmapDrawableResources res,位图位图代替BitmapDrawableBitmap位图: return new BitmapDrawable(ApplicationConstants.ref_currentActivity.getResources(),BitmapFactory.decodeByteArray(imageBytes,

编辑一个:

根据Joseph的回答所做的更改:

在bytesToDrawablebyte[]imageBytes中:

更改了以下内容:使用BitmapDrawableResources res,位图位图代替BitmapDrawableBitmap位图:

return new BitmapDrawable(ApplicationConstants.ref_currentActivity.getResources(),BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, options));
这是这一变化的结果:略有不同的问题:

问题:

如果我正在使用位图可绘制的新构造函数,并且它根据所需的目标密度缩放图像,那么我还需要使用CalculatesSampleSize方法吗

原始问题:

嗨,朋友们

我的应用程序是基于模块的,因此特定于该模块的图像仅从包含它们的模块加载,而不是从主应用程序加载

每个模块都有自己的ModularImageLoader——它基本上允许我根据在jar中找到的图像的名称获取Drawables

构造器从zip文件中接收zipFileModule和文件名列表(任何以.png结尾的文件)

进行的研究:

我使用了以下方法:

起初,我创建的图像大小为每种密度,但现在我只有一组图像图标大小为96x96

如果屏幕密度小于xhdpi,我将加载96x96图像的较小采样尺寸-对于ldpi为36x36,对于mdpi为48x48,对于hdpi为72x72。否则我只返回96x96图像。查看方法CalculatesSampleSize和bytesToDrawable

我认为通过代码更容易理解这个概念:下面是ModularImageLoader

代码:

问题:

下图显示了4个正在运行的模拟器,这些是它们的规范以及我如何在eclipse AVD中设置它们:

LDPI:密度120,皮肤QVGA MDPI:密度160,皮肤HVGA HDPI:密度240,皮肤WVGA800 XHDPI:密度320,外皮800x1280

图像显示问题:

问题:

基于XHDPI窗口中的代码,为什么联系人图像这么小?除了从主应用程序加载外,新闻图像也是96x96,因此它位于res>XHDPI下。 问题是,我认为MDPI屏幕和HDPI屏幕的加载很好,但其他屏幕的加载很奇怪。有什么想法吗?

您应该使用BitmapDrawableResources res,位图位图构造器,它将确保drawable的目标密度设置正确,您使用的构造器不推荐使用

如果你看你的LDPI屏幕,联系人的图像实际上有点太小,HDPI屏幕也有点太小。只有在MDPI屏幕上,它才看起来完全正确,因为默认的目标密度是MDPI

您应该使用BitmapDrawableResources res,位图位图构造函数,它将确保可绘制文件的目标密度设置正确,您使用的构造函数已被弃用


如果你看你的LDPI屏幕,联系人的图像实际上有点太小,HDPI屏幕也有点太小。只有在MDPI屏幕上,它才看起来完全正确,因为默认的目标密度是MDPI

您可以使用dp创建所需的高度和宽度,然后将其转换为px,以获得缩放图像的正确大小

假设您希望您的图像为32x32dp

int reqWidth = dpToPx(context, 32);
int reqHeight = dpToPx(context, 32);

public static int dpToPx(Context context, int dp) {
    return (int) (dp * (context.getResources().getDisplayMetrics().densityDpi / 160f) + 0.5f);
}

您可以使用dp创建所需的高度和宽度,然后将其转换为px以获得缩放图像的正确大小

假设您希望您的图像为32x32dp

int reqWidth = dpToPx(context, 32);
int reqHeight = dpToPx(context, 32);

public static int dpToPx(Context context, int dp) {
    return (int) (dp * (context.getResources().getDisplayMetrics().densityDpi / 160f) + 0.5f);
}

如果使用BitmapFactory.Options提供密度信息,则BitmapFactory可以为您缩放图像。如果这样做,您应该能够删除ModularImageLoader中的自定义缩放代码

指定inDensity和inTargetDensity-如下所示:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inDensity = DisplayMetrics.DENSITY_MEDIUM;
options.inTargetDensity = activityRef.getResources().getDisplayMetrics().densityDpi;
options.inScaled = true;
return BitmapFactory.decodeStream(openByteStream(), null, options);

BitmapFactory.decodeByteArray中显然存在忽略某些缩放选项的错误,因此您可能需要将字节数组包装在ByteArrayInputStream中,并使用BitmapFactory.decodeStream,如上图所示。如果使用BitmapFactory.options提供密度信息,BitmapFactory可以为您缩放图像。如果这样做,您应该能够删除ModularImageLoader中的自定义缩放代码

指定inDensity和inTargetDensity-如下所示:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inDensity = DisplayMetrics.DENSITY_MEDIUM;
options.inTargetDensity = activityRef.getResources().getDisplayMetrics().densityDpi;
options.inScaled = true;
return BitmapFactory.decodeStream(openByteStream(), null, options);
BitmapFactory.decodeByteArray中显然存在忽略某些缩放选项的错误,因此您可能需要将字节数组包装在ByteArrayInputStream中,并使用BitmapFactory.decodeStream,如上图所示。请参见。

ldpi-36x36 mdpi-48x48 hdpi-72x72 xhdpi-96x96

如果这些都是彼此的纯倍数,那就太好了,因为位图工厂以整数处理样本大小,因此样本大小需要是一个整数,没有尾随小数才能完全准确

解决方案:

在开始采样之前,每种屏幕类型有一个图像,如果该图像处于按下状态,则会有两个单独的图像

因此,对于一个图像-我在应用程序中实际需要4,如果该图像已按下状态-一个图像将需要8 ima 盖斯

我的主要目标是减少图像的数量,这样我就不会过载位图堆分配并可能抛出内存不足异常,我已经看到这个异常为我抛出,当我的位图大小完全合理时,我相信这与堆上的图像数量以及它们各自的图像大小有关。如果我错了,请纠正我。。当然,我想减少我的模块大小

所以我决定: 每个图像有2个图像-一个大小为72,一个大小为96-这样我就有了xhdpi和hdpi密度屏幕所需的图标,我可以在需要时使用ldpi和mdpi

72/2=36 96/2=48

这样的话,每个图像只有2个图像,最坏的情况是,如果该图像已按下状态,我将有4个图像。 这将图像库的大小减少了近50%,并使我的模块更小。我注意到模块大小从525KB变为329 kb左右

这确实是我的目标

谢谢大家的帮助!如果有任何问题,请随时发表评论,我会尽快回复您。

ldpi-36x36 mdpi-48x48 hdpi-72x72 xhdpi-96x96

如果这些都是彼此的纯倍数,那就太好了,因为位图工厂以整数处理样本大小,因此样本大小需要是一个整数,没有尾随小数才能完全准确

解决方案:

在开始采样之前,每种屏幕类型有一个图像,如果该图像处于按下状态,则会有两个单独的图像

因此,对于一个图像-我在应用程序中实际需要4个,如果该图像已按下状态-一个图像将需要8个图像

我的主要目标是减少图像的数量,这样我就不会过载位图堆分配并可能抛出内存不足异常,我已经看到这个异常为我抛出,当我的位图大小完全合理时,我相信这与堆上的图像数量以及它们各自的图像大小有关。如果我错了,请纠正我。。当然,我想减少我的模块大小

所以我决定: 每个图像有2个图像-一个大小为72,一个大小为96-这样我就有了xhdpi和hdpi密度屏幕所需的图标,我可以在需要时使用ldpi和mdpi

72/2=36 96/2=48

这样的话,每个图像只有2个图像,最坏的情况是,如果该图像已按下状态,我将有4个图像。 这将图像库的大小减少了近50%,并使我的模块更小。我注意到模块大小从525KB变为329 kb左右

这确实是我的目标


谢谢大家的帮助!如果任何人有任何问题,请随时留下评论,我会尽快回复您。

我很喜欢这样做,但我更愿意使用“位图工厂采样”选项。我将在将来的某个时候在我的应用程序中尝试这一点,因为我肯定可以将其用于大徽标,我希望适合任何任意值的特定大小。我确实喜欢这一点,但我宁愿使用位图工厂选项的采样。我将在将来的某个时候在我的应用程序中尝试这一点,因为我肯定可以将其用于大型徽标,我希望适合任何任意值的特定大小。你是对的,我已将其更改以反映较新的构造函数。好主意。你说得对,我修改了它以反映新的构造函数。好主意。你能解释一下inDensity到底是做什么的吗?我可以告诉你将其设置为中等,然后将目标密度设置为手机返回的屏幕密度。你能解释inDensity的确切功能吗?我可以告诉你,你把它设置为中等,然后你把目标密度设置为手机返回的屏幕密度。天哪。我在这个问题上花了几个小时,所做的一切就是改变这个:使用BitmapDrawableResources res,位图位图而不是BitmapDrawableBitmap位图:谢谢谢谢谢谢!!!!天哪。我在这个问题上花了几个小时,所做的一切就是改变这个:使用BitmapDrawableResources res,位图位图而不是BitmapDrawableBitmap位图:谢谢谢谢谢谢!!!!