FLUTTER ECOSYSTEM

RafaelBarbosatec/tutorial_coach_mark

教程教练标记

tutorial_coach_mark 项目封面
Stars
613
Forks
238
最近推送(UTC)
2026年8月28日
项目状态
未归档
Rafael Almeida Barbosa GitHub avatar
GITHUB User

Rafael Almeida Barbosa ↗

Mobile Developer(Android/Flutter) In love with solutions that fit in the palm of the hand

São Paulo/São Paulo Brasil
语言DartCMakeC++Objective-CSwiftCKotlin

技术话题

此仓库发布的插件

使用的依赖

依赖清单 3 项
  • flutter{"sdk":"flutter"}
  • flutter_test开发依赖{"sdk":"flutter"}
  • flutter_lints开发依赖^2.0.0

原始 README

以下为英文项目原文快照,最新内容请访问 GitHub。

展开 / 收起项目 README

pub package buymeacoffee

TutorialCoachMark

Create a beautiful and easy tutorial for your application.

Example 1 Example 2
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

Usage

To use this plugin, add tutorial_coach_mark as a dependency in your pubspec.yaml file.

Example
import 'package:flutter/material.dart';
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';

void showTutorial() {
    TutorialCoachMark tutorial = TutorialCoachMark(
      targets: targets, // List<TargetFocus>
      colorShadow: Colors.red, // DEFAULT Colors.black
       // opacityShadow = 0.8,
       // alignSkip: Alignment.bottomRight,
       // textSkip: "SKIP",
       // textStyleSkip: const TextStyle(color: Colors.white),
       // skipWidget: MyWidget(),
       // hideSkip: false
       // showSkipInLastTarget: true,
       // paddingFocus: 10,
       // focusAnimationDuration: Duration(milliseconds: 500),
       // unFocusAnimationDuration: Duration(milliseconds: 500),
       // pulseAnimationDuration: Duration(milliseconds: 500),
       // pulseVariation: Tween(begin: 1.0, end: 0.99),
       // pulseEnable: true,
       // imageFilter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
       // initialFocus: 0,
       // useSafeArea: true,
       // finish: (){},
       // clickTarget: (TargetFocus) {},
       // onClickTargetWithTapPosition: (TargetFocus, TapDownDetails) {},
       // clickOverlay: (TargetFocus) {},
       // disableBackButton: false // If true disable native back button. 
      onFinish: (){
        print("finish");
      },
      onClickTargetWithTapPosition: (target, tapDetails) {
        print("target: $target");
        print("clicked at position local: ${tapDetails.localPosition} - global: ${tapDetails.globalPosition}");
      },
      onClickTarget: (target){
        print(target);
      },
      onSkip: (){
        print("skip");
        return true;
      }
    )..show(context:context);

    // tutorial.skip();
    // tutorial.finish();
    // tutorial.next(); // call next target programmatically
    // tutorial.previous(); // call previous target programmatically
    // tutorial.goTo(3); // call target programmatically by index
  }
Creating targets (TargetFocus)

TargetFocus is the class that represents the widget that will be focused and configure what will be displayed after you focus it.

Attributes:

Attribute Type Description
identify dynamic free for identification use
keyTarget GlobalKey GlobalKey widget that wants to be focused
targetPosition TargetPosition If you do not want to use GlobalKey, you can create a TargetPosition to determine where to focus
contents ContentTarget[] Content list you want to display after focusing widget
shape ShapeLightFocus ShapeLightFocus.Circle or ShapeLightFocus.RRect
radius double Use when shape = ShapeLightFocus.RRect
borderSide BorderSide
color Color Custom color to target
enableOverlayTab bool enable click in all screen to call next step
enableTargetTab bool enable click in target to call next step
alignSkip Alignment use to align the skip in the target
paddingFocus Alignment settings padding of the focus in target
focusAnimationDuration Duration override the widget's global focus animation duration
unFocusAnimationDuration Duration override the widget's global unfocus animation duration
pulseVariation Tween override interval pulse animation
Creating contents (ContentTarget)

ContentTarget is the class responsible for determining what should be displayed and how it will appear after focusing on the widget.

Attributes:

Attribute Type Description
align AlignContent With this attribute you determine in which region to display the content in relation to the focused widget (top,bottom,left,right)
padding EdgeInsets Padding of the content
child Widget Content you want to be displayed
builder Widget Content you want to be displayed
customPosition CustomTargetContentPosition Add custom position when align is AlignContent.custom
Example Complete
import 'package:flutter/material.dart';
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';

List<TargetFocus> targets = List();

 @override
 void initState() {
    targets.add(
        TargetFocus(
            identify: "Target 1",
            keyTarget: keyButton,
            contents: [
              TargetContent(
                  align: ContentAlign.bottom,
                  child: Container(
                    child:Column(
                      mainAxisSize: MainAxisSize.min,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(
                          "Titulo lorem ipsum",
                          style: TextStyle(
                            fontWeight: FontWeight.bold,
                            color: Colors.white,
                            fontSize: 20.0
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.only(top: 10.0),
                          child: Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin pulvinar tortor eget maximus iaculis.",
                            style: TextStyle(
                                color: Colors.white
                            ),),
                        )
                      ],
                    ),
                  )
              )
            ]
        )
    );

    targets.add(
        TargetFocus(
            identify: "Target 2",
            keyTarget: keyButton4,
            contents: [
              TargetContent(
                  align: ContentAlign.left,
                  child: Container(
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(
                          "Multiples content",
                          style: TextStyle(
                              fontWeight: FontWeight.bold,
                              color: Colors.white,
                              fontSize: 20.0
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.only(top: 10.0),
                          child: Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin pulvinar tortor eget maximus iaculis.",
                            style: TextStyle(
                                color: Colors.white
                            ),),
                        )
                      ],
                    ),
                  )
              ),
              TargetContent(
                  align: ContentAlign.top,
                  child: Container(
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(
                          "Multiples content",
                          style: TextStyle(
                              fontWeight: FontWeight.bold,
                              color: Colors.white,
                              fontSize: 20.0
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.only(top: 10.0),
                          child: Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin pulvinar tortor eget maximus iaculis.",
                            style: TextStyle(
                                color: Colors.white
                            ),),
                        )
                      ],
                    ),
                  )
              )
            ]
        )
    );

    targets.add(
        TargetFocus(
            identify: "Target 3",
            keyTarget: keyButton5,
            contents: [
              TargetContent(
                  align: ContentAlign.right,
                  child: Container(
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(
                          "Title lorem ipsum",
                          style: TextStyle(
                              fontWeight: FontWeight.bold,
                              color: Colors.white,
                              fontSize: 20.0
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.only(top: 10.0),
                          child: Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin pulvinar tortor eget maximus iaculis.",
                            style: TextStyle(
                                color: Colors.white
                            ),),
                        )
                      ],
                    ),
                  )
              )
            ]
        )
    );
}

void showTutorial() {
    TutorialCoachMark(
      targets: targets, // List<TargetFocus>
      colorShadow: Colors.red, // DEFAULT Colors.black
       // alignSkip: Alignment.bottomRight,
       // textSkip: "SKIP",
       // paddingFocus: 10,
       // opacityShadow: 0.8,
      onClickTarget: (target){
        print(target);
      },
      onClickTargetWithTapPosition: (target, tapDetails) {
        print("target: $target");
        print("clicked at position local: ${tapDetails.localPosition} - global: ${tapDetails.globalPosition}");
      },
      onClickOverlay: (target){
        print(target);
      },
      onSkip: (){
        print("skip");
        return true;
      },
      onFinish: (){
        print("finish");
      },
    )..show(context:context);
  }

Contribution

If 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!