onItemClick给出可见页面上项目的索引/位置...不是列表中项目的实际索引..启用setTextFilterEnabled时的项目

问题描述 投票:4回答:7

我正在创建一个列表..列表的元素是从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);

我有什么方法可以获得项目的原始索引/位置,而不是过滤后的文本中显示的那个...过滤时。

android sqlite listview indexing position
7个回答
9
投票

我最近对这个问题进行了一些摔跤,解决方案结果相当简单。您可以使用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
投票

Abhinav我完全理解你的问题,因为我在过去两天一直在努力解决同样的问题。我没有意识到“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
投票

其中一种方法可能是在绘制View#setTag()时使用索引标记视图,并在需要时使用View#getTag()读取它们


1
投票

我认为这是一个应该修复的错误:例如,如果您在条目号150上单击(使用鼠标),则会返回条目150的名称和ID为150.但是如果您输入的字符为您提供条目150返回,它是您输入的相同字符的三个中的第一个,您返回0并且条目0的名称(当然在原始列表中不是您想要的)。这应该返回条目150的id和名称,如果过滤,并且必须做abhinav上面所做的事情(虽然,对我来说很有用),在我不那么谦虚的意见中是克服的。


0
投票

在Adapter类中,使用以下代码覆盖以下方法。

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

0
投票

我刚刚为这个问题找到了一个简单的解决方案。第一个问题,在您的适配器中,您使用的是ArrayList <String>还是String []? 尝试创建一个类来保存所需的信息。 然后,在适配器中使用ArrayList <DataHoldingClass>。 例如 :

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()方法,以适配器知道List中显示的信息。然后,代码中的某个地方:

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
投票

我花了好几个小时试图找到这个过滤器问题的解决方案,所以万一其他人都在苦苦挣扎,这是对我有用的快速写法。

使用Arthur答案中的一些代码:

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

并将其与最佳答案here相结合,以在同一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循环将单击的列表项的内容与数组中的所有名称进行比较。这将检索已过滤搜索列表中所单击项目的正确位置,而不是错误地在同一位置打开原始列表项目的详细信息。

© www.soinside.com 2019 - 2024. All rights reserved.