How to make a circular List of Items like a WheelView?

767

I hope that following example solve your problem.

import 'dart:math';
import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  List<int> data = [1,2,3,4,5,6,7,8];

  double radius =  125.0;

  List<Widget> list(){
    final double firstItemAngle = pi;
    final double lastItemAngle = pi;
    final double angleDiff = (firstItemAngle + lastItemAngle) / 6;
    double currentAngle = firstItemAngle;

    return data.map((int index){
      currentAngle += angleDiff;
      return _radialListItem(currentAngle,index);
    }).toList();
  }

  Widget _radialListItem(double angle, int index){

    final x = cos(angle)  * radius;
    final y = sin(angle) * radius;


    return Center(
      child: Transform(
        transform: index == 1 ? Matrix4.translationValues(0.0, 0.0 , 0.0) : Matrix4.translationValues(x, y , 0.0),
        child: InkWell(
          onTap: (){
            print(index.toString());
          },
          child: CircleAvatar(
            radius: 50.0,
            backgroundImage: AssetImage("images/c1.jpeg"),
          ),
        )
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: new Text("hello World"),
      ),
      body: new Stack(
        children: list()
      ),
    );
  }
}
Share:
767
JTorrus
Author by

JTorrus

Mobile developer currently working with Flutter

Updated on December 07, 2022

Comments

  • JTorrus
    JTorrus over 1 year

    I'm currently developing an app where I need to display a list of options in a circular way. Just like a ¿revolver? / ¿wheel? I don't even know how to define it with words.

    For a reference, I want something like Glovo: Screenshot_Glovo

    I tried something by my own but it's a mess and doesn't fit the aspect ratio of each device. Here's the code

    /* HomeBubbleItem is just a Container with BoxShape.circle and Text */
    
    Widget _buildExperiencesSection() {
        return Center(
          child: Stack(
            children: <Widget>[
              Positioned(
                top: MediaQuery.of(context).size.height / 3,
                left: MediaQuery.of(context).size.width / 3,
                child: HomeBubbleItem(experience: _experiences[0], color: Colors.blue, icon: Icons.check,),
              ),
              Positioned(
                top: MediaQuery.of(context).size.height / 4,
                left: MediaQuery.of(context).size.width / 32,
                child: HomeBubbleItem(experience: _experiences[1], color: Colors.blue, icon: Icons.check,),
              ),
              Positioned(
                top: MediaQuery.of(context).size.height / 4,
                right: MediaQuery.of(context).size.width / 32,
                child: HomeBubbleItem(experience: _experiences[2], color: Colors.blue, icon: Icons.check,),
              ),
              Positioned(
                top: MediaQuery.of(context).size.height / 7,
                left: MediaQuery.of(context).size.width / 3,
                child: HomeBubbleItem(experience: _experiences[3], color: Colors.blue, icon: Icons.check,),
              ),
              Positioned(
                bottom: MediaQuery.of(context).size.height / 14,
                left: MediaQuery.of(context).size.width / 3,
                child: HomeBubbleItem(experience: _experiences[4], color: Colors.blue, icon: Icons.check,),
              ),
              Positioned(
                bottom: MediaQuery.of(context).size.height / 6.5,
                left: MediaQuery.of(context).size.width / 32,
                child: HomeBubbleItem(experience: _experiences[5], color: Colors.blue, icon: Icons.check,),
              ),
              Positioned(
                bottom: MediaQuery.of(context).size.height / 6.5,
                right: 11.0,
                child: HomeBubbleItem(experience: _experiences[6], color: Colors.blue, icon: Icons.check,),
              ),
            ],
          ),
        );
      }
    

    And here my sad result: My_Screenshot

    I'd like to know if there's a better optimized way to achieve this.

    Thanks!

  • Wicked Gummy Bear
    Wicked Gummy Bear over 3 years
    Is it possible to have the first index start at the top? I have a listview of only 4/5 items and I dont want to spread them out across the whole circle, but instead start at the top and go from there.
  • Viren V Varasadiya
    Viren V Varasadiya over 3 years
    Yes, surely you can make it just change the angle according @WickedGummyBear.
  • Wicked Gummy Bear
    Wicked Gummy Bear over 3 years
    I've tried changing the angle, but all it does is change all the widgets and moving them further apart. I cannot grasp how to rotate the whole picture till the first one is at the top. It's messing me up, so frustrating
  • Viren V Varasadiya
    Viren V Varasadiya over 3 years
    All I can say is, You need to do angle calculation accordingly. You can contact me on my email, if you need more help.