2011-11-11 8 views
27

Tôi muốn thay đổi định kỳ các đề xuất do AutoCompleteTextview đưa ra bằng cách lấy danh sách từ một dịch vụ web RESTful và không thể làm cho nó hoạt động trơn tru. Tôi thiết lập một danh sách mã hóa cứng các gợi ý để đảm bảo nó hoạt động:Tự động cập nhật bộ điều hợp AutoCompleteTextView

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, new String[] {"Hi", "Ho"}); 
speciesName.setAdapter(adapter);//my autocomplete tv 

Tôi đã có một TextWatcher trên TextView và khi thay đổi văn bản mà ra mắt một cuộc gọi non-blocking để có được một danh sách mới gợi ý - phần này nhận được một danh sách mới đang hoạt động tốt. Sau đó, tôi muốn đặt lại adapter, như vậy:

public void setOptionsAndUpdate(String[] options) { 
    Log.d(TAG, "setting options"); 
    //speciesName.setAdapter((ArrayAdapter<String>)null); 
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, options); 
    speciesName.setAdapter(adapter); 
} 

Phương pháp này được gọi, nhưng không hoạt động - danh sách đề xuất hoặc biến mất hoặc những gợi ý hiển thị vẫn không thay đổi bất chấp những lời kêu gọi setAdapter.

Đây có phải là phương pháp phù hợp không? Tôi đã xem SimpleCursorAdapter nhưng không thể xem cách đăng ký dịch vụ web của mình với tư cách nhà cung cấp nội dung. (Đó là dạng http://www.blah.com/query?term=XX, nơi mà các XX là đầu vào từ ứng dụng của tôi, và câu trả lời là một mảng JSON các chuỗi.)

+0

Tôi đang làm điều gì đó tương tự TẠI ĐÂY !!! http://stackoverflow.com/questions/12854336/autocompletetextview-backed-by-cursorloader – toobsco42

Trả lời

14

Đây là cách tôi cập nhật AutoCompleteTextView tôi:

String[] data = terms.toArray(new String[terms.size()]); // terms is a List<String> 
ArrayAdapter<?> adapter = new ArrayAdapter<Object>(activity, android.R.layout.simple_dropdown_item_1line, data); 
keywordField.setAdapter(adapter); // keywordField is a AutoCompleteTextView 
if(terms.size() < 40) keywordField.setThreshold(1); 
else keywordField.setThreshold(2); 

Bây giờ tất nhiên , đây là tĩnh và không đối phó với một over-the-air gợi ý nhưng, tôi cũng có thể đề nghị bạn để thông báo cho bộ chuyển đổi cho những thay đổi sau khi bạn gán nó vào AutoCompleteTextView:

adapter.notifyDataSetChanged(); 

Hope this helps.

-serkan

+0

Cảm ơn rất nhiều, giải quyết nó cho tôi. – jaybee

+0

@serkan: Tuyệt vời, đây là những gì tôi cần. Tuy nhiên, tôi nghĩ ngưỡng này không được cập nhật, đúng không? Vì vậy, trong ví dụ của bạn, nếu 'terms.size() <40' ở đầu, ngưỡng sẽ ở trong 1 mãi mãi. Tất nhiên bạn có thể chạy lại dòng mã đó để cập nhật. Cảm ơn! –

+0

Cảm ơn Luis. Vâng, những gì tôi đang làm chỉ là nói rằng, nếu tôi có một danh sách nhỏ các thứ, tôi có thể bắt đầu gợi ý ngay cả sau khi 1 nhân vật được nhập vào; tuy nhiên nếu hồ bơi của tôi lớn, thì tôi nên đợi cho đến khi hai ký tự được nhập vào để tôi đề xuất bất cứ điều gì - vì mục đích hiệu quả. Bạn chắc chắn giữ nó 1, hoặc 2 ở tất cả các lần. – serkanozel

18

Có một hướng dẫn khá tốt về chủ đề này sử dụng dữ liệu từ xa trong Google Map API để cư một AutoCompleteTextView here.

Nếu bạn cần phiên bản được lưu trong bộ nhớ cache, tôi đã truy xuất phiên bản đó từ here. Hướng dẫn ban đầu đã bị xóa, nhưng về cơ bản bạn cần phải viết một ArrayAdapter với một bộ lọc tùy chỉnh theo cách tương tự như được hiển thị bên dưới và gán nó cho AutoCompleteTextView của bạn.

Lưu ý: Bạn cần triển khai phương thức tự động hoàn tất() thực hiện bất kỳ thao tác nào được yêu cầu để tìm nạp đồng thời và trả về các mục tự động hoàn thành. Khi bộ lọc được gọi trong một chuỗi nền, bộ lọc này sẽ không chặn luồng giao diện người dùng chính.

private class PlacesAutoCompleteAdapter extends ArrayAdapter<String> implements Filterable { 
private ArrayList<String> resultList; 

public PlacesAutoCompleteAdapter(Context context, int textViewResourceId) { 
    super(context, textViewResourceId); 
} 

@Override 
public int getCount() { 
    return resultList.size(); 
} 

@Override 
public String getItem(int index) { 
    return resultList.get(index); 
} 

@Override 
public Filter getFilter() { 
    Filter filter = new Filter() { 
     @Override 
     protected FilterResults performFiltering(CharSequence constraint) { 
      FilterResults filterResults = new FilterResults(); 
      if (constraint != null) { 
       // Retrieve the autocomplete results. 
       resultList = autocomplete(constraint.toString()); 

       // Assign the data to the FilterResults 
       filterResults.values = resultList; 
       filterResults.count = resultList.size(); 
      } 
      return filterResults; 
     } 

     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) { 
      if (results != null && results.count > 0) { 
       notifyDataSetChanged(); 
      } 
      else { 
       notifyDataSetInvalidated(); 
      } 
     }}; 
    return filter; 
} 
} 
+0

Hoàn hảo! Liên kết đó chỉ là ngọt ngào! Cảm ơn cho nó! :) – Jona

+0

Nó không chặn trhead UI khi nó thực hiện cuộc gọi mạng – jonney

+0

Tôi đã có cùng một câu hỏi về chuỗi giao diện người dùng. @manyobject bạn có thể clerify? –

28

Tôi không có may mắn khi sử dụng adapter.notifyDataSetChanged() khi tự động thêm và thay đổi dữ liệu trong bộ điều hợp. Trong tình huống của tôi, tôi đã gõ một api bên ngoài không đồng bộ và nhận được một danh sách dữ liệu hoàn thành định kỳ.

Mã này xóa bộ điều hợp và thêm dữ liệu mới như bạn mong đợi. Tuy nhiên, tôi phải gọi phương thức getFilter() để lọc dữ liệu hiển thị. Ngoài ra, tôi đã phải lọc một cách rõ ràng dựa trên văn bản hiện tại trong AutocompleteTextView vì cuộc gọi api của tôi không đồng bộ.

adapter.clear(); 
for (Map<String, String> map : completions) { 
    adapter.add(map.get("name")); 
} 

//Force the adapter to filter itself, necessary to show new data. 
//Filter based on the current text because api call is asynchronous. 
adapter.getFilter().filter(autocompleteTextView.getText(), null); 
+0

thay vì đi qua trong 'null', bạn có thể vượt qua trong' autocompleteTextView' để nó hoạt động giống như cách 'AutoCompleteTextView.performFiltering()' thực hiện - đó là phương thức thường được gọi sau khi văn bản được thay đổi – kassim

+0

Giờ chi tiêu tìm kiếm điều này. Tôi sở hữu một ly bia của bạn :) – codingpuss

+0

Cảm ơn @GLee. Bạn đã làm cho ngày của tôi. –

2

Kể từ khi tôi không thể thêm một nhận xét, tôi đang đưa ra một câu trả lời mới Không cần cho thanh toán bù trừ adapter hoặc gọi adapter.getFilter(). Lọc (...) ... Để tự động cập nhật bộ điều hợp AutoCompleteTextView, chỉ cần thêm mục mới vào bộ điều hợp và setAdapter một lần nữa. Đối với ví dụ được đưa ra trong câu hỏi ban đầu, tôi đã thử những điều sau đây và nó hoạt động (đoạn mã dưới đây không hiển thị thiết lập ban đầu của bộ điều hợp, vì nhiều câu trả lời ở đây bao gồm. Điều này chỉ cho thấy việc cập nhật bộ điều hợp động). Bản cập nhật bộ điều hợp có thể cùng với mã cập nhật Danh sách được liên kết với ArrayAdapter.

adapter.add(String newSuggestion); // this goes inside a loop for adding multiple suggestions 
    speciesName.setAdapter(adapter) ; // speciesName is an AutoCompleteTextView as given in the original question.