android 3d城市源码,[转载]android Gallery3D源码分析
一、布局
gallery3d的界面生成和普通的應用程序不一樣。普通程序一般一個界面就是一個activity,布局用xml或代碼都可以實現,界面切換是activity的切換方式;而gallery3d沒有用android的UI系統,而是用opengl畫出來的,即界面是在同一個activity的,如主界面,縮略圖界面,單張圖片查看界面,標記界面等都屬于同一個activity。
?重要線程推薦
在利用過程中有三個極其重要的線程存在:主線程(Gallery隨activity的生命周期啟用燒毀)、MediaFeed初始化線程(進去過程時只運行順次,用于加載相冊初始消息)、MediaFeed監聽線程(始終在跑,監聽相冊和相片的改變),其中MediaFeed初始化線程的工作是:調用MediaFeed
的loadMediaSets加載相冊,MediaFeed監聽線程MediaFeed.run()的工作是:依據“內容改變監聽器“歸來的媒體改變消息(增刪改),繼續不時的更新
MediaFeed中的相冊和相片變量。
那么這界面布局不同的界面是如何組合到一起的呢?分析代碼,可以把它看成一個狀態機
:
1、標記模式?public static final int MODE_SELECT =
1;(HudLayer)
包含了主界面標記模式,縮略界面矩陣游覽時標記模式、縮略圖界面分類游覽時標記模式3個界面
2、普通模式?public static final int
MODE_NORMAL = 0;(HudLayer)
包含了?public static final int
STATE_MEDIA_SETS = 0;主界面
public static final int
STATE_GRID_VIEW = 1;縮略圖矩陣瀏覽
public static final int
STATE_FULL_SCREEN = 2;查看界面
public static final int
STATE_TIMELINE = 3;縮略圖界面分類瀏覽
?切換界面流程
相冊界面,縮略圖界面,以及圖片博覽界面等,這些界面的跳轉不同于activity之間的跳轉,因為它們并不是每個都對應一個獨自的activity而是分享一個activity。Gallery3D里面用不同的事態來標識不同的界面,這些事態定義在GridLayer里面如下:
public static final int STATE_MEDIA_SETS = 0;
public static final int STATE_GRID_VIEW = 1;
public static final int STATE_FULL_SCREEN = 2;
public static final int STATE_TIMELINE = 3;
事態的改變引起界面的改變,Gallery3D里面批準了通知形式,事態改變的接口為GridLayer中的public void
setState(int state),通知接口為HudLayer中的public void
onGridStateChanged()。界面的切換是由事件發動的,因而在事件的響應函數里面會對用戶的觸屏動作分解成一個個的事態,如剛進去Gallery3D的時候會穿越調用setState(STATE_MEDIA_SETS)設置事態為STATE_MEDIA_SETS,并發送通知即調用onGridStateChanged()最后調用HudLayer的updateViews()措施舉行描摹與更新,從而進去相冊界面;同樣當用戶點擊相冊的時候,會改換事態為STATE_GRID_VIEW,然后重新描摹界面進去縮略圖界面,其他界面的切換也是同樣的理由,當事態未曾發生改變的時候將不會厲行回調函數setState()和onGridStateChanged()。
有了以上狀態分類后,在渲染的時候就能根據些界面的組成來定哪些控件譔隱藏,哪些要顯示了。
下面是基本控件:
com.cooliris.media.GridLayer :網格所略圖揭示和個體圖片揭示
com.cooliris.media.BackgroundLayer:背景
com.cooliris.media.HudLayer:相冊揭示
com.cooliris.media.ImageButton:圖片按鈕(重要指進去Gallery后右上角的那個控件)
com.cooliris.media.TimeBar:進去Gallery后下方可拖動的懸浮控件
com.cooliris.media.MenuBar :點擊圖片時彈出的菜單按鈕
com.cooliris.media.PopupMenu:點擊菜單按鈕后彈出來的菜單項
com.cooliris.media.PathBarLayer:現今Gallery后左上方揭示圖片路徑的空間
在渲染時,每一幀所有界面上的元素都畫了,由于根據上面的狀態只把特定窗口的特定元素顯示出來,其它窗口中的隱藏,所以不會亂。
Layer是上面控件的基類,上面控件的類也就有了下面兩個方法來隱藏不譔顯示的界面元素。
public boolean isHidden()
{
return
mHidden;
}
public void setHidden(boolean
hidden) {
if (mHidden
!= hidden) {
mHidden =
hidden;
onHiddenChanged();
}
}
下面是根據上面分類來畫不同元素所用的標識:
public static final int
PASS_THUMBNAIL_CONTENT = 0;
public static final int
PASS_FOCUS_CONTENT = 1;
public static final int
PASS_FRAME = 2;
public static final int
PASS_PLACEHOLDER = 3;
public static final int
PASS_FRAME_PLACEHOLDER = 4;
public static final int
PASS_TEXT_LABEL = 5;
public static final int
PASS_SELECTION_LABEL = 6;
public static final int
PASS_VIDEO_LABEL = 7;
public static final int
PASS_LOCATION_LABEL = 8;
public static final int
PASS_MEDIASET_SOURCE_LABEL = 9;
drawDisplayItem(view, gl, displayItem, texture,
PASS_THUMBNAIL_CONTENT, placeholder,
displayItem.mAnimatedPlaceholderFade);
畫縮略圖的,注掉此句,前兩屏只顯示框,第三屏OK
drawDisplayItem(view, gl, displayItem, texture, PASS_FOCUS_CONTENT,
null, 0.0f);畫單張圖片的,注掉,第三屏黑屏
drawDisplayItem(view, gl, itemDrawn, textureToUse, PASS_FRAME,
previousTexture, ratio);畫邊框的,注掉,前兩屏明顯沒有邊框,巨齒明顯
drawDisplayItem(view, gl, displayItem, textureString,
PASS_TEXT_LABEL, null, 0);畫文本標簽的
drawDisplayItem(view, gl, displayItem, textureToUse,
PASS_SELECTION_LABEL, null, 0);畫選中標記的
drawDisplayItem(view, gl, displayItem, videoTexture,
PASS_VIDEO_LABEL, null, 0);畫視頻標記的
drawDisplayItem(view, gl, displayItem, locationTexture,
PASS_LOCATION_LABEL, null, 0);畫位置標記的
drawDisplayItem(view, gl, displayItem, locationTexture,
PASS_MEDIASET_SOURCE_LABEL,
transparentTexture, 0.85f);畫源來源圖標的(相機或一般文件夾)
?渲染流程
Gallery3D的渲染從 RenderView 開始。RenderView 從 GLSu***ceView
繼承而來,批準了通知型描摹形式,即穿越調用requestRender 通知 RenderView 重繪屏幕。RenderView
將所有必需描摹的對象都保留一個 Lists中,Lists 包括了5個ArrayList,其定義如下所示:
public final ArrayList
updateList =
newArrayList();
public final ArrayList
opaqueList =
newArrayList();
public final ArrayList
blendedList =
newArrayList();
public final ArrayList
hitTestList =
newArrayList();
public final ArrayList
systemList = new
ArrayList();
RenderView 的onDrawFrame接口告終每一幀的描摹壟斷,描摹時遍歷 lists 里每個 list 的每一個成員并調用其
renderXXX 函數。重要代碼如下所示:
...
final Lists lists = sLists;
final ArrayList updateList =
lists.updateList;
boolean isDirty = false;
for (int i = 0,imomc.com size = updateList.size(); i != size;
++i) {
boolean retVal =
updateList.get(i).update(this,mFrameInterval);
isDirty |= retVal;
}
if (isDirty) {
requestRender();
}
// Clear the depth buffer.
gl.glClear(GL11.GL_DEPTH_BUFFER_BIT);
gl.glEnable(GL11.GL_SCISSOR_TEST);
gl.glScissor(0, 0, getWidth(), getHeight());
// Run the opaque pass.
gl.glDisable(GL11.GL_BLEND);
final ArrayList opaqueList =
lists.opaqueList;
for (int i = opaqueList.size() - 1; i >= 0; --i)
{
final Layer layer = opaqueList.get(i);
if (!layer.mHidden) {
layer.renderOpaque(this,gl);
}
}
// Run the blended pass.
gl.glEnable(GL11.GL_BLEND);
final ArrayList blendedList =
lists.blendedList;
for (int i = 0, size = blendedList.size(); i != size; ++i) {
final Layer layer = blendedList.get(i);
if (!layer.mHidden) {
layer.renderBlended(this,gl);
}
}
gl.glDisable(GL11.GL_BLEND);
lists 的各個 list 里包括的各個 layer 如下所示:
lists
|-----------------------|-----------------------|-----------------------|-----------------------|
updateListopaqueList blendedList systemListhitTestList
| ||| |
GridLayerGridLayer GridLayerGridLayerGridLayer
BackgroudLayerBackgroudLayer BackgroudLayer
HudLayerHudLayerHudLayerHudLayer
TimeBarTimeBar TimeBar
PathBar PathBar PathBar
XXXButton XXXButtonXXXButton
XXXMenuXXXMenuXXXMenu
Layer供給了update(....),renderOpaque(....),renderBlended(....)接口,這些接口會在RenderView的onDrawFrame描摹代碼中被調用。GridLayer
中有個
GridDrawManager,專程負責描摹,在前面的那幾個接口中會調用到GridDrawManager的一些翔實描摹函數告終懇摯的畫圖工作如:
drawDisplayItem(view, gl, displayItem, texture,
PASS_THUMBNAIL_CONTENT,placeholder,
displayItem.mAnimatedPlaceholderFade); 畫縮略圖的
drawDisplayItem(view, gl, displayItem, texture, PASS_FOCUS_CONTENT,
null,0.0f);畫單張圖片的
drawDisplayItem(view, gl, itemDrawn, textureToUse, PASS_FRAME,
previousTexture,ratio);畫邊框的
drawDisplayItem(view, gl, displayItem, textureString,
PASS_TEXT_LABEL, null,0);畫文本標簽的
drawDisplayItem(view, gl, displayItem, textureToUse,
PASS_SELECTION_LABEL,null, 0);畫選中符號的
drawDisplayItem(view, gl, displayItem, videoTexture,
PASS_VIDEO_LABEL, null,0);畫視頻符號的
drawDisplayItem(view, gl, displayItem, locationTexture,
PASS_LOCATION_LABEL,null, 0);畫位置符號的
drawDisplayItem(view, gl, displayItem, locationTexture,
PASS_MEDIASET_SOURCE_LABEL,transparentTexture,0.85f);畫源起源圖標的(相機或等閑文件夾)
?事件機制
由于所有界面都同屬于一個activity,因而所有的事件引發動作都起源于主線程,切實上是主線程中的RenderView的onTouchEvent:
public boolean onTouchEvent(MotionEvent event) {
// Ignore events received before thesu***ce is created to
avoid
// deadlocking with GLSu***ceView'sneedToWait().
if (mGL == null) {
returnfalse;
}
// Wait for the render thread toprocess this event.
if (mTouchEventQueue.size() >
8&& event.getAction() ==
MotionEvent.ACTION_MOVE)
return true;
synchronized (mTouchEventQueue) {
MotionEventeventCopy = MotionEvent.obtain(event);
mTouchEventQueue.addLast(eventCopy);
requestRender();
}
return true;
}
在這里它將所有的觸屏事件放在一個待處理的事件隊列里面,當隊列里面的事件數大于8可能該事件屬于拖動事件的時候它將期待,否則會將該事件加入隊列,并調用requestRender()哀求描摹。于是會重新調用RenderView的onDrawFrame描摹代碼,其中有個函數processTouchEvent(),這個函數的重要功能是負責處理事件隊列中的事件,查找該事件起源于哪個控件(對應翔實的某個Layer子類),然后將事件發放給該控件處理,控件接受到事件的時候會調用切身的onTouchEvent()函數,在這里會依據事件的不同設置一些不同的數據重要是給描摹的時候要用的,最后會調用到懇摯的事件處理類GestureDetector.Java的相干措施包括對是否是雙擊阿單擊阿等。在這里必需解釋一下,它并未曾把響應事件的翔實告終放在每個layer的子類中,而是提取出了一個類GestureDetector.Java專程負責響應事件。以上即便全副事件的響應流程,事件統一由RenderView負責創立,然后依據條件的不同下發給相應的控件響應
二、特效
舉如何顯示一張圖片為例,在圖片完全顯示出來經過這樣一個過程,附近的圖片漸小漸出,當前圖片漸大漸入,當前圖片逐漸變大直到全屏。實現這個特效,要進行很多幀的渲染。就是說并不是只調一次onDrawFrame函數就可以了,要調用多次。可以把這個特效的實現想成一個狀態變化的過程,在每一個狀態,紋理的顯示大小和位置都不同,這也符合動畫的基本原理。放大、縮小我們只要改變頂點數據就可以做到,gallery3d也是這樣做的,下面是主要代碼:
我們知道調用onDrawFrame來渲染,最后調到下面的drawFocusItems函數,
GridQuad quad = GridDrawables.sFullscreenGrid[vboIndex];
float u = texture.getNormalizedWidth();
float v = texture.getNormalizedHeight();
float imageWidth = texture.getWidth();
float imageHeight = texture.getHeight();
boolean portrait = ((theta / 90) % 2 == 1);
if (portrait) {
viewAspect =
1.0f / viewAspect;
}
quad.resizeQuad(viewAspect, u, v, imageWidth,
imageHeight);//改變用來貼圖片的長方形的大小
quad.bindArrays(gl);//綁定新數據,為渲染做準備。
而位置的改變有兩種方式,一種是直接以頂點數據中改變,另一種是計算出在3維3個方向的偏移量,再調用gltranslate來做,從代碼可以看出采用的是第二種方式來做的,比第一種方式更方便一些。代碼:
gl.glTranslatef(-translateXf, -translateYf, -translateZf);
而這里的3個偏移量的計算是和camera相關的,相關文件為GridCamera.java,GridCameraManager.java,過程很復雜,理清楚后再細化吧。
cache管理
下面是cache文件
/sdcard/Android/data/com.cooliris.media/cache/local-album-cache
d---rwxr-x system?sdcard_rw?2010-05-21
09:56 local-album-cache
d---rwxr-x system?sdcard_rw?2010-05-21
09:56 local-meta-cache
----rwxr-x system?sdcard_rw?299877 2010-05-28 07:36
local-album-cachechunk_0
d---rwxr-x system?sdcard_rw?2010-05-21
09:56 geocoder-cache
----rwxr-x system?sdcard_rw?284
2010-05-28 07:36 local-album-cacheindex
d---rwxr-x system?sdcard_rw?2010-05-21
09:56 local-image-thumbs
d---rwxr-x system?sdcard_rw?2010-05-21
09:56 local-video-thumbs
d---rwxr-x system?sdcard_rw?2010-05-21
09:56 picasa-thumbs
----rwxr-x system?sdcard_rw?80
2010-05-28 07:36 local-meta-cachechunk_0
----rwxr-x system?sdcard_rw?164
2010-05-28 07:36 local-meta-cacheindex
d---rwxr-x system?sdcard_rw?2010-05-21
09:56 hires-image-cache
----rwxr-x system?sdcard_rw?627629 2010-05-28 07:37
local-image-thumbschunk_0
----rwxr-x system?sdcard_rw?3914
2010-05-21 09:56 local-image-thumbsindex
----rwxr-x system?sdcard_rw?53343 2010-05-28 07:34
hires-image-cache-4982941342287215583_1024.cache
----rwxr-x system?sdcard_rw?237692 2010-05-28 07:33
hires-image-cache3684568484369117627_1024.cache
----rwxr-x system?sdcard_rw?133182 2010-05-28 07:34
hires-image-cache607542544081226432_1024.cache
----rwxr-x system?sdcard_rw?83223 2010-05-28 07:34
hires-image-cache4275479623210216146_1024.cache
----rwxr-x system?sdcard_rw?292837 2010-05-28 07:34
hires-image-cache-646316556936433937_1024.cache
----rwxr-x system?sdcard_rw?191377 2010-05-28 07:35
hires-image-cache2631364604509958174_1024.cache
----rwxr-x system?sdcard_rw?366905 2010-05-28 07:35
hires-image-cache-3280562009766080884_1024.cache
----rwxr-x system?sdcard_rw?323671 2010-05-28 07:35
hires-image-cache5752471827533329222_1024.cache
創建cache的關鍵代碼
LocalDataSource
public static final DiskCache sThumbnailCache = new
DiskCache("local-image-thumbs");----------------------local-image-thumbs
local-image-thumbschunk_0?local-image-thumbsindex
public static final DiskCache sThumbnailCacheVideo = new
DiskCache("local-video-thumbs");--------------------local-video-thumbs
public static final DiskCache sAlbumCache = new
DiskCache("local-album-cache");----------------------local-album-cache?local-album-cacheindex
public static final DiskCache sMetaAlbumCache = new
DiskCache("local-meta-cache");------------------local-meta-cache?local-meta-cacheindex
getChunkFile
--------------local-meta-cachechunk_0?local-album-cachechunk_0
ReverseGeocoder::?private static
final DiskCache sGeoCache = new DiskCache("geocoder-cache");
-------------------------geocoder-cache
PicasaDataSource:: public static final DiskCache sThumbnailCache =
new
DiskCache("picasa-thumbs");-----------------------------picasa-thumbs
UriTexture::writeToCache?--------------------------hires-image-cache-xxx_1024.cache
歡迎大家多交流,不對之處請大家指正。
總結
以上是生活随笔為你收集整理的android 3d城市源码,[转载]android Gallery3D源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Teams App 扫描二维码
- 下一篇: 面试 - 智力测试