2011-02-16 30 views
71

我想在我的活動中使用AutoCompleteTextView,並通過查詢Web API以用戶類型填充數據。我如何去做這件事?如何使用AutoCompleteTextView並使用來自Web API的數據填充它?

我是否創建一個新類並覆蓋AutoCompleteTextView.performFiltering,或者是否使用自定義列表適配器並提供覆蓋performFiltering的自定義android.widget.Filter

或者是否有更好的方法來獲得我的最終目標?

我做了一些有點類似的事情,但它是用於快速搜索框,它涉及實施服務,但我相信這不是我想要在這裏做的。

+4

一個了不起的鏈接,未來的觀衆:):HTTP://makovkastar.github。 io/blog/2014/04/12/android-autocompletetextview-with-suggestions-from-a-web-service/ – Tina 2015-12-26 09:39:59

回答

90

我想出了一個解決方案,我不知道它是否是最好的解決方案,但它似乎工作得很好。我所做的是創建了一個擴展ArrayAdapter的自定義適配器。在自定義適配器中,我覆蓋了getFilter並創建了自己的Filter類來覆蓋performFiltering。這將啓動一個新的線程,因此它不會中斷用戶界面。以下是一個準系統的例子。

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; 
    } 
} 
+2

好的解決方案 - 正是我需要的。如果我可能會問,但是...您將樣式返回到simple_dropdown_item_1line佈局。你如何從你的Style類中獲取適當的值?對我來說,這是我創建的類,我希望文本值getStyleName顯示在我的列表項中,但它很簡單顯示類的名稱。 – bugfixr 2011-04-02 20:25:15

3

楚:要定製視圖的外觀和在展開的對象來獲取更多的控制,執行下列操作...

@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; 
    } 
5

在上面的AJ.的回答擴展,下面的自定義適配器包括•服務器請求和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(); 
      } 
     }; 
    } 

,並用同樣的方式:

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); 
    } 
} 
相關問題