preface

The previous article shared the wechat/Weibo 9 grid of Flutter. Has achieved similar wechat/Weibo display picture nine grid, drag and drop sorting, wechat group picture, pin group picture. This shared Flutter implementation imitates the QQ discussion group picture.

The resources

Calculate the radius of the circle, here a direct reference to YiiGuxing’s CompositionAvatar project, article. View width D, small blue circle radius R, large red circle radius r, Y offset dy, number of heads n.

The body of the

Calculate the central coordinates of each small circle

  1. First we need to get the coordinates of the center of the great circle. In this example, the number of heads n is 3.
// Center coordinate x.
double centerX = width / 2;
// center coordinate y, Because 3 and 5 have offsets on the Y-axis, they need to be calculated separately.
double centerY = width / 2;
// Small circle radius.
double r;
// The radius from the center of a large circle to the center of a small circle.
double r1;
switch (n) {
  case 3:
    r = width / (2 + 4 * math.sin(math.pi * (n - 2) / (2 * n)));
    r1 = r / math.cos(math.pi * (n - 2) / (2 * n));
    double R = r * (1 + math.sin(math.pi / n)) / math.sin(math.pi / n);
    double dy = 0.5 * (width - R - r * (1 + 1 / math.tan(math.pi / n)));
    centerY = dy + r + r1;
    break;    
}
Copy the code
  1. General formula for the coordinates of the center of a circle, the initial Angle is -45 degrees when n is 2 and 4.
for (int i = 0; i < n; i++) {
  double degree1 = (n = = 2 || n = = 4) ? (-math.pi / 4) : 0;
  double x = centerX + r1 * math.sin(degree1 + i * 2 * math.pi / n);
  double y = centerY - r1 * math.cos(degree1 + i * 2 * math.pi / n);
}
Copy the code

How to realize arc notch

Use ClipPath component to customize clipper.

class QQClipper extends CustomClipper<Path> {
  QQClipper({
    this.total,
    this.index,
    this.initIndex: 1.
    this.previousX,
    this.previousY,
    this.degree,
    this.arcAngle: 60.
  }) : assert(arcAngle ! = null && arcAngle > = 0 && arcAngle < = 180);
  // Number of heads.
  final int total;
  // avatar index.
  final int index;
  // avatar initIndex.
  final int initIndex;
  // The last center coordinates x.
  final double previousX;
  // The last center coordinate y.
  final double previousY;
  // Arc center Angle.
  final double degree;
  // Arc Angle.
  final double arcAngle;

  @override
  Path getClip(Size size) {
    double r = size.width / 2;
    Path path = Path();
    List<Offset> points = List();
    // If the number of heads is 2 and the index of heads is initIndex, keep the circle full.
    if (total = = 2 && index = = initIndex) {
      path.addOval(Rect.fromLTRB(0, 0. size.width, size.height));
    } else {
      // Arc path coordinates.
      double spaceA = arcAngle / 2;
      double startA = degree + spaceA;
      double endA = degree - spaceA;
      for (double i = startA; i < = 360 + endA; i = i + 1) {
        double x1 = r + r * math.sin(d2r(i));
        double y1 = r - r * math.cos(d2r(i));
        points.add(Offset(x1, y1));
      }

      // Arc notch path coordinates.
      double spaceB = math.atan(
              r * math.sin(d2r(spaceA)) / (2 * r - r * math.cos(d2r(spaceA)))) /
          math.pi *
          180;
      double r1 = (2 * r - r * math.cos(d2r(spaceA))) / math.cos(d2r(spaceB));
      double startB = degree - 180 - spaceB;
      double endB = degree - 180 + spaceB;
      List<Offset> pointsB = List();
      for (double i = startB; i < endB; i = i + 1) {
        double x1 = previousX + r1 * math.sin(d2r(i));
        double y1 = previousY - r1 * math.cos(d2r(i));
        pointsB.add(Offset(x1, y1));
      }
      points.addAll(pointsB.reversed);
      path.addPolygon(points, true);
    }
    return path;
  }

  /// degree to radian.
  double d2r(double degree) {
    return degree / 180 * math.pi;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) {
    return this ! = oldClipper;
  }
}
Copy the code

Screenshots

GitHub

nine_grid_view

About the author

GitHub: Sky24n nuggets: Sky24n Brief notes: Sky24n