2013-07-25 3 views
1

У меня есть AutoCompleteTextView, который динамически обновляет список предложений по типу пользователя. Моя проблема в том, что по мере ввода списка список обновляется, но раскрывающийся список не отображается! Но когда я удаляю символ (backspace), появляется раскрывающееся меню!Android - AutoCompleteTextView работает только при обратном перемещении

Я даже попытался явно позвонить autoText.showDropDown(); после изменения текста, но он не работает.

Вот мой TextChangedListener:

private TextWatcher textChecker = 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) { 
     if(autoText.length()>9){ 
      new GeoTask().execute(); 
     } 
    } 

    @Override 
    public void afterTextChanged(Editable editable) { 
     if(autoText.length()>9){ 
      autoText.showDropDown(); 
      Log.i("UPDATE","showDropDown"); 
     } 
    } 
}; 

Я даже попытался сбросить адаптер над autoText.showDropDown();, но до сих пор ничего:

autoText.setAdapter(null); 
autoText.setAdapter(adapter); 

Есть ли способ, чтобы заставить его работать?


EDIT: Вот полный код деятельности. Может быть, кто-то может найти то, что я делаю неправильно ...

public class TestDoctor extends Activity { 

    TextView latText; 
    TextView lngText; 
    AutoCompleteTextView autoText; 
    ArrayAdapter<String> adapter; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.test_doctor); 

     latText = (TextView) findViewById(R.id.latTextView); 
     lngText = (TextView) findViewById(R.id.longTextView); 
     autoText = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView); 


     Button button = (Button) findViewById(R.id.buttonDoctor); 
     button.setOnClickListener(new Button.OnClickListener() { 
      public void onClick(View v) { 
       new GeoTask().execute(); 
      } 
     }); 
     autoText.setThreshold(10); 
     autoText.setHint("Οδός Αριθμός, Περιοχή"); 
     adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line); 
     autoText.setAdapter(adapter); 
     adapter.setNotifyOnChange(true); 
     autoText.addTextChangedListener(textChecker); 
    } 

    private TextWatcher textChecker = 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) { 
      if(autoText.length()>9){ 
       new GeoTask().execute(); 
      } 
     } 

     @Override 
     public void afterTextChanged(Editable editable) {} 
    }; 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
    } 

    private List<SimpleAddress> getAddressesFromText(String address) { 
     address = address.replace(' ', '+'); 
     HttpHelper httpHelper = new HttpHelper(); 
     InputStream inputStream = httpHelper.makeHttpGetRequest("http://maps.google.com/maps/api/geocode/json?address=" + address + "&sensor=false"); 
     String response = httpHelper.inputStreamToString(inputStream); 

     List<SimpleAddress> simpleAddresses = new ArrayList<SimpleAddress>(); 
     try { 
      JSONObject jsonObject = new JSONObject(response); 


      int size = ((JSONArray) jsonObject.get("results")).length(); 

      for (int i = 0; i<size; i++){ 
       String formatted_address = ((JSONArray) jsonObject.get("results")).getJSONObject(i) 
         .getString("formatted_address"); 

       Double lng = ((JSONArray) jsonObject.get("results")).getJSONObject(i) 
         .getJSONObject("geometry").getJSONObject("location") 
         .getDouble("lng"); 

       Double lat = ((JSONArray) jsonObject.get("results")).getJSONObject(i) 
         .getJSONObject("geometry").getJSONObject("location") 
         .getDouble("lat"); 
       simpleAddresses.add(i,new SimpleAddress(formatted_address,lat,lng)); 
      } 
      return simpleAddresses; 
     } catch (JSONException e) { 
      return null; 
     } 
    } 

    public class GeoTask extends AsyncTask<Void, Void, Void> { 
     List<SimpleAddress> simpleAddresses = new ArrayList<SimpleAddress>(); 

     @Override 
     protected Void doInBackground(Void... voids) { 
      Log.i("UPDATE","1"); 
      try { 
       simpleAddresses = getAddressesFromText(autoText.getText().toString()); 
      } catch (NullPointerException e) { 
      } 
      Log.i("UPDATE","2"); 
      return null; 
     } 

     @Override 
     protected void onPostExecute(Void aVoid) { 
      Log.i("UPDATE", "3"); 

      int size = simpleAddresses.size(); 

      if(size > 0){ 
       adapter.clear(); 
       Log.i("ADAPTER_SIZE",""+size); 
       for (int i = 0; i< size; i++){ 
        adapter.add(simpleAddresses.get(i).getFormatted_address()); 
        Log.i("ADDED",simpleAddresses.get(i).getFormatted_address()); 
       } 
       Log.i("UPDATE","4"); 
       autoText.setAdapter(null); 
       autoText.setAdapter(adapter); 
       autoText.showDropDown(); 
       Log.i("UPDATE","showDropDown"); 
      } 
      super.onPostExecute(aVoid); 
     } 
    } 
} 

EDIT 2 я попытался также это, но до сих пор не работает. Выпадающий показывает только, когда я нажимаю забой ...

@Override 
public void afterTextChanged(Editable editable) { 
    runOnUiThread(updateAdapter); 
} 

...

private Runnable updateAdapter = new Runnable() { 

    public void run(){ 
     Log.i("ADAPTER_UPDATE","start"); 
     adapter.notifyDataSetChanged(); 
     autoText.showDropDown(); 
     Log.i("ADAPTER_UPDATE","end"); 
    } 
}; 

ПРИМЕЧАНИЕ Проблема: Я набираете адрес. Когда я печатаю, ничего не появляется. Но я вижу, что в logcat адаптер обновлен. Но выпадающий список не отображается. Затем, когда я удаляю один символ, выпадающее меню появляется ?? !!

+0

Вы можете попробовать adapter.setNotifyOnChange (ложь), а затем вручную вызвать adapter.notifyDataSetChanged() в конце onPostExecute(). –

+0

Я просто попробовал. Это не работает ... –

ответ

10

Похоже, что вам действительно нужно реализовать фильтр:

import java.io.InputStream; 
import java.util.ArrayList; 
import java.util.List; 

import org.json.JSONArray; 
import org.json.JSONException; 
import org.json.JSONObject; 

import android.app.Activity; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.Menu; 
import android.view.View; 
import android.widget.ArrayAdapter; 
import android.widget.AutoCompleteTextView; 
import android.widget.Button; 
import android.widget.Filter; 
import android.widget.TextView; 

public class TestDoctor extends Activity { 

    TextView latText; 
    TextView lngText; 
    AutoCompleteTextView autoText; 
    ArrayAdapter<String> adapter; 
    private Filter filter; 
    private static final int ADDRESS_TRESHOLD = 10; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.test_doctor); 

    latText = (TextView) findViewById(R.id.latTextView); 
    lngText = (TextView) findViewById(R.id.longTextView); 
    autoText = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView); 

    Button button = (Button) findViewById(R.id.buttonDoctor); 
    button.setOnClickListener(new Button.OnClickListener() { 
     public void onClick(View v) { 
     new AdapterUpdaterTask().execute(); 
     } 
    }); 

    autoText.setThreshold(ADDRESS_TRESHOLD); 
    autoText.setHint("Οδός Αριθμός, Περιοχή"); 

    filter = new Filter() { 
     @Override 
     protected void publishResults(CharSequence constraint, 
      FilterResults results) { 
     } 

     @Override 
     protected FilterResults performFiltering(CharSequence constraint) { 
     Log.i("Filter", 
      "Filter:" + constraint + " thread: " + Thread.currentThread()); 
     if (constraint != null && constraint.length() > ADDRESS_TRESHOLD) { 
      Log.i("Filter", "doing a search .."); 
      new AdapterUpdaterTask().execute(); 
     } 
     return null; 
     } 
    }; 

    adapter = new ArrayAdapter<String>(this, 
     android.R.layout.simple_dropdown_item_1line) { 
     public android.widget.Filter getFilter() { 
     return filter; 
     } 
    }; 

    autoText.setAdapter(adapter); 
    adapter.setNotifyOnChange(false); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
    } 

    private List<SimpleAddress> getAddressesFromText(String address) { 
    address = address.replace(' ', '+'); 
    HttpHelper httpHelper = new HttpHelper(); 
    InputStream inputStream = httpHelper 
     .makeHttpGetRequest("http://maps.google.com/maps/api/geocode/json?address=" 
      + address + "&sensor=false"); 
    String response = httpHelper.inputStreamToString(inputStream); 

    List<SimpleAddress> simpleAddresses = new ArrayList<SimpleAddress>(); 
    try { 
     JSONObject jsonObject = new JSONObject(response); 

     int size = ((JSONArray) jsonObject.get("results")).length(); 

     for (int i = 0; i < size; i++) { 
     String formatted_address = ((JSONArray) jsonObject.get("results")) 
      .getJSONObject(i).getString("formatted_address"); 

     Double lng = ((JSONArray) jsonObject.get("results")).getJSONObject(i) 
      .getJSONObject("geometry").getJSONObject("location") 
      .getDouble("lng"); 

     Double lat = ((JSONArray) jsonObject.get("results")).getJSONObject(i) 
      .getJSONObject("geometry").getJSONObject("location") 
      .getDouble("lat"); 
     simpleAddresses.add(i, new SimpleAddress(formatted_address, lat, lng)); 
     } 
     return simpleAddresses; 
    } catch (JSONException e) { 
     return null; 
    } 
    } 

    public class AdapterUpdaterTask extends AsyncTask<Void, Void, Void> { 
    List<SimpleAddress> simpleAddresses = new ArrayList<SimpleAddress>(); 

    @Override 
    protected Void doInBackground(Void... voids) { 
     Log.i("UPDATE", "1"); 
     try { 
     simpleAddresses = getAddressesFromText(autoText.getText().toString()); 
     } catch (NullPointerException e) { 
     } 
     Log.i("UPDATE", "2"); 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void aVoid) { 
     Log.i("UPDATE", "3"); 

     int size = simpleAddresses.size(); 

     if (size > 0) { 
     adapter.clear(); 
     Log.i("ADAPTER_SIZE", "" + size); 
     for (int i = 0; i < size; i++) { 
      adapter.add(simpleAddresses.get(i).getFormatted_address()); 
      Log.i("ADDED", simpleAddresses.get(i).getFormatted_address()); 
     } 
     Log.i("UPDATE", "4"); 

     adapter.notifyDataSetChanged(); 
     autoText.showDropDown(); 

     } 
     super.onPostExecute(aVoid); 
    } 
    } 

} 
+1

Вы также должны убедиться, что за один раз выполняется только один поиск и этот поиск выполняется только после небольшой задержки ввода. –

+0

Спасибо !!! Это сработало! Я потерял надежду. И ты прав насчет задержки. Это улучшит производительность и работу пользователя. Еще раз спасибо! :) –

+0

Не беспокойтесь. Мне тоже это нужно. –

2

Это может иметь какое-то отношение к autoText.showDropDown(), не вызываемому в основной теме. может быть, вы можете попробовать сделать это вместо:

autoText.getHandler().post(new Runnable() { 
    @Override 
    public void run() { 
     autoText.showDropDown(); 
    } 
}) 
+0

Я добавил это в OnCreate(), и он разбил программу ... –

+0

Я не хотел просто добавлять его в OnCreate, но для этого кода вместо 'autoText.showDropDown() '. Поэтому везде, где бы вы это ни делали, используйте код, который я разместил _instead_ –

+0

Все тот же ... Я не понимаю. Это так расстраивает. –