Kel
Kel

Reputation: 463

Flutter: How to use DropDown Button to sorting Data

I have a JSON file like this (API)

[
  {
    "language": "English",
    "bySpeakers": 1121,
    "inCountry": 59,
    "onInternet": 0.04
  },
  {
    "language": "French",
    "bySpeakers": 284.9,
    "inCountry": 29,
    "onInternet": 0.02
  },
  {
    "language": "Spanish",
    "bySpeakers": 512.9,
    "inCountry": 21,
    "onInternet": 0.01
  },
  {
    "language": "Arabic",
    "bySpeakers": 422,
    "inCountry": 26,
    "onInternet": 0.053
  },
  {
    "language": "Portuguse",
    "bySpeakers": 236.5,
    "inCountry": 9,
    "onInternet": 0.01
  }
]

I want that when I click on the DropdownButton then select each button => the list will be sorted as follows:

enter image description here

So pls help me, this is the main file:

import 'package:ask/model/sort_model.dart';
import 'package:ask/services/sort_service.dart';
import 'package:flutter/material.dart';

class SortPage extends StatefulWidget {
  @override
  _SortPageState createState() => _SortPageState();
}

class _SortPageState extends State<SortPage> {
  List<Sort> _sort = [];
  List<String> dropDown = <String>["Default", "Alphabet", "By Speakers", "In Countries", "On Internet"];

  @override
  void initState() {
    super.initState();
    SortServices.getData().then((data) {
      setState(() {
        _sort = data;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text('Sort'),
            new DropdownButton<String>(
                underline: Container(),
                icon: Icon(Icons.sort,color: Colors.white),
                items: dropDown.map<DropdownMenuItem<String>>((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(value),
                  );
                }).toList(),
                onChanged: (String value) {
                  setState(() {});
                })
          ],
        )),
        body: Column(
          children: [
            Container(
              color: Colors.grey,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [Text('Language'), Text('By Speakers'), Text('In Countries'), Text('On Internet')],
              ),
            ),
            for (Sort s in _sort)
              Row(children: [
                Expanded(child: Text(s.language)),
                Expanded(child: Text('${s.bySpeakers} billion')),
                Expanded(child: Text('${s.inCountry} countries')),
                Expanded(child: Text('${s.onInternet * 100} %')),
              ])
          ],
        ));
  }
}


Upvotes: 0

Views: 5115

Answers (2)

md naime
md naime

Reputation: 1

import 'package:ask/model/sort_model.dart';
import 'package:ask/services/sort_service.dart';
import 'package:flutter/material.dart';

class SortPage extends StatefulWidget {
  @override
  _SortPageState createState() => _SortPageState();
}

class _SortPageState extends State<SortPage> {
  List<Sort> _sort = [];
  List<String> dropDown = <String>["Default", "Alphabet", "By Speakers", "In Countries", "On Internet"];

  @override
  void initState() {
    super.initState();
    SortServices.getData().then((data) {
      setState(() {
        _sort = data;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text('Sort'),
            new DropdownButton<String>(
                underline: Container(),
                icon: Icon(Icons.sort,color: Colors.white),
                items: dropDown.map<DropdownMenuItem<String>>((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(value),
                  );
                }).toList()..sort((a, b) => b.value!.compareTo(a.value!)),
                onChanged: (String value) {
                  setState(() {});
                })
          ],
        )),
        body: Column(
          children: [
            Container(
              color: Colors.grey,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [Text('Language'), Text('By Speakers'), Text('In Countries'), Text('On Internet')],
              ),
            ),
            for (Sort s in _sort)
              Row(children: [
                Expanded(child: Text(s.language)),
                Expanded(child: Text('${s.bySpeakers} billion')),
                Expanded(child: Text('${s.inCountry} countries')),
                Expanded(child: Text('${s.onInternet * 100} %')),
              ])
          ],
        ));
  }
}

Upvotes: 0

Omar Hurani
Omar Hurani

Reputation: 36

In Dart, the List type has a sort function which lets you sort the list. You give the sort function another function that compares between any two objects in the list. It returns an integer that represents whether an object is less than, equal to or larger than the other object. If the returned value is -1 (might work for all negative numbers but I'm not sure), this means that the first object is less that the second object. If it's 0, they're equal, and if it's 1 (again, might work for all positives but not sure) the first object is larger than the second.

I assume your Sort class is defined as follows:

class Sort{
  String language;
  double bySpeakers, inCountries, onInternet;
}

To sort the list _sort alphabetically, your sort call will look something like this:

_sort.sort((first, second) => first.language.compareTo(second.language));

Note that this function call will change the list itself. If you want to keep your original list, make sure you're sorting a copy of the list. A soft copy (only copy references to a new array) can be achieved using map like this:

List<Sort> copy = _sort.map((e) => e).toList();

I'll give one more sort example for the bySpeakers field:

// Sort the list using the bySpeakers attribute
_sort.sort((first, second){
  if(first.bySpeakers > second.bySpeakers)
    return 1;
  else if(first.bySpeakers < second.bySpeakers)
    return -1;
  else
    return 0;
});

Note that sort sorts in ascending order. To make it descending, you can swap between return 1; and return -1;, or use the getter reversed on the list, which will return an Iterable containing the reversed list.

So define a function that does the sorting:

// function defined in the state class
void sortItems(String value){
  // assuming the original list is stored _originalList
  _sort = _originalList.map((e)=>e).toList();
  switch(value){
    case 'Alphabet':
      _sort.sort((first, second)=>first.language.comprateTo(second.language));
      break;
    case 'By Speakers':
      _sort.sort((first, second){
        if(first.bySpeakers > second.bySpeakers)
          return -1; // reversed
        else if(first.bySpeakers < second.bySpeakers)
          return 1; // reversed
        else
          return 0;
      });
      break;
    
    case 'In Countries':
      _sort.sort((first, second){
        if(first.inCountries > second.inCountries)
          return -1; // reversed
        else if(first.inCountries < second.inCountries)
          return 1; // reversed
        else
          return 0;
      });
      break;
    
    case 'On Internet':
      _sort.sort((first, second){
        if(first.onInternet > second.onInternet)
          return -1; // reversed
        else if(first.onInternet < second.onInternet)
          return 1; // reversed
        else
          return 0;
      });
      break;
    default:
      break;
  }
}

Now you will need to call this function inside the onChanged function for the DropdownButton, something like this:

onChanged: (String value) {
  setState(() {
    sortItems(value);
  });
})

Upvotes: 2

Related Questions