当前位置: 代码迷 >> Android >> Android Gallery 3D 奇效精华
  详细解决方案

Android Gallery 3D 奇效精华

热度:512   发布时间:2016-05-01 19:37:56.0
Android Gallery 3D 特效精华

Android Gallery 3D 特效精华

?

一、布局
gallery3d 的界面生成和普通的应用程序不一样。普通程序一般一个界面就是一
个activity,布局用xml或代码都可以实现,界面切换是activity 的切换方式;
而 gallery3d没有用android 的UI 系统,而是用opengl 画出来的,即界面是在
同一个 activity 的,如主界面,缩略图界面,单张图片查看界面,标记界面等
都属于同一个activity。那么这界面布局不同的界面是如何组合到一起的呢?
分析代码,可以把它看成一个状态机:
1、标记模式???????????? public static final int MODE_SELECT = 1;(HudLayer)
包含了主界面标记模式,缩略界面矩阵游览时标记模式、缩略图界面分类游览时
标记模式 3个界面
2、普通模式?????????? public static final int MODE_NORMAL = 0;(HudLayer)
包含了

Java 代码

?? 1.? public static final int STATE_MEDIA_SETS = 0;主界面
?? 2.??? public static final int STATE_GRID_VIEW = 1;缩略图矩阵浏览
?? 3.??? public static final int STATE_FULL_SCREEN = 2;查看界面
?? 4.??? public static final int STATE_TIMELINE = 3;缩略图界面分类浏览

有了以上状态分类后,在渲染的时候就能根据些界面的组成来定哪些控件譔隐藏,
哪些要显示了。
下面是基本控件:

Java 代码

??? 1.? com.cooliris.media.GridLayer
??? 2.? com.cooliris.media.BackgroundLayer
??? 3.? com.cooliris.media.HudLayer
??? 4.? com.cooliris.media.ImageButton
??? 5.? com.cooliris.media.TimeBar
??? 6.? com.cooliris.media.MenuBar
??? 7.? com.cooliris.media.PopupMenu
??? 8.? com.cooliris.media.PathBarLayer

在渲染时,每一帧所有界面上的元素都画了,由于根据上面的状态只把特定窗口
的特定元素显示出来,其它窗口中的隐藏,所以不会乱。
Layer 是上面控件的基类,上面控件的类也就有了下面两个方法来隐藏不譔显示
的界面元素。

Java 代码

??? 1.? public boolean isHidden() {
??? 2.????? return mHidden;
??? 3.??? }
??? 4.
??? 5.??? public void setHidden(boolean hidden) {
??? 6.????? if (mHidden != hidden) {
??? 7.??????? mHidden = hidden;
??? 8.??????? onHiddenChanged();
??? 9.????? }
??? 10.?? }

下面是根据上面分类来画不同元素所用的标识:

Java 代码

??? 1.? public static final int PASS_THUMBNAIL_CONTENT = 0;
??? 2.??? public static final int PASS_FOCUS_CONTENT = 1;
??? 3.??? public static final int PASS_FRAME = 2;

?4.??? public static final int PASS_PLACEHOLDER = 3;
?? 5.??? public static final int PASS_FRAME_PLACEHOLDER = 4;
?? 6.??? public static final int PASS_TEXT_LABEL = 5;
?? 7.??? public static final int PASS_SELECTION_LABEL = 6;
?? 8.??? public static final int PASS_VIDEO_LABEL = 7;
?? 9.??? public static final int PASS_LOCATION_LABEL = 8;
??? 10.? public static final int PASS_MEDIASET_SOURCE_LABEL = 9;

Java 代码

?? 1.? drawDisplayItem(view, gl, displayItem, texture, PASS_THUMBNAIL_CONTENT, placeholde

?????? r,displayItem.mAnimatedPlaceholderFade); 画缩略图的,注掉此句,前两屏只显示框,
?????? 第三屏 OK
?? 2.? drawDisplayItem(view, gl, displayItem, texture, PASS_FOCUS_CONTENT, null, 0.0f);画单
?????? 张图片的,注掉,第三屏黑屏
?? 3.? drawDisplayItem(view, gl, itemDrawn, textureToUse, PASS_FRAME, previousTexture, ratio
?????? );画边框的,注掉,前两屏明显没有边框,巨齿明显
?? 4.? drawDisplayItem(view, gl, displayItem, textureString, PASS_TEXT_LABEL, null, 0);画文本
?????? 标签的
?? 5.? drawDisplayItem(view, gl, displayItem, textureToUse, PASS_SELECTION_LABEL, null, 0);画
?????? 选中标记的
?? 6.? drawDisplayItem(view, gl, displayItem, videoTexture, PASS_VIDEO_LABEL, null, 0);画视频
?????? 标记的
?? 7.? drawDisplayItem(view, gl, displayItem, locationTexture, PASS_LOCATION_LABEL, null, 0);
?????? 画位置标记的
?? 8.? drawDisplayItem(view, gl, displayItem, locationTexture, PASS_MEDIASET_SOURCE_LABEL
?????? ,transparentTexture, 0.85f);画源来源图标的(相机或一般文件夹)

二、特效
举如何显示一张图片为例,在图片完全显示出来经过这样一个过程,附近的图片
渐小渐出,当前图片渐大渐入,当前图片逐渐变大直到全屏。实现这个特效,要
进行很多帧的渲染。就是说并不是只调一次 onDrawFrame 函数就可以了,要调用
多次。可以把这个特效的实现想成一个状态变化的过程,在每一个状态,纹理的
显示大小和位置都不同,这也符合动画的基本原理。放大、缩小我们只要改变顶
点数据就可以做到,gallery3d 也是这样做的,下面是主要代码:
我们知道调用onDrawFrame来渲染,最后调到下面的 drawFocusItems 函数,

Java 代码

?? 1.? GridQuad quad = GridDrawables.sFullscreenGrid[vboIndex];
?? 2.? float u = texture.getNormalizedWidth();
3.? float v = texture.getNormalizedHeight();
??? 4.? float imageWidth = texture.getWidth();
??? 5.? float imageHeight = texture.getHeight();
??? 6.? boolean portrait = ((theta / 90) % 2 == 1);
??? 7.? if (portrait) {
??? 8.?????? viewAspect = 1.0f / viewAspect;
??? 9.? }

??? 10.? quad.resizeQuad(viewAspect, u, v, imageWidth, imageHeight);//改变用来贴图片的长方
??????? 形的大小
??? 11.? quad.bindArrays(gl);//绑定新数据,为渲染做准备。

而位置的改变有两种方式,一种是直接以顶点数据中改变,另一种是计算出在 3
维 3个方向的偏移量,再调用 gltranslate来做,从代码可以看出采用的是第二
种方式来做的,比第一种方式更方便一些。代码:

Java 代码

??? 1.? gl.glTranslatef(-translateXf, -translateYf, -translateZf);

而这里的3个偏移量的计算是和camera相关的,相关文件为GridCamera.java,
GridCameraManager.java,过程很复杂,理清楚后再细化吧。

cache管理
下面是cache文件

Java 代码

??? 1.? /sdcard/Android/data/com.cooliris.media/cache/local-album-cache
??? 2.? d---rwxr-x system? sdcard_rw?????? 2010-05-21 09:56 local-album-cache
??? 3.? d---rwxr-x system? sdcard_rw?????? 2010-05-21 09:56 local-meta-cache
??? 4.? ----rwxr-x system? sdcard_rw?? 299877 2010-05-28 07:36 local-album-cachechunk_0
??? 5.? d---rwxr-x system? sdcard_rw?????? 2010-05-21 09:56 geocoder-cache
??? 6.? ----rwxr-x system? sdcard_rw??? 284 2010-05-28 07:36 local-album-cacheindex
??? 7.? d---rwxr-x system? sdcard_rw?????? 2010-05-21 09:56 local-image-thumbs
??? 8.? d---rwxr-x system? sdcard_rw?????? 2010-05-21 09:56 local-video-thumbs
??? 9.? d---rwxr-x system? sdcard_rw?????? 2010-05-21 09:56 picasa-thumbs
??? 10.? ----rwxr-x system sdcard_rw???? 80 2010-05-28 07:36 local-meta-cachechunk_0
??? 11.? ----rwxr-x system sdcard_rw??? 164 2010-05-28 07:36 local-meta-cacheindex
??? 12.? d---rwxr-x system sdcard_rw?????? 2010-05-21 09:56 hires-image-cache
??? 13.? ----rwxr-x system sdcard_rw?? 627629 2010-05-28 07:37 local-image-thumbschunk_0
??? 14.? ----rwxr-x system sdcard_rw??? 3914 2010-05-21 09:56 local-image-thumbsindex
??? 15.? ----rwxr-x system sdcard_rw?? 53343 2010-05-28 07:34 hires-image-cache-4982941342
??????? 287215583_1024.cache
16.? ----rwxr-x system sdcard_rw?? 237692 2010-05-28 07:33 hires-image-cache36845684843
???????? 69117627_1024.cache
??? 17.? ----rwxr-x system sdcard_rw??? 133182 2010-05-28 07:34 hires-image-cache60754254408
???????? 1226432_1024.cache
??? 18.? ----rwxr-x system sdcard_rw??? 83223 2010-05-28 07:34 hires-image-cache42754796232
???????? 10216146_1024.cache
??? 19.? ----rwxr-x system sdcard_rw?? 292837 2010-05-28 07:34 hires-image-cache-6463165569
???????? 36433937_1024.cache
??? 20.? ----rwxr-x system sdcard_rw??? 191377 2010-05-28 07:35 hires-image-cache26313646045
???????? 09958174_1024.cache
??? 21.? ----rwxr-x system sdcard_rw?? 366905 2010-05-28 07:35 hires-image-cache-3280562009
???????? 766080884_1024.cache
??? 22.? ----rwxr-x system sdcard_rw?? 323671 2010-05-28 07:35 hires-image-cache57524718275
???????? 33329222_1024.cache

创建 cache 的关键代码

Java 代码

??? 1.?? LocalDataSource
??? 2.?? public static final DiskCache sThumbnailCache = new DiskCache("local-image-thumbs");--
???????? --------------------local-image-thumbs local-image-thumbschunk_0 local-image-thumbsind
???????? ex
??? 3.?? public static final DiskCache sThumbnailCacheVideo = new DiskCache("local-video-thum
???????? bs");--------------------local-video-thumbs
??? 4.?? public static final DiskCache sAlbumCache = new DiskCache("local-album-cache");---------
???????? -------------local-album-cache local-album-cacheindex
??? 5.?? public static final DiskCache sMetaAlbumCache = new DiskCache("local-meta-cache");----
???????? --------------local-meta-cache local-meta-cacheindex
??? 6.?? getChunkFile --------------local-meta-cachechunk_0 local-album-cachechunk_0
??? 7.
??? 8.?? ReverseGeocoder::?? private static final DiskCache sGeoCache = new DiskCache("geocoder
???????? -cache"); -------------------------geocoder-cache
??? 9.?? PicasaDataSource:: public static final DiskCache sThumbnailCache = new DiskCache("pica
???????? sa-thumbs");-----------------------------picasa-thumbs
??? 10.? UriTexture::writeToCache? --------------------------hires-image-cache-xxx_1024.cache

布局补充:
在画一个界面是,是分类化的,比如第一个界面是显示所有有图片的文件夹,在代
码里叫专辑.有这些元素要创建:
文本标签??????????? 显示专辑名和专辑内图片或视频数
路径条 显示路径名
按纽 拍照按纽,放大/缩小

菜单栏 全选,取消全选,分享,删除,更多等
图片边框
用于显示图片的矩形
在渲染时一次把一类元素画完,再画另一类.如主界面顺序为:
路径条->按纽->文本标签->图片边框->图片.
具体代码见drawBlendedComponents 函数

1.CacheService.java 中 写 缓 存 :??????? sAlbumCache.put(ALBUM_CACHE_LOCALE_INDEX,
sDummyData, 0);

?第一个是 key???? ,这里是正常数据,当然还有别的 key?????????????? , key? 分别是 -1,-2,-3,-4,-5 。

2.DiskCache.java 中,执行上面的写的过程,这里先得明白他的 cache???????????????? 怎么装的:

? 它是由很多称之为“片”的文件组成的,形成一个 List?????????????????? 形式: private final

LongSparseArray<RandomAccessFile>??????? mChunkFiles??????????? =?????????? new
LongSparseArray<RandomAccessFile>();

即 mChuckFiles 就是整个 cache???? ,里面包括很多 chunk(?????? 即片 )?? ,每一个 chunk???? 大小为
1MB.

当要写入某一个 chunk????????? 里面的时候,先要找到他在? mChuckFiles?????????????? 里面的索引值即
chunkIndex, 由

mChunkFiles.get(chunkIndex); 来获取这个文件, chunkIndex??? 怎么来的呢?

private LongSparseArray<Record> mIndexMap;

Record record = mIndexMap.get(key); 这里的 key 就是上面用 put?? 方法传过来的

ALBUM_CACHE_LOCALE_INDEX?? 的值(就是 -5???? )

int chunkIndex = record.chunk;

这么一步步来的。

当然了,第一次都是空的,也就是 get???????????????? 不到东西 mChunkFiles.get(chunkIndex);? 和 Record
record =

mIndexMap.get(key); 都 get 不到,那么第一次就先把东西放进去,mIndexMap.put(key, new
Record

(chunkIndex, record.offset, data.length, record.sizeOnDisk,? timestamp)); (记录key 值)以及
final

String chunkFilePath = mCacheDirectoryPath + CHUNK_FILE_PREFIX + chunk; chunkFile = new

RandomAccessFile(chunkFilePath, "rw");mChunkFiles.put(chunk, chunkFile); (三句代码来新建
一个

chunkfile 并放到 cache? 列表里面)

注意:Record??? 是内部类,只是一个数据集合类而已,相当于文件描述信息。每个 cache???????????????????????????? (即
chunk )对应一个。

private???? final?? LongSparseArray<RandomAccessFile>?? mChunkFiles??? =???? new
LongSparseArray<RandomAccessFile>(); 中 mChunkFiles 最大装 13? 个,每个 chunk???? 是 1M,
所以全部 Cache???? 是 13M.

  相关解决方案