2013-04-19 18 views
6

Sfondo: Ho una coppia ScrollView/TextView che riceve un flusso di testo intermittente da una fonte esterna. Scorre automaticamente verso il basso su ogni aggiornamento.Come distinguere lo scorrimento dell'utente finale di un scrollView Android dallo scorrimento programmato?

Mi piacerebbe che l'utente fosse in grado di uscire da quella modalità di scorrimento automatico scorrendo manualmente da qualche parte, tuttavia non sono chiaro come distinguere lo scorrimento manuale dallo scorrimento programmatico che sto facendo io stesso.

mio aggiornamento dell'interfaccia utente viene eseguito su un timer per tamponare ridisegna:

private Handler outputUpdater = new Handler(); 
private static String outputBuffer = ""; 
private static boolean outputHasChanged = false; 
private static final Object lock = new Object(); 

private Runnable outputUpdaterTask = new Runnable() { 
    public void run() { 
     synchronized (lock) { 

      // if the output has changed, update the TextView 
      if (outputHasChanged) { 
       TextView tv = (TextView) findViewById (R.id.textView); 
       tv.setText (outputBuffer); 
      } 

      // if the output has changed, or the scroll hasn't reached the bottom yet 
      // then keep scrolling down 
      if (outputHasChanged || !scrollAtBottom()) { 
       ScrollView sv = (ScrollView) findViewById (R.id.scrollView); 
       sv.fullScroll (View.FOCUS_DOWN); 
      } 

      outputHasChanged = false; 
     } 

     outputUpdater.postDelayed (this, 100); 
    } 
}; 

scrollAtBottom ottiene il suo valore da un gestore onScrollChanged.

Tutto funziona correttamente. È necessario chiamare fullScroll anche se non è presente alcun aggiornamento di testo perché una singola chiamata a fullScroll non va sempre in fondo se ci sono aggiornamenti TextView in corso, o la visibilità della tastiera virtuale cambiata, ecc.

I'd così se l'utente scorre manualmente, che potrei sapere per decidere di smettere di chiamare fullScroll.

Purtroppo è Sembra che non basta semplicemente per trattare qualsiasi transizione da "in basso, modalità automatica" a "non a fondo" come spunto per passare alla modalità manuale, perché i vari cambiamenti dell'interfaccia utente sembrano spostare la vista di scorrimento off anche il fondo (es. tastiera virtuale che mostra).

Domanda riparata: Come si può distinguere lo scorrimento avviato dall'utente dallo scorrimento programmatico?

risposta

8

Hai provato a usare un boolean con onTouchEvent, qualcosa di simile a:

boolean userIntercept = false; 
@Override 
public boolean onTouchEvent(MotionEvent me) { 
    int action = me.getAction(); 
    if (action == MotionEvent.ACTION_MOVE) { 
      userIntercept = true; 
    } 
    return super.onTouchEvent(me); 
} 

poi nella vostra outputUpdaterTask:

// if the output has changed, or the scroll hasn't reached the bottom yet 
// then keep scrolling down 
if (outputHasChanged || !scrollAtBottom() && !userIntercept) { 
    ScrollView sv = (ScrollView) findViewById (R.id.scrollView); 
    sv.fullScroll (View.FOCUS_DOWN); 
} 

si avrebbe solo bisogno di determinare il modo in cui è possibile restituire il userIntercept a false, a seconda di quale si adatta meglio alla tua applicazione.

+4

Grazie, questa è l'idea di base che funziona. Per completezza, quello che sto facendo ora è: ACTION_MOVE o ACTION_DOWN avviare la modalità manuale e attivare lo stato "finger down". ACTION_UP disattiva lo stato "finger down". onScrollChanged e ACTION_UP accendono entrambi di nuovo lo scorrimento automatico se lo stato delle dita e atBottom sono entrambi veri. – idij

+1

è necessario uscire dalla modalità manuale in onScrollChanged in base allo stato delle dita perché è possibile "sfogliare" lo schermo per scorrere e si ottiene ACTION_UP prima dello scorrimento. – idij

Problemi correlati