Câu hỏi Làm thế nào để sử dụng AutoCompleteTextView và điền nó với dữ liệu từ một API web?


Tôi muốn sử dụng AutoCompleteTextView trong hoạt động của tôi và điền dữ liệu khi người dùng nhập bằng cách truy vấn API web. Làm thế nào để tôi làm việc này?

Tôi có tạo một lớp mới và ghi đè không AutoCompleteTextView.performFilteringhoặc tôi sử dụng bộ điều hợp danh sách tùy chỉnh và cung cấp tùy chỉnh android.widget.Filter ghi đè performFiltering?

Hay là có cách nào tốt hơn để đạt được mục tiêu cuối cùng của tôi?

Tôi đã làm một cái gì đó hơi tương tự, nhưng nó đã được cho hộp tìm kiếm nhanh và nó liên quan đến việc thực hiện một dịch vụ, nhưng tôi tin rằng đó không phải là những gì tôi muốn làm ở đây.


76
2018-02-16 23:54


gốc


một liên kết tuyệt vời cho người xem trong tương lai :): makovkastar.github.io/blog/2014/04/12/… - Tina


Các câu trả lời:


Tôi đã đưa ra một giải pháp, tôi không biết nếu nó là giải pháp tốt nhất, nhưng nó dường như hoạt động rất tốt. Những gì tôi đã làm đã được tạo ra một adapter tùy chỉnh mở rộng ArrayAdapter. Trong adapter tùy chỉnh tôi overrode getFilter và tạo ra lớp Filter của riêng tôi ghi đè performFiltering. Điều này bắt đầu một chuỗi mới để nó không làm gián đoạn giao diện người dùng. Dưới đây là một ví dụ về barebones.

MyActivity.java

public class MyActivity extends Activity {
    private AutoCompleteTextView style;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        style = (AutoCompleteTextView) findViewById(R.id.style);
        adapter = new AutoCompleteAdapter(this, android.R.layout.simple_dropdown_item_1line); 
        style.setAdapter(adapter);
    }
}

AutoCompleteAdapter.java

public class AutoCompleteAdapter extends ArrayAdapter<Style> implements Filterable {
    private ArrayList<Style> mData;

    public AutoCompleteAdapter(Context context, int textViewResourceId) {
        super(context, textViewResourceId);
        mData = new ArrayList<Style>();
    }

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

    @Override
    public Style getItem(int index) {
        return mData.get(index);
    }

    @Override
    public Filter getFilter() {
        Filter myFilter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults filterResults = new FilterResults();
                if(constraint != null) {
                    // A class that queries a web API, parses the data and returns an ArrayList<Style>
                    StyleFetcher fetcher = new StyleFetcher();
                    try {
                        mData = fetcher.retrieveResults(constraint.toString());
                    }
                    catch(Exception e) {
                        Log.e("myException", e.getMessage());
                    }
                    // Now assign the values and count to the FilterResults object
                    filterResults.values = mData;
                    filterResults.count = mData.size();
                }
                return filterResults;
            }

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

92
2018-02-19 14:05



Giải pháp tốt - chính xác những gì tôi cần. Nếu tôi có thể hỏi mặc dù ... bạn trả lại một kiểu cho layout simple_dropdown_item_1line của bạn. Làm thế nào để bạn lấy một giá trị thích hợp từ lớp Style của bạn? Đối với tôi, đó là một lớp tôi đã tạo và tôi muốn giá trị văn bản getStyleName hiển thị trong mục danh sách của tôi, nhưng nó đơn giản hiển thị tên của lớp. - bugfixr
@bugfixr Thêm phương thức toString công khai vào lớp của bạn. Trong ví dụ của tôi nó là: public String toString () {return name; } - AJ.
Tôi luôn luôn nhận được null như biến hạn chế. Những gì tôi đang làm sai? Tôi đang sử dụng Honeycomb làm thiết bị - Alex
Cần thiết lập Tokenizer !!!! - Alex
@Tohid Đây vẫn là câu trả lời hay nhất, chỉ có một điều có thể được thêm vào điều này. Đó là trình xử lý bị trì hoãn có thể được sử dụng để kích hoạt cuộc gọi API. Như được hiển thị ở đây: truiton.com/2018/06/… - KnowIT


Mở rộng trên AJ.Câu trả lời ở trên, bộ điều hợp tùy chỉnh sau bao gồm việc xử lý các yêu cầu máy chủ và phân tích cú pháp json:

class AutoCompleteAdapter extends ArrayAdapter<String> implements Filterable
{
    private ArrayList<String> data;
    private final String server = "http://myserver/script.php?query=";

    AutoCompleteAdapter (@NonNull Context context, @LayoutRes int resource)
    {
        super (context, resource);
        this.data = new ArrayList<>();
    }

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

    @Nullable
    @Override
    public String getItem (int position)
    {
        return data.get (position);
    }

    @NonNull
    @Override
    public Filter getFilter()
    {
        return new Filter()
        {
            @Override
            protected FilterResults performFiltering (CharSequence constraint)
            {
                FilterResults results = new FilterResults();
                if (constraint != null)
                {
                    HttpURLConnection conn = null;
                    InputStream input = null;
                    try
                    {
                        URL url = new URL (server + constraint.toString());
                        conn = (HttpURLConnection) url.openConnection();
                        input = conn.getInputStream();
                        InputStreamReader reader = new InputStreamReader (input, "UTF-8");
                        BufferedReader buffer = new BufferedReader (reader, 8192);
                        StringBuilder builder = new StringBuilder();
                        String line;
                        while ((line = buffer.readLine()) != null)
                        {
                            builder.append (line);
                        }
                        JSONArray terms = new JSONArray (builder.toString());
                        ArrayList<String> suggestions = new ArrayList<>();
                        for (int ind = 0; ind < terms.length(); ind++)
                        {
                            String term = terms.getString (ind);
                            suggestions.add (term);
                        }
                        results.values = suggestions;
                        results.count = suggestions.size();
                        data = suggestions;
                    }
                    catch (Exception ex)
                    {
                        ex.printStackTrace();
                    }
                    finally
                    {
                        if (input != null)
                        {
                            try
                            {
                                input.close();
                            }
                            catch (Exception ex)
                            {
                                ex.printStackTrace();
                            }
                        }
                        if (conn != null) conn.disconnect();
                    }
                }
                return results;
            }

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

và sử dụng nó theo cùng một cách:

public class MyActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        AutoCompleteTextView textView = (AutoCompleteTextView) findViewById (R.id.style);
        int layout = android.R.layout.simple_list_item_1;
        AutoCompleteAdapter adapter = new AutoCompleteAdapter (this, layout); 
        textView.setAdapter (adapter);
    }
}

5
2018-04-25 16:55





Chu: Để tùy chỉnh giao diện trông như thế nào và có nhiều quyền kiểm soát hơn đối với việc mở đối tượng, hãy làm như sau ...

    @Override
    public View getView (int position, View convertView, ViewGroup parent) {
        TextView originalView = (TextView) super.getView(position, convertView, parent); // Get the original view

        final LayoutInflater inflater = LayoutInflater.from(getContext());
        final TextView view = (TextView) inflater.inflate(android.R.layout.simple_dropdown_item_1line, parent, false);

        // Start tweaking
        view.setText(originalView.getText());
        view.setTextColor(R.color.black);  // also useful if you have a color scheme that makes the text show up white
        view.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10); // override the text size
        return view;
    }

3
2018-04-22 04:13