Как получить правильный идентификатор адаптера AutoCompleteTextView

Я новичок в разработке Android и столкнулся с проблемой, которую мне трудно решить. Я пытаюсь понять, как правильно использовать виджет AutoCompleteTextView. Я хочу создать AutoCompleteTextView, используя данные XML из веб-службы. Мне удалось заставить его работать, но я определенно не доволен результатом.

Я хотел бы поместить HashMap с парами id => name в AutoCompleteTextView и получить идентификатор щелкнутого элемента. Когда я нажимаю на вывод отфильтрованного набора автозаполнения, я хочу заполнить список под полем автозаполнения, что мне также удалось заставить работать.

Сделано до сих пор:

  • автозаполнение хорошо работает для простых ArrayList, все данные отфильтрованы правильно
  • onItemClick событие срабатывает правильно после клика
  • parent.getItemAtPosition(position) возвращает правильное String представление выбранного элемента

Событие onItemClick(AdapterView parent, View v, int position, long id) ведет себя не так, как хотелось бы. Как я могу определить позицию нефильтрованного массива выбранного элемента? Позиция отфильтрованного меня не интересует.

Дальнейшие вопросы:

  • Как обрабатывать HashMaps или Collections в AutoCompleteTextView
  • Как получить правильный itemId в событии onItemClick

Я провел очень обширное исследование по этому вопросу, но не нашел никакой ценной информации, которая могла бы ответить на мои вопросы.


person sarath    schedule 17.07.2012    source источник
comment
Привет, друг, я пытался решить эту проблему, но не смог... Интересно. Почему нет решений от андроидных тигров???   -  person i leaf    schedule 20.07.2012


Ответы (4)


Событие onItemClick(AdapterView parent, View v, int position, long id) ведет себя не так, как хотелось бы.

Это нормальная ситуация при фильтрации адаптера. Хотя адаптер хранит ссылку на исходные нефильтрованные данные, со своей точки зрения, он имеет единственный набор данных, на котором основан (независимо от того, является ли он исходным или полученным в результате операции фильтрации). Но это не должно вызвать никаких проблем. С адаптерами sdk по умолчанию (или с подклассом) в onItemClick() вы получаете position для списка current, на котором основан адаптер. Затем вы можете использовать getItem(), чтобы получить элемент данных для этого position (опять же, это не имеет значения, исходный или отфильтрованный).

String data = getItem(position);
int realPosition = list.indexOf(data); // if you want to know the unfiltered position

это будет работать для списков и Maps (при условии, что вы используете SimpleAdapter). А для Maps у вас всегда есть возможность добавить дополнительный ключ, чтобы установить нефильтрованную позицию в исходном списке.

Если вы используете свой собственный адаптер вместе с AutoCompleteTextView, вы можете заставить onItemClick() дать вам правильное id (положение, однако, вы не можете изменить).

public class SpecialAutoComplete extends AutoCompleteTextView {

    public SpecialAutoComplete(Context context) {
        super(context);
    }

    @Override
    public void onFilterComplete(int count) {
        // this will be called when the adapter finished the filter
        // operation and it notifies the AutoCompleteTextView
        long[] realIds = new long[count]; // this will hold the real ids from our maps
        for (int i = 0; i < count; i++) {
            final HashMap<String, String> item = (HashMap<String, String>) getAdapter()
                    .getItem(i);
            realIds[i] = Long.valueOf(item.get("id")); // get the ids from the filtered items
        }
        // update the adapter with the real ids so it has the proper data
        ((SimpleAdapterExtension) getAdapter()).setRealIds(realIds);
        super.onFilterComplete(count);
    }


}

и адаптер:

public class SimpleAdapterExtension extends SimpleAdapter {

    private List<? extends Map<String, String>> mData;
    private long[] mCurrentIds;

    public SimpleAdapterExtension(Context context,
            List<? extends Map<String, String>> data, int resource,
            String[] from, int[] to) {
        super(context, data, resource, from, to);
        mData = data;
    }

    @Override
    public long getItemId(int position) {       
        // this will be used to get the id provided to the onItemClick callback
        return mCurrentIds[position];
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

    public void setRealIds(long[] realIds) {
        mCurrentIds = realIds;
    }

}

Если вы также реализуете класс Filter для адаптера, вы можете получить оттуда идентификаторы без необходимости переопределять класс AutoCompleTextView.

person user    schedule 15.06.2013

Используя подход Luksprog, я сделал нечто подобное с ArrayAdapter.

    public class SimpleAutoCompleteAdapter extends ArrayAdapter<String>{
        private String[] mData;
        private int[] mCurrentIds;

        public SimpleAutoCompleteAdapter(Context context, int textViewResourceId,
             String[] objects) {
             super(context, textViewResourceId, objects);
             mData=objects;
        }

        @Override
        public long getItemId(int position) {
            String data = getItem(position);
            int index = Arrays.asList(mData).indexOf(data);
            /*
             * Atention , if your list has more that one same String , you have to improve here  
             */
            // this will be used to get the id provided to the onItemClick callback
            if (index>0)
                return (long)mCurrentIds[index];
            else return 0;
        }

        @Override
        public boolean hasStableIds() {
            return true;
        }

        public void setRealIds(int[] realIds) {
            mCurrentIds = realIds;
        }

    }
person Felipe FMMobile    schedule 15.04.2014

Реализуйте onItemClickListener для AutoCompleteTextView, затем используйте indexOf в своем списке, чтобы найти индекс выбранного элемента.

actvCity.setOnItemClickListener(new OnItemClickListener() {

     @Override
     public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
          long arg3) {
          int index = cityNames.indexOf(actvCity.getText().toString());
          // Do Whatever you want to do ;)
     }
});
person SANAT    schedule 18.11.2014

Сначала добавьте свои данные в пользовательский массив

    // mList used for adding custom data into your model
        private List<OutletListSRModel> mList = new ArrayList<>();
      // listdata used for adding string data for auto completing.
        ArrayList<String> listdata = new ArrayList<String>();
        for (int i = 0; i < JArray.length(); i++) {
           JSONObject responseJson = JArray.getJSONObject(i);
           OutletListSRModel mModel = new OutletListSRModel();
           mModel.setId(responseJson.getString("id"));
           mModel.name(responseJson.getString("outlet_name"));
           listdata.add(responseJson.getString("outlet_name"));
        }

    ArrayAdapter adapter = new
                            ArrayAdapter(getActivity(),
 android.R.layout.simple_list_item_1, listdata);
    searchOutletKey.setAdapter(adapter);

Теперь для получения любого значения из модели, которую мы добавили выше. мы можем получить вот так.

searchOutletKey.setOnItemClickListener ( new AdapterView.OnItemClickListener ( ) {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String txtOutletId = mOutletListSRModel.get(position).getId();
            }
        });
person shubomb    schedule 08.12.2016