Pergunta sobre android, long-press, timer – Android: Como implementar o longpress manualmente no evento touch?

2

Versão curta: Eu quero uma maneira de iniciar um contador baseado em tempo em um onTouchEvent e testar para ver se um determinado período de tempo passou antes de responder, como uma detecção manual de LongTouch.

Explicação: Eu tenho um imageView personalizado que desliza dentro / fora da tela em flings de dois dedos. Eu quero adicionar eventos de arrastar para ele, mas estes precisam ser mais rápidos do que um longo. Eu posso atrasar o evento arrastar usando um contador que atualiza uma vez por onTouchEvent e só ativa o arrastar, digamos, 10 contagens, mas o contador só atualiza em eventos de toque e o dedo deve estar em movimento.

Como posso criar um contador baseado em tempo, um campo de nível de atividade que é incrementado 60 vezes por segundo ou algo assim?

Sua resposta

4   a resposta
8

mas parece que você está tentando implementar um evento catch long click no seu onTouchListener, exceto que você precisa executar algum tipo de lógica antes do evento ACTION_UP acontecer? Se assim for, esse é o mesmo problema exato que eu estava tendo. Eu também tentei usar System.nanoTime (), mas eu encontrei um método menos complicado. Você PODE usar um cronômetro, basta agendá-lo no primeiro evento ACTION_DOWN e cancelá-lo quando acontecer algo adverso (como um ACTION_UP, o que significa que não foi um toque longo, mas apenas um clique ou um ACTION_MOVE com um deslocamento sobre um determinado limiar). Algo como o seguinte:

<code>layout.seyOnTouchListener(new OnTouchListener(){
    private Timer longpressTimer; //won't depend on a motion event to fire
    private final int longpressTimeDownBegin = 500; //0.5 s
    private Point previousPoint;

    switch(event.getAction()){

    case MotionEvent.ACTION_DOWN:{
        longPressTimer = new Timer();
        longpressTimer.schedule(new TimerTask(){
            //whatever happens on a longpress
        }, longpressTimeDownBegin);
        return true; //the parent was also handling long clicks
    }
    case MotionEvent.ACTION_MOVE:{
        Point currentPoint = new Point((int)event.getX(), (int)event.getY());

        if(previousPoint == null){
            previousPoint = currentPoint;
        }
        int dx = Math.abs(currentPoint.x - previousPoint.x);
        int dy = Math.abs(currentPoint.y - previousPoint.y);
        int s = (int) Math.sqrt(dx*dx + dy*dy);
        boolean isActuallyMoving = s >= minDisToMove; //we're moving

        if(isActuallyMoving){ //only restart timer over if we're actually moving (threshold needed because everyone's finger shakes a little)
            cancelLongPress();
            return false; //didn't trigger long press (will be treated as scroll)
        }
        else{ //finger shaking a little, so continue to wait for possible long press
            return true; //still waiting for potential long press
        }
    }
    default:{
        cancelLongPress();
        return false;
    }
    }
}
</code>
Provavelmente não há muita diferença, mas como uma otimização eu recomendaria remover a função Math.sqrt () como calcular a raiz quadrada de um número tende a ser lenta. Apenas altere minDisToMove para minSquareDisToMove e atribua como limite o quadrado da distância. Veja também issoresponda como uma alternativa para detectar um longpress. manu3d
0

Use o clock do sistema (elapsedRealtime ()) e meça os milissegundos desde que a impressora foi iniciada. Fácil uma vez que você começa a pegar o jeito dele.

1

Pressione e segure no GestureDetector inicia uma mensagem atrasada em "key down". Quando esta mensagem vem antes de "chave", é um toque longo.

Apenas um link para a fontehttp://www.devdaily.com/java/jwarehouse/android/core/java/android/view/GestureDetector.java.shtml

Claro, no entanto, uma olhada na fonte do GestureDetector mostrará como resolver isso. A mensagem atrasada é o seu "relógio" stefan bachert
Obrigado pela fonte. Olhando agora. Tickled Pink
Obrigado, mas não estou usando gestos. A avaliação manual de eventos de toque é mais flexível e conveniente para o que eu quero fazer. O sistema de eventos por toque fornece excelentes informações, exceto o tempo. Daí a necessidade de um relógio simples para medir as prensas dentro do evento de toque. ;) Tickled Pink
1

mo true quando ocorrer Action_Down. Se action_up ocorrer, defina o booleano como false. Também inicie um conjunto postDelayed para qualquer atraso desejado quando ocorrer action_down. No postdelayed, se o booleano que você definiu como verdadeiro ainda é verdade, faça o que quiser. Desculpe por uma resposta tão verbal, mas é assim que eu faria.

Ah, tudo bem, eu vejo o que você está dizendo. Se bem me lembro, o primeiro dedo para baixo tem um Id de 0. Eu faria o postDelayed que eu disse acima, mas o fator decisivo seria se você reconhece um segundo dedo ou não, ou se o segundo pointerIndex event.getAction = ActionDown ou ActionMove . Algo parecido. Apenas algumas ideias testingtester
Eu descobri que posso usar o SystemClock e medir a diferença de tempo de quando o primeiro toque aconteceu. : D Tickled Pink
Ok, eu vejo o que você está dizendo. Atrase a execução e interrompa-a. Isso não vai funcionar, eu acho, porque eu não executo um ActionUp. Eu tenho duas ações. 1) Arraste os ícones do menu 2) Toque duas vezes na tela de ativação / desativação do menu. O atraso no arrasto é apenas para permitir que o segundo dedo atinja a tela, caso contrário, o arrasto é iniciado antes que a luta com dois dedos possa ser. Então, basicamente, se não houver um segundo ponteiro de 100ms após ACTION_DOWN, faça um arrastar Tickled Pink

Perguntas relacionadas