85 votes

Détecter un appui long avec Android

j'utilise actuellement

 onTouchEvent(MotionEvent event){
}

pour détecter lorsque l'utilisateur appuie sur mon glSurfaceView, existe-t-il un moyen de détecter lorsqu'un clic long est effectué. Je suppose que si je ne trouve pas grand-chose dans les documents de développement, ce sera une sorte de méthode de contournement. Quelque chose comme enregistrer ACTION_DOWN et voir combien de temps il reste avant ACTION_UP.

Comment détectez-vous les appuis longs sur Android en utilisant opengl-es ?

165voto

MSquare Points 1232

GestureDetector est la meilleure solution.

Voici une alternative intéressante. Dans onTouchEvent, sur chaque programme ACTION_DOWN, un Runnable doit s'exécuter en 1 seconde. À chaque ACTION_UP ou ACTION_MOVE , annulez le Runnable programmé. Si l'annulation se produit moins d'une seconde après l' événement ACTION_DOWN, Runnable ne s'exécutera pas.

 final Handler handler = new Handler(); 
Runnable mLongPressed = new Runnable() { 
    public void run() { 
        Log.i("", "Long press!");
    }   
};

@Override
public boolean onTouchEvent(MotionEvent event, MapView mapView){
    if(event.getAction() == MotionEvent.ACTION_DOWN)
        handler.postDelayed(mLongPressed, ViewConfiguration.getLongPressTimeout());
    if((event.getAction() == MotionEvent.ACTION_MOVE)||(event.getAction() == MotionEvent.ACTION_UP))
        handler.removeCallbacks(mLongPressed);
    return super.onTouchEvent(event, mapView);
}

118voto

Daniel Fekete Points 2378

Essaye ça:

 final GestureDetector gestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
    public void onLongPress(MotionEvent e) {
        Log.e("", "Longpress detected");
    }
});

public boolean onTouchEvent(MotionEvent event) {
    return gestureDetector.onTouchEvent(event);
};

7voto

SanVed Points 704

J'ai un code qui détecte un clic, un clic long et un mouvement. C'est assez une combinaison de la réponse donnée ci-dessus et des modifications que j'ai apportées en regardant dans chaque page de documentation.

 //Declare this flag globally
boolean goneFlag = false;

//Put this into the class
final Handler handler = new Handler(); 
    Runnable mLongPressed = new Runnable() { 
        public void run() { 
            goneFlag = true;
            //Code for long click
        }   
    };

//onTouch code
@Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {    
        case MotionEvent.ACTION_DOWN:
            handler.postDelayed(mLongPressed, 1000);
            //This is where my code for movement is initialized to get original location.
            break;
        case MotionEvent.ACTION_UP:
            handler.removeCallbacks(mLongPressed);
            if(Math.abs(event.getRawX() - initialTouchX) <= 2 && !goneFlag) {
                //Code for single click
                return false;
            }
            break;
        case MotionEvent.ACTION_MOVE:
            handler.removeCallbacks(mLongPressed);
            //Code for movement here. This may include using a window manager to update the view
            break;
        }
        return true;
    }

Je confirme que cela fonctionne car je l'ai utilisé dans ma propre application.

4voto

Benjoyo Points 343

J'ai créé un extrait - inspiré de la source View actuelle - qui détecte de manière fiable les clics/pressions longs avec un délai personnalisé. Mais c'est dans Kotlin :

 val LONG_PRESS_DELAY = 500

val handler = Handler()
var boundaries: Rect? = null

var onTap = Runnable {
    handler.postDelayed(onLongPress, LONG_PRESS_DELAY - ViewConfiguration.getTapTimeout().toLong())
}

var onLongPress = Runnable {

    // Long Press
}

override fun onTouch(view: View, event: MotionEvent): Boolean {
    when (event.action) {
        MotionEvent.ACTION_DOWN -> {
            boundaries = Rect(view.left, view.top, view.right, view.bottom)
            handler.postDelayed(onTap, ViewConfiguration.getTapTimeout().toLong())
        }
        MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
            handler.removeCallbacks(onLongPress)
            handler.removeCallbacks(onTap)
        }
        MotionEvent.ACTION_MOVE -> {
            if (!boundaries!!.contains(view.left + event.x.toInt(), view.top + event.y.toInt())) {
                handler.removeCallbacks(onLongPress)
                handler.removeCallbacks(onTap)
            }
        }
    }
    return true
}

3voto

Ian Points 2012

Quand vous voulez dire que l'utilisateur appuie, voulez-vous dire un clic ? Un clic est lorsque l'utilisateur appuie puis lève immédiatement le doigt. Par conséquent, il englobe deux événements onTouch. Vous devez conserver l'utilisation d'onTouchEvent pour les choses qui se produisent lors du premier contact ou après la libération.

Ainsi, vous devriez utiliser onClickListener s'il s'agit d'un clic.

Votre réponse est analogue : utilisez onLongClickListener.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X