{"id":17320624,"url":"https://github.com/rafaelbarbosatec/tutorial_coach_mark","last_synced_at":"2025-05-14T17:07:58.744Z","repository":{"id":34836126,"uuid":"183692838","full_name":"RafaelBarbosatec/tutorial_coach_mark","owner":"RafaelBarbosatec","description":"TutorialCoachMark","archived":false,"fork":false,"pushed_at":"2025-04-24T02:52:43.000Z","size":6516,"stargazers_count":570,"open_issues_count":52,"forks_count":219,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-14T17:07:27.280Z","etag":null,"topics":["dart","flutter","flutter-package","tutorial"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RafaelBarbosatec.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-04-26T20:53:30.000Z","updated_at":"2025-05-12T17:52:49.000Z","dependencies_parsed_at":"2023-10-11T16:44:53.267Z","dependency_job_id":"812eb33d-212b-4df0-8dc2-5ec65d8e2e40","html_url":"https://github.com/RafaelBarbosatec/tutorial_coach_mark","commit_stats":{"total_commits":172,"total_committers":28,"mean_commits":6.142857142857143,"dds":0.4883720930232558,"last_synced_commit":"ba344d1bdc28640f96607dfdea6b0814ed7eab18"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RafaelBarbosatec%2Ftutorial_coach_mark","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RafaelBarbosatec%2Ftutorial_coach_mark/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RafaelBarbosatec%2Ftutorial_coach_mark/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RafaelBarbosatec%2Ftutorial_coach_mark/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RafaelBarbosatec","download_url":"https://codeload.github.com/RafaelBarbosatec/tutorial_coach_mark/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254190396,"owners_count":22029632,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dart","flutter","flutter-package","tutorial"],"created_at":"2024-10-15T13:32:56.987Z","updated_at":"2025-05-14T17:07:58.724Z","avatar_url":"https://github.com/RafaelBarbosatec.png","language":"Dart","readme":"[![pub package](https://img.shields.io/pub/v/tutorial_coach_mark.svg)](https://pub.dartlang.org/packages/tutorial_coach_mark)\n[![buymeacoffee](https://i.imgur.com/aV6DDA7.png)](https://www.buymeacoffee.com/rafaelbarbosa)\n\n# TutorialCoachMark\n\nCreate a beautiful and easy tutorial for your application.\n\nExample 1             |  Example 2\n:-------------------------:|:-------------------------:\n![](https://raw.githubusercontent.com/RafaelBarbosatec/tutorial_coach_mark/master/img/exampleTutorialCoachMark.gif)  |  ![](https://raw.githubusercontent.com/RafaelBarbosatec/tutorial_coach_mark/master/img/example_boleiro.gif)\n\n# Usage\nTo use this plugin, add `tutorial_coach_mark` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/).\n\n### Example\n\n``` dart\nimport 'package:flutter/material.dart';\nimport 'package:tutorial_coach_mark/tutorial_coach_mark.dart';\n\nvoid showTutorial() {\n    TutorialCoachMark tutorial = TutorialCoachMark(\n      targets: targets, // List\u003cTargetFocus\u003e\n      colorShadow: Colors.red, // DEFAULT Colors.black\n       // opacityShadow = 0.8,\n       // alignSkip: Alignment.bottomRight,\n       // textSkip: \"SKIP\",\n       // textStyleSkip: const TextStyle(color: Colors.white),\n       // skipWidget: MyWidget(),\n       // hideSkip: false\n       // showSkipInLastTarget: true,\n       // paddingFocus: 10,\n       // focusAnimationDuration: Duration(milliseconds: 500),\n       // unFocusAnimationDuration: Duration(milliseconds: 500),\n       // pulseAnimationDuration: Duration(milliseconds: 500),\n       // pulseVariation: Tween(begin: 1.0, end: 0.99),\n       // pulseEnable: true,\n       // imageFilter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),\n       // initialFocus: 0,\n       // useSafeArea: true,\n       // finish: (){},\n       // clickTarget: (TargetFocus) {},\n       // onClickTargetWithTapPosition: (TargetFocus, TapDownDetails) {},\n       // clickOverlay: (TargetFocus) {},\n      onFinish: (){\n        print(\"finish\");\n      },\n      onClickTargetWithTapPosition: (target, tapDetails) {\n        print(\"target: $target\");\n        print(\"clicked at position local: ${tapDetails.localPosition} - global: ${tapDetails.globalPosition}\");\n      },\n      onClickTarget: (target){\n        print(target);\n      },\n      onSkip: (){\n        print(\"skip\");\n        return true;\n      }\n    )..show(context:context);\n\n    // tutorial.skip();\n    // tutorial.finish();\n    // tutorial.next(); // call next target programmatically\n    // tutorial.previous(); // call previous target programmatically\n    // tutorial.goTo(3); // call target programmatically by index\n  }\n```\n\n### Creating targets (TargetFocus)\n\nTargetFocus is the class that represents the widget that will be focused and configure what will be displayed after you focus it.\n\nAttributes:\n\n| Attribute | Type | Description |\n| --- | --- | --- |\n| `identify` | dynamic | free for identification use |\n| `keyTarget` | GlobalKey | GlobalKey widget that wants to be focused |\n| `targetPosition` | TargetPosition | If you do not want to use GlobalKey, you can create a TargetPosition to determine where to focus |\n| `contents` | ContentTarget[] | Content list you want to display after focusing widget |\n| `shape` | ShapeLightFocus | ShapeLightFocus.Circle or ShapeLightFocus.RRect |\n| `radius` | double | Use when shape = ShapeLightFocus.RRect |\n| `borderSide` | BorderSide |  |\n| `color` | Color | Custom color to target |\n| `enableOverlayTab` | bool | enable click in all screen to call next step |\n| `enableTargetTab` | bool | enable click in target to call next step |\n| `alignSkip` | Alignment | use to align the skip in the target |\n| `paddingFocus` | Alignment | settings padding of the focus in target |\n| `focusAnimationDuration` | Duration | override the widget's global focus animation duration |\n| `unFocusAnimationDuration` | Duration | override the widget's global unfocus animation duration |\n| `pulseVariation` | Tween | override interval pulse animation |\n\n### Creating contents (ContentTarget)\n\nContentTarget is the class responsible for determining what should be displayed and how it will appear after focusing on the widget.\n\nAttributes:\n\n| Attribute | Type | Description |\n| --- | --- | --- |\n| `align` | AlignContent | With this attribute you determine in which region to display the content in relation to the focused widget (top,bottom,left,right) |\n| `padding` | EdgeInsets | Padding of the content |\n| `child` | Widget | Content you want to be displayed |\n| `builder` | Widget | Content you want to be displayed |\n| `customPosition` | CustomTargetContentPosition | Add custom position when `align` is AlignContent.custom |\n\n### Example Complete\n\n``` dart\nimport 'package:flutter/material.dart';\nimport 'package:tutorial_coach_mark/tutorial_coach_mark.dart';\n\nList\u003cTargetFocus\u003e targets = List();\n\n @override\n void initState() {\n    targets.add(\n        TargetFocus(\n            identify: \"Target 1\",\n            keyTarget: keyButton,\n            contents: [\n              TargetContent(\n                  align: ContentAlign.bottom,\n                  child: Container(\n                    child:Column(\n                      mainAxisSize: MainAxisSize.min,\n                      crossAxisAlignment: CrossAxisAlignment.start,\n                      children: \u003cWidget\u003e[\n                        Text(\n                          \"Titulo lorem ipsum\",\n                          style: TextStyle(\n                            fontWeight: FontWeight.bold,\n                            color: Colors.white,\n                            fontSize: 20.0\n                          ),\n                        ),\n                        Padding(\n                          padding: const EdgeInsets.only(top: 10.0),\n                          child: Text(\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin pulvinar tortor eget maximus iaculis.\",\n                            style: TextStyle(\n                                color: Colors.white\n                            ),),\n                        )\n                      ],\n                    ),\n                  )\n              )\n            ]\n        )\n    );\n\n    targets.add(\n        TargetFocus(\n            identify: \"Target 2\",\n            keyTarget: keyButton4,\n            contents: [\n              TargetContent(\n                  align: ContentAlign.left,\n                  child: Container(\n                    child: Column(\n                      mainAxisSize: MainAxisSize.min,\n                      crossAxisAlignment: CrossAxisAlignment.start,\n                      children: \u003cWidget\u003e[\n                        Text(\n                          \"Multiples content\",\n                          style: TextStyle(\n                              fontWeight: FontWeight.bold,\n                              color: Colors.white,\n                              fontSize: 20.0\n                          ),\n                        ),\n                        Padding(\n                          padding: const EdgeInsets.only(top: 10.0),\n                          child: Text(\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin pulvinar tortor eget maximus iaculis.\",\n                            style: TextStyle(\n                                color: Colors.white\n                            ),),\n                        )\n                      ],\n                    ),\n                  )\n              ),\n              TargetContent(\n                  align: ContentAlign.top,\n                  child: Container(\n                    child: Column(\n                      mainAxisSize: MainAxisSize.min,\n                      crossAxisAlignment: CrossAxisAlignment.start,\n                      children: \u003cWidget\u003e[\n                        Text(\n                          \"Multiples content\",\n                          style: TextStyle(\n                              fontWeight: FontWeight.bold,\n                              color: Colors.white,\n                              fontSize: 20.0\n                          ),\n                        ),\n                        Padding(\n                          padding: const EdgeInsets.only(top: 10.0),\n                          child: Text(\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin pulvinar tortor eget maximus iaculis.\",\n                            style: TextStyle(\n                                color: Colors.white\n                            ),),\n                        )\n                      ],\n                    ),\n                  )\n              )\n            ]\n        )\n    );\n\n    targets.add(\n        TargetFocus(\n            identify: \"Target 3\",\n            keyTarget: keyButton5,\n            contents: [\n              TargetContent(\n                  align: ContentAlign.right,\n                  child: Container(\n                    child: Column(\n                      mainAxisSize: MainAxisSize.min,\n                      crossAxisAlignment: CrossAxisAlignment.start,\n                      children: \u003cWidget\u003e[\n                        Text(\n                          \"Title lorem ipsum\",\n                          style: TextStyle(\n                              fontWeight: FontWeight.bold,\n                              color: Colors.white,\n                              fontSize: 20.0\n                          ),\n                        ),\n                        Padding(\n                          padding: const EdgeInsets.only(top: 10.0),\n                          child: Text(\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin pulvinar tortor eget maximus iaculis.\",\n                            style: TextStyle(\n                                color: Colors.white\n                            ),),\n                        )\n                      ],\n                    ),\n                  )\n              )\n            ]\n        )\n    );\n}\n\nvoid showTutorial() {\n    TutorialCoachMark(\n      targets: targets, // List\u003cTargetFocus\u003e\n      colorShadow: Colors.red, // DEFAULT Colors.black\n       // alignSkip: Alignment.bottomRight,\n       // textSkip: \"SKIP\",\n       // paddingFocus: 10,\n       // opacityShadow: 0.8,\n      onClickTarget: (target){\n        print(target);\n      },\n      onClickTargetWithTapPosition: (target, tapDetails) {\n        print(\"target: $target\");\n        print(\"clicked at position local: ${tapDetails.localPosition} - global: ${tapDetails.globalPosition}\");\n      },\n      onClickOverlay: (target){\n        print(target);\n      },\n      onSkip: (){\n        print(\"skip\");\n        return true;\n      },\n      onFinish: (){\n        print(\"finish\");\n      },\n    )..show(context:context);\n  }\n```\n\n# Contribution\n\nIf you find any errors or want to add improvements, you can open a issue or develop the fix and open a pull request. Thank you for your cooperation!\n","funding_links":["https://www.buymeacoffee.com/rafaelbarbosa"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafaelbarbosatec%2Ftutorial_coach_mark","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frafaelbarbosatec%2Ftutorial_coach_mark","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafaelbarbosatec%2Ftutorial_coach_mark/lists"}