skip to Main Content

enter image description here

I have tried several packages and found the following package fulfilling the purpose to some extent. https://pub.dev/packages/circle_list

One requirement missing in this package is the click-on icon and icon rotating in the center.

2

Answers


  1. I figured it out. With RotateMode.stopRotate everything is working as you wanted it to be, but if you plan to allow the user to rotate it, then the order of elements (indexes) becomes messed up, so in that case, you’ll need to figure out how to track the latest position of the first element to know where the start is and where it should go (and I’m not sure if it’s even possible with this package).

    class Sample extends StatefulWidget {
      const Sample({Key? key}) : super(key: key);
      @override
      State<Sample> createState() => _SampleState();
    }
    
    class _SampleState extends State<Sample> with SingleTickerProviderStateMixin {
      late AnimationController animationController;
    
      @override
      void initState() {
        animationController = AnimationController(
          upperBound: pi * 2,
          vsync: this,
          duration: const Duration(seconds: 2),
        );
        super.initState();
      }
    
      @override
      void dispose() {
        animationController.dispose();
        super.dispose();
      }
    
      List<int> elements = List.generate(10, (index) => index);
    
      _center(int index) {
        final angle = (pi * 2) * (index / 10);
        animationController.animateTo(angle);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(),
          drawer: const Drawer(),
          body: Center(
            child: AnimatedBuilder(
              animation: animationController,
              builder: ((context, child) {
                return CircleList(
                  onDragEnd: () => {},
                  initialAngle: -animationController.value - pi / 2,
                  centerWidget: Text('center'),
                  rotateMode: RotateMode.stopRotate,
                  origin: Offset(0, 0),
                  children: elements
                      .map(
                        (index) => IconButton(
                          onPressed: () => _center(index),
                          icon: Icon(Icons.notifications),
                          color: Colors.blue.withOpacity(index * 0.05 + .3),
                        ),
                      )
                      .toList(),
                );
              }),
            ),
          ),
        );
      }
    }
    
    Login or Signup to reply.
  2. Source Code

    class RotatingSliderWidget extends StatefulWidget {
      const RotatingSliderWidget({Key? key}) : super(key: key);
    
      @override
      State<RotatingSliderWidget> createState() => _RotatingSliderWidgetState();
    }
    
    class _RotatingSliderWidgetState extends State<RotatingSliderWidget>
        with SingleTickerProviderStateMixin {
      late AnimationController animationController;
    
      @override
      void initState() {
        animationController = AnimationController(
          upperBound: pi * 2,
          vsync: this,
          duration: const Duration(seconds: 2),
        );
        super.initState();
      }
    
      @override
      void dispose() {
        animationController.dispose();
        super.dispose();
      }
    
      ContentModel? center;
    
      final elements = [
        ContentModel(index: 0, backgroundColor: const Color(0xFFFFEC38)),
        ContentModel(index: 1, backgroundColor: const Color(0xFFEA1863)),
        ContentModel(index: 2, backgroundColor: Colors.black),
        ContentModel(index: 3, backgroundColor: const Color(0xFFF44133)),
        ContentModel(index: 4, backgroundColor: const Color(0xFF1B97F3)),
        ContentModel(index: 5, backgroundColor: Colors.white),
        ContentModel(index: 6, backgroundColor: const Color(0xFF58BA61)),
        ContentModel(index: 7, backgroundColor: const Color(0xFF9F9F9F)),
      ];
    
      _center(int index) {
        center = elements[index];
        final angle = (pi * 2) * (index / 10);
        animationController.animateTo(angle);
        setState(() {});
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(),
          drawer: const Drawer(),
          body: Center(
            child: AnimatedBuilder(
              animation: animationController,
              builder: ((context, child) {
                return CircleList(
                    centerWidget: center == null
                        ? null
                        : Container(
                            decoration: BoxDecoration(
                              color: center!.backgroundColor,
                              shape: BoxShape.circle,
                            ),
                            child: IconButton(
                              onPressed: () => _center(center!.index),
                              icon: const Icon(Icons.notifications, size: 35),
                              color: const Color(0xFFA6F4CE),
                            ),
                          ),
                    onDragStart: (_) {},
                    onDragEnd: () {},
                    outerCircleColor: const Color(0xFFA6F4CE),
                    initialAngle: -animationController.value - pi / 2,
                    rotateMode: RotateMode.stopRotate,
                    origin: const Offset(0, 0),
                    children: elements
                        .map((index) => Container(
                              decoration: BoxDecoration(
                                color: index.backgroundColor,
                                shape: BoxShape.circle,
                              ),
                              child: IconButton(
                                onPressed: () => _center(index.index),
                                icon: const Icon(Icons.notifications, size: 35),
                                color: const Color(0xFFA6F4CE),
                              ),
                            ))
                        .toList());
              }),
            ),
          ),
        );
      }
    }
    
    class ContentModel {
      final int index;
      final Color backgroundColor;
    
      ContentModel({required this.index, required this.backgroundColor});
    }
    

    You can see Result in attached video

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search