android - 在 ExpandableListView 上分组数据

标签 android expandablelistview android-cursoradapter custom-cursor

我在 SQLite 表中有以下格式的数据:

id|datetime|col1|col2
1|2013-10-30 23:59:59|aaa|aab
2|2013-10-30 23:59:59|abb|aba
3|2013-10-30 23:59:59|abb|aba
4|2013-10-31 23:59:59|abb|aba
5|2013-10-31 23:59:59|abb|aba

我想实现一个 ExpandableListView 以便数据按 datetime 分组并显示如下:

> 2013-10-30 23:59:59 // Group 1
1|aaa|aab
2|abb|aba
3|abb|aba
> 2013-10-31 23:59:59 // Group 2
4|abb|aba
5|abb|aba

我有一个自定义的 CursorAdapter,我可以轻松地使用它来填充 ListView,显示每个项目的日期,但我不知道如何“分组” "数据并将其填充到 ExpandableListView - 你能给我任何提示吗?

最佳答案

I have a custom CursorAdapter that I can easily use to populate ListView, showing date for every single item but I don't know how to "group" the data and populate it on an ExpandableListView - could you please give me any hints?

这是我目前在我的项目中使用的解决方案:

您不能(不应该)使用 CursorAdapter,因为它不适合您的解决方案。您需要通过从 BaseExpandableListAdapter 扩展来创建和实现自己的适配器

然后因为你想创建“你自己的分组”你需要改变你当前的应用程序逻辑:

  • 您需要创建从数据库返回的对象集合(例如 演示我将使用名称 Foo)

解决方案:

因此您的 Foo 对象应该如下所示(根据您的要求,变量名称仅用于解释解决方案的想法):

public class Foo {

   private String title;
   private List<Data> children;

   public void setChildren(List<Data> children) {
      this.children = children;
   }

}

title 将是您数据库中的日期列children 将是特定(唯一)日期的列

由于你的例子:

id|datetime|col1|col2
1|2013-10-30 23:59:59|aaa|aab
2|2013-10-30 23:59:59|abb|aba
3|2013-10-30 23:59:59|abb|aba
4|2013-10-31 23:59:59|abb|aba
5|2013-10-31 23:59:59|abb|aba

一个特定的日期(对象 Foo 的标题属性)有更多关联行,因此将使用 Foo 对象中定义的子集来模拟。

所以现在你需要 在你的 getAll() 方法中(从数据库返回数据的方法,通常类似这样调用)你的 DAO 对象(与数据库通信的对象,它只是术语)创建 Foo这个逻辑中的对象。

由于您需要为每个唯一日期正确初始化子项集合,因此您需要使用两个选择查询。您的第一个选择将返回不同的日期 - 因此,如果您在数据库中有 40 行具有 10 个不同(唯一)日期,那么您的选择将包含具有这些唯一日期的 10 行。

确定现在您的 ListView 有了“组”

现在您需要为每个已创建的“组”创建其子项。所以这里是第二个选择,它将选择所有行,并在正确的条件下为每个“组”分配 Foo 对象自己的子集合。

这是伪代码#1:

String query = "select * from YourTable";
Cursor c = db.rawQuery(query, null);
List<Data> childen = new ArrayList<Data>();
if (c != null && c.moveToFirst()) {
   for (Foo item: collection) {
      // search proper child for current item
      do {
         // if current row date value equals with current item datetime
         if (item.getTitle().equals(c.getString(2))) {
            children.add(new Data(column3, column4)); // fetch data from columns
         } 
      } while (c.moveToNext());

      // assign created children into current item
      item.setChildren(children);

      // reset List that will be used for next item
      children = null;
      children = new ArrayList<Data>();

      // reset Cursor and move it to first row again
      c.moveToFirst();
   }
}
// finally close Cursor and database

现在您的集合已“分组”,现在剩下的工作在您实现的 ListAdapter 上 - 这并不棘手。

您只需要正确实现 getGroupView()getChildView() 方法即可。

“组方法” 中,您将使用 Foo 对象集合中的标题扩充和初始化行。这些行将成为 ListView 中的组。

“子方法” 中,您将做同样的事情,但您不会膨胀集合中的标题,而是膨胀集合中当前 Foo 对象的子对象。这些行将成为一个特定组的子行。

注意事项:

由于#1。我出于演示目的简化了源代码。但是“在行动中”你可以改变一些事情:

  • 获取第二列通常不是 c.getString(2) 建议使用列名,所以你应该使用 c.getColumnIndex("columnName") 代替。

  • 将源代码包装到 try-finally block 中是一种很好的做法 finnaly 阻止关闭并释放使用过的资源,例如游标和 数据库。

  • 在示例中,与其“重用”相同的子集合,不如 您可以在 Foo 类中创建公共(public)方法,将项目添加到 直接收集(代码 fragment #2)。

代码 fragment #2:

public class Foo {

   private String title;
   private List<Data> children = new ArrayList<Data>();

   public void addChild(Data child) {
      this.children.add(child);
   }
   ...
}

总结:

希望您能理解我(我试图以尽可能简单的方式解释事情,不幸的是,面对面的个人交流是最好的,但我们无法使用此解决方案)并且我希望我能帮助您解决您的问题问题。

关于android - 在 ExpandableListView 上分组数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20349069/

相关文章:

android - 我要使用什么 CursorAdapter?

android - 在 android 2.2 中使用 Cursor Adapters 和 Content Provider 的正确方法是什么

android - 如何使用 Espresso 测试 fragment

android - 快速滚动 Gridview 时项目消失。快速滚动时图像尺寸也会发生变化

android - NavigationView 内的 ExpandableListView

android - 使用android espresso访问自定义可扩展列表中的 child

android - 默认共享首选项使用的文件名是什么?

java - 矩形之间的碰撞检测 libgdx

ExpandableListView 的 child 的android 奇怪的背景

android - ListView requestLayout() 警告