GithubHelp home page GithubHelp logo

mindinventory / flutter-review-page-interaction Goto Github PK

View Code? Open in Web Editor NEW
306.0 17.0 115.0 5.68 MB

Implementation of this review page interaction with Flutter

Home Page: https://www.mindinventory.com/flutter-app-development.php

License: MIT License

Kotlin 0.95% Swift 1.11% Objective-C 0.10% Dart 97.84%
flutter custom-components android ios ui-components dart

flutter-review-page-interaction's Issues

arc menu position

Hello
please how change position of arc menu from bottom to left

thanks

Enhancement! Help in 5 smiley option

I had a requirement where i needed 5 smileys. I tried my best but it's still having issues where the ArcSelector is not working properly. Can you please help me and guide me?

Code is as follows

ArcChooser.dart
`
import 'dart:math';
import 'dart:ui';

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

class ArcChooser extends StatefulWidget {
late ArcSelectedCallback arcSelectedCallback;

@OverRide
State createState() {
return ChooserState(arcSelectedCallback);
}
}

class ChooserState extends State
with SingleTickerProviderStateMixin {
var slideValue = 200;
Offset? centerPoint;

double userAngle = 0.0;

double? startAngle;

static double center = 270.0;
static double centerInRadians = degreeToRadians(center);
static double angle = 45.0;

static double angleInRadians = degreeToRadians(angle);
static double angleInRadiansByTwo = angleInRadians / 2;
static double centerItemAngle = degreeToRadians(center - (angle / 2));
late List arcItems;

late AnimationController animation;
double? animationStart;
double animationEnd = 0.0;

int currentPosition = 0;

Offset? startingPoint;
Offset? endingPoint;

late ArcSelectedCallback arcSelectedCallback;

ChooserState(ArcSelectedCallback arcSelectedCallback) {
this.arcSelectedCallback = arcSelectedCallback;
}

static double degreeToRadians(double degree) {
return degree * (pi / 180);
}

static double radianToDegrees(double radian) {
return radian * (180 / pi);
}

@OverRide
void initState() {
arcItems = List.empty(growable: true);

arcItems.add(ArcItem("OK", [Color(0xFF21e1fa), Color(0xff3bb8fd)],
    angleInRadiansByTwo + userAngle));
arcItems.add(ArcItem("Better", [Color(0xFF2EA44F), Color(0xFF41f7c7)],
    angleInRadiansByTwo + userAngle + (angleInRadians)));
arcItems.add(ArcItem("GOOD", [Color(0xFF3ee98a), Color(0xFF41f7c7)],
    angleInRadiansByTwo + userAngle + (2 * angleInRadians)));
arcItems.add(ArcItem("BADD", [Color(0xFFfe0944), Color(0xFFfeae96)],
    angleInRadiansByTwo + userAngle + (3 * angleInRadians)));
arcItems.add(ArcItem("UGH", [Color(0xFFF9D976), Color(0xfff39f86)],
    angleInRadiansByTwo + userAngle + (4 * angleInRadians)));
arcItems.add(ArcItem("OK", [Color(0xFF21e1fa), Color(0xff3bb8fd)],
    angleInRadiansByTwo + userAngle + (5 * angleInRadians)));
arcItems.add(ArcItem("Better", [Color(0xFF2EA44F), Color(0xFF41f7c7)],
    angleInRadiansByTwo + userAngle + (6 * angleInRadians)));
arcItems.add(ArcItem("GOOD", [Color(0xFF3ee98a), Color(0xFF41f7c7)],
    angleInRadiansByTwo + userAngle + (7 * angleInRadians)));
arcItems.add(ArcItem("BAD2", [Color(0xFFfe0944), Color(0xFFfeae96)],
    angleInRadiansByTwo + userAngle + (8 * angleInRadians)));
arcItems.add(ArcItem("UGH", [Color(0xFFF9D976), Color(0xfff39f86)],
    angleInRadiansByTwo + userAngle + (8 * angleInRadians)));
animation = new AnimationController(
    duration: const Duration(milliseconds: 200), vsync: this);
animation.addListener(() {
  userAngle = lerpDouble(animationStart, animationEnd, animation.value)!;
  setState(() {
    for (int i = 0; i < arcItems.length; i++) {
      arcItems[i].startAngle =
          angleInRadiansByTwo + userAngle + (i * angleInRadians);
    }
  });
});
super.initState();

}

@OverRide
Widget build(BuildContext context) {
double centerX = MediaQuery.of(context).size.width / 2;
double centerY = MediaQuery.of(context).size.height * 1.5;
centerPoint = Offset(centerX, centerY);

return new GestureDetector(

// onTap: () {
// print('ChooserState.build ONTAP');
// animationStart = touchAngle;
// animationEnd = touchAngle + angleInRadians;
// animation.forward(from: 0.0);
// },
onPanStart: (DragStartDetails details) {
startingPoint = details.globalPosition;
var deltaX = centerPoint!.dx - details.globalPosition.dx;
var deltaY = centerPoint!.dy - details.globalPosition.dy;
startAngle = atan2(deltaY, deltaX);
},
onPanUpdate: (DragUpdateDetails details) {
endingPoint = details.globalPosition;
var deltaX = centerPoint!.dx - details.globalPosition.dx;
var deltaY = centerPoint!.dy - details.globalPosition.dy;
var freshAngle = atan2(deltaY, deltaX);
userAngle += freshAngle - startAngle!;
setState(() {
for (int i = 0; i < arcItems.length; i++) {
arcItems[i].startAngle =
angleInRadiansByTwo + userAngle + (i * angleInRadians);
}
});
startAngle = freshAngle;
},
onPanEnd: (DragEndDetails details) {
//find top arc item with Magic!!
bool rightToLeft = startingPoint!.dx < endingPoint!.dx;

// Animate it from this values
animationStart = userAngle;
if (rightToLeft) {
animationEnd += angleInRadians;
currentPosition--;
if (currentPosition < 0) {
currentPosition = arcItems.length - 1;
}
} else {
animationEnd -= angleInRadians;
currentPosition++;
if (currentPosition >= arcItems.length) {
currentPosition = 0;
}
}

    if (arcSelectedCallback != null) {
      arcSelectedCallback(
          currentPosition,
          arcItems[(currentPosition >= (arcItems.length - 1))
              ? 0
              : currentPosition + 1]);
    }

    animation.forward(from: 0.0);
  },
  child: CustomPaint(
    size: Size(MediaQuery.of(context).size.width,
        MediaQuery.of(context).size.width * 1 / 1.5),
    painter: ChooserPainter(arcItems, angleInRadians),
  ),
);

}
}

// draw the arc and other stuff
class ChooserPainter extends CustomPainter {
//debugging Paint
final debugPaint = new Paint()
..color = Colors.red.withAlpha(100) //0xFFF9D976
..strokeWidth = 1.0
..style = PaintingStyle.stroke;

final linePaint = new Paint()
..color = Colors.black.withAlpha(65) //0xFFF9D976
..strokeWidth = 2.0
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.square;

final whitePaint = new Paint()
..color = Colors.white //0xFFF9D976
..strokeWidth = 1.0
..style = PaintingStyle.fill;

late List arcItems;
late double angleInRadians;
late double angleInRadiansByTwo;
late double angleInRadians1;
late double angleInRadians2;
late double angleInRadians3;
late double angleInRadians4;

ChooserPainter(List arcItems, double angleInRadians) {
this.arcItems = arcItems;
this.angleInRadians = angleInRadians;
this.angleInRadiansByTwo = angleInRadians / 2;

angleInRadians1 = angleInRadians / 6;
angleInRadians2 = angleInRadians / 3;
angleInRadians3 = angleInRadians * 4 / 6;
angleInRadians4 = angleInRadians * 5 / 6;

}

@OverRide
void paint(Canvas canvas, Size size) {
//common calc
double centerX = size.width / 2;
double centerY = size.height * 1.6;
Offset center = Offset(centerX, centerY);
double radius = sqrt((size.width * size.width) / 2);

// var mainRect = Rect.fromLTRB(0.0, 0.0, size.width, size.height);
// canvas.drawRect(mainRect, debugPaint);

//for white arc at bottom
double leftX = centerX - radius;
double topY = centerY - radius;
double rightX = centerX + radius;
double bottomY = centerY + radius;

//for items
double radiusItems = radius * 1.5;
double leftX2 = centerX - radiusItems;
double topY2 = centerY - radiusItems;
double rightX2 = centerX + radiusItems;
double bottomY2 = centerY + radiusItems;

//for shadow
double radiusShadow = radius * 1.13;
double leftX3 = centerX - radiusShadow;
double topY3 = centerY - radiusShadow;

double rightX3 = centerX + radiusShadow;
double bottomY3 = centerY + radiusShadow;

double radiusText = radius * 1.30;
double radius4 = radius * 1.12;
double radius5 = radius * 1.06;
var arcRect = Rect.fromLTRB(leftX2, topY2, rightX2, bottomY2);

var dummyRect = Rect.fromLTRB(0.0, 0.0, size.width, size.height);

canvas.clipRect(dummyRect, clipOp: ClipOp.intersect);

for (int i = 0; i < arcItems.length; i++) {
  canvas.drawArc(
      arcRect,
      arcItems[i].startAngle,
      angleInRadians,
      true,
      new Paint()
        ..style = PaintingStyle.fill
        ..shader = new LinearGradient(
          colors: arcItems[i].colors,
        ).createShader(dummyRect));

  //Draw text
  TextSpan span = new TextSpan(
      style: new TextStyle(
          fontWeight: FontWeight.normal,
          fontSize: 32.0,
          color: Colors.white),
      text: arcItems[i].text);
  TextPainter tp = new TextPainter(
    text: span,
    textAlign: TextAlign.center,
    textDirection: TextDirection.ltr,
  );
  tp.layout();

  //find additional angle to make text in center
  double f = tp.width / 2;
  double t = sqrt((radiusText * radiusText) + (f * f));

  double additionalAngle = acos(
      ((t * t) + (radiusText * radiusText) - (f * f)) /
          (2 * t * radiusText));

  double tX = center.dx +
      radiusText *
          cos(arcItems[i].startAngle +
              angleInRadiansByTwo -
              additionalAngle); // - (tp.width/2);
  double tY = center.dy +
      radiusText *
          sin(arcItems[i].startAngle +
              angleInRadiansByTwo -
              additionalAngle); // - (tp.height/2);

  canvas.save();
  canvas.translate(tX, tY);

// canvas.rotate(arcItems[i].startAngle + angleInRadiansByTwo);
canvas.rotate(arcItems[i].startAngle +
angleInRadians +
angleInRadians +
angleInRadiansByTwo);
tp.paint(canvas, new Offset(0.0, 0.0));
canvas.restore();

  //big lines
  canvas.drawLine(
      new Offset(center.dx + radius4 * cos(arcItems[i].startAngle),
          center.dy + radius4 * sin(arcItems[i].startAngle)),
      center,
      linePaint);

  canvas.drawLine(
      new Offset(
          center.dx +
              radius4 * cos(arcItems[i].startAngle + angleInRadiansByTwo),
          center.dy +
              radius4 * sin(arcItems[i].startAngle + angleInRadiansByTwo)),
      center,
      linePaint);

  //small lines
  canvas.drawLine(
      new Offset(
          center.dx +
              radius5 * cos(arcItems[i].startAngle + angleInRadians1),
          center.dy +
              radius5 * sin(arcItems[i].startAngle + angleInRadians1)),
      center,
      linePaint);

  canvas.drawLine(
      new Offset(
          center.dx +
              radius5 * cos(arcItems[i].startAngle + angleInRadians2),
          center.dy +
              radius5 * sin(arcItems[i].startAngle + angleInRadians2)),
      center,
      linePaint);

  canvas.drawLine(
      new Offset(
          center.dx +
              radius5 * cos(arcItems[i].startAngle + angleInRadians3),
          center.dy +
              radius5 * sin(arcItems[i].startAngle + angleInRadians3)),
      center,
      linePaint);

  canvas.drawLine(
      new Offset(
          center.dx +
              radius5 * cos(arcItems[i].startAngle + angleInRadians4),
          center.dy +
              radius5 * sin(arcItems[i].startAngle + angleInRadians4)),
      center,
      linePaint);
}

//shadow
Path shadowPath = new Path();
shadowPath.addArc(
    Rect.fromLTRB(leftX3, topY3, rightX3, bottomY3),
    ChooserState.degreeToRadians(180.0),
    ChooserState.degreeToRadians(180.0));
canvas.drawShadow(shadowPath, Colors.black, 18.0, true);

//bottom white arc
canvas.drawArc(
    Rect.fromLTRB(leftX, topY, rightX, bottomY),
    ChooserState.degreeToRadians(180.0),
    ChooserState.degreeToRadians(180.0),
    true,
    whitePaint);

}

@OverRide
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}

typedef void ArcSelectedCallback(int position, ArcItem arcitem);

class ArcItem {
String text;
List colors;
double startAngle;

ArcItem(this.text, this.colors, this.startAngle);
}
`

smiley.dart
`import 'dart:ui';

import 'package:flutter/material.dart';

class SmilePainter extends CustomPainter {
//debugging Paint
final debugPaint = new Paint()
..color = Colors.grey //0xFFF9D976
..strokeWidth = 1.0
..style = PaintingStyle.stroke;

final whitePaint = new Paint()
..color = Colors.white //0xFFF9D976
..style = PaintingStyle.fill;

int slideValue = 200;

ReviewState? badReview;
ReviewState? ughReview;
ReviewState? okReview;
ReviewState? betterReview;

ReviewState? goodReview;

double? centerCenter;
double? leftCenter;
double? rightCenter;

double? smileHeight;
double? halfWidth;
double? halfHeight;

double? radius;

double? diameter;
double? startingY;
double? startingX;

double? endingX;
double? endingY;

double? oneThirdOfDia;

double? oneThirdOfDiaByTwo;

double? eyeRadius;

double? eyeRadiusbythree;

double? eyeRadiusbytwo;

SmilePainter(int slideValue) : slideValue = slideValue;

Size? lastSize;

ReviewState? currentState;

@OverRide
void paint(Canvas canvas, Size size) {
if (size != lastSize) {
lastSize = size;

  smileHeight = size.width / 2;
  halfWidth = size.width / 2;
  halfHeight = smileHeight! / 2;

  radius = 0.0;
  eyeRadius = 10.0;
  if (smileHeight! < size.width) {
    radius = halfHeight! - 16.0;
  } else {
    radius = halfWidth! - 16.0;
  }
  eyeRadius = radius! / 6.5;
  eyeRadiusbythree = eyeRadius! / 3;
  eyeRadiusbytwo = eyeRadius! / 2;

  diameter = radius! * 2;
  //left top corner
  startingX = halfWidth! - radius!;
  startingY = halfHeight! - radius!;

  oneThirdOfDia = (diameter! / 3);
  oneThirdOfDiaByTwo = oneThirdOfDia! / 2;

  //bottom right corner
  endingX = halfWidth! + radius!;
  endingY = halfHeight! + radius!;

  final leftSmileX = startingX! + (radius! / 2);

  badReview = ReviewState(
      Offset(leftSmileX, endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Offset(startingX! + oneThirdOfDia!,
          startingY! + radius! + (oneThirdOfDiaByTwo)!),
      Offset(
          endingX! - radius!, startingY! + radius! + (oneThirdOfDiaByTwo)!),
      Offset(
          endingX! - radius!, startingY! + radius! + (oneThirdOfDiaByTwo)!),
      Offset(endingX! - oneThirdOfDia!,
          startingY! + radius! + (oneThirdOfDiaByTwo)!),
      Offset(
          endingX! - (radius! / 2), endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Color(0xFFfe0944),
      Color(0xFFfeae96),
      Color(0xFFfe5c6e),
      'BAD');

  ughReview = ReviewState(
      Offset(leftSmileX, endingY! - (radius! / 2)),
      Offset(diameter!, endingY! - oneThirdOfDia!),
      Offset(endingX! - radius!, endingY! - oneThirdOfDia!),
      Offset(endingX! - radius!, endingY! - oneThirdOfDia!), //New
      Offset(endingX! - (radius! / 2), endingY! - oneThirdOfDia!),
      Offset(endingX! - (radius! / 2), endingY! - oneThirdOfDia!),
      Color(0xFFF9D976),
      Color(0xfff39f86),
      Color(0xFFf6bc7e),
      'UGH');

  okReview = ReviewState(
      Offset(leftSmileX, endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Offset(diameter!, endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Offset(endingX! - radius!, endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Offset(endingX! - radius!, endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Offset(startingX! + radius!, endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Offset(
          endingX! - (radius! / 2), endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Color(0xFF21e1fa),
      Color(0xff3bb8fd),
      Color(0xFF28cdfc),
      'OK');
  betterReview = ReviewState(
      Offset(leftSmileX, endingY! - (oneThirdOfDiaByTwo! * 1.75)),
      Offset(diameter!, endingY! - (oneThirdOfDiaByTwo! * 1.75)),
      Offset(endingX! - radius!, endingY! - (oneThirdOfDiaByTwo! * 1.75)),
      Offset(endingX! - radius!, endingY! - (oneThirdOfDiaByTwo! * 1.75)),
      Offset(startingX! + radius!, endingY! - (oneThirdOfDiaByTwo! * 1.75)),
      Offset(endingX! - (radius! / 2),
          endingY! - (oneThirdOfDiaByTwo! * 1.75)),
      Color(0xFF21e1fa),
      Color(0xff3bb8fd),
      Color(0xFF28cdfc),
      'Better');
  goodReview = ReviewState(
      Offset(
          startingX! + (radius! / 2), endingY! - (oneThirdOfDiaByTwo! * 2)),
      Offset(startingX! + oneThirdOfDia!,
          startingY! + (diameter! - oneThirdOfDiaByTwo!)),
      Offset(endingX! - radius!,
          startingY! + (diameter! - oneThirdOfDiaByTwo!)),
      Offset(endingX! - radius!,
          startingY! + (diameter! - oneThirdOfDiaByTwo!)),
      Offset(endingX! - oneThirdOfDia!,
          startingY! + (diameter! - oneThirdOfDiaByTwo!)),
      Offset(
          endingX! - (radius! / 2), endingY! - (oneThirdOfDiaByTwo! * 2)),
      Color(0xFF3ee98a),
      Color(0xFF41f7c7),
      Color(0xFF41f7c6),
      'GOOD');

  //get max width of text, that is width of GOOD text
  TextSpan spanGood = new TextSpan(
      style: new TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 52.0,
          color: okReview!.titleColor),
      text: "GOOD");
  TextPainter tpGood =
      new TextPainter(text: spanGood, textDirection: TextDirection.ltr);
  tpGood.layout();
  double goodWidth = tpGood.width;
  double halfGoodWidth = goodWidth / 2;

  //center points of BIG labels
  centerCenter = halfWidth;
  leftCenter = centerCenter! - goodWidth;
  rightCenter = centerCenter! + goodWidth;
}

if (slideValue <= 100) {
  tweenText(badReview!, ughReview!, slideValue / 100, canvas);
} else if (slideValue <= 200) {
  tweenText(ughReview!, okReview!, (slideValue - 100) / 100, canvas);
} else if (slideValue <= 300) {
  tweenText(okReview!, betterReview!, (slideValue - 200) / 100, canvas);
} else if (slideValue <= 400) {
  tweenText(betterReview!, goodReview!, (slideValue - 300) / 100, canvas);
} else if (slideValue <= 500) {
  tweenText(goodReview!, badReview!, (slideValue - 400) / 100, canvas);
}

//draw the outer circle------------------------------------------

final centerPoint = Offset(halfWidth!, halfHeight!);
final circlePaint = genGradientPaint(
  new Rect.fromCircle(
    center: centerPoint,
    radius: radius!,
  ),
  currentState!.startColor,
  currentState!.endColor,
  PaintingStyle.stroke,
)..strokeCap = StrokeCap.round;

canvas.drawCircle(centerPoint, radius!, circlePaint);
//---------------------------------------------------------------

//draw smile curve with path ------------------------------------------
canvas.drawPath(getSmilePath(currentState!), circlePaint);

//---------------------------------------------------------------

//draw eyes---------------------------------------------------
//ele calc
final leftEyeX = startingX! + oneThirdOfDia!;
final eyeY = startingY! + (oneThirdOfDia! + oneThirdOfDiaByTwo! / 4);
final rightEyeX = startingX! + (oneThirdOfDia! * 2);

final leftEyePoint = Offset(leftEyeX, eyeY);
final rightEyePoint = Offset(rightEyeX, eyeY);

final Paint leftEyePaintFill = genGradientPaint(
  new Rect.fromCircle(center: leftEyePoint, radius: eyeRadius!),
  currentState!.startColor,
  currentState!.endColor,
  PaintingStyle.fill,
);

final Paint rightEyePaintFill = genGradientPaint(
  new Rect.fromCircle(center: rightEyePoint, radius: eyeRadius!),
  currentState!.startColor,
  currentState!.endColor,
  PaintingStyle.fill,
);

canvas.drawCircle(leftEyePoint, eyeRadius!, leftEyePaintFill);
canvas.drawCircle(rightEyePoint, eyeRadius!, rightEyePaintFill);

//draw the edges of BAD Review
if (slideValue <= 100 || slideValue > 300) {
  double diff = -1.0;
  double tween = -1.0;

  if (slideValue <= 100) {
    diff = slideValue / 100;
    tween = lerpDouble(
        eyeY - (eyeRadiusbythree! * 0.6), eyeY - eyeRadius!, diff)!;
  } else if (slideValue > 300) {
    diff = (slideValue - 300) / 100;
    tween = lerpDouble(
        eyeY - eyeRadius!, eyeY - (eyeRadiusbythree! * 0.6), diff)!;
  }

  List<Offset> polygonPath = List<Offset>.empty(growable: true);
  polygonPath.add(Offset(leftEyeX - eyeRadiusbytwo!, eyeY - eyeRadius!));
  polygonPath.add(Offset(leftEyeX + eyeRadius!, tween));
  polygonPath.add(Offset(leftEyeX + eyeRadius!, eyeY - eyeRadius!));

  Path clipPath = new Path();
  clipPath.addPolygon(polygonPath, true);

  canvas.drawPath(clipPath, whitePaint);

  List<Offset> polygonPath2 = List<Offset>.empty(growable: true);
  polygonPath2.add(Offset(rightEyeX + eyeRadiusbytwo!, eyeY - eyeRadius!));
  polygonPath2.add(Offset(rightEyeX - eyeRadius!, tween));
  polygonPath2.add(Offset(rightEyeX - eyeRadius!, eyeY - eyeRadius!));

  Path clipPath2 = new Path();
  clipPath2.addPolygon(polygonPath2, true);

  canvas.drawPath(clipPath2, whitePaint);
}

//draw the balls of UGH Review
if (slideValue > 0 && slideValue < 200) {
  double diff = -1.0;
  double leftTweenX = -1.0;
  double leftTweenY = -1.0;

  double rightTweenX = -1.0;
  double rightTweenY = -1.0;

  if (slideValue <= 100) {

// bad to ugh
diff = slideValue / 100;
leftTweenX = lerpDouble(leftEyeX - eyeRadius!, leftEyeX, diff)!;
leftTweenY = lerpDouble(eyeY - eyeRadius!, eyeY, diff)!;

    rightTweenX = lerpDouble(rightEyeX + eyeRadius!, rightEyeX, diff)!;
    rightTweenY =
        lerpDouble(eyeY, eyeY - (eyeRadius! + eyeRadiusbythree!), diff)!;
  } else {

// ugh to ok
diff = (slideValue - 100) / 100;

    leftTweenX = lerpDouble(leftEyeX, leftEyeX - eyeRadius!, diff)!;
    leftTweenY = lerpDouble(eyeY, eyeY - eyeRadius!, diff)!;

    rightTweenX = lerpDouble(rightEyeX, rightEyeX + eyeRadius!, diff)!;
    rightTweenY =
        lerpDouble(eyeY - (eyeRadius! + eyeRadiusbythree!), eyeY, diff)!;
  }

  canvas.drawOval(
      Rect.fromLTRB(leftEyeX - (eyeRadius! + eyeRadiusbythree!),
          eyeY - (eyeRadius! + eyeRadiusbythree!), leftTweenX, leftTweenY),
      whitePaint);

  canvas.drawOval(
      Rect.fromLTRB(
          rightTweenX,
          eyeY,
          rightEyeX + (eyeRadius! + eyeRadiusbythree!),
          eyeY - (eyeRadius! + eyeRadiusbythree!)),
      whitePaint);
}

//---------------------------------------------------------------

//drawing stuff for debugging-----------------------------------

// canvas.drawRect(
// Rect.fromLTRB(0.0, 0.0, size.width, smileHeight), debugPaint);
// canvas.drawRect(
// Rect.fromLTRB(startingX, startingY, endingX, endingY), debugPaint);
//
// canvas.drawLine(
// Offset(startingX, startingY), Offset(endingX, endingY), debugPaint);
// canvas.drawLine(
// Offset(endingX, startingY), Offset(startingX, endingY), debugPaint);
// canvas.drawLine(Offset(startingX + radius, startingY),
// Offset(startingX + radius, endingY), debugPaint);
// canvas.drawLine(Offset(startingX, startingY + radius),
// Offset(endingX, startingY + radius), debugPaint);
//
// //horizontal lines
// canvas.drawLine(Offset(startingX, startingY + oneThirdOfDia),
// Offset(endingX, startingY + oneThirdOfDia), debugPaint);
// canvas.drawLine(Offset(startingX, endingY - oneThirdOfDia),
// Offset(endingX, endingY - oneThirdOfDia), debugPaint);
// canvas.drawLine(Offset(startingX, endingY - oneThirdOfDiaByTwo),
// Offset(endingX, endingY - oneThirdOfDiaByTwo), debugPaint);
//
// //vertical lines
// canvas.drawLine(Offset(startingX + oneThirdOfDiaByTwo, startingY),
// Offset(startingX + oneThirdOfDiaByTwo, endingY), debugPaint);
// canvas.drawLine(Offset(startingX + oneThirdOfDia, startingY),
// Offset(startingX + oneThirdOfDia, endingY), debugPaint);
// canvas.drawLine(Offset(endingX - oneThirdOfDia, startingY),
// Offset(endingX - oneThirdOfDia, endingY), debugPaint);
// canvas.drawLine(Offset(endingX - oneThirdOfDiaByTwo, startingY),
// Offset(endingX - oneThirdOfDiaByTwo, endingY), debugPaint);
//--------------------------------------------------------------
}

tweenText(ReviewState centerReview, ReviewState rightReview, double diff,
Canvas canvas) {
currentState = ReviewState.lerp(centerReview, rightReview, diff);

TextSpan spanCenter = new TextSpan(
    style: new TextStyle(
        fontWeight: FontWeight.bold,
        fontSize: 52.0,
        color:
            centerReview.titleColor.withAlpha(255 - (255 * diff).round())),
    text: centerReview.title);
TextPainter tpCenter =
    new TextPainter(text: spanCenter, textDirection: TextDirection.ltr);

TextSpan spanRight = new TextSpan(
    style: new TextStyle(
        fontWeight: FontWeight.bold,
        fontSize: 52.0,
        color: rightReview.titleColor.withAlpha((255 * diff).round())),
    text: rightReview.title);
TextPainter tpRight =
    new TextPainter(text: spanRight, textDirection: TextDirection.ltr);

tpCenter.layout();
tpRight.layout();

Offset centerOffset =
    new Offset(centerCenter! - (tpCenter.width / 2), smileHeight!);
Offset centerToLeftOffset =
    new Offset(leftCenter! - (tpCenter.width / 2), smileHeight!);

Offset rightOffset =
    new Offset(rightCenter! - (tpRight.width / 2), smileHeight!);
Offset rightToCenterOffset =
    new Offset(centerCenter! - (tpRight.width / 2), smileHeight!);

tpCenter.paint(
    canvas, Offset.lerp(centerOffset, centerToLeftOffset, diff)!);
tpRight.paint(canvas, Offset.lerp(rightOffset, rightToCenterOffset, diff)!);

}

Path getSmilePath(ReviewState state) {
var smilePath = Path();
smilePath.moveTo(state.leftOffset.dx, state.leftOffset.dy);
smilePath.quadraticBezierTo(state.leftHandle.dx, state.leftHandle.dy,
state.centerOffset.dx, state.centerOffset.dy);
smilePath.quadraticBezierTo(state.rightHandle.dx, state.rightHandle.dy,
state.rightOffset.dx, state.rightOffset.dy);
return smilePath;
}

Paint genGradientPaint(
Rect rect, Color startColor, Color endColor, PaintingStyle style) {
final Gradient gradient = new LinearGradient(
colors: [
startColor,
endColor,
],
);

return new Paint()
  ..strokeWidth = 10.0
  ..style = style
  ..shader = gradient.createShader(rect);

}

@OverRide
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}

class ReviewState {
//smile points
Offset leftOffset;
Offset centerOffset;
Offset centerset;

Offset rightOffset;
Offset leftHandle;
Offset rightHandle;

String title;
Color titleColor;

Color startColor;
Color endColor;

ReviewState(
this.leftOffset,
this.leftHandle,
this.centerOffset,
this.centerset,
this.rightHandle,
this.rightOffset,
this.startColor,
this.endColor,
this.titleColor,
this.title);

//create new state between given two states.
static ReviewState lerp(ReviewState start, ReviewState end, double ratio) {
var startColor = Color.lerp(start.startColor, end.startColor, ratio);
var endColor = Color.lerp(start.endColor, end.endColor, ratio);

return ReviewState(
    Offset.lerp(start.leftOffset, end.leftOffset, ratio)!,
    Offset.lerp(start.leftHandle, end.leftHandle, ratio)!,
    Offset.lerp(start.centerOffset, end.centerOffset, ratio)!,
    Offset.lerp(start.centerset, end.centerset, ratio)!,
    Offset.lerp(start.rightHandle, end.rightHandle, ratio)!,
    Offset.lerp(start.rightOffset, end.rightOffset, ratio)!,
    startColor!,
    endColor!,
    start.titleColor,
    start.title);

}
}
`

Assestment.dart
`import 'package:flutter/material.dart';
import 'package:relaxa/components/ArcChooser.dart';
import 'package:relaxa/components/smiley.dart';

class MyAssestmenetPage extends StatefulWidget {
final List question;
final int index;
MyAssestmenetPage({Key? key, required this.question, required this.index})
: super(key: key);

@OverRide
_MyAssestmenetPageState createState() => new _MyAssestmenetPageState();
}

class _MyAssestmenetPageState extends State
with TickerProviderStateMixin {
final PageController pageControl = new PageController(
initialPage: 2,
keepPage: false,
viewportFraction: 0.2,
);

int slideValue = 200;
int lastAnimPosition = 2;

AnimationController? animation;

List arcItems = List.empty(growable: true);

late ArcItem badArcItem;
late ArcItem ughArcItem;
late ArcItem okArcItem;
late ArcItem betterArcItem;

late ArcItem goodArcItem;

late Color startColor;
late Color endColor;
bool lastIndex = false;
@OverRide
void initState() {
super.initState();
print(widget.index);
print(widget.question.length);
if (widget.question.length == widget.index + 1) {
setState(() {
lastIndex = true;
});
}
print(lastIndex);
badArcItem =
ArcItem("Most Days", [Color(0xFFfe0944), Color(0xFFfeae96)], 0.0);
ughArcItem =
ArcItem("Sometimes", [Color(0xFFF9D976), Color(0xfff39f86)], 0.0);
okArcItem =
ArcItem("Not Sure", [Color(0xFF21e1fa), Color(0xff3bb8fd)], 0.0);
betterArcItem =
ArcItem("Not Exactly", [Color(0xFF21e1fa), Color(0xff3bb8fd)], 0.0);
goodArcItem = ArcItem("Never", [Color(0xFF3ee98a), Color(0xFF41f7c7)], 0.0);

arcItems.add(badArcItem);
arcItems.add(ughArcItem);
arcItems.add(okArcItem);
arcItems.add(betterArcItem);

arcItems.add(goodArcItem);

startColor = Color(0xFF21e1fa);
endColor = Color(0xff3bb8fd);

animation = new AnimationController(
  value: 0.0,
  lowerBound: 0.0,
  upperBound: 500.0,
  duration: const Duration(milliseconds: 800),
  vsync: this,
)..addListener(() {
    setState(() {
      slideValue = animation!.value.toInt();

      double ratio;

      if (slideValue <= 100) {
        ratio = animation!.value / 100;
        startColor =
            Color.lerp(badArcItem.colors[0], ughArcItem.colors[0], ratio)!;
        endColor =
            Color.lerp(badArcItem.colors[1], ughArcItem.colors[1], ratio)!;
      } else if (slideValue <= 200) {
        ratio = (animation!.value - 100) / 100;
        startColor =
            Color.lerp(ughArcItem.colors[0], okArcItem.colors[0], ratio)!;
        endColor =
            Color.lerp(ughArcItem.colors[1], okArcItem.colors[1], ratio)!;
      } else if (slideValue <= 300) {
        ratio = (animation!.value - 200) / 100;
        startColor = Color.lerp(
            okArcItem.colors[0], betterArcItem.colors[0], ratio)!;
        endColor = Color.lerp(
            okArcItem.colors[1], betterArcItem.colors[1], ratio)!;
      } else if (slideValue <= 400) {
        ratio = (animation!.value - 300) / 100;
        startColor = Color.lerp(
            betterArcItem.colors[0], goodArcItem.colors[0], ratio)!;
        endColor = Color.lerp(
            betterArcItem.colors[1], goodArcItem.colors[1], ratio)!;
      } else if (slideValue <= 500) {
        ratio = (animation!.value - 300) / 100;
        startColor =
            Color.lerp(goodArcItem.colors[0], badArcItem.colors[0], ratio)!;
        endColor =
            Color.lerp(goodArcItem.colors[1], badArcItem.colors[1], ratio)!;
      }
    });
  });

animation!.animateTo(slideValue.toDouble());

}

@OverRide
Widget build(BuildContext context) {
var textStyle = new TextStyle(
color: Colors.white, fontSize: 24.00, fontWeight: FontWeight.bold);

return Container(
  color: Colors.white,
  margin: MediaQuery.of(context).padding,
  child: SingleChildScrollView(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: <Widget>[
        Center(
          child: Padding(
            padding: const EdgeInsets.all(26.0),
            child: Text(
              widget.question[widget.index],
              textAlign: TextAlign.center,
              style: Theme.of(context).textTheme.headline5,
            ),
          ),
        ),
        SizedBox(
          height: 60,
        ),
        CustomPaint(
          size: Size(MediaQuery.of(context).size.width,
              (MediaQuery.of(context).size.width / 2) + 60),
          painter: SmilePainter(slideValue),
        ),

// Slider(
// min: 0.0,
// max: 400.0,
// value: slideValue.toDouble(),
// onChanged: (double newValue) {
// setState(() {
// slideValue = newValue.round();
// });
// },
// ),

// new SizedBox(
// height: 50.0,
// child: new NotificationListener(
// onNotification: (ScrollNotification notification){
// if(!notification.metrics.atEdge){
// print('_MyReviewPageState.build ' + MediaQuery.of(context).size.width.toString() + " " + notification.metrics.pixels.toString());
// }
//
// },
// child: PageView.builder(
// pageSnapping: true,
// onPageChanged: (int value) {
// print('_MyReviewPageState._onPageChanged ' + value.toString());
// animation.animateTo(value*100.0);
// },
// controller: pageControl,
// itemCount: arcItems.length,
// physics: new AlwaysScrollableScrollPhysics(),
// itemBuilder: (context, index) {
// return new Container(
// decoration: new BoxDecoration(
// gradient: new LinearGradient(
// colors: [
// arcItems[index].colors[0],
// arcItems[index].colors[1]
// ]
// ),
// ),
// alignment: Alignment.center,
// child: new Text(
// arcItems[index].text,
// style: textStyle,
// ));
// },
// ),
// ),
// ),
Stack(
alignment: AlignmentDirectional.bottomCenter,
children: [
ArcChooser()
..arcSelectedCallback = (int pos, ArcItem item) {
int animPosition = pos - 2;
if (animPosition > 4) {
animPosition = animPosition - 5;
}

                  if (animPosition < 0) {
                    animPosition = 5 + animPosition;
                  }

                  if (lastAnimPosition == 4 && animPosition == 0) {
                    animation!.animateTo(5 * 100.0);
                  } else if (lastAnimPosition == 0 && animPosition == 4) {
                    animation!.forward(from: 5 * 100.0);
                    animation!.animateTo(animPosition * 100.0);
                  } else if (lastAnimPosition == 0 && animPosition == 3) {
                    animation!.forward(from: 5 * 100.0);
                    animation!.animateTo(animPosition * 100.0);
                  } else if (lastAnimPosition == 0 && animPosition == 1) {
                    animation!.forward(from: 0.0);
                    animation!.animateTo(animPosition * 100.0);
                  } else {
                    animation!.animateTo(animPosition * 100.0);
                  }

                  lastAnimPosition = animPosition;
                },
              Padding(
                padding: const EdgeInsets.all(28.0),
                child: lastIndex
                    ? MaterialButton(
                        onPressed: () => {},
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(25.0)),
                        elevation: 8.0,
                        child: Container(
                            width: 150.0,
                            height: 50.0,
                            decoration: BoxDecoration(
                              gradient: LinearGradient(
                                  colors: [startColor, endColor]),
                            ),
                            alignment: Alignment.center,
                            child: Text(
                              'SUBMIT',
                              style: textStyle,
                            )),
                      )
                    : MaterialButton(
                        onPressed: () => Navigator.of(context).push(
                          MaterialPageRoute(
                              builder: (_) => MyAssestmenetPage(
                                    question: widget.question,
                                    index: widget.index + 1,
                                  )),
                        ),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(25.0)),
                        elevation: 8.0,
                        child: Container(
                            width: 150.0,
                            height: 50.0,
                            decoration: BoxDecoration(
                              gradient: LinearGradient(
                                  colors: [startColor, endColor]),
                            ),
                            alignment: Alignment.center,
                            child: Text(
                              'Next',
                              style: textStyle,
                            )),
                      ),

// child: RaisedButton(
// shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16.0)),
// child: Text('SUBMIT'),
// onPressed: () {
// print('cool');
// },
// ),
)
]),
],
),
),
);
}
}
`

Note that this code is in Null Safety.
image
image
Initially the Ugh is not visible within first round in the list. Help

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.