问题描述
我有一个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);
有没有办法将其工作?
编辑:这是活动的完整代码.也许有人可以找到我做错了...
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); } } }
编辑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中看到适配器更新.但下降没有显示.然后,当我删除一个角色时,下拉会显示出来?? !!
推荐答案
似乎您真的需要实现过滤器:
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); } } }
其他推荐答案
它可以与autoText.showDropDown()未被调用在主线程中有关.也许你可以尝试这样做:
autoText.getHandler().post(new Runnable() { @Override public void run() { autoText.showDropDown(); } })
问题描述
I have an AutoCompleteTextView that dynamically updates the list of suggestions as the user types. My problem is that as I type the list gets updated but the drop-down isn't shown! But when I delete a character (backspace) the drop-down shows up!
I even tried to explicitly call the autoText.showDropDown(); after the text change but it doesn't work.
Here is my 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"); } } };
I even tried resetting the adapter above the autoText.showDropDown(); but still nothing:
autoText.setAdapter(null); autoText.setAdapter(adapter);
Is there a way to get it to work?
EDIT: Here is the complete code of the activity. Perhaps someone can find what i am doing wrong...
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 i tried also this but still it doesn't work. The dropdown shows only when i press the backspace...
@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"); } };
NOTE The problem is: I type an address. As i type nothing shows up. But i see in the logcat the the adapter is updated. But the dropdown doesn't show. Then when i delete one character the dropdown shows up??!!
推荐答案
Seems like you really need to implement a filter:
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); } } }
其他推荐答案
It could have something to do with autoText.showDropDown() not being called in main thread. maybe you can try to do this instead:
autoText.getHandler().post(new Runnable() { @Override public void run() { autoText.showDropDown(); } })