2013-03-19 55 views
4

我有一個editText表示搜索條件的輸入。我想知道是否有方法檢測用戶何時停止編輯此editText,以便我可以查詢數據庫以獲取我的列表的數據。例如,如果用戶鍵入「測試」,我只想在用戶鍵入單詞後纔會收到通知,而不是在用戶鍵入每個字母之後(例如文本觀察者所做的)。你有什麼想法?我會避免使用一些計時器來測量按鍵事件之間經過的毫秒數。android editText:當用戶停止編輯時檢測

+1

難道你不能使用空格作爲分隔符嗎?在TextWatcher中指定正則表達式並驗證空格 – Neil 2013-03-19 10:24:42

+0

不,也許用戶不按空格鍵,或者他只鍵入名稱的一半,他期望看到可用結果 – 2013-03-19 10:25:53

+0

但是然後您想要使用字符。你想在用戶輸入時避免對你的數據庫有多個請求嗎? – Neil 2013-03-19 10:27:03

回答

10

不令人難以置信的優雅,但這應該工作。

初始化:

long idle_min = 4000; // 4 seconds after user stops typing 
long last_text_edit = 0; 
Handler h = new Handler(); 
boolean already_queried = false; 

設置你可運行將從文本觀察家稱爲:

last_text_edit = System.currentTimeMillis(); 
h.postDelayed(input_finish_checker, idle_min); 
+0

Thanx ..這真的對我有幫助.. – 2013-08-23 10:19:14

+0

它只需要幾個字符,當我把它放在textwatcher就像當我鍵入「你好」然後它只需要「他」 – 2014-08-12 11:55:55

+1

我得到了問題的解決方案。實際上每次它創建新的線程,所以我們需要停止早期的線程 因此,我們需要停止早期的線程 這裏是功能 h.removeCallbacks(input_finish_checker); – 2014-08-12 13:35:22

7

首先創建:

private Runnable input_finish_checker = new Runnable() { 
    public void run() { 
      if (System.currentTimeMillis() > (last_text_edit + idle_min - 500)) { 
       // user hasn't changed the EditText for longer than 
       // the min delay (with half second buffer window) 
       if (!already_queried) { // don't do this stuff twice. 
        already_queried = true; 
        do_stuff(); // your queries 
       } 
      } 
    } 
}; 

在文本觀察家將這個以下領域:

private Date    _lastTypeTime = null; 

然後確保你對你EDITTEXT工具 'TextWatcher':

_editText.addTextChangedListener(this); 

然後,覆蓋interface`s方法如下:

@Override 
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) 
{ 
    _lastTypeTime = new Date(); 
} 

@Override 
public void afterTextChanged(Editable arg0) 
{ 
} 

@Override 
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) 
{ 
    // dispatch after done typing (1 sec after) 
    Timer t = new Timer(); 
    TimerTask tt = new TimerTask() 
    { 
     @Override 
     public void run() 
     { 
      Date myRunTime = new Date(); 

      if ((_lastTypeTime.getTime() + 1000) <= myRunTime.getTime()) 
      { 
       post(new Runnable() 
       { 
        @Override 
        public void run() 
        { 
         Log.d("<tag>", "typing finished!!!"); 
        } 
       }); 
      } 
      else 
      { 
       Log.d("<tag>", "Canceled"); 
      } 
     } 
    }; 

    t.schedule(tt, 1000); 
} 
+0

非常感謝@gor,這是迄今爲止最好的解決方案:D – 2013-07-11 18:50:24

+0

很好的答案,但我認爲你需要該視圖才能讓發佈工作。 – Sotti 2014-09-29 14:17:05

+1

方法'post'不存在 – 2015-08-19 16:38:59

4

這裏是你如何可以檢測事件中,你正在尋找對於。

聲明和初始化:

private Timer timer = new Timer(); 
private final long DELAY = 1000; // in ms 

偵聽在例如onCreate()

EditText editText = (EditText) findViewById(R.id.editTextStopId); 
    editText.addTextChangedListener(new TextWatcher() { 
     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, 
       int after) { 
     } 
     @Override 
     public void onTextChanged(final CharSequence s, int start, int before, 
       int count) { 
      if(timer != null) 
       timer.cancel(); 
     } 
     @Override 
     public void afterTextChanged(final Editable s) { 
      //avoid triggering event when text is too short 
      if (s.length() >= 3) {    

       timer = new Timer(); 
       timer.schedule(new TimerTask() { 
        @Override 
        public void run() { 
         // TODO: do what you need here (refresh list) 
         // you will probably need to use 
         // runOnUiThread(Runnable action) for some specific 
         // actions 
         queryDB(); 
        } 

       }, DELAY); 
      } 
     } 
    }); 

所以,當文本被改變時,定時器開始等待下一次發生的改變。當它們發生時,定時器被取消,然後再次啓動。

+0

這將肯定會等待1000米或任何延遲,但它會多次運行queryDB()因爲有字符... – Micro 2016-03-04 00:46:07

+0

這怎麼可能?它只會運行一次,但是在運行()之後寫入另一個字母可能會再次觸發它。爲了應對該輸入可以暫時禁用。 – ZimaXXX 2016-03-04 11:46:55

+0

我發現如果你輸入「micro」的速度真的很快,系統將等待1000ms,那麼它將會不間斷地運行'queryDB()'兩次。這就是我的測試顯示至少和我逐字複製它。把一個日誌語句內的'run()'方法,並嘗試它自己? – Micro 2016-03-04 14:58:29

0

這就是我爲我做的和爲我工作的!

long delay = 1000; // 1 seconds after user stops typing 
long last_text_edit = 0; 
Handler handler = new Handler(); 

private Runnable input_finish_checker = new Runnable() { 
    public void run() { 
     if (System.currentTimeMillis() > (last_text_edit + delay - 500)) { 
      // TODO: do what you need here 
      DoStaff(); 
     } 
    } 
}; 

EditText editText = (EditText) findViewById(R.id.editTextStopId); 
editText.addTextChangedListener(new TextWatcher() { 
    @Override 
    public void beforeTextChanged(CharSequence s, int start, int count, 
      int after) { 
    } 
    @Override 
    public void onTextChanged(final CharSequence s, int start, int before, 
      int count) { 
     //You need to remove this to run only once 
     handler.removeCallbacks(input_finish_checker); 

    } 
    @Override 
    public void afterTextChanged(final Editable s) { 
     //avoid triggering event when text is empty 
     if (s.length() > 0) {    
      last_text_edit = System.currentTimeMillis(); 
      handler.postDelayed(input_finish_checker, delay); 
     } else { 

     } 
    } 
}); 
相關問題