Flutter: Sorting ListView items based on type
Asked Answered
N

2

5

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": []
}

]

Nate answered 25/4, 2019 at 18:32 Comment(0)
A
5

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(
      ...
    )
  }
)
Aromatic answered 25/4, 2019 at 19:16 Comment(2)
Thanks man, can you explain how I would implement this in a good way? :)Nate
It's actually pretty simple. I've edited the answer and added a implementationAromatic
G
2

I found this helpful article with a great example to sort a list of objects by any field: https://www.kindacode.com/article/sorting-lists-in-dart/

Example:

 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()}');
}
Gorden answered 12/8, 2022 at 12:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.