2010-03-29 15 views
11

La mia classe estende View e ho bisogno di ottenere eventi di tocco continuo su di esso.Come ottenere un evento di tocco continuo?

se uso:

public boolean onTouchEvent(MotionEvent me) { 

    if(me.getAction()==MotionEvent.ACTION_DOWN) { 
     myAction(); 
    } 
    return true; 
} 

... l'evento tocco è acquisito una volta.

Cosa succede se ho bisogno di ottenere tocchi continui senza muovere il dito? Per favore, dimmi che non ho bisogno di usare discussioni o timer. La mia app è già troppo pesante.

Grazie.

risposta

15

Utilizzare if(me.getAction() == MotionEvent.ACTION_MOVE). È impossibile tenere il dito completamente fermo al 100% sullo schermo in modo che Action_Move venga chiamato ogni volta che il dito si muove, anche se è solo un pixel o due.

È inoltre possibile ascoltare me.getAction() == MotionEvent.ACTION_UP - finché ciò non accade, l'utente deve comunque avere il dito sullo schermo.

+2

Corretto, io preferirei la soluzione per impostare una bandiera sul ACTION_DOWN e l'uso che fino a quando è impostato il flag su false su ACTION_UP – WarrenFaith

+0

Davvero grazie. – daliz

+0

Vedo questo menzionato ovunque ma non sembra essere il mio caso. Se tocchi e tengo immobile, non ricevo eventi ACTION_MOVE. ACTION_MOVE sembra innescare solo se metto il dito in un modo o nell'altro. Potrebbe essere un'impostazione sul mio telefono che la rende meno sensibile? – clusterflux

3

Her è il frammento di codice semplice che mostra come è possibile gestire l'evento di tocco continuo. Quando si tocca il dispositivo e si mantiene il tocco e si sposta il mirino, viene eseguita l'azione Tocca movimento.

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    float x = event.getX(); 
    float y = event.getY(); 
    if(isTsunami){ 
    switch (event.getAction()) { 
     case MotionEvent.ACTION_DOWN: 
      // Write your code to perform an action on down 
      break; 
     case MotionEvent.ACTION_MOVE: 
      // Write your code to perform an action on contineus touch move 
      break; 
     case MotionEvent.ACTION_UP: 
      // Write your code to perform an action on touch up 
      break; 
    } 
    } 
    return true; 
} 
1

Prova questo. Si lavora per me:

public static OnTouchListener loadContainerOnTouchListener() { 
    OnTouchListener listener = new OnTouchListener(){ 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     LinearLayout layout = (LinearLayout)v; 
     for(int i =0; i< layout.getChildCount(); i++) 
     { 
      View view = layout.getChildAt(i); 
      Rect outRect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); 
      if(outRect.contains((int)event.getX(), (int)event.getY())) 
      { 
       Log.d(this.getClass().getName(), String.format("Over view.id[%d]", view.getId())); 
      } 
     } 

    } 

Ricordate: l'avrete modo insieme ascoltatore deve essere un layout di contenitore (griglia, Parente, lineare).

LinearLayout layout = findViewById(R.id.yourlayoutid); 
layout.setOnTouchListener(HelperClass.loadContainerOnTouchListener()); 
5

È necessario impostare questa proprietà per l'elemento Android: attivabile = "true" android: cliccabile = "true" se non, solo produrre l'azione verso il basso.

0

Stavo creando una partita con una visualizzazione personalizzata utilizzata come controllo del pollice. . . ecco quello che ho fatto

float x = 0, y = 0; 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    x = event.getX(); 
    y = event.getY(); 

    // handle touch events with 
    switch(event.getActionMasked()) { 
     case MotionEvent.ACTION_DOWN : 
      if(cont) 
      { 
       // remove any previous callbacks 
       removeCallbacks(contin); 

       // post new runnable 
       postDelayed(contin, 10); 
      } 
      invalidate(); 
      return true; 
     case MotionEvent.ACTION_MOVE : 
      if(!cont && thumbing != null) 
      { 
       // do non-continuous operations here 
      } 
      invalidate();  
      return true; 
     case MotionEvent.ACTION_UP : 

      // set runnable condition to false 
      x = 0; 

      // remove the callbacks to the thread 
      removeCallbacks(contin); 
      invalidate(); 
      return true; 
     default : 
      return super.onTouchEvent(event); 
    } 
} 

public boolean cont = false; 

// sets input to continuous 
public void set_continuous(boolean b) { cont = b; } 


public Runnable contin = new Runnable() 
{ 

    @Override 
    public void run() { 
     if(x != 0) 
     { 
      // do continuous operations here 
      postDelayed(this, 10); 
     } 
    } 

}; 

Una breve nota tuttavia, assicurarsi che nella vostra attività principale che chiama questo punto di vista rimuove i callback manualmente tramite il metodo onPause come segue

@Override 
protected void onPause() { 
    if(left.cont) left.removeCallbacks(left.contin); 
    if(right.cont) right.removeCallbacks(left.contin); 
    super.onPause(); 
} 

In questo modo se si mette in pausa e torna indietro Gli eventi di tocco non vengono gestiti due volte e la vista è libera dal sovraccarico del thread.

** testato su Samsung Galaxy S3 con l'accelerazione hardware su **

0

Tutti questi risposta sono parzialmente corretti ma non risolvono nel modo giusto il problema.

Prima di tutto, per tutti quelli che decidono di tenere traccia quando l'evento è ACTION_MOVE. Beh, questo funziona solo a indovinare quando? Quando l'utente muove il dito, è possibile farlo se si decide di implementare un controllo personalizzato del pollice, ma per un normale pulsante personalizzato non è il caso.

In secondo luogo, utilizzando una bandiera all'interno ACTION_DOWN e controllare in ACTION_UP sembra il modo logica per farlo, ma come Clusterfux scoprire se si implementa una logica while(!up_flag) ti trovi in ​​difficoltà in difficoltà;)

Quindi il modo corretto per farlo è menzionata qui:

Continuous "Action_DOWN" in Android

Basta tenere a mente che se la logica che si sta andando a scrivere durante la pressa continua è di modificare l'interfaccia utente, in qualche modo, si deve farlo dalla thread principale in tutti gli altri casi è meglio usare un altro thread.

0

Questo potrebbe aiutare,

requestDisallowInterceptTouchEvent(true); 

sulla vista primaria, come questo -

 @Override 
     public boolean onTouch(View view, MotionEvent motionEvent) { 
      view.getParent().requestDisallowInterceptTouchEvent(true); 
      switch(motionEvent.getActio){ 
      } 

      return false; 

     }