简体   繁体   中英

unable to stack 5 circles on each other in flutter

What i am trying to achieve is: 在此处输入图片说明 what i have achieved and stuck on is: 在此处输入图片说明 i am using inkwell widget inside a container

Code:

Container(
                alignment: Alignment.center,
                child: InkWell(
                  child: new Container(
                    width: 120.0,
                    height: 120.0,
                    padding: const EdgeInsets.all(20.0),//I used some padding without fixed width and height
                    decoration: new BoxDecoration(
                      shape: BoxShape.circle,// You can use like this way or like the below line
                      //                borderRadius: new BorderRadius.circular(30.0),
                      color: Colors.white,
                    ),
                    child: new Text("", style: new TextStyle(color: Colors.black, fontSize: 30.0, fontWeight: FontWeight.bold)),
                    alignment: Alignment.center,
                    // You can add a Icon instead of text also, like below.
                    //child: new Icon(Icons.arrow_forward, size: 50.0, color: Colors.black38)),
                  ),

please help.

maybe you can use Alignment(x, y) and ClipPath :

class Demo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Demo'),
      ),
      body: Center(
        child: Container(
          color: Colors.grey,
          width: 200,
          height: 200,
          child: Stack(
            children: [
              Align(
                alignment: Alignment(-0.15, 0.3),
                child: buildCircle(Colors.purpleAccent),
              ),
              Align(
                alignment: Alignment(0.2, 0.3),
                child: buildCircle(Colors.blue),
              ),
              Align(
                alignment: Alignment(0.3, -0.1),
                child: buildCircle(Colors.red),
              ),
              Align(
                alignment: Alignment(0.0, -0.3),
                child: buildCircle(Colors.yellow),
              ),
              Align(
                alignment: Alignment(-0.3, -0.1),
                child: ClipPath(
                  // Clip the green circle.
                  clipper: Clipper(),
                  child: buildCircle(Colors.green),
                ),
              ),
              Align(
                child: buildCircle(Colors.white, width: 30, height: 30),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Container buildCircle(
    Color color, {
    double width = 50,
    double height = 50,
  }) {
    return Container(
      alignment: Alignment.center,
      width: width,
      height: height,
      child: InkWell(
        child: new Container(
          width: width,
          height: height,
          padding: const EdgeInsets.all(20.0),
          //I used some padding without fixed width and height
          decoration: new BoxDecoration(
            shape: BoxShape.circle,
            // You can use like this way or like the below line
            //                borderRadius: new BorderRadius.circular(30.0),
            color: color,
          ),
          child: new Text("",
              style: new TextStyle(
                  color: Colors.black,
                  fontSize: 30.0,
                  fontWeight: FontWeight.bold)),
          alignment: Alignment.center,
          // You can add a Icon instead of text also, like below.
          //child: new Icon(Icons.arrow_forward, size: 50.0, color: Colors.black38)),
        ),
      ),
    );
  }
}

class Clipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    return Path.combine(
      PathOperation.difference,
      Path()
        ..addOval(
          Rect.fromCircle(
            center: size.center(Offset(0, 0)),
            radius: 25.0,
          ),
        ),
      Path()
        ..addOval(
          Rect.fromCircle(
            center: size.center(Offset(10, 30)),
            radius: 25.0,
          ),
        ),
    );
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) => true;
}

在此处输入图片说明

在此处输入图片说明

You can notice, that actually this is one element with different colors, it is going through the circle with angle of 360/5 degrees

  • you can use
Path.combine(
          PathOperation.reverseDifference,

在此处输入图片说明

    import 'dart:math' as math;

    import 'package:flutter/material.dart';

    const double degrees2Radians = math.pi / 180.0;
    void main() => runApp(MyApp());

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Scaffold(
            body: SafeArea(
              child: MyHomePage(),
            ),
          ),
        );
      }
    }

    class MyHomePage extends StatefulWidget {
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }

    class _MyHomePageState extends State<MyHomePage> {
      int _currentSliderValue = 2;

      List<Color> colors = [
        Colors.blue,
        Colors.red,
        Colors.yellow,
        Colors.green,
        Colors.purple,
        Colors.orange,
      ];
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            Expanded(
              child: Container(
                width: double.infinity,
                child: CustomPaint(
                  painter: MyPainter(
                    colors: colors.take(_currentSliderValue).toList(),
                  ),
                ),
              ),
            ),
            Slider(
              value: _currentSliderValue.toDouble(),
              min: 2,
              max: 6,
              label: _currentSliderValue.toString(),
              onChanged: (value) {
                setState(() {
                  _currentSliderValue = value.round();
                });
              },
            ),
          ],
        );
      }
    }

    class MyPainter extends CustomPainter {
      const MyPainter({
        @required this.colors,
      }) : super();

      final List<Color> colors;

      @override
      void paint(Canvas canvas, Size size) {
        var paths = <Color, Path>{};
        colors.asMap().forEach((index, color) {
          var degree = 360 / colors.length * (index + 0.5);
          var radian = degree * degrees2Radians;

          var path = _onePath(radian, size);

          if (index > 0) {
            path = Path.combine(
              PathOperation.difference,
              path,
              paths[colors[index - 1]],
            );
          }
          if (index == colors.length - 1) {
            paths[colors[0]] = Path.combine(
              PathOperation.reverseDifference,
              path,
              paths[colors[0]],
            );
          }
          paths[color] = path;
        });

        for (final color in colors) {
          var path = paths[color];

          final fillPaint = Paint()
            ..color = color
            ..style = PaintingStyle.fill;
          canvas.drawPath(path, fillPaint);

          final strokePaint = Paint()
            ..color = Color(0xFFC4C4C4)
            ..style = PaintingStyle.stroke
            ..strokeCap = StrokeCap.butt
            ..strokeWidth = 10;

          canvas.drawPath(path, strokePaint);
        }
      }

      Path _onePath(double radian, Size size) {
        var circleSize = 150.0;
        var center = size.center(Offset.zero);
        var maxSize = math.min(size.height, size.width) / 4;
        var sin = math.sin(radian);
        var cos = math.cos(radian);

        var rect = Rect.fromLTWH(
          center.dx - circleSize / 2 + (sin * maxSize),
          center.dy - circleSize / 2 + (cos * maxSize),
          circleSize,
          circleSize,
        );
        return Path()
          ..addRRect(
            RRect.fromRectAndRadius(
              rect,
              Radius.circular(
                rect.height / 2,
              ),
            ),
          )
          ..close();
      }

      @override
      bool shouldRepaint(CustomPainter oldDelegate) => true;
    }

You can use FractionalTranslation :

Center(
  child: Container(
    height: 400,
    child: Stack(
      children: <Widget>[
        FractionalTranslation(
          translation: Offset(-0.22, -0.1),
          child: CircleContainer(color: Colors.green),
        ),
        FractionalTranslation(
          translation: Offset(-0.15, 0.2),
          child: CircleContainer(color: Colors.purple),
        ),
        FractionalTranslation(
          translation: Offset(0.15, 0.2),
          child: CircleContainer(color: Colors.blue),
        ),
        FractionalTranslation(
          translation: Offset(0.22, -0.1),
          child: CircleContainer(color: Colors.red),
        ),
        FractionalTranslation(
          translation: Offset(0, -0.25),
          child: CircleContainer(color: Colors.yellow),
        ),
        CircleContainer(color: Colors.white, size: 130),
      ],
    ),
  ),
)
Widget CircleContainer({Color color = Colors.white, double size = 160}) {
  return Container(
    alignment: Alignment.center,
    child: InkWell(
      child: new Container(
        width: size,
        height: size,
        padding: const EdgeInsets.all(
          20.0), //I used some padding without fixed width and height
        decoration: new BoxDecoration(
          shape: BoxShape
          .circle, // You can use like this way or like the below line
          //                borderRadius: new BorderRadius.circular(30.0),
          color: color,
        ),
        child: new Text("",
                        style: new TextStyle(
                          color: Colors.black,
                          fontSize: 30.0,
                          fontWeight: FontWeight.bold)),
        alignment: Alignment.center,
// You can add a Icon instead of text also, like below.
//child: new Icon(Icons.arrow_forward, size: 50.0, color: Colors.black38)),
      )));
}

Result:

资源

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM