Android-AutoCompleteTextView只在后退时工作[英] Android - AutoCompleteTextView only works when backspacing

本文是小编为大家收集整理的关于Android-AutoCompleteTextView只在后退时工作的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我有一个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();
    }
})

本文地址:https://www.itbaoku.cn/post/102566.html

问题描述

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