Geocoder autocomplete in android

徘徊边缘 提交于 2019-12-18 12:24:25

问题


I've been googling my ass of trying to find someone that are having the same problem as me, without luck. So here's my problem:

I'm trying to implement a autocomplete suggestion of addresses as the user types the name of a place using the geocoder in Android. I want this to behave much the same as the javascript version using a combbox.

I am using a layout with an AutoCompleteTextView, and an arrayadapter to dynamically update the suggestionlist as the user types. I have added a 500ms delay from when the onTextChanged() event is received before a call to the geocoder.getFromLocationName is called using a Handler. If a user types more letter within 500ms, the last event will be cancelled. The problem I am encountering is that the suggestions almost never show up in the UI as selectables in the dropdown. I get the address suggestions, but when I add them to the adapter attached to the autocomplatetextview they simple wont show.

I'm running this on an emulator using API level 7, with google apis included.

Now some source code to aid you: The layout:

<LinearLayout android:id="@+id/searchInputLayout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="6dip"
    android:orientation="vertical">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/searchMessage" />
    <EditText android:id="@+id/freetextInput" 
        android:hint="@string/searchFreetextLabel"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:background="@android:drawable/editbox_background" />
    <CheckBox android:id="@+id/includeVincinityCheckbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/includeVincinityLabel"
        android:checked="true"
        android:onClick="includeVincinityClick" />
    <AutoCompleteTextView android:id="@+id/locationInput" 
        android:hint="@string/locationInputHint"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" />
    <Button android:id="@+id/searchButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/searchBtnLabel" 
        android:onClick="searchBtnClicked" />
    </LinearLayout>

The source code of my activity (I've omitted code not relevant):

public class SearchLocationTabActivity extends Activity implements TextWatcher, OnItemSelectedListener {

private static final int MESSAGE_TEXT_CHANGED = 0;
private static final int AUTOCOMPLETE_DELAY = 500;
private static final int THRESHOLD = 3;
private String latitude, longitude;
private List<Address> autoCompleteSuggestionAddresses;
private ArrayAdapter<String> autoCompleteAdapter;
private Handler messageHandler;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.search);
    setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);

    messageHandler = new MyMessageHandler(this, this);
    autoCompleteAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, new ArrayList<String>());
    autoCompleteAdapter.setNotifyOnChange(false);
    AutoCompleteTextView locationinput = (AutoCompleteTextView) findViewById(R.id.locationInput);
    locationinput.addTextChangedListener(this);
    locationinput.setOnItemSelectedListener(this);
    locationinput.setThreshold(THRESHOLD);
    locationinput.setAdapter(autoCompleteAdapter);
}

@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
    messageHandler.removeMessages(MESSAGE_TEXT_CHANGED);
}

@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
String value = arg0.toString();
if (!"".equals(value) && value.length() >= THRESHOLD) {
    Message msg = Message.obtain(messageHandler, MESSAGE_TEXT_CHANGED, arg0.toString());
    messageHandler.sendMessageDelayed(msg, AUTOCOMPLETE_DELAY);
} else {
    autoCompleteAdapter.clear();
}
}

@Override
public void afterTextChanged(Editable arg0) {
}

@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
    if (arg2 < autoCompleteSuggestionAddresses.size()) {
        Address selected = autoCompleteSuggestionAddresses.get(arg2);
        latitude = Double.toString(selected.getLatitude());
        longitude = Double.toString(selected.getLongitude());
    }
}

private void notifyResult(List<Address> suggestions) {
    latitude = longitude = null;
    autoCompleteAdapter.clear();
    for (Address a : autoCompleteSuggestionAddresses) {
        autoCompleteAdapter.add(a.toString());//TODO: figure out a nice way to display this address in list
    }
    autoCompleteAdapter.notifyDataSetChanged();
}

@Override
public void onNothingSelected(AdapterView<?> arg0) {
    latitude = longitude = null;
}

private class MyMessageHandler extends Handler {

    private Context context;
    private AsyncTaskSubscriber subscriber;

    public MyMessageHandler(Context context, AsyncTaskSubscriber subscriber) {
        this.context = context;
        this.subscriber = subscriber;
    }

    @Override
    public void handleMessage(Message msg) {
        if (msg.what == MESSAGE_TEXT_CHANGED) {
            String enteredText = (String) msg.obj;

            try {
                autoCompleteSuggestionAddresses = new Geocoder(context).getFromLocationName(enteredText, 10);

                notifyResult(response);
            } catch (IOException ex) {
                Log.e(GeoCoderAsyncTask.class.getName(), "Failed to get autocomplete suggestions", ex);
            }
        }
    }
}
}

Any help is much appreciated!


回答1:


For those who did not managed to remove the filtering, here is what I've done (among other small modifications but I don't think they have an impact on the filtering part). Note also that for a click on one of the item to be detected, you need to add an OnItemClickListener.

autoCompleteAdapter = new ArrayAdapterNoFilter(this, android.R.layout.simple_dropdown_item_1line);

Where ArrayAdapterNoFilter is inspired from this other answer:

public class ArrayAdapterNoFilter extends ArrayAdapter<String> {

    public ArrayAdapterNoFilter(Context context, int textViewResourceId) {
        super(context, textViewResourceId);
    }

    private static final NoFilter NO_FILTER = new NoFilter();

    /**
     * Override ArrayAdapter.getFilter() to return our own filtering.
     */
    @Override
    public Filter getFilter() {
        return NO_FILTER;
    }

    /**
     * Class which does not perform any filtering. Filtering is already done by
     * the web service when asking for the list, so there is no need to do any
     * more as well. This way, ArrayAdapter.mOriginalValues is not used when
     * calling e.g. ArrayAdapter.add(), but instead ArrayAdapter.mObjects is
     * updated directly and methods like getCount() return the expected result.
     */
    private static class NoFilter extends Filter {
        protected FilterResults performFiltering(CharSequence prefix) {
            return new FilterResults();
        }

        protected void publishResults(CharSequence constraint, FilterResults results) {
            // Do nothing
        }
    }
}



回答2:


ok, this one has a really simple solution. The results did not show up all the time because of the filtering mechanism in the AutoCompleteTExtView component. Because all results from the geocoder did not necessarily contain the string typed in, it did not show those results.




回答3:


This actually works for my geocoding code. I can add the textwatcher to a autocomplete text view, and then get the text and run an async task that will get the list of addresses from googles GeoCode class. Using this no filter array adapter above makes it display the addresses as I type the letters correctly.

Thanks!



来源:https://stackoverflow.com/questions/9142885/geocoder-autocomplete-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!