CJSZ
CJSZ

Reputation: 41

Position widgets in orbit around another widget in Flutter

anyone has an idea on how's the best way to position widgets in orbit AROUND another (circular) widget in flutter like this? Example

Thank you very much for any help you can give :D

Upvotes: 0

Views: 484

Answers (2)

Md. Yeasin Sheikh
Md. Yeasin Sheikh

Reputation: 63809

 /// from  https://gist.github.com/pskink/50554a116698f03a862a356c38b75eb3#file-rotary_dial-dart-L225
Iterable<Rect> getBounds(Rect rect, int length) sync* {
  final s = Size.square(rect.shortestSide / 6.5);
  final radius = (rect.shortestSide - s.shortestSide) * 0.40;
  for (var i = 0; i < length; i++) {
    /// distance +
    final angle = i * pi / 6 + pi * .01;
    final center = rect.center + Offset(cos(angle), sin(angle)) * radius;
    yield Rect.fromCenter(center: center, width: s.width, height: s.height);
  }
}
class Avatar3xBtnMultiChildLayoutDelegate extends MultiChildLayoutDelegate {
  final double iconSize;
  Avatar3xBtnMultiChildLayoutDelegate(this.iconSize);

  @override
  void performLayout(Size size) {
    int id = 1;

    getBounds(Offset.zero & size, 3).forEach(
      (rect) {
        layoutChild(id, BoxConstraints.tight(rect.size));
        positionChild(id, rect.centerRight);
        id++;
      },
    );
  }

  @override
  bool shouldRelayout(
      covariant Avatar3xBtnMultiChildLayoutDelegate oldDelegate) {
    return true;
  }
}

And using it

class CAPG extends StatefulWidget {
  const CAPG({Key? key}) : super(key: key);

  @override
  State<CAPG> createState() => _CAPGState();
}

class _CAPGState extends State<CAPG> {
  double value = 300;
  final iconSize = 24.0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            Slider(
                value: value,
                max: 500,
                onChanged: (v) {
                  setState(() {
                    value = v;
                  });
                }),
            Container(
              width: value,
              height: value,
              clipBehavior: Clip.none,
              decoration: BoxDecoration(
                color: Colors.cyanAccent.withOpacity(.2),
                shape: BoxShape.circle,
                border: Border.all(),
              ),
              child: CustomMultiChildLayout(
                delegate: Avatar3xBtnMultiChildLayoutDelegate(iconSize),
                children: [
                  LayoutId(
                      id: 1,
                      child: Material(
                        color: Colors.purple,
                        shape: CircleBorder(),
                        child: Icon(Icons.one_k, size: iconSize),
                      )),
                  LayoutId(
                      id: 2,
                      child: Material(
                        color: Colors.purple,
                        shape: CircleBorder(),
                        child: Icon(Icons.two_k, size: iconSize),
                      )),
                  LayoutId(
                    id: 3,
                    child: Material(
                      color: Colors.purple,
                      shape: CircleBorder(),
                      child: Icon(Icons.three_k_outlined, size: iconSize),
                    ),
                  ),
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

enter image description here

Upvotes: 2

Tasnuva Tavasum oshin
Tasnuva Tavasum oshin

Reputation: 4750

You can Use Stack Widget . For your Idea here is the Example:

import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(home: new ExampleWidget()));
}

class ExampleWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Widget bigCircle = new Container(
      width: 300.0,
      height: 300.0,
      decoration: new BoxDecoration(
        color: Colors.orange,
        shape: BoxShape.circle,
      ),
    );

    return new Material(
      color: Colors.black,
      child: new Center(
        child: new Stack(
          children: <Widget>[
            bigCircle,
            new Positioned(
              child: new CircleButton(onTap: () => print("Cool"), iconData: Icons.favorite_border),
              top: 10.0,
              left: 130.0,
            ),
            new Positioned(
              child: new CircleButton(onTap: () => print("Cool"), iconData: Icons.timer),
              top: 120.0,
              left: 10.0,
            ),
            new Positioned(
              child: new CircleButton(onTap: () => print("Cool"), iconData: Icons.place),
              top: 120.0,
              right: 10.0,
            ),
            new Positioned(
              child: new CircleButton(onTap: () => print("Cool"), iconData: Icons.local_pizza),
              top: 240.0,
              left: 130.0,
            ),
            new Positioned(
              child: new CircleButton(onTap: () => print("Cool"), iconData: Icons.satellite),
              top: 120.0,
              left: 130.0,
            ),
          ],
        ),
      ),
    );
  }
}

class CircleButton extends StatelessWidget {
  final GestureTapCallback onTap;
  final IconData iconData;

  const CircleButton({Key key, this.onTap, this.iconData}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    double size = 50.0;

    return new InkResponse(
      onTap: onTap,
      child: new Container(
        width: size,
        height: size,
        decoration: new BoxDecoration(
          color: Colors.white,
          shape: BoxShape.circle,
        ),
        child: new Icon(
          iconData,
          color: Colors.black,
        ),
      ),
    );
  }
}

Upvotes: 1

Related Questions