2012-04-18 11 views
18

Io uso il seguente codice per eseguire la ricerca quando utente digita in un EditText:Come evitare più trigger su EditText mentre l'utente sta digitando?

EditText queryView = (EditText) findViewById(R.id.querybox); 
queryView.addTextChangedListener(new TextWatcher() { 
    @Override 
    public void afterTextChanged(Editable s) { 
    triggerSearch(s.toString()); 
    } 
    @Override 
    public void beforeTextChanged(CharSequence s, int start, int count, int after) { 
    } 
    @Override 
    public void onTextChanged(CharSequence s, int start, int before, int count) { 
    } 
}); 

Tuttavia, questo innesca più volte quando l'utente sta scrivendo una parola. Cioè se l'utente sta scrivendo "ciao", questo codice si innesca 5 volte con valori ("h", "he", "hel", "hell", "hello"). Normalmente, ciò andrebbe bene, ma la ricerca attivata è costosa e non voglio sprecare risorse per ricerche intermedie che non sono di grande utilità. Quello che voglio è un ascoltatore che attiva solo una certa soglia dopo che l'utente inizia a digitare, o un qualche tipo di framework, che aspetta nell'ascoltatore prima di chiamare triggerSearch e se un altro evento viene attivato prima di quell'attesa, annulla sé stesso.

risposta

45

Dal momento che non riusciva a trovare un'interfaccia evento appropriato, provato innescando una ricerca ritardata. Il codice è in realtà piuttosto semplice e robusto.

private final int TRIGGER_SERACH = 1; 
// Where did 1000 come from? It's arbitrary, since I can't find average android typing speed. 
private final long SEARCH_TRIGGER_DELAY_IN_MS = 1000; 

    private Handler handler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
     if (msg.what == TRIGGER_SERACH) { 
     triggerSearch(); 
     } 
    } 
    }; 

queryView.addTextChangedListener(new TextWatcher() { 

    @Override 
    public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { 

    } 

    @Override 
    public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { 

    } 

    @Override 
    public void afterTextChanged(Editable s) { 
    handler.removeMessages(TRIGGER_SERACH); 
    handler.sendEmptyMessageDelayed(TRIGGER_SERACH, SEARCH_TRIGGER_DELAY_IN_MS); 
    }); 
+2

Questa classe del gestore deve essere statica o potrebbero verificarsi perdite. – Choletski

+0

@Choletski si prega di elaborare come potrebbero verificarsi perdite e rendere statico lo impedirà? – jitenagarwal19

+0

@ jitenagarwal19 un gestore statico non manterrebbe un riferimento alla classe di chiusura – andrei

4

Una soluzione potrebbe essere quella di non eseguire immediatamente la ricerca attivata ma dopo un intervallo, ad esempio 100ms, è trascorso dal momento in cui viene chiamato il metodo onTextChanged. Inoltre, ripristina questo intervallo ogni volta che viene digitato il testo.

In questo modo la ricerca attivata non viene chiamata mentre l'utente sta digitando.

3

Per attendere nell'ascoltatore prima di chiamare triggerSearch; prova la lunghezza di Editable s.

if(s.length() > THRESHOLD)

+0

come si determina una soglia appropriata? Inoltre, questo non funzionerà se l'utente sta digitando una lunga parola che è composta da molte lettere più lunghe della soglia. – slayton

+0

Come hai notato, l'utente non ha specificato quale ricerca attivano. Senza contesto non speculerò sul fatto che qualcosa sia troppo limitato o eccessivo. Hai preso in considerazione quando qualcuno digita meno di 10 lettere al secondo, dove "h", "he", "hel", "inferno", "ciao" viene chiamato perché la tua soglia è troppo corta? Entrambe le risposte sono valide, si prega di segnalare la mia risposta se si è ancora offesi e ritengono che sia necessaria una revisione della comunità. – Sam

+0

+1 poiché è ancora un approccio più intelligente per alcune situazioni – aProgrammer

0

Se non si desidera attivare la ricerca su ogni tasto premuto, allora avete bisogno di sapere quando l'utente è fatto. Eviterei le idee complesse di cercare di capire quando l'utente ha finito di digitare. Ciò porterà all'utente a essere confuso su quando si verifica la ricerca.

La risposta semplice è quindi un pulsante "completato" e applicare un onClickListener sul pulsante ed eseguire la ricerca lì.

codice più semplice: in XML

<Button 
android:onClick="onDoneClicked" 
... the rest of your button layout 
/> 

in Java:

@Override 
public void onDoneClicked(View view){ 
EditText queryView = (EditText) findViewById(R.id.querybox); 
triggerSearch(queryView.toString()); 
} 
Problemi correlati