Gallery3d 学习笔记(6)

继续讲解前,我们先回顾一下前面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);



mDrawManager就是负责界面的显示的。我们仔细看下。


大家还记得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画缩略图


在这里我们看到了缩略图显示刷新,但是还有一些疑问,数据从哪里来的,而且这里只有一个界面的显示,其他的界面如何显示的?下次探讨吧。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值