Flutter: Sorting ListView items based on type

12,134

You should sort the data before creating the ListView. You can use basic dart sort method. Basically you just need to implement the compare function which returns an integer that the sign of the return value specify items order.

Read this example code for better understanding:

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

Implementing in your code should be something like this

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(
      ...
    )
  }
)
Share:
12,134
William Abrahamsson
Author by

William Abrahamsson

Updated on December 10, 2022

Comments

  • William Abrahamsson
    William Abrahamsson over 1 year

    So I have a listview.builder in my Project management app in Flutter. This listview is filled with tasks(they can be: new, started, done). I get this data from an API and want the ones that are "new" to appear at the top, the ones that are started to be in the middle and the bottom for the "done" ones! - This is how it looks right now This is my Class, notice that I get the state from the 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": []
    }
    

    ]