Android onDoubleTap, onScroll, onFling не работает, а onDown и onLongPress работают?

Я пытаюсь использовать метод onScroll в своем пользовательском представлении. onDown и onLongPress работают, но почему не работает мой onScroll, onFling или onDoubleTap? Вот мой код, это почти все, что Google предоставил на своем веб-сайте developer.android.com...

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.MotionEventCompat;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.*;

public class GameView extends View implements GestureDetector.OnGestureListener,      GestureDetector.OnDoubleTapListener{

public static int cols = 10;
public static int rows = 9;

private String DEBUG_TAG = "Debug";

private GestureDetectorCompat mDetector;
private GameThread mGameThread;
private Sprite mSprite;
private MineField mMineField;
private Context context;
private Paint mPaint;

public GameView(Context context) {
    super(context);
    this.context = context;
    if(mMineField == null)buildMineField(cols, rows);
    mPaint = new Paint();
    mSprite = new Sprite(context, this);
    mGameThread = new GameThread(this, mSprite, mMineField);
    mGameThread.start();

    mPaint.setColor(Color.WHITE);
    mPaint.setStyle(Style.FILL);
    mPaint.setTextSize(50);

    mDetector = new GestureDetectorCompat(context, this);
}

public Sprite getSprite() {
    return mSprite;
}

public MineField getMineField() {
    return mMineField;
}

public void buildMineField(int cols, int rows) {
    if(cols >= 1 && rows >= 1) {
        mMineField = new MineField(cols, rows, context, this);
    }
}

public void drawMineField(Canvas canvas) {
    for(int i = 0; i < mMineField.rows; i++) {
        for(int j = 0; j < mMineField.cols; j++) {
            canvas.drawBitmap(mMineField.mines[j][i].getBitmap(), mMineField.mines[j][i].getX(), mMineField.mines[j][i].getY(), null);
        }
    }
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawColor(Color.BLACK);
    drawMineField(canvas);
    if(mSprite.isVisible()) {
        canvas.drawBitmap(mSprite.getBitmap(), mSprite.getX(), mSprite.getY(), null);
    }
    canvas.drawText(Long.toString(mGameThread.getFPS()), 50, 50, mPaint);
}

@Override
public void postInvalidate() {
    super.postInvalidate();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    this.mDetector.onTouchEvent(event);
    return super.onTouchEvent(event);
}

@Override
public boolean onDoubleTap(MotionEvent arg0) {
    // TODO Auto-generated method stub
    return false;
}

@Override
public boolean onDoubleTapEvent(MotionEvent e) {
    Log.d(DEBUG_TAG, "onDoubleTap: " + e.toString());
    return true;
}

@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
    // TODO Auto-generated method stub
    return false;
}

@Override
public boolean onDown(MotionEvent arg0) {
    Log.d(DEBUG_TAG,"onDown: " + arg0.toString()); 
    return true;
}

@Override
public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2,
        float arg3) {
    // TODO Auto-generated method stub
    return false;
}

@Override
public void onLongPress(MotionEvent arg0) {
    Log.d(DEBUG_TAG, "onLongPress: " + arg0.toString()); 
}

@Override
public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2,
        float arg3) {
    Log.d(DEBUG_TAG, "onScroll");
    return true;
}

@Override
public void onShowPress(MotionEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public boolean onSingleTapUp(MotionEvent arg0) {
    // TODO Auto-generated method stub
    return false;
}



}

Я только что обновил код, и метод onDown() был отредактирован, чтобы «вернуть false».

@Override 
public boolean onTouchEvent(MotionEvent event){ 
    this.mDetector.onTouchEvent(event);
    // Be sure to call the superclass implementation
    return super.onTouchEvent(event);
}

@Override
public boolean onDown(MotionEvent event) { 
    Log.d(DEBUG_TAG,"onDown: " + event.toString()); 
    return false;
}

@Override
public boolean onFling(MotionEvent event1, MotionEvent event2, 
        float velocityX, float velocityY) {
    Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString());
    return true;
}

@Override
public void onLongPress(MotionEvent event) {
    Log.d(DEBUG_TAG, "onLongPress: " + event.toString()); 
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
        float distanceY) {
    Log.d(DEBUG_TAG, "onScroll: " + e1.toString()+e2.toString());
    return true;
}

@Override
public void onShowPress(MotionEvent event) {
    Log.d(DEBUG_TAG, "onShowPress: " + event.toString());
}

@Override
public boolean onSingleTapUp(MotionEvent event) {
    Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString());
    return true;
}

@Override
public boolean onDoubleTap(MotionEvent event) {
    Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString());
    return true;
}

@Override
public boolean onDoubleTapEvent(MotionEvent event) {
    Log.d(DEBUG_TAG, "onDoubleTapEvent: " + event.toString());
    return true;
}

@Override
public boolean onSingleTapConfirmed(MotionEvent event) {
    Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString());
    return true;
}

Но, тем не менее, при касании экрана я получаю уведомление об отладке «OnDown», а также «OnShowPress» и «OnLongPress»... Но я установил для возврата значение false?


person user2410644    schedule 31.05.2013    source источник
comment
когда вы пытаетесь прокрутить, вместо этого вы получаете onDown? читайте ссылки внимательнее и все получится   -  person mc_fish    schedule 31.05.2013
comment
он показывает onDown, когда я просто касаюсь экрана. Я получаю onDown, onShowPress и onLongPress, но не onScroll и не onFling?   -  person user2410644    schedule 31.05.2013


Ответы (3)


У меня была аналогичная проблема, когда я разрабатывал что-то подобное в xamarin (используя С# вместо java) для Android.

Я решил, что он возвращает false в таких событиях, как onDown(...), НО возвращает true в onTouchEvent(), поэтому попробуйте что-то вроде этого, чтобы проверить, работает ли:

@Override
public boolean onTouchEvent(MotionEvent event) {
    this.mDetector.onTouchEvent(event);
    return true;
}

Кстати, вы реализуете OnGestureListener, поэтому я думаю, что, возможно, не стоит переопределять такие методы, как onDown(). Однако onTouchEven() необходимо переопределить.

// without the overriden directive
public boolean onDown(MotionEvent event) { 
    Log.d(DEBUG_TAG,"onDown: " + event.toString()); 
    return false;
}

Надеюсь, это поможет вам найти решение.

person tomasofen    schedule 23.06.2013
comment
возвращение true в onTouchEvent() у меня тоже сработало - person Sudara; 26.04.2016

Конечно... Так что ваша проблема "простая"

@Override
public boolean onDown(MotionEvent arg0) {
    Log.d(DEBUG_TAG,"onDown: " + arg0.toString()); 
    return false;
}

Если вы вернете false... Вы скажете слушателю: "Я не потреблял это событие" и пусть оно "пузырится"

person mc_fish    schedule 31.05.2013
comment
Даже если я верну его как false, я все равно получу сообщение о том, что onDown был вызван... - person user2410644; 31.05.2013
comment
и когда я прокручиваю экран, я должен включить прокрутку, но я этого не делаю...? - person user2410644; 31.05.2013
comment
есть другое возможное решение... вы в эмуляторе? - person mc_fish; 31.05.2013
comment
Нет, я на своем Galaxy Nexus. Пользовательский вид находится внутри DrawerLayout, может быть, это может помочь в дальнейших исследованиях? У меня был почти такой же код, только без DrawerLayout и GestureDetector в main_activity, а не в самом Custom View. Там это работало нормально, и onScroll тоже работал. Но теперь GestureDetector работает только внутри пользовательского представления, а не в основном действии. - person user2410644; 31.05.2013
comment
это звучит для меня как проблема просмотра (я имею в виду, что ваш пользовательский вид не находится сверху, и он не улавливает никаких жестов) - person mc_fish; 03.06.2013
comment
Вы не получите событие onScroll, если вернете false в onDown. - person ; 01.08.2014

Возврат true внутрь onTouchEvent у меня тоже работает. Но это кажется неправильным, поскольку оно будет перехватывать все «щелчки», даже если вы этого не собираетесь делать.

Сначала я решил эту проблему с помощью теста, например:

if (event.getAction()==MotionEvent.ACTION_SCROLL)

внутри onTouchEvent, но это не всегда работает.

Я предполагаю, что мое понимание недостаточно хорошо.

person Feriaman    schedule 16.11.2013