createTutorialOverlay function
void
createTutorialOverlay({
- required String tagName,
- required BuildContext context,
- Function? onTap,
- Color? bgColor,
- Widget? description,
- bool enableHolesAnimation = true,
- bool enableAnimationRepeat = true,
- double defaultPadding = 4,
- List<
WidgetData> widgetsData = const [], - int highlightCount = 3,
- int animationMilliseconds = 150,
- int animationRepeatDelayMilliseconds = 3000,
- bool isOverlayBgTransparent = false,
Implementation
void createTutorialOverlay({
required String tagName,
required BuildContext context,
Function? onTap,
Color? bgColor,
Widget? description,
bool enableHolesAnimation = true,
bool enableAnimationRepeat = true,
double defaultPadding = 4,
List<WidgetData> widgetsData = const [],
int highlightCount = 3,
int animationMilliseconds = 150,
int animationRepeatDelayMilliseconds = 3000,
bool isOverlayBgTransparent = false,
}) {
final String generatedUUID = Uuid().v4();
_printIfDebug('createTutorialOverlay', "starteed for tag $tagName");
if (_visibleOverlayPage != null && _visibleOverlayPage!.tagName == tagName) {
// removes shown overlay if it's beiong rewritten
hideOverlayEntryIfExists();
}
int enabledVisibleWidgetsCount = 0;
int disabledVisibleWidgetsCount = 0;
List<GlobalKey> widgetsGlobalKeys = [];
widgetsData.forEach((WidgetData data) {
widgetsGlobalKeys.add(data.key);
if (data.isEnabled) {
enabledVisibleWidgetsCount++;
} else {
disabledVisibleWidgetsCount++;
}
});
AnimationController? animationController;
late CurvedAnimation animation;
if (!isOverlayBgTransparent && enableHolesAnimation) {
animationController = AnimationController(
vsync: Overlay.of(context)!,
duration: Duration(milliseconds: animationMilliseconds));
animation = CurvedAnimation(
parent: animationController,
curve: Curves.easeInOut,
reverseCurve: Curves.easeInOut);
int animCount = 0;
bool inTheMiddleOfFuture = false;
animationController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
if (animCount < highlightCount) {
animationController!.reverse();
animCount++;
}
} else if (status == AnimationStatus.dismissed) {
if (animCount < highlightCount) {
animationController!.forward();
} else {
animCount = 0;
if (_visibleOverlayPage?.uuid == generatedUUID &&
enableAnimationRepeat) {
if (!inTheMiddleOfFuture) {
inTheMiddleOfFuture = true;
Future.delayed(
Duration(milliseconds: animationRepeatDelayMilliseconds))
.then((d) {
if (_visibleOverlayPage?.uuid == generatedUUID) {
animationController!.forward();
inTheMiddleOfFuture = false;
}
});
}
}
}
}
});
}
_overlays[tagName] = OverlayData(
isOverlayBgTransparent: isOverlayBgTransparent,
uuid: generatedUUID,
context: context,
animationController: animationController!,
widgetsGlobalKeys: widgetsGlobalKeys,
enabledVisibleWidgetsCount: enabledVisibleWidgetsCount,
disabledVisibleWidgetsCount: disabledVisibleWidgetsCount,
tagName: tagName,
showOverlay: () {
animationController?.reset();
animationController?.forward();
},
hideOverlay: () {
animationController?.reset();
},
entry: OverlayEntry(
builder: (BuildContext context) => FutureBuilder(
future: waitForFrameToEnd(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (isOverlayBgTransparent) {
return description!;
} else {
return GestureDetector(
onTap: onTap as void Function()?,
child: ClipPath(
clipper: InvertedClipper(
padding: defaultPadding,
animation: animation,
reclip: animationController,
widgetsData: widgetsData),
child: CustomPaint(
child: Container(
child: description,
),
painter: OverlayPainter(
padding: defaultPadding,
animation: animation,
bgColor: bgColor,
context: context,
widgetsData: widgetsData,
),
),
),
);
}
},
),
),
);
}