Flutter:基于类型对ListView项目进行排序

5

我在Flutter的项目管理应用中使用了一个ListView.builder。这个ListView填充了任务列表(包括:新的、进行中的和已完成的)。我从API获取这些数据并希望“新建”的任务显示在顶部,“进行中”的任务位于中部,“已完成”的任务在底部!- 这是当前的情况 这是我的,请注意我从API / JSON获取状态。

class ProjectTask {
final int id;
final String description;
final String state;
final List assigned_users;
final List subtasks;

ProjectTask(this.id,
  this.description,
  this.state,
  this.assigned_users,
  this.subtasks);
}

The ListView

else return ListView.builder(
        itemCount: snapshot.data.length,
        itemBuilder: (BuildContext context, int index) {

          if(snapshot.data[index].state == "done") {
            return Slidable(

              //SLIDABLE STUFF
              delegate: SlidableStrechDelegate(),
              actionExtentRatio: 0.25,
              actions: <Widget>[

                //ACTION ONE
                IconSlideAction(
                  caption: ("Information"),
                  foregroundColor: Colors.white,
                  color: Colors.black38,
                  icon: Icons.info,
                  onTap: () {
                    Navigator.push(context, MaterialPageRoute(builder: (context)=>projectTask(snapshot.data[index])));
                  },
                ),
              ],

              child: ListTile(
                onTap: () {
                  Navigator.push(context, MaterialPageRoute(builder: (context) => projectTask(
                      snapshot.data[index],
                  )));
                },
                title: Text("${snapshot.data[index].description[0].toString().toUpperCase()}"
                    "${snapshot.data[index].description.toString().substring(1)}", maxLines: 1, style: TextStyle(
                    color: Colors.black87, fontSize: 17)
                ),
                subtitle: Text("done"),
                leading: Icon(Icons.check_circle, color: Colors.green),
                trailing: Icon(Icons.arrow_right, color: Colors.black54,),
              ),
            );
          }
          else if(snapshot.data[index].state == "started") {
            return Slidable(

              //SLIDABLE STUFF
              delegate: SlidableStrechDelegate(),
              actionExtentRatio: 0.25,
              actions: <Widget>[
                //ACTION ONE
                IconSlideAction(
                  caption: ("Information"),
                  foregroundColor: Colors.white,
                  color: Colors.black38,
                  icon: Icons.info,
                  onTap: () {
                    Navigator.push(context, MaterialPageRoute(builder: (context)=>projectTask(snapshot.data[index])));
                  },
                ),
              ],
              secondaryActions: <Widget>[

                //ACTION TWO
                IconSlideAction(
                  caption: ("Complete Me"),
                  color: Colors.green,
                  icon: Icons.radio_button_checked,
                  onTap: () {
                    Navigator.push(context, MaterialPageRoute(builder: (context)=>projectTask(snapshot.data[index])));
                  },
                )
              ],

              child: ListTile(
                onTap: () {
                  Navigator.push(context, MaterialPageRoute(builder: (context) => projectTask(
                    snapshot.data[index],
                  )));
                },
                title: Text("${snapshot.data[index].description[0].toString().toUpperCase()}"
                    "${snapshot.data[index].description.toString().substring(1)}", maxLines: 1, style: TextStyle(
                    color: Colors.black87, fontSize: 17)
                ),
                subtitle: Text("working"),
                leading: Icon(Icons.radio_button_checked, color: Colors.blue),
                trailing: Icon(Icons.arrow_right, color: Colors.black54,),
              ),
            );
          }
          else {
            return Slidable(

              //SLIDABLE STUFF
              delegate: SlidableStrechDelegate(),
              actionExtentRatio: 0.25,
              actions: <Widget>[
                //ACTION ONE
                IconSlideAction(
                  caption: ("Information"),
                  foregroundColor: Colors.white,
                  color: Colors.black38,
                  icon: Icons.info,
                  onTap: () {
                    Navigator.push(context, MaterialPageRoute(builder: (context)=>projectTask(snapshot.data[index])));
                  },
                ),
              ],
              secondaryActions: <Widget>[

                //ACTION TWO
                IconSlideAction(
                  caption: ("Start Work"),
                  color: Colors.blue,
                  icon: Icons.radio_button_checked,
                  onTap: () {
                    Navigator.push(context, MaterialPageRoute(builder: (context)=>projectTask(snapshot.data[index])));
                  },
                )
              ],

              //LISTTILE
              child: ListTile(
                onTap: () {
                  Navigator.push(context, MaterialPageRoute(builder: (context) => projectTask(
                    snapshot.data[index],
                  )));
                },
                title: Text("${snapshot.data[index].description[0].toString().toUpperCase()}"
                    "${snapshot.data[index].description.toString().substring(1)}", maxLines: 1, style: TextStyle(
                    color: Colors.black87, fontSize: 17)
                ),
                subtitle: Text("new"),
                leading: Icon(Icons.radio_button_checked, color: Colors.red),
                trailing: Icon(Icons.arrow_right, color: Colors.black54,),
              ),
            );
          }
        }
      );

JSON

[
{
    "id": 7,
    "description": "Finishedddddd",
    "state": "done",
    "assigned_users": [
        {
            "username": "hugo",
            "fullname": "Hugo Johnsson"
        }
    ],
    "subtasks": []
},
{
    "id": 9,
    "description": "Newwww task for Huuugo",
    "state": "started",
    "assigned_users": [
        {
            "username": "hugo",
            "fullname": "Hugo Johnsson"
        }
    ],
    "subtasks": []
},
{
    "id": 11,
    "description": "Google presentation om IKEAS ekonomi",
    "state": "done",
    "assigned_users": [
        {
            "username": "studentone",
            "fullname": "Student One"
        }
    ],
    "subtasks": []
},
{
    "id": 15,
    "description": "entail",
    "state": "new",
    "assigned_users": [],
    "subtasks": [
        {
            "id": 1,
            "description": "dasdasdasd"
        },
        {
            "id": 2,
            "description": "fsdfsdfsdf"
        }
    ]
},
{
    "id": 17,
    "description": "gmmgmsgd",
    "state": "new",
    "assigned_users": [],
    "subtasks": []
},
{
    "id": 18,
    "description": "dasd",
    "state": "started",
    "assigned_users": [],
    "subtasks": []
},
{
    "id": 19,
    "description": "fsdfdsfsd",
    "state": "started",
    "assigned_users": [],
    "subtasks": []
},
{
    "id": 20,
    "description": "Werner",
    "state": "new",
    "assigned_users": [],
    "subtasks": []
},
{
    "id": 21,
    "description": "teadfsd",
    "state": "done",
    "assigned_users": [],
    "subtasks": []
},
{
    "id": 22,
    "description": "task",
    "state": "new",
    "assigned_users": [],
    "subtasks": []
},
{
    "id": 23,
    "description": "asdasd",
    "state": "started",
    "assigned_users": [],
    "subtasks": []
},
{
    "id": 24,
    "description": "asdasd",
    "state": "new",
    "assigned_users": [
        {
            "username": "hugo",
            "fullname": "Hugo Johnsson"
        }
    ],
    "subtasks": []
}

]

2个回答

5

在创建 ListView 之前,您应对数据进行排序。您可以使用基本的 Dart 排序方法。基本上,您只需要实现 compare 函数,该函数返回一个整数,该返回值的符号指定了项目的顺序。

阅读此示例代码以更好地理解:

enum TaskState {
  newTask, done, started
}

class Task {
  Task(this.id, this.state);
  final int id;
  final TaskState state;

  String toString() {
    return "$id";
  }
}

int compare(TaskState a, TaskState b) {
  if (a == b) return 0;
  switch(a) {
    case TaskState.newTask:
      return -1;
      break;
    case TaskState.started:
      if(b == TaskState.newTask) return 1;
      return -1;
      break;
    case TaskState.done:
      return 1;
      break;
  }
}

void main() {
  List<Task> list = [
    Task(1, TaskState.done),
    Task(3, TaskState.newTask),
    Task(4, TaskState.started),
    Task(2, TaskState.done),
    Task(10, TaskState.newTask),
  ];
  list.sort((a, b) => compare(a.state, b.state));
  print(list);
}


您的代码实现应该类似于以下内容:
FutureBuilder<List<ProjectTask>>(
  future: someQuery(),
  builder: (BuildContext context, AsyncSnapshot<dynamic> snap) {
    snap.data.sort((a, b) => {
      if (a == b) return 0;
      switch(a) {
        case "new":
          return -1;
          break;
        case "started":
          if(b == "new") return 1;
          return -1;
          break;
        case "done":
          return 1;
          break;
      }
    });
    return ListView.builder(
      ...
    )
  }
)

谢谢,能否解释一下如何以良好的方式实现这个? :) - William Abrahamsson
这其实很简单。我已经编辑了答案并添加了一个实现。 - Mahdi Zakizadeh

2
我找到了一篇有用的文章,其中有一个很好的示例可以按任何字段对对象列表进行排序:https://www.kindacode.com/article/sorting-lists-in-dart/ 示例:
 class User {
  String name;
  int age;

  User(this.name, this.age);

  @override
  toString() {
    return ('$name - $age years old \n');
  }
}

void main() {
  List<User> users = [
    User('Plumber', 10),
    User('John Doe', 50),
    User('Pipi', 4),
    User('Invisible Man', 31),
    User('Electric Man', 34)
  ];

  // Age from small to large
  users.sort((a, b) => a.age.compareTo(b.age));
  print('Age ascending order: ${users.toString()}');

  // Age from large to small
  users.sort((a, b) => b.age.compareTo(a.age));
  print('Age descending order: ${users.toString()}');
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接