2012-04-18 28 views
18

tôi sử dụng đoạn mã sau để thực hiện tìm kiếm khi người dùng nhập vào một EditText:Làm cách nào để tránh nhiều trình kích hoạt trên EditText khi người dùng đang gõ?

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

Tuy nhiên, điều này gây nên nhiều lần khi người dùng gõ một từ. Đó là nếu người dùng gõ "hello", mã này sẽ kích hoạt 5 lần với các giá trị ("h", "he", "hel", "hell", "hello"). Thông thường, điều này sẽ ổn nhưng việc tìm kiếm được kích hoạt là tốn kém và tôi không muốn lãng phí tài nguyên cho các tìm kiếm trung gian không sử dụng tuyệt vời. Điều tôi muốn là người nghe chỉ kích hoạt một ngưỡng nhất định sau khi người dùng bắt đầu nhập hoặc một số loại khung hình chờ đợi trong người nghe trước khi gọi số triggerSearch và nếu một sự kiện khác được kích hoạt trước thời gian chờ đó, hãy tự hủy.

Trả lời

45

Kể từ khi không thể tìm thấy một giao diện sự kiện thích hợp, cố gắng kích hoạt một tìm kiếm bị trì hoãn. Mã thực sự khá đơn giản và mạnh mẽ.

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

Lớp xử lý này phải là tĩnh hoặc rò rỉ có thể xảy ra. – Choletski

+0

@Choletski hãy giải thích cách rò rỉ có thể xảy ra và làm cho tĩnh sẽ ngăn chặn điều đó? – jitenagarwal19

+0

@ jitenagarwal19 một trình xử lý tĩnh sẽ không giữ tham chiếu đến lớp kèm theo – andrei

4

Một giải pháp sẽ không thực hiện tìm kiếm được kích hoạt của bạn ngay lập tức nhưng sau một khoảng thời gian, giả sử 100ms đã trôi qua kể từ khi phương thức onTextChanged được gọi. Ngoài ra, đặt lại khoảng thời gian này mỗi lần nhập văn bản.

Bằng cách này, tìm kiếm được kích hoạt không được gọi trong khi người dùng đang nhập.

3

Để chờ trong người nghe trước khi gọi triggerSearch; kiểm tra độ dài Editable s.

if(s.length() > THRESHOLD)

+0

làm cách nào để xác định ngưỡng thích hợp? Ngoài ra, điều này sẽ không hoạt động nếu người dùng nhập một từ dài có nhiều chữ cái dài hơn ngưỡng. – slayton

+0

Khi bạn nhận thấy người dùng không chỉ định tìm kiếm nào họ kích hoạt. Nếu không có bối cảnh tôi sẽ không suy đoán rằng một cái gì đó quá hạn chế hoặc quá mức cần thiết. Bạn có cân nhắc khi một người nào đó nhập ít hơn 10 chữ cái mỗi giây, trong đó "h", "anh ấy", "hel", "địa ngục", "hello" được gọi vì ngưỡng của bạn quá ngắn không? Cả hai câu trả lời đều hợp lệ, vui lòng gắn cờ câu trả lời của tôi nếu bạn vẫn phạm tội và nghĩ rằng nó cần xem xét cộng đồng. – Sam

+0

+1 vì nó vẫn là một cách tiếp cận thông minh nhất đối với một số tình huống – aProgrammer

0

Nếu bạn không muốn kích hoạt tìm kiếm trên tất cả các nút nhấn, sau đó bạn cần phải biết khi người dùng được thực hiện. Tôi sẽ tránh những ý tưởng phức tạp của việc cố gắng tìm ra khi người dùng gõ xong. Nó sẽ dẫn đến người dùng bị nhầm lẫn khi tìm kiếm xảy ra.

Câu trả lời đơn giản sau đó được đặt nút "xong" và áp dụng onClickListener trên nút và thực hiện tìm kiếm của bạn ở đó.

đang dễ nhất: trong xml

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

trong java:

@Override 
public void onDoneClicked(View view){ 
EditText queryView = (EditText) findViewById(R.id.querybox); 
triggerSearch(queryView.toString()); 
} 
Các vấn đề liên quan