2012-04-18 8 views
18

私はときのEditTextでユーザーが検索を実行するには、次のコードを使用します。ユーザーが入力中にEditTextで複数のトリガーを避けるには?

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) { 
    } 
}); 

ユーザーが単語を入力しているときは、この複数回トリガします。つまり、ユーザーが "hello"と入力すると、このコードは値( "h"、 "he"、 "hell"、 "hell"、 "hello")を5回トリガーします。通常、これは問題ありませんが、トリガされた検索は高価で、中間検索でリソースを無駄にしたくない場合は大したことはありません。私が望むのは、ユーザーが入力を開始した後に特定のしきい値のみをトリガーするリスナーか、またはtriggerSearchを呼び出す前にリスナーで待機し、その待機の前に別のイベントがトリガーされた場合に、それ自体をキャンセルするものです。

答えて

45

適切なイベントインターフェイスを見つけることができなかったので、遅延検索をトリガーしようとしました。コードは実際には非常に簡単で堅牢です。

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

このHandlerクラスは静的であるか、リークが発生する可能性があります。 – Choletski

+0

@Choletskiリークがどのように起こるかを詳しく教えてください。 – jitenagarwal19

+0

@ jitenagarwal19静的ハンドラは、囲むクラスへの参照を保持しません – andrei

4

すぐにトリガー検索を実行しないでください。ただし、onTextChangedメソッドが呼び出されてから一定の間隔、たとえば100msを過ぎた後に実行することをお勧めします。さらに、テキストが入力されるたびにこの間隔をリセットします。

この方法では、ユーザーが入力中にトリガー検索が呼び出されません。

3

triggerSearchを呼び出す前にリスナーで待機する。 Editable sの長さをテストします。

if(s.length() > THRESHOLD)

+0

どのように適切なしきい値を決定しますか?また、ユーザーがしきい値よりも長い文字数の長い単語を入力している場合、これは機能しません。 – slayton

+0

あなたが気づいたように、ユーザーは検索を指定しませんでした。文脈がなければ、私は何かがあまりにも限られていることや過度のものではないと推測しません。あなたのしきい値が短すぎるため、 "h"、 "he"、 "hell"、 "hello"が呼び出される毎秒10文字未満の人が入力されたときを考えましたか?両方の回答が有効です。あなたがまだ嫌悪感を抱き、コミュニティレビューが必要だと思うなら、私の答えにフラグを立ててください。 – Sam

+0

+1これはまだいくつかの状況では賢明なアプローチです – aProgrammer

0

あなたが押されたすべてのボタンで検索をトリガしたくない場合は、ユーザーが実行されたときに知っておく必要があります。私は、ユーザーが入力を終えた時点を把握しようとする複雑な考えを避けるだろう。それは、検索がいつ行われるかについてユーザが混乱することにつながる。

「完了」ボタンをクリックし、ボタンにonClickListenerを適用し、そこで検索を実行します。

最も簡単なコード:JavaでXMLで

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

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