【问题标题】:Wrong item selected on Listview onItemClick在 Listview onItemClick 上选择了错误的项目
【发布时间】:2014-09-29 05:16:54
【问题描述】:

面临一个非常奇怪的问题。我在每个项目上都有一个listviewcheckbox,当我单击listview 的第一个项目时,它被选中,但是与这个项目一起,列表视图的最后一个项目也被选中! 当我滚动列表视图时。没有滚动它可以完美运行。

另外,当我选择最后一个项目时,滚动后第一个项目也随之被选中。提醒一下,第一个和最后一个之间的所有其他项目都可以正常工作。有趣的是,在选择第一个或最后一个项目后,如果我不滚动 listview 2-3 秒,它就会完美运行。所以我期待这可能是一个问题视图渲染或有点。谁能指点我这里到底发生了什么..

Cursor cursor = queryDatabase();

    // The desired columns to be bound
      String[] columns = new String[] {               
        DataBaseHelper.ROW_PROFILE_NAME,
        DataBaseHelper.ROW_PROFILE_TYPE,
        DataBaseHelper.ROW_ID
      };

      // the XML defined views which the data will be bound to
      int[] to = new int[] { 
        R.id.profileName,
        R.id.profileStatus
      };

      // create the adapter using the cursor pointing to the desired data 
      //as well as the layout information
      mAdapter = new SimpleCursorAdapter(
        this, R.layout.profile_listview_delete_item, 
        cursor, 
        columns, 
        to,
        0);

      listView = (ListView) findViewById(R.id.profile_listview_delete_main);
      // Assign adapter to ListView
      listView.setAdapter(mAdapter);

      listView.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
            // TODO Auto-generated method stub

            CheckBox cb;                

            Cursor c = mAdapter.getCursor();
            String prodile_id = c.getString(c.getColumnIndex(DataBaseHelper.ROW_ID));

            cb = (CheckBox)arg1.findViewById(R.id.checkbox);
            cb.toggle();

            if(cb.isChecked())
            {                   
                profileStack.add(prodile_id);                   
                //Toast.makeText(getApplicationContext(), String.valueOf(profileStack), Toast.LENGTH_LONG).show();                  
                counter++;              
            }
            else if(!cb.isChecked())
            {
                profileStack.remove(prodile_id);                    
                //Toast.makeText(getApplicationContext(), String.valueOf(profileStack), Toast.LENGTH_LONG).show();                  
                counter--;                  
            }               
            countSelectedItem.setText(String.valueOf(counter)+" items selected");

            mAdapter.notifyDataSetChanged();                                
        }
    });

【问题讨论】:

  • 您能否发布您的适配器类我认为这是视图持有者模式的问题?
  • @Rajesh,我正在使用 SimpleCursorAdapter,你可以看到上面的代码。
  • 你的编码方式不对。您必须将自定义适配器与 viewholder 类一起使用,从该适配器更改复选框的值时,您必须从适配器更改字段的值,这与此复选框有关。单击列表视图后,获取位置并从适配器获取值。

标签: android listview simplecursoradapter onitemclick


【解决方案1】:

您应该为此使用自定义Adapter(模型类是optional。这里TemaRescatado 是sn-p 中的模型类)。在getView(...) 你必须使用CompoundButton.OnCheckedChangeListener 尝试使用ViewHolder pattern

代码 sn-p

viewHolder.checkbox = (CheckBox) view.findViewById(R.id.checkBox1);
viewHolder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

      @Override
      public void onCheckedChanged(CompoundButton buttonView,
         boolean isChecked) {
         TemaRescatado element = (TemaRescatado) viewHolder.checkbox
                  .getTag();
         element.setSelected(buttonView.isChecked());

         }
      });

【讨论】:

  • 不能用当前代码改正问题吗?因为我告诉过所有其他项目都运行良好。
  • 我不确定,但是自定义适配器不可能更好,因为它会优化您的代码并实现ViewHolder 模式ListView's 滚动会顺利
  • 你可以在notifyDataSetChanged()之后尝试mAdapter.notifyDataSetInvalidated()
  • 正如@kaushik 建议的那样...使用视图,否则你会得到不想要的结果
  • @kaushik,notifyDataSetInvalidated() 也不起作用,我知道 ViewHolder 可能会解决这个问题,但是更改最终应用程序的代码将是一项漫长的任务!
【解决方案2】:

您应该从作为参数传递给 onItemClick 方法的 AdapterView 中获取光标。

更改代码。

Cursor c = mAdapter.getCursor();

Cursor c = (Cursor) arg0.getItemAtPosition(position);

【讨论】:

  • 不,这不会改变情况。
  • 更新了我的答案,检查一下,让我知道它没有工作。
  • 不,它不起作用。还是一样,检查第一个项目,然后滚动,看到最后一个项目也被选中了!但是检查第一项,等待 2 秒钟,滚动浏览,然后看到它运行良好!奇怪!
【解决方案3】:

出现此问题是因为 ListView 的回收。只要不可见,它就会重新使用第一个可见的Views 来显示适配器的下一个数据。因此,当您选中并选中List 位置中的数据时。它会和你离开时一样。所以我对这个问题的解决方案是:

在适配器的getView()

输入一个简单的 if-else 语句来检查复选框是否应该被选中,如下所示:

// note that this is a pseudo code
if(ID exist in profileStack){
//set checkBox
}
else{
//set checkBox
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多