2013-03-13 53 views
3

我有ListViewBaseAdapter并具有2种视图类型的自定义适配器。当我运行我的adapter.removeRow(position)方法时,适配器的数据已正确更新,并且列表反映了这一点,但视图类型未正确更新。适配器通过删除/删除项目后刷新listView与多种视图类型

ArrayList<Map<String, String>> rows = new ArrayList<Map<String, String>>();

备份和我有一个子集

List<Integer> flashSet = new ArrayList<Integer>();

这是所有那些ViewType 1(的位置的列表,而不是标准视图类型0 )。

这里是我的适配器removeRow(position)方法:

public void removeRow(int position) { 
     if (getItemViewType(position) == TYPE_FLASH) { 
      flashSet.remove(position); 
     } 
     for (int flashPosition:flashSet) { 
      System.out.println(tag+"is "+flashPosition+" going to be moved?"); 
      if (flashPosition > position) { 
       flashPosition -= 1; 
       System.out.println(tag+"Yes! It's been moved to "+flashPosition); 
      } 
     } 
     rows.remove(position); 
     notifyDataSetChanged(); 
    } 

这里是我的getView方法:

@Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     FlashHolder flashHolder; 
     ClipHolder clipHolder; 
     int type = getItemViewType(position); 
     if (convertView == null) { 
      if (type == TYPE_CLIP) { 
       convertView = rowInflater.inflate(R.layout.clip_note_row_layout, null); 
       clipHolder = new ClipHolder(); 
       flashHolder = null; 
       clipHolder.textView = (TextView)(convertView.findViewById(R.id.clip_text)); 
       convertView.setTag(clipHolder); 
      } else { 
       convertView = rowInflater.inflate(R.layout.flash_row_layout, null); 
       clipHolder = null; 
       flashHolder = new FlashHolder(); 
       flashHolder.front = (TextView)(convertView.findViewById(R.id.flash_text)); 
       flashHolder.back = (TextView)(convertView.findViewById(R.id.clip_text)); 
       convertView.setTag(flashHolder); 
      } 
     } else { 
      if (type == TYPE_CLIP) { 
       clipHolder = (ClipHolder)convertView.getTag(); 
       flashHolder = null; 
      } else { 
       clipHolder = null; 
       flashHolder = (FlashHolder)convertView.getTag(); 
      } 
     } 
     if (type == TYPE_CLIP) { 
      clipHolder.textView.setText(rows.get(position).get("clip")); 
     } else { 
      flashHolder.front.setText(rows.get(position).get("flash_text")); 
      flashHolder.back.setText(rows.get(position).get("clip")); 
     } 
     return convertView; 
    } 

我知道我可以创建一个新的adapter,给它更新ArrayList并调用listView.setAdapter(adapter)但当我只是试图从一个可能的长列表中删除一个项目时,这看起来总是过度杀伤。删除之前和之后请参阅图片: Before

然后删除第一项。 “其中”被隐藏背后的“让我们看看它是”项目现在的“启发......”项目背后却隐藏着一个空白项3.

After

这样的话,数据更新,视图类型AREN “T。谢谢您的帮助!

+0

+ 1为应用程序的外观和感觉问题和解决问题 – Nezam 2013-03-13 10:48:00

+0

谢谢。如果您感兴趣,我会在发布时通知您。 – willlma 2013-03-13 11:05:00

+0

你在适配器中覆盖'getViewTypeCount()'和'getItemViewType()'方法吗? – 2013-03-13 11:15:16

回答

1

我想通了。这对任何人都是有用的,因为我不希望别人犯同样的错误。

我天真地认为,通过这样

for (int flashPosition:flashSet) { 
     System.out.println(tag+"is "+flashPosition+" going to be moved?"); 
     if (flashPosition > position) { 
      flashPosition -= 1; 
      System.out.println(tag+"Yes! It's been moved to "+flashPosition); 
     } 
    } 

我改变存储在List<Integer> flashSet = new ArrayList<Integer>();

事实上的实际价值,我需要做的,而不是执行以下操作:

for (int flashPosition:flashSet) { 
    System.out.println(tag+"is "+flashPosition+" going to be moved?"); 
    if (flashPosition > position) { 
     flashSet.remove((Object)flashPosition); 
     flashPosition -= 1; 
     flashSet.add(flashPosition); 
     System.out.println(tag+"Yes! It's been moved to "+flashPosition); 
    } 
} 
+1

拥有ArrayList '会不会更容易? 'MyListData'是一个抽象类,有一个'int类型'变量。现在你只需要不同的具体实现。这样,您可以在ListView中拥有尽可能多的'View'类型,而无需管理复杂和缓慢的索引维护机制。例如。在你的'getItemViewType()'我猜你依靠'List.contains()'方法,而在上述方法中,你可以调用'return rows.get(position).type'。 – 2013-03-13 11:34:08

+0

是的,我使用'List.contains()'。我明白你的意思了。是个好主意。你认为它会提供性能改进还是你认为它更优雅?如果我需要第三种视图类型,我会执行它。谢谢。 – willlma 2013-03-13 12:08:39

+1

'contains()'方法需要'O(n)'来找到一个项目。在我看来,当用户滚动浏览ListView时,'getIteViewType()'被多次调用,并且每次'contains()'方法都会迭代你的flasSet,消耗更多的资源。这就是我所说的。它更好地写第一次灵活的代码,而不是回来和改变整个代码,只是因为你想在你的'ListView'的某些地方添加标题或幻想线:) – 2013-03-13 12:45:24

0

尝试此操作,删除或添加项目后,您需要调用适配器刷新。的

notifyDataSetChanged(); 

Youradapter.notifyDataSetChanged(); 
+0

我在'removeRow()'方法的末尾完成了这个操作。 – willlma 2013-03-13 10:44:44

0

使用yourlistview.invalidateViews()

相反,它为我工作。

+0

不幸的是,我得到了同样的结果。 – willlma 2013-03-13 10:43:01