继续讲解前,我们先回顾一下前面5节的分析。
首先在开机或者加载外部存储器时,在mediaprivder里面receiver会得到广播消息,receiver开启服务进行扫描,生成数据库,并在T卡上生成缩略图临时文件,
然后在第一个Activity里面有两个关于opengl的成员,RenderView和作为Root Layer 的GridLayer成员,并且关联了RenderView和Root Layer,并且在Activity里面通过调用RenderView的同名成员函数的办法,将按键响应以及渲染的暂停和继续同Activity同步关联。
而RenderView在刷新时,通过调用generate接口,生成Root层的,Root层调用generate接口生成背景层和Hud层,同样的办法Hud层生成其他的层,并将RendView保存到自己的成员变量中。
而这些层又分成了几个类,放在几个层的列表中,决定哪些层响应点击事件,哪些层透明。
现在我们要分析的问题是,界面和层是如何关联的,又是如何切换的?
这个问题比较多,会花几个部分解决。
我们先探讨一个小的问提,我们先使用下Gallery3d ,你会发现长按键后可以标记相册或者单一图片或者视频。
说明Gallery3d里面又两种模式,普通模式和选择模式对应的代码是在HudLayer中:
public final class HudLayer extends Layer {
public static final int MODE_NORMAL = 0;
public static final int MODE_SELECT = 1;
那么在关键的HudLayer中又用了两个方法来读取和设置模式
int getMode() {
return mMode;
}
void setMode(int mode) {
if (mMode != mode) {
mMode = mode;
updateViews();
}
}
在哪里调用的呢
public void enterSelectionMode() {
// Do not enter selection mode if the feed is about to change.
if (mGridLayer.feedAboutToChange())
return;
// Disable sharing if it is the pick intent.
if (mGridLayer.getPickIntent()) {
mSingleViewIntentBottomMenu = mSingleViewIntentBottomMenuNoShare;
mNormalBottomMenu = mNormalBottomMenuNoShare;
}
setAlpha(1.0f);
setMode(HudLayer.MODE_SELECT);
// if we are in single view mode, show the bottom menu without the
// delete button.
if (mGridLayer.noDeleteMode()) {
mSelectionMenuBottom.setMenus(mSingleViewIntentBottomMenu);
} else {
mSelectionMenuBottom.setMenus(mNormalBottomMenu);
}
}
public void cancelSelection() {
mSelectionMenuBottom.close();
closeSelectionMenu();
setMode(MODE_NORMAL);
}
就是通过HudLayer中的进入选择模式和退出选择模式来切换模式的和菜单的显示。那么从用户长按又是如何到enterSelectMode函数的呢?
首先触摸是各个层里面处理的,而按键都是Root Layer处理的,谁是Root Layer,当然是GridLayer,我们看下GridLayer是如何处理的
@Override
public boolean onTouchEvent(MotionEvent event) {
return mInputProcessor.onTouchEvent(event);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (mInputProcessor != null)
return mInputProcessor.onKeyDown(keyCode, event, mState);
return false;
}
说明所有GridLayer的按键和触摸都交给了一个叫做mInputProcessor的成员去处理了。对应的是
GridInputProcessor类
public void onLongPress(MotionEvent e) {
if (mZoomGesture)
return;
if (mLayer.getFeed() != null && mLayer.getFeed().isSingleImageMode()) {
HudLayer hud = mLayer.getHud();
hud.getPathBar().setHidden(true);
hud.getMenuBar().setHidden(true);
if (hud.getMode() != HudLayer.MODE_NORMAL)
hud.setMode(HudLayer.MODE_NORMAL);
}
if (mCurrentFocusSlot != Shared.INVALID) {
vibrateLong();
GridLayer layer = mLayer;
if (layer.getState() == GridLayer.STATE_FULL_SCREEN) {
layer.deselectAll();
}
HudLayer hud = layer.getHud();
hud.enterSelectionMode();
layer.addSlotToSelectedItems(mCurrentFocusSlot, true, true);
}
}
那么,我们重新整理下思路:
用户长按 Activity --> 因为Acitvity中的触摸是层里面处理的,所以给了根层GridLayer去处理,而GridLayer嫌麻烦,另外写了一个类GridInputProcessor的成员处理,而再这个类中,调用通过传进来的GridLayer上下文和方法 getHud获得了Hud层的对象,然后调用他的enterSelectionMode方法,将状态设置成了选择模式。
长按和处理我们看完了,其他的拖动和点击请自己再分析下,作为今天的作业吧,呵呵。
那么我们再来看GridLayer界面的显示,再构造函数我们可以看到下面的代码。
mCameraManager = new GridCameraManager(mCamera);
mDrawManager = new GridDrawManager(context, mCamera, mDrawables, mDisplayList, mDisplayItems, mDisplaySlots);
mInputProcessor = new GridInputProcessor(context, mCamera, this, mView, mTempVec, mDisplayItems);
大家还记得RenderView里面对三组层的列表进行的统一刷新么?
其中对opaque层是怎么刷新的,使用的是一个循环,加上调用层的renderOpaque方法,那么我们来看这个里面是否有?我们看GridLayer层的刷新函数
// Renders the node in a given pass.
public void renderOpaque(RenderView view, GL11 gl) {
GridCamera camera = mCamera;
int selectedSlotIndex = mInputProcessor.getCurrentSelectedSlot();
computeVisibleItems();
gl.glMatrixMode(GL11.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, -camera.mEyeX, -camera.mEyeY, -camera.mEyeZ, -camera.mLookAtX, -camera.mLookAtY, -camera.mLookAtZ,
camera.mUpX, camera.mUpY, camera.mUpZ);
view.setAlpha(1.0f);
if (mSelectedAlpha != 1.0f) {
gl.glEnable(GL11.GL_BLEND);
gl.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
view.setAlpha(mSelectedAlpha);
}
if (selectedSlotIndex != Shared.INVALID) {
mTargetAlpha = 0.0f;
} else {
mTargetAlpha = 1.0f;
}
mDrawManager.prepareDraw(mBufferedVisibleRange, mVisibleRange, selectedSlotIndex, mInputProcessor.getCurrentFocusSlot(),
mInputProcessor.getCurrentScaledSlot(), mInputProcessor.isFocusItemPressed(), mInputProcessor.getScale(),
mInputProcessor.getScaleGestureDetector(), mFeedAboutToChange);
if (mSelectedAlpha != 0.0f) {
mDrawManager.drawThumbnails(view, gl, mState);
}
if (mSelectedAlpha != 1.0f) {
gl.glDisable(GL11.GL_BLEND);
}
// We draw the selected slotIndex.
if (selectedSlotIndex != Shared.INVALID) {
mDrawManager.drawFocusItems(view, gl, mZoomValue, mSlideshowMode, mTimeElapsedSinceView);
mCurrentFocusItemWidth = mDrawManager.getFocusQuadWidth();
mCurrentFocusItemHeight = mDrawManager.getFocusQuadHeight();
}
view.setAlpha(mSelectedAlpha);
}
在这里面,我们找到了实质性刷界面的函数
ComputerVisibleItem();计算可见项目
mDrawManager.prepareDraw准备工作
mDrawManager.drawThumnails画缩略图
在这里我们看到了缩略图显示刷新,但是还有一些疑问,数据从哪里来的,而且这里只有一个界面的显示,其他的界面如何显示的?下次探讨吧。