Part I 空气曲棍球 Chapter9(9.1 Adding Touch Support to Our Activity)

9.1 增加触摸反馈(Adding Touch Support to Our Activity)

    这里将会拦截Android事件系统中的事件,首先持有渲染器的一个引用,打开AirHockeyActivity然后修改setRenderer(),代码如下:

//AirHockeyTouch/src/com/airhockey/android/AirHockeyActivity.java
final AirHockeyRenderer airHockeyRenderer = new AirHockeyRenderer(this);
if (supportsEs2) {
    // ...
    glSurfaceView.setRenderer(airHockeyRenderer);
    // ...
}

    我们将会使用这个引用把相关事件通知到渲染器。
9.1.1 事件监听(Listening to Touch Events)
    现在开始写事件处理器,在setContentView()之前增加如下代码:

//AirHockeyTouch/src/com/airhockey/android/AirHockeyActivity.java
glSurfaceView.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event != null) {
            // Convert touch coordinates into normalized device
            // coordinates, keeping in mind that Android's Y
            // coordinates are inverted.
            final float normalizedX = (event.getX() / (float) v.getWidth()) * 2 - 1;
            final float normalizedY = -((event.getY() / (float) v.getHeight()) * 2 - 1);
            // ...
}

    在Android里面我们可以调用函数setOnTouchListener()设置一个事件监听器,当用户触摸相应view的时候我们就可以在onTouch()中处理相应的事件。
    首先检测是否有要处理的事件;在Android中,触摸事件坐标位于view坐标空间中,因此左上角对应于顶点(0, 0),右下角对应于view的尺寸。比如我们的view为480x800(宽x高),所以右下角坐标将会映射到(480, 800)。
    由于在渲染器中我们都是使用规范化坐标的,所以我们需要通过反转y坐标然后把每一个坐标规范化到范围[-1, 1]中。
9.1.2 事件转发(Forwarding Touch Events to Our Renderer)
    下面是事件转发的完整代码:

@Override
public boolean onTouch(View v, MotionEvent event) {
    if (event != null) {           
        // Convert touch coordinates into normalized device
        // coordinates, keeping in mind that Android's Y
        // coordinates are inverted.
        final float normalizedX = (event.getX() / (float) v.getWidth()) * 2 - 1;
        final float normalizedY = -((event.getY() / (float) v.getHeight()) * 2 - 1);
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            glSurfaceView.queueEvent(new Runnable() {
                @Override
                public void run() {
                    airHockeyRenderer.handleTouchPress(normalizedX, normalizedY);
                }
            });
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            glSurfaceView.queueEvent(new Runnable() {
                @Override
                public void run() {
                    airHockeyRenderer.handleTouchDrag(normalizedX, normalizedY);
                }
            });
        }                    

        return true;                    
    } else {
        return false;
    }
}

    这里分区分事件是点击还是滑动,因为针对这两种情况有不同的事件处理,点击事件对应于MotionEvent.ACTION_DOWN,滑动事件对应于MotionEvent.ACTION_MOVE。
    需要注意的一点Android的UI运行于主线程中,而GLSurfaceView在一个独立的线程中,因此我们需要在这两个线程之间使用一种安全的方式交互。我们可以使用方法queueEvent()把调用分派到OpenGL 线程中,然后在OpenGL线程中调用方法airHockeyRenderer.handleTouchPress() 处理点击事件,调用方法 airHockeyRenderer.handleTouchDrag() 处理滑动事件。由于还没有创建这两个方法,所以接下来将会创建他们。
    上面的方法中通过传入true表示我们将会消耗事件,假如事件为null我们将会返回false。
    打开渲染器AirHockeyRenderer,并加入如何存根方法:

//AirHockeyTouch/src/com/airhockey/android/AirHockeyRenderer.java
public void handleTouchPress(float normalizedX, float normalizedY) {
}
public void handleTouchDrag(float normalizedX, float normalizedY) {
}

   作为一个小的练习,你可以在上面的方法中加入一些log打印方法,运行程序并观察触摸屏幕的时候输出的log信息。

    下一节,我们将学习如何增加相交测试(点击进入下一节)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值