《Android 2.3 Gallery3D添加gif支持——概要(一)》
对于Gallery3D如何显示一张图片,请参看这位网友的Gallery3D笔记 。
欢迎转载,请务必注明出处:http://blog.csdn.net/yihongyuelan
在Gallery3D中,图片显示包括了缩略图和单张大图的显示,当我们点击缩略图时,会有一个动画效果,然后再显示大图片,如果显示图片较大,可能大图会先模糊一下然后再清晰显示。我们先来看看Gallery3D的基本结构,如图1:
图1
这是整个Gallery3D组成以及它们之间的关系。这有什么意义呢?回到我们本文的主旨图片显示:缩略图和大图。
缩略图由Gallery3D中的CacheService创建,这些缩略图以Cache的方式存放在路径/mnt/sdcard/Android/data/com.cooliris.media/中。缩略图是显示在一个个固定宽高(在GridLayer中设定)的方框中,CacheService.getImageList从数据库中获取图片信息,CacheService.refresh()方法负责建立相册并把图片放到相册中。
大图片的显示过程。在Android系统中,通过MediaScanner的扫描,会将扫描的媒体文件信息(路径,类型等等)存放到数据库中(/data/data/com.android.providers.media/databases/external.db),当用户点击缩略图时,触发界面重绘,同时会将该张缩略图的真实路径从数据库中获取出来,并调用图片解码器进行解码,最终返回到重绘后的界面。解析成功后的图片会以Cache的形式保存在SD卡中,再次加载速度就会更快了。
对于大图片的绘制,每一帧图片都会调用onDrawFrame来完成渲染,最终调用到GridDrawManager.java中的drawFocusItems()函数中。画单张图片最终调用的方法是drawDisplayItem(view, gl, displayItem, fsTexture, PASS_FOCUS_CONTENT, null, 1.0f);
代码如下:
private void drawDisplayItem(RenderView view, GL11 gl, DisplayItem displayItem, Texture texture, int pass, Texture previousTexture, float mixRatio) { GridCamera camera = mCamera; Vector3f animatedPosition = displayItem.mAnimatedPosition; float translateXf = animatedPosition.x * camera.mOneByScale; float translateYf = animatedPosition.y * camera.mOneByScale; float translateZf = -animatedPosition.z; int stackId = displayItem.getStackIndex(); final int maxDisplayedItemsPerSlot = (displayItem.mCurrentSlotIndex == mCurrentScaleSlot && mCurrentScaleSlot != Shared.INVALID) ? GridLayer.MAX_DISPLAYED_ITEMS_PER_FOCUSED_SLOT : GridLayer.MAX_DISPLAYED_ITEMS_PER_SLOT; if (pass == PASS_PLACEHOLDER || pass == PASS_FRAME_PLACEHOLDER) { translateZf = -0.04f; } else { if (pass == PASS_FRAME) translateZf += 0.02f; if ((pass == PASS_TEXT_LABEL || pass == PASS_LOCATION_LABEL || pass == PASS_SELECTION_LABEL) && !displayItem.isAlive()) { translateZf = 0.0f; } if (pass == PASS_TEXT_LABEL && translateZf > 0) { translateZf = 0.0f; } } boolean usingMixedTextures = false; boolean bind = false; if ((pass != PASS_THUMBNAIL_CONTENT) || (stackId < maxDisplayedItemsPerSlot && texture.isLoaded() && (previousTexture == null || previousTexture .isLoaded()))) { if (mixRatio == 1.0f || previousTexture == null || texture == previousTexture) { bind = view.bind(texture); } else if (mixRatio != 0.0f) { if (!texture.isLoaded() || !previousTexture.isLoaded()) { // Submit the previous texture to the load queue view.bind(previousTexture); bind = view.bind(texture); } else { usingMixedTextures = true; bind = view.bindMixed(previousTexture, texture, mixRatio); } } else { bind = view.bind(previousTexture); } } else if (stackId >= maxDisplayedItemsPerSlot && pass == PASS_THUMBNAIL_CONTENT) { mDisplayList.setAlive(displayItem, true); } if (!texture.isLoaded() || !bind) { if (pass == PASS_THUMBNAIL_CONTENT) { if (previousTexture != null && previousTexture.isLoaded() && translateZf == 0.0f) { translateZf = -0.08f; bind |= view.bind(previousTexture); } if (!bind) { return; } } else { return; } } else { if (pass == PASS_THUMBNAIL_CONTENT || pass == PASS_FOCUS_CONTENT) { if (!displayItem.mAlive) { mDisplayList.setAlive(displayItem, true); } } } gl.glTranslatef(-translateXf, -translateYf, -translateZf); float theta = (pass == PASS_FOCUS_CONTENT) ? displayItem.mAnimatedImageTheta + displayItem.mAnimatedTheta : displayItem.mAnimatedTheta; if (theta != 0.0f) { gl.glRotatef(theta, 0.0f, 0.0f, 1.0f); } float orientation = 0.0f; if (pass == PASS_THUMBNAIL_CONTENT && displayItem.mAnimatedImageTheta != 0.0f) { orientation = displayItem.mAnimatedImageTheta; } if (pass == PASS_FRAME || pass == PASS_FRAME_PLACEHOLDER) { GridQuadFrame.draw(gl); } else { GridQuad.draw(gl, orientation); } if (theta != 0.0f) { gl.glRotatef(-theta, 0.0f, 0.0f, 1.0f); } gl.glTranslatef(translateXf, translateYf, translateZf); if (usingMixedTextures) { view.unbindMixed(); } }
本文只是一个总结性的笔记,并没有设计到代码的详细分析,对于Gallery3D的代码来讲,网上已经有网友比较详细的分析了,这里也就不再赘述。同时在Android 4.0中,Google并没有继续沿用Gallery3D,而是将自己之发布的Gallery进行了重写,也就是我们现在看到的Gallery2,并且弃用了Android 2.3中的Gallery3D(毕竟这是一个第三方的应用啊),所以在Android 4.0上许多东西都改变了。