ryv*_*ron 1 android module screen android-emulator bitmapfactory
编辑一个:
根据约瑟夫的回答做出的改变:
在bytesToDrawable(byte [] imageBytes)中:
更改了以下内容:使用BitmapDrawable(资源res,位图位图)而不是BitmapDrawable(位图位图):
return new BitmapDrawable(ApplicationConstants.ref_currentActivity.getResources(),BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, options));
Run Code Online (Sandbox Code Playgroud)
这是这种变化的结果:略有不同的问题:

题:
如果我正在使用新的构造函数来绘制位图并将图像缩放到所需的目标密度,那么我还需要使用我的calculateSampleSize方法吗?
原始问题:
嗨朋友们,
我的应用程序是基于模块的,因此特定于该模块的图像仅从包含它们的jar(模块)加载,而不是从主应用程序加载.
每个模块都有自己的ModularImageLoader - 它基本上允许我根据jar中找到的图像名称来获取Drawables.
构造函数接收zipFile(模块A)和文件名列表(zip中以".png"结尾的任何文件).
研究实施:
我使用了以下内容:有效加载位图链接到开发人员页面
最初我是为每个密度创建大小的图像,但现在我只有一组大小为96x96的图像图标.
如果屏幕密度小于xhdpi,我会加载96x96图像的较小采样大小 - 36x36(对于ldpi),48x48(对于mdpi),72x72(对于hdpi).否则我只返回96x96图像.(查看方法calculateSampleSize()和bytesToDrawable())
我认为用代码更容易理解这个概念:所以这里是ModularImageLoader
码:
public class ModularImageLoader
{
public static HashMap<String, Drawable> moduleImages = new HashMap<String, Drawable>();
public static int reqHeight = 0;
public static int reqWidth = 0;
public ModularImageLoader(ZipFile zip, ArrayList<String> fileNames)
{
float sdpi = ApplicationConstants.ref_currentActivity.getResources().getDisplayMetrics().density;
if(sdpi == 0.75)
{
reqHeight = 36;
reqWidth = 36;
}
else if(sdpi == 1.0)
{
reqHeight = 48;
reqWidth = 48;
}
else if (sdpi == 1.5)
{
reqHeight = 72;
reqWidth = 72;
}
else if (sdpi == 2.0)
{
reqHeight = 96;
reqWidth = 96;
}
String names = "";
for(String fileName : fileNames)
{
names += fileName + " ";
}
createByteArrayImages(zip, fileNames);
}
public static Drawable findImageByName(String imageName)
{
Drawable drawableToReturn = null;
for (Entry<String, Drawable> ent : moduleImages.entrySet())
{
if(ent.getKey().equals(imageName))
{
drawableToReturn = ent.getValue();
}
}
return drawableToReturn;
}
private static void createByteArrayImages(ZipFile zip, ArrayList<String> fileNames)
{
InputStream in = null;
byte [] temp = null;
int nativeEndBufSize = 0;
for(String fileName : fileNames)
{
try
{
in = zip.getInputStream(zip.getEntry(fileName));
nativeEndBufSize = in.available();
temp = toByteArray(in,nativeEndBufSize);
// get rid of .png
fileName = fileName.replace(".png", "");
fileName = fileName.replace("Module Images/", "");
moduleImages.put(fileName, bytesToDrawable(temp));
}
catch(Exception e)
{
System.out.println("getImageBytes() threw an exception: " + e.toString());
e.printStackTrace();
}
}
try
{
in.close();
}
catch (IOException e)
{
System.out.println("Unable to close inputStream!");
e.toString();
e.printStackTrace();
}
}
public static byte[] toByteArray(InputStream is, int length) throws IOException
{
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int l;
byte[] data = new byte[length];
while ((l = is.read(data, 0, data.length)) != -1)
{
buffer.write(data, 0, l);
}
buffer.flush();
return buffer.toByteArray();
}
public static Drawable bytesToDrawable(byte[] imageBytes)
{
try
{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, options);
String imageType = options.outMimeType;
Log.d("ImageInfo : ", "Height:" + imageHeight +",Width:" +imageWidth + ",Type:" + imageType);
options.inJustDecodeBounds = false;
//Calculate sample size
options.inSampleSize = calculateSampleSize(options);
return new BitmapDrawable(BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, options));
}
catch(Exception e)
{
Message.errorMessage("Module Loading Error", "The images in this module are too large to load onto cell memory. Please contact your administrator",
"Source of error: ModularImageLoader - bytesToDrawable method", e.toString());
return null;
}
}
public static int calculateSampleSize(BitmapFactory.Options options)
{
// raw height and width of the image itself
int sampleSize = 1;
int height = options.outHeight;
int width = options.outWidth;
if(height > reqHeight || width > reqWidth)
{
if(width > height)
{
sampleSize = Math.round((float)height / (float)reqHeight);
}
else
{
sampleSize = Math.round((float)width / (float)reqWidth);
}
}
return sampleSize;
}
}
Run Code Online (Sandbox Code Playgroud)
问题:
下图显示了4个正在运行的仿真器,这些是他们的规格以及我如何在eclipse AVD中设置它们:
LDPI:密度120,皮肤QVGA MDPI:密度160,皮肤HVGA HDPI:密度240,皮肤WVGA800 XHDPI:密度320,皮肤800x1280
图像显示问题:

题:
基于代码 - 在XHDPI窗口中,为什么联系人图像如此之小?新闻图片也是96x96(除了它从主应用程序加载 - 所以它在res> XHDPI).问题是,我认为MDPI屏幕和HDPI屏幕的加载非常好,但其余部分却很奇怪.有任何想法吗?
如果您使用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);
Run Code Online (Sandbox Code Playgroud)
BitmapFactory.decodeByteArray中显然存在忽略某些缩放选项的错误,因此您可能需要将字节数组包装在ByteArrayInputStream中并使用BitmapFactory.decodeStream,如上所示(请参阅http://code.google.com/p/android/issues/detail?id = 7538).
| 归档时间: |
|
| 查看次数: |
2244 次 |
| 最近记录: |