ListWheelScrollView Flutter Example

Last updated Aug 25, 2020

How to create Wheel view in a flutter, How we can achieve to display items in like wheel design.

Flutter provided a widget called ListWheelScrollView, which will use to display items in Wheel with animation.

 

What is ListWheelScrollView?

ListWheelScrollView is a widget which aligns all its children in a scrollable wheel. That results in a 3D effect as if the children are rotating in a wheel. The currently selected item will be in the center wheel. In this example we will learn  how to  create a ListWheelScrollView including how to customize the look and how to handle when the selected item changes.

 

ListWheelScrollView

 

Create ListWheelScrollView

ListWheelScrollView has default constructor to create ListWheelScrollView.

This contains 2 required parameters children (List<Widget>) and itemExtent (double)

children: The child items which we are going to display

itemExtent : size of each child item

 


 ListWheelScrollView(
    itemExtent: 75,
    children: items,
  )

 

Example

Padding(
  padding: const EdgeInsets.all(8.0),
  child: Card(
    elevation: 4,

    color: Colors.grey,

    child: Padding(
      padding: const EdgeInsets.all(4.0),
      child: Container(
        color: Colors.white,
        child: Row(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Text("Day of Week",style: TextStyle(color: Colors.green,fontWeight: FontWeight.bold,fontSize: 20),),
            Container(
              width: 200,
              height: 180,
              child: ListWheelScrollView(
                useMagnifier: true,
                magnification: 1.2,
                diameterRatio: 3,
                itemExtent: 50,
                onSelectedItemChanged: (index){

                },
                physics: FixedExtentScrollPhysics(),
                children:  [

                  getWeekDay("Sunday"),
                  getWeekDay("Monday"),
                  getWeekDay("Tuesday"),
                  getWeekDay("Wednesday"),
                  getWeekDay("Thursday"),
                  getWeekDay("Friday"),
                  getWeekDay("Sateday")
                ],
              ),
            )
          ],
        ),
      ),
    ),
  ),
)

 

 

getWeekDay(day)
{
  return Container(
    decoration: BoxDecoration(
        border: Border(
          top: BorderSide(color: Colors.green,width: 1),

        )
    ),
    child: ListTile(


      title: Text(day,textAlign: TextAlign.center,style: TextStyle(fontSize: 20),),

    ),
  );
}

 

We have another way to create a ListWheelScrollView by using .useDelegate() named constructor. Instead of passing children, you need to pass a ListWheelChildDelegate to build the children

 

Padding(
  padding: const EdgeInsets.all(8.0),
  child: Card(
    elevation: 4,

    color: Colors.grey,

    child: Padding(
      padding: const EdgeInsets.all(4.0),
      child: Container(
        color: Colors.white,
        child: Row(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [

            Container(
              width: 50,
              height: 100,
              child: ListWheelScrollView.useDelegate(

                childDelegate: ListWheelChildBuilderDelegate(
                    childCount: days.length,
                    builder: (BuildContext context, int index) {
                      if (index < 0 || index > days.length) {
                        return null;
                      }
                      return Container(
                        decoration: BoxDecoration(
                            border: Border(
                              top: BorderSide(color: Colors.green,width: 1),

                            )
                        ),
                        child: ListTile(

                          title: Text(days[index].toString(),style: TextStyle(fontSize: 20)),

                        ),
                      );
                    }),
                useMagnifier: true,
                magnification: 1.2,
                diameterRatio: 3,
                itemExtent: 50,
                onSelectedItemChanged: (index){

                },
                physics: FixedExtentScrollPhysics(),

              ),
            ),
            Container(
              width: 100,
              height: 180,
              child: ListWheelScrollView.useDelegate(
                childDelegate: ListWheelChildBuilderDelegate(
                    childCount: listMonths.length,
                    builder: (BuildContext context, int index) {
                      if (index < 0 || index > listMonths.length) {
                        return null;
                      }
                      return Container(
                        decoration: BoxDecoration(
                            border: Border(
                              top: BorderSide(color: Colors.green,width: 1),

                            )
                        ),
                        child: ListTile(

                          title: Text(listMonths[index],style: TextStyle(fontSize: 20)),

                        ),
                      );
                    }),

                useMagnifier: true,
                magnification: 1.2,
                diameterRatio: 3,
                itemExtent: 50,
                onSelectedItemChanged: (index){
                  setState(() {
                    selectedmonth=index;
                    getDays();
                  });
                },
                physics: FixedExtentScrollPhysics(),

              ),
            ),
            Container(
              width: 100,
              height: 180,
              child: ListWheelScrollView(
                useMagnifier: true,
                magnification: 1.2,
                diameterRatio: 3,
                itemExtent: 50,
                onSelectedItemChanged: (index){

                },
                physics: FixedExtentScrollPhysics(),
                children:  [

                  getWeekDay("2020"),
                  getWeekDay("2021"),
                  getWeekDay("2022"),
                  getWeekDay("2023"),
                  getWeekDay("2024"),
                  getWeekDay("2025"),
                ],
              ),
            )
          ],
        ),
      ),
    ),
  ),
),

 

Magnifier Property

We can have magnifier for the center item by setting useMagnifier property to true. To set the zoom-in rate, use magnification property which defaults to 1.0. If the value is greater than 1.0, it will look bigger. Setting the value to be lower than 1.0 makes the magnified item looks smaller

 

ListWheelScrollView(
    itemExtent: 40,
    children: items,
    useMagnifier: true,
    magnification: 1.5,
  )

 

Diameter Ratio

The diameter of the cylinder can be set using diameterRatio property value. The default value is 2.

ListWheelScrollView(
    itemExtent: 40,
    children: items,
    diameterRatio: 1,
  )

 

Setting Controller

The controller used is typically a FixedExtentScrollController. It will be used if you don't set the controller property. Be careful if you change it to ScrollController as it will cause onSelectedItemChanged not working as it doesn't provide FixedExtentMetrics

 

Complete code for above screenshot

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_provider/listwheel/country_model.dart';


class ListWheelScroll extends StatefulWidget{
  @override
  _ListWheelScrollState createState() => _ListWheelScrollState();
}

class _ListWheelScrollState extends State<ListWheelScroll> {
  List<CountryModel>listCountry;
  List<String>listMonths;
  List<int>days;
  int selectedmonth=1;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    listCountry=List();
    listMonths=List();
    days=List();
    loadData(context);
    getMonths();
    getDays();
  }
  @override
  Widget build(BuildContext context) {

    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(title: Text("ListWheelScroll"),backgroundColor: Colors.green,),
      body: SingleChildScrollView(
        child: Column(
          children: [
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Card(
                elevation: 4,

                color: Colors.grey,

                child: Padding(
                  padding: const EdgeInsets.all(4.0),
                  child: Container(
                    color: Colors.white,
                    child: Row(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: [

                        Container(
                          width: 50,
                          height: 100,
                          child: ListWheelScrollView.useDelegate(

                            childDelegate: ListWheelChildBuilderDelegate(
                                childCount: days.length,
                                builder: (BuildContext context, int index) {
                                  if (index < 0 || index > days.length) {
                                    return null;
                                  }
                                  return Container(
                                    decoration: BoxDecoration(
                                        border: Border(
                                          top: BorderSide(color: Colors.green,width: 1),

                                        )
                                    ),
                                    child: ListTile(

                                      title: Text(days[index].toString(),style: TextStyle(fontSize: 20)),

                                    ),
                                  );
                                }),
                            useMagnifier: true,
                            magnification: 1.2,
                            diameterRatio: 3,
                            itemExtent: 50,
                            onSelectedItemChanged: (index){

                            },
                            physics: FixedExtentScrollPhysics(),

                          ),
                        ),
                        Container(
                          width: 100,
                          height: 180,
                          child: ListWheelScrollView.useDelegate(
                            childDelegate: ListWheelChildBuilderDelegate(
                                childCount: listMonths.length,
                                builder: (BuildContext context, int index) {
                                  if (index < 0 || index > listMonths.length) {
                                    return null;
                                  }
                                  return Container(
                                    decoration: BoxDecoration(
                                        border: Border(
                                          top: BorderSide(color: Colors.green,width: 1),

                                        )
                                    ),
                                    child: ListTile(

                                      title: Text(listMonths[index],style: TextStyle(fontSize: 20)),

                                    ),
                                  );
                                }),

                            useMagnifier: true,
                            magnification: 1.2,
                            diameterRatio: 3,
                            itemExtent: 50,
                            onSelectedItemChanged: (index){
                              setState(() {
                                selectedmonth=index;
                                getDays();
                              });
                            },
                            physics: FixedExtentScrollPhysics(),

                          ),
                        ),
                        Container(
                          width: 100,
                          height: 180,
                          child: ListWheelScrollView(
                            useMagnifier: true,
                            magnification: 1.2,
                            diameterRatio: 3,
                            itemExtent: 50,
                            onSelectedItemChanged: (index){

                            },
                            physics: FixedExtentScrollPhysics(),
                            children:  [

                              getWeekDay("2020"),
                              getWeekDay("2021"),
                              getWeekDay("2022"),
                              getWeekDay("2023"),
                              getWeekDay("2024"),
                              getWeekDay("2025"),
                            ],
                          ),
                        )
                      ],
                    ),
                  ),
                ),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Card(
                elevation: 4,

                color: Colors.grey,

                child: Padding(
                  padding: const EdgeInsets.all(4.0),
                  child: Container(
                    color: Colors.white,
                    child: Row(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: [
                        Text("Country",style: TextStyle(color: Colors.green,fontWeight: FontWeight.bold,fontSize: 20),),
                        Container(
                          width: 200,
                          height: 180,
                          child: ListWheelScrollView(
                            useMagnifier: true,
                            magnification: 1.2,
                            diameterRatio: 3,
                            itemExtent: 50,
                            onSelectedItemChanged: (index){
                              print("Selected Country ${listCountry[index].name}");
                            },
                            physics: FixedExtentScrollPhysics(),
                            children:  getChildItems(),
                          ),
                        )
                      ],
                    ),
                  ),
                ),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Card(
                elevation: 4,

                color: Colors.grey,

                child: Padding(
                  padding: const EdgeInsets.all(4.0),
                  child: Container(
                    color: Colors.white,
                    child: Row(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: [
                        Text("Day of Week",style: TextStyle(color: Colors.green,fontWeight: FontWeight.bold,fontSize: 20),),
                        Container(
                          width: 200,
                          height: 180,
                          child: ListWheelScrollView(
                            useMagnifier: true,
                            magnification: 1.2,
                            diameterRatio: 3,
                            itemExtent: 50,
                            onSelectedItemChanged: (index){

                            },
                            physics: FixedExtentScrollPhysics(),
                            children:  [

                              getWeekDay("Sunday"),
                              getWeekDay("Monday"),
                              getWeekDay("Tuesday"),
                              getWeekDay("Wednesday"),
                              getWeekDay("Thursday"),
                              getWeekDay("Friday"),
                              getWeekDay("Sateday")
                            ],
                          ),
                        )
                      ],
                    ),
                  ),
                ),
              ),
            ),

          ],
        ),


      ),
    );
  }

  getChildItems()
  {
    List<Widget>listWidgets=List();
    for(var k=0;k<listCountry.length;k++)
      {
        listWidgets.add(Container(
          decoration: BoxDecoration(
            border: Border(
              top: BorderSide(color: Colors.green,width: 1),

            )
          ),
          child: ListTile(
               leading:Image.asset("images/"+listCountry[k].flag,height: 40,width: 40,),

                title: Text(listCountry[k].name,style: TextStyle(fontSize: 20)),

              ),
        ), );

        print("Count ${listCountry[k].flag}");
      }
    return listWidgets;
  }

loadData(context) async
{
  await DefaultAssetBundle.of(context).loadString("assets/CountryJson.json")
      .then((s) {
    setState(() {

      var response = json.decode(s);


      for (var k = 0; k < response.length; k++) {
        listCountry.add(CountryModel.fromJson( response[k]));
      }
      getChildItems();

    });
  }).catchError((error) {

    print(error);
  });
}


    getWeekDay(day)
    {
      return Container(
        decoration: BoxDecoration(
            border: Border(
              top: BorderSide(color: Colors.green,width: 1),

            )
        ),
        child: ListTile(


          title: Text(day,textAlign: TextAlign.center,style: TextStyle(fontSize: 20),),

        ),
      );
    }

    getDays()
    {

      days.clear();
      switch(selectedmonth)
      {
        case 0:
          for(int k=0;k<31;k++)
            days.add(k+1);
          break;
        case 1:
          for(int k=0;k<28;k++)
            days.add(k+1);
          break;
          case 2:
          for(int k=0;k<31;k++)
            days.add(k+1);
          break;
          case 3:
          for(int k=0;k<30;k++)
            days.add(k+1);
          break;
          case 4:
          for(int k=0;k<31;k++)
            days.add(k+1);
          break;
          case 5:
          for(int k=0;k<31;k++)
            days.add(k+1);
          break;
          case 6:
          for(int k=0;k<30;k++)
            days.add(k+1);
          break;
          case 7:
          for(int k=0;k<31;k++)
            days.add(k+1);
          break;
          case 8:
          for(int k=0;k<30;k++)
            days.add(k+1);
          break;
          case 9:
          for(int k=0;k<31;k++)
            days.add(k+1);
          break;
          case 10:
          for(int k=0;k<30;k++)
            days.add(k+1);
          break;
          case 11:
          for(int k=0;k<31;k++)
            days.add(k+1);
          break;
      }

      return days;
    }

    getMonths()
    {
      listMonths.add("Jan");
      listMonths.add("Feb");
      listMonths.add("Mar");
      listMonths.add("Apr");
      listMonths.add("May");
      listMonths.add("Jun");
      listMonths.add("July");
      listMonths.add("Aug");
      listMonths.add("Sept");
      listMonths.add("Oct");
      listMonths.add("Nov");
      listMonths.add("Dec");
    }
}

 

ListWheelScrollView Properties

  • Key key: The widget key, used to control if it's should be replaced.
  • ScrollController controller: Used to control the current item, typically a FixedExtentScrollController, which will be used if none is provided. Changing it to ScrollController will cause onSelectedItemChanged not working as it doesn't provide FixedExtentMetrics.
  • ScrollPhysics physics: How the scroll view should respond to user input. By default it uses platform conventions.
  • diameterRatio: Ratio of the wheel diameter compared to the size of the viewport.
  • double perspective: Perspective of the cylindrical projection.
  • double offAxisFraction: How much the wheel is horizontally off-center, as a fraction of its width. Defaults to 0.0
  • bool useMagnifier: Whether to use magnifier for the current item. Defaults to false.
  • double magnification: The zoom-in rate if magnifier is used.
  • double itemExtent*: Size of each child in the main axis.
  • double squeeze: The angular compactness of the items in the wheel.
  • onSelectedItemChanged: Listener that will be called whenever the center item changes.
  • clipToSize: Whether to clip painted children to the inside of this viewport.
  • renderChildrenOutsideViewport: Whether to paint children inside the viewport only. Defaults to false.
  • List<Widget> : List of Widgets to be set as the items of ListWheelScrollView..
  • ListWheelChildDelegate childDelegate*: A delegate that helps lazily instantiating child

 

Tags: WheelView, ListView, Flutter UI

 

Article Contributed By :
https://www.rrtutors.com/site_assets/profile/assets/img/avataaars.svg

3026 Views