onItemClick дает индекс / позицию элемента на видимой странице ... не фактический индекс элемента в списке .. вопрос о включении setTextFilterEnabled - PullRequest
4 голосов
/ 26 марта 2010

Я создаю список .. элементы списка взяты из базы данных sqlite .. Я заполняю список с помощью ArrayList и ArrayAdapter ... после нажатия на элементы в списке, я хочу иметь возможность запустить намерение, содержащее информация о предмете, по которому щелкнули ... информация, такая как порядковый номер элемента ..

с использованием метода: onItemClick (AdapterView av, View v, int index, long arg)

Я получаю индекс предмета, по которому щелкнули. однако это список, который отображается в данный момент. проблема возникает, когда я делаю setFilterTextEnabled (true) и в типе приложения в некотором тексте, чтобы найти какой-либо элемент ... и затем щелкнуть его .. вместо того, чтобы дать мне индекс элемента в исходном списке, он дает мне индекс в отфильтрованном списке ..

следующий фрагмент кода:

myListView.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> av, View v, int index, long arg) {
            Intent lyricsViewIntent = new Intent(iginga.this, LyricsPage.class);

            lyricsViewIntent.putExtra("title", songList.get((int)arg).getTitle());
            lyricsViewIntent.putExtra("id", songList.get((int)arg).getSongId());
            startActivity(lyricsViewIntent);
        }
    });

    myListView.setTextFilterEnabled(true);

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

Ответы [ 7 ]

9 голосов
/ 28 февраля 2011

В последнее время у меня была небольшая борьба с этой проблемой, и решение оказалось довольно простым. Вы можете получить «видимый список», используя getListAdapter() на ListActivity, который отражает текущий отфильтрованный вид списка.

Например, в вашем ListActivity подклассе onCreate():

final ListView listView = getListView();
final ListAdapter listAdapter = getListAdapter();

listView .setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        MyClass item = (MyClass) listAdapter .getItem(position);
        // now do something with that item
    }
});

Итак, проигнорируйте «оригинальный» список, который вы поместили в адаптер списка, и вместо этого запрашивайте список из адаптера каждый раз, когда происходит событие.

5 голосов
/ 27 марта 2011

Абхинав Я полностью понимаю вашу проблему, так как я боролся с той же проблемой в течение последних двух дней. Я не осознавал, что значения «int position» и «int id» меняются, когда вы используете программную клавиатуру для фильтрации данных, пока я не начал использовать точки останова в отладчике. Надеюсь, что этот код поможет вам лучше понять, как решить ваши проблемы. В итоге я написал цикл for, чтобы сопоставить toString () отфильтрованного списка с toString () нефильтрованного списка. Таким образом, я мог получить / исправить значение «int position».

public class FacultyActivity extends ListActivity
{   
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);

        // Retrieves the array stored in strings.xml
        final String[] facultyList1 = getResources().getStringArray(R.array.professor_name);
        final String[] facultyList2 = getResources().getStringArray(R.array.professor_email);

        // Develop an array based on the list_view.xml template
        setListAdapter(new ArrayAdapter<String>(this, R.layout.faculty, facultyList1));
        final ListView lv = getListView();

        // Allow the user to filter the array based on text input
        lv.setTextFilterEnabled(true);

        // Handle the user event where the user clicks on a professor's name
        lv.setOnItemClickListener(new OnItemClickListener() 
        {
          public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
          {

              /* Filtering text changes the size of the array[index].  By clicking on a filtered 
               * entry the int position and long id does not correlate to the original array list.
               * This block of code will search the original array based on the toString() function
               * and for loop the orignial array to find the matching string, retrieving the 
               * correct index/position.
               */
              String name = lv.getItemAtPosition(position).toString();

              for (int index = 0; index < facultyList1.length; index++)
              {
                  if (name.equals(facultyList1[index]))
                  {
                      position = index;
                      break;
                  }
              }

              Bundle bundle = new Bundle();
              bundle.putString("email", facultyList2[position]);
              startActivity(new Intent(FacultyActivity.this, EmailActivity.class).putExtras(bundle)); 
          }
        });  
    }
}
1 голос
/ 14 сентября 2011

Я думаю, что это ошибка, которая должна быть исправлена: если вы щелкнете (например, мышью) по номеру записи 150, вы получите имя записи 150 и идентификатор 150. Но если вы введете символы что возвращает вам запись 150, и это первая из трех с теми же набранными вами символами, вы получаете 0 и имя записи 0 (что, конечно, в вашем первоначальном списке не то, что вы хотите). Это должно вернуть идентификатор и имя для записи 150, если оно отфильтровано, и сделать то, что abhinav сделал выше (хотя и полезно для меня), глупо, по моему не столь скромному мнению.

1 голос
/ 26 марта 2010

Одним из способов сделать это может быть пометка представления с его индексом при рисовании их View#setTag() и чтение их в любое время с помощью View#getTag()

0 голосов
/ 24 февраля 2019

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

Используйте часть кода из ответа Артура:

      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

          String name = lv.getItemAtPosition(position).toString();
          for (int index = 0; index < facultyList1.length; index++)
          {
              if (name.equals(facultyList1[index]))
              {
                  position = index;
                  break;
              }
          }
      }

и объедините его с лучшим ответом здесь чтобы создать этот функциональный код в том же onItemClick:

            /* Filtering text changes the size of the array[index]. By clicking on a filtered
             * entry the int position changes, taking you to the details of food in the original
             * list's details. This block of code will take FoodsData, which contains all of the
             * textviews within a list item, and compare the contents of the chosen filtered list item
             * with every food name within foodsArray by using a loop, retrieving the correct index/position.

             * But this was the most important answer that helped me get it working in my code:
             * https://stackoverflow.com/questions/11164543/how-to-extract-objects-from-listview-getitematposition-wont-work
             */

            FoodsData chosenFilteredListItem = (FoodsData) (lv.getItemAtPosition(position));
            String chosenFilteredListItemFoodName = chosenFilteredListItem.getFoodName();

            for (int index = 0; index < foodsArray.length; index++)
            {
                if (chosenFilteredListItemFoodName.equals(foodsArray[index]))
                {
                    position = index;
                }
            }

Как говорится в моем комментарии в коде, в нем используется класс FoodsData, который описывает различные текстовые представления в пределах одного элемента списка и сравнивает содержимое элемента списка, по которому щелкнули мышью, со всеми именами в массиве, используя цикл for , Это позволяет получить правильную позицию выбранного элемента в отфильтрованном списке поиска вместо неправильного открытия сведений об элементе исходного списка в той же позиции.

0 голосов
/ 17 февраля 2013

Я только что нашел простое решение для этой же проблемы. Первый вопрос в вашем адаптере: используете ли вы ArrayList или String []?
Попробуйте создать класс для хранения желаемой информации.
А затем используйте ArrayList в своем адаптере.
Например:

public class DataHoldingClass {
private Integer id;
private String name;

     public DataHoldingClass(Integer id,String name){
       this.id=id;    
       this.name=name;
      }
       public Integer getDataId(){
         return id;
       }

      @Override
  public String toString() {
    return name;
  } 
 //implements getters and setters to name and other fields if you want

 }

Необходимо переопределить метод toString (), чтобы адаптер знал, какая информация отображается в списке. Тогда где-то в коде:

ArrayList< DataHoldingClass> info = new ArrayList<DataHoldingClass>();
  info.add( new DataHoldingClass(id,name) ) //here you populate the ArrayList with the desired informations to be showed at List


  adapter = new ArrayAdapter< DataHoldingClass>(context,
           android.R.layout.simple_dropdown_item_1line, info);`

И в конце концов:

`@Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Log.d(" arg2 ="+arg2+" arg3="+arg3+" Real id ="+((DataHoldingClass)arg0.getAdapter().getItem(arg2)).getDataId(),"");
}

Это сработало для меня. Надеюсь, я тебе помог.

0 голосов
/ 09 сентября 2012

В классе адаптера переопределите следующие методы с помощью следующего кода.

@Override
public long getItemId(int position) {       
    return position;
}

@Override
public int getPosition(StateFlower item) {
    return allItemsArray.indexOf(item);
}


@Override
public StateFlower getItem(int arg0) {
    return allItemsArray.get(arg0);
}
...