0
votes

enter image description here

I want make design like contact , it will show list person and grouped by first letter of name like above image. I create class Alphabet to filter name by first letter and class Person as list

Model


class Person {
  int id;
  String fullName;
  Person({this.id, this.fullName});
}

List<Person> listPerson = [
  Person(id: 1, fullName: 'Zeffry Reynando'),
  Person(id: 2, fullName: 'Alexander'),
  Person(id: 3, fullName: 'Zulkarnain'),
  Person(id: 4, fullName: 'Zahira'),
  Person(id: 5, fullName: 'Syarif H'),
  Person(id: 6, fullName: 'Helmoy'),
];

class Alphabet {
  int id;
  String name;

  Alphabet({this.id, this.name});
}

List<Alphabet> listAlphabet = [
  Alphabet(id: 1, name: 'a'),
  Alphabet(id: 2, name: 'b'),
  Alphabet(id: 3, name: 'c'),
  Alphabet(id: 4, name: 'd'),
  Alphabet(id: 5, name: 'e'),
  Alphabet(id: 6, name: 'f'),
  Alphabet(id: 7, name: 'g'),
  Alphabet(id: 8, name: 'h'),
  Alphabet(id: 9, name: 'i'),
  Alphabet(id: 10, name: 'j'),
  Alphabet(id: 11, name: 'k'),
  Alphabet(id: 12, name: 'l'),
  Alphabet(id: 13, name: 'm'),
  Alphabet(id: 14, name: 'n'),
  Alphabet(id: 15, name: 'o'),
  Alphabet(id: 16, name: 'p'),
  Alphabet(id: 17, name: 'q'),
  Alphabet(id: 18, name: 'r'),
  Alphabet(id: 19, name: 's'),
  Alphabet(id: 20, name: 't'),
  Alphabet(id: 21, name: 'u'),
  Alphabet(id: 22, name: 'v'),
  Alphabet(id: 23, name: 'w'),
  Alphabet(id: 24, name: 'x'),
  Alphabet(id: 25, name: 'y'),
  Alphabet(id: 26, name: 'z'),
];

After that , i create function to return List Map<String,List Person> key as first letter of name and value as List Person.

Map<String, List<Person>> grupPerson() {
  Map<String, List<Person>> tempMap = {};
  for (var i = 0; i < listAlphabet.length; i++) {
    final result = listPerson
        .where((person) => person.fullName.toLowerCase().startsWith(listAlphabet[i].name))
        .toList();
    for (var j = 0; j < result.length; j++) {
      final original = tempMap[listAlphabet[i].name];
      if (original == null) {
        tempMap[listAlphabet[i].name] = [result[j]];
      } else {
        tempMap[listAlphabet[i].name] = [...original, result[j]];
      }
    }
  }

  return tempMap;
}

/// Result 
{a: [Instance of 'Person'], h: [Instance of 'Person'], s: [Instance of 'Person'], z: [Instance of 'Person', Instance of 'Person', Instance of 'Person']}

But i don't know how make design like above using my return Map. How can i do this ?

1

1 Answers

1
votes

Here is a full example of how you can do it:

enter image description here

class MyHomePage extends StatelessWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  final list = [
    Person('John'),
    Person('Mark'),
    Person('Jessica'),
    Person('Alexander'),
    Person('Zahira'),
    Person('Alexander'),
    Person('John'),
    Person('Mark'),
    Person('Jessica'),
    Person('Alexander'),
    Person('Zahira'),
    Person('Alexander'),
    Person('John'),
    Person('Mark'),
    Person('Jessica'),
    Person('Alexander'),
    Person('Zahira'),
    Person('Alexander'),
    Person('John'),
    Person('Mark'),
    Person('Jessica'),
    Person('Alexander'),
    Person('Zahira'),
    Person('Alexander'),
    Person('John'),
    Person('Mark'),
    Person('Jessica'),
    Person('Alexander'),
    Person('Zahira'),
    Person('Alexander'),
    Person('John'),
    Person('Mark'),
    Person('Jessica'),
    Person('Alexander'),
    Person('Zahira'),
    Person('Alexander'),
  ];

  final Map<String, List<Person>> groupedLists = {};

  void groupMyList() {
    list.forEach((person) {
      if (groupedLists['${person.name[0]}'] == null) {
        groupedLists['${person.name[0]}'] = <Person>[];
      }

      groupedLists['${person.name[0]}'].add(person);
    });
  }

  @override
  Widget build(BuildContext context) {
    groupMyList();

    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: ListView(
        children: [
          for (var entry in groupedLists.entries)
            SizedBox(
              width: double.infinity,
              height: 90,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(entry.key),
                  Container(
                    height: 60,
                    child: ListView.builder(
                      itemCount: entry.value.length,
                      scrollDirection: Axis.horizontal,
                      itemBuilder: (context, index) {
                        return Padding(
                          padding: const EdgeInsets.all(16),
                          child: Text(entry.value[index].name),
                        );
                      },
                    ),
                  ),
                ],
              ),
            ),
        ],
      ),
    );
  }
}

Don't forget to mark it as answered if it's correct, Thank you!