ACTION_UP is not working, but ACTION_DOWN works fine

时间:2015-07-31 20:28:14

标签: java android android-studio event-handling eventhandler

I've been learning (slowly) how to program Android games using Java and Android Studio. My main source of learning was following the tutorials that are located on the Kilobolt Tutorial Website. I have found these extremely helpful, but because they are tutorials on Android ADT for Eclipse, and they are 3 years old, I have had to do a lot learning with each section to learn Android Studio (a huge process).

I have found that, mostly, that the logic on the tutorial has been solid. My issue is that in the SingleTouchHandler class of the framework provided by Kilobolt, ACTION_UP does not seem to work. Here is the Input Class:

public interface Input {

public static class TouchEvent {
    public static final int TOUCH_DOWN = 0;
    public static final int TOUCH_UP = 1;
    public static final int TOUCH_DRAGGED = 2;
    public static final int TOUCH_HOLD = 3;

    public int type;
    public int x, y;
    public int pointer;

}

public boolean isTouchDown(int pointer);

public int getTouchX(int pointer);

public int getTouchY(int pointer);

public List<TouchEvent> getTouchEvents();

}

and here is it's implementation:

public class SingleTouchHandler implements TouchHandler {
boolean isTouched;
int touchX;
int touchY;
Pool<TouchEvent> touchEventPool;
List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();
List<TouchEvent> touchEventsBuffer = new ArrayList<TouchEvent>();
float scaleX;
float scaleY;

public SingleTouchHandler(View view, float scaleX, float scaleY) {
    PoolObjectFactory<TouchEvent> factory = new PoolObjectFactory<TouchEvent>() {
        @Override
        public TouchEvent createObject() {
            return new TouchEvent();
        }
    };
    touchEventPool = new Pool<TouchEvent>(factory, 100);
    view.setOnTouchListener(this);

    this.scaleX = scaleX;
    this.scaleY = scaleY;
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    synchronized(this) {
        TouchEvent touchEvent = touchEventPool.newObject();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchEvent.type = TouchEvent.TOUCH_DOWN;
                isTouched = true;
                break;
            case MotionEvent.ACTION_MOVE:
                touchEvent.type = TouchEvent.TOUCH_DRAGGED;
                isTouched = true;
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                touchEvent.type = TouchEvent.TOUCH_UP;
                isTouched = false;
                break;
        }

        touchEvent.x = touchX = (int)(event.getX() * scaleX);
        touchEvent.y = touchY = (int)(event.getY() * scaleY);
        touchEventsBuffer.add(touchEvent);

        return true;
    }
}

@Override
public boolean isTouchDown(int pointer) {
    synchronized(this) {
        if(pointer == 0)
            return isTouched;
        else
            return false;
    }
}

@Override
public int getTouchX(int pointer) {
    synchronized(this) {
        return touchX;
    }
}

@Override
public int getTouchY(int pointer) {
    synchronized(this) {
        return touchY;
    }
}

@Override
public List<TouchEvent> getTouchEvents() {
    synchronized(this) {
        int len = touchEvents.size();
        for( int i = 0; i < len; i++ )
            touchEventPool.free(touchEvents.get(i));
        touchEvents.clear();
        touchEvents.addAll(touchEventsBuffer);
        touchEventsBuffer.clear();
        return touchEvents;
    }
}
}

Again, these are a framework provided by the good man James Cho from Kilobolt and readily available on the Kilobolt website if wanted.

In my implementation: TOUCH_DOWN, a variable used to represent any ACTION_DOWN usage, work fine. However, TOUCH_UP (for ACTION_UP) doesn't work at all. Here is a block of code where I use it in my games Update Function:

    int len = touchEvents.size();
    for (int i = 0; i < len; i++) {
        TouchEvent event = (TouchEvent) touchEvents.get(i);
        if (event.type == TouchEvent.TOUCH_DOWN) {



        }

        if (event.type == TouchEvent.TOUCH_UP) {
            if (inBounds(event, 190, 350, 100, 100)) {

                game.setScreen(new Menu(game));
            }
        }
    }

In my code above, when the touch is lifted off the screen, TOUCH_UP should allow my game state to change to the Menu Screen. However, nothing happens.

If I placed game.setScreen(new Menu(game)); in the if statement:

if (event.type == TouchEvent.TOUCH_DOWN) it works fine.

Is it an error in the code or do I have a misunderstanding of how ACTION_UP and the other actions work? I test using a Samsung Galaxy S5.

Thanks for any help. Learning Android Studio and game development has been one heck of a process, but I'm definitely getting better.

2 个答案:

答案 0 :(得分:1)

您可能会在false上返回ACTION_DOWN

ACTION_UP仅在您true事件返回ACTION_DOWN时有效。

答案 1 :(得分:0)

你好像在这里重新发明轮子。你尝试过一种更简单的方法吗?

首先,实现实际的侦听器,如View.OnTouchListener。它很简单,在API级别1中引入,并且运行良好。

事实上,我甚至不会有一个SingleTouchHandler类(除非您计划在多个视图上设置此触摸侦听器。在这种情况下,实现OnTouchListener而不是TouchHandler)。我只是在OnTouchListener的构造函数中初始化onTouch方法,如下所示:

view.setOnTouchListener(new View.OnTouchListener(){
    @Override
    public boolean onTouch(View v, MotionEvent event){
        //Synchronize if you wish
        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN:
                //Press code
                break;
            case MotionEvent.ACTION_MOVE:
                //Move code
                break;
            case MotionEvent.ACTION_UP:
                //release code
                break;
        }
        return true;
    }
});

根本不需要额外的课程。只需将它包含在View子类的构造函数中即可。这已经过测试,并且在SurfaceViews上按预期工作,如果您正在编写动态游戏,那么您应该正在使用它。其次,如上所述,如果您希望在多个视图上设置此OnTouchListener,那么您需要将其设置为自己的类,如您已有的类(SingleTouchHandler)并使其实现View.OnTouchListener(而不是TouchHandler) )。然而,再次假设您正在编写动态游戏,所有图形很可能都是在一个SurfaceView上绘制的,这意味着只有一个View可以在其上分配这个OnTouchListener,从而无需一个类一起使用(使用上面显示的方法。)