2011-02-16 15 views
71

Etkinliğimde bir AutoCompleteTextView kullanmak ve bir web API'sini sorgulayarak verileri kullanıcı türleri olarak doldurmak istiyorum. Bunu yapmayı nasıl yaparım?AutoCompleteTextView'ı nasıl kullanırım ve bir web API'sındaki verilerle birlikte kullanabilir miyim?

Yeni bir sınıf oluşturabilir ve AutoCompleteTextView.performFiltering geçersiz kılar mıyım yoksa özel bir liste bağdaştırıcısı kullanıp, özel bir android.widget.Filter özelliğine sahip Performansı gerçekleştirmeyi geçersiz kılar mı?

Veya son hedefimi elde etmenin daha iyi bir yolu var mı?

Biraz benzer bir şey yaptım, ancak Hızlı Arama kutusu içindi ve bir hizmetin uygulanmasını içeriyordu, ancak bunun burada yapmak istediğim şey olmadığına inanıyorum.

+4

müthiş linki yanı ayrıştırma sunucu istekleri ve json ele alınmasını s. io/blog/2014/04/12/android-autocompletetextview-ile-öneriler-bir-web-servis/ – Tina

cevap

90

Bir çözüm buldum, en iyi çözüm olup olmadığını bilmiyorum, ama çok iyi çalışıyor gibi görünüyor. Ne yaptım ArrayAdapter uzatan bir özel adaptör yaratıldı. Özel bağdaştırıcıda getFilter'ı geçersiz kıldım ve performFiltering'i geçersiz kılan kendi Filter sınıfımı oluşturdum. Bu yeni bir iş parçacığı başlatır, dolayısıyla UI'yi kesmez. Aşağıda bir barebone örneğidir.

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

İyi bir çözüm - tam olarak ne ihtiyacım vardı. Yine de sorabilirsem ... basit bir şekilde style_dropdown_item_1line düzenine dönersin. Stil sınıfınızdan uygun bir değeri nasıl alırsınız? Benim için, oluşturduğum bir sınıf ve liste öğesiimde getStyleName metin değerinin görüntülenmesini istiyorum, ancak sınıfın adını basit olarak görüntüler. – bugfixr

+6

@bugfixr Sınıfınızda herkese açık bir toString yöntemi ekleyin. Örneğimde şu oldu: Genel dize toString() {return name; } –

+0

Her zaman sınır değişken olarak boş olurum. Ne yapıyorum yanlış? Cihaz olarak Honeycomb kullanıyorum – Alex

3

Chu: ... aşağıdakileri yapın nasıl görünüm görünüyor özelleştirmek ve nesneyi unwrapping üzerinde daha fazla kontrol elde etmek için

@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. 'un yanıtı üstünde, aşağıdaki özel bağdaştırıcı şunları içerir:

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

ve bunu aynı şekilde kullanabilirsiniz: http: //makovkastar.github gelecek izleyicilerin :) için

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); 
    } 
} 
İlgili konular