tuxin_tutorial_overlay 0.4.3

tuxin_tutorial_overlay #

an overlay flutter package that can be used for tutorials and walk-through

I was looking for an easier way to add tutorial walk-through to an existing app without cascading more elements into my app.

I wanted a walk-through that I can use as an overlay, that can have several widget behind it being shown, some widgets to allow interaction and some not, and also to be able to have specific shapes of holes (rect, oval and so on) so I made this :)

btw.. I'm new to flutter programming so I apologize for any mistakes and would appreciate any comments. thanks!

API #

WidgetData.dart contains the following definitions:

enum WidgetShape { Oval, Rect, RRect } - to define the shape of the hole that will grant the requested widget visibility (default is Oval).

the Widget Data class:

class WidgetData {
  GlobalKey key;
  WidgetShape shape;
  bool isEnabled;
  double padding;

  WidgetData(
      {@required this.key,
      this.shape = WidgetShape.Oval,
      this.isEnabled = true,
      this.padding = 0});
}

you use it to define each widget's relevant properties, like padding, enabled/disabled (allow user interaction) and the shape of the hole in the Overlay

TutorialOverlayUtil.dart contains the following function:

void createTutorialOverlay(
    {@required String tagName,
      @required BuildContext context,
      bool enableHolesAnimation = true,
      bool enableAnimationRepeat = true,
      double defaultPadding = 4,
    List<WidgetData> widgetsData = const [],
    Function onTap,
    Color bgColor,
    Widget description,
    int highlightCount=3,
    int animationMilliseconds=150,
    int animationRepeatDelayMilliseconds = 3000
    })

tagName - the name of the overlay screen, to be used later when you want to show it

context - the BuildContext of the page

enableHolesAnimation - enable animation on visible widgets to draw attention to them

enableAnimationRepeat - enable animation repeat

defaultPadding - default padding to add to each hole that shows a widget

widgetsData - is a List of each widget that you want to be fully visible and the relevant properties (padding, enable/disable interaction and hole shape)

onTap - a callback that will be called when the user taps on the overlay itself

bgColor - a custom background color. default is Black with opacity of 0.4.

description - a Widget to display on top of the overlay, usually contains instructions on current frame

highlightCount - number of times to run the highlight animation

animationMilliseconds - the milliseconds that each direction of animation will take (forward, reverse)

animationRepeatDelayMilliseconds - milliseconds to wait before animation repeats itself

I also created two functions to show and hide an overlay.

void showOverlayEntry({String tagName, bool redisplayOverlayIfSameTAgName = true}) async;
void hideOverlayEntryIfExists();

showOverlayEntry() is used to show the overlay that you created earlier with createTutorialOverlay().

hideOverlayEntryIfExists() is used to hide the overlay

  • please note that you need to use the createTutorialOverlay() function only after the elements have been drawn in order to get their proper location and size. in my example I created the overlay at the initState() function of my StatefulWidget, so in order for the elements to be drawn first I needed to execute the function inside a post frame callback:

import 'package:flutter/scheduler.dart';

...

@override
  void initState() {
    SchedulerBinding.instance.addPostFrameCallback((_) {
      createTutorialOverlay(
      tagName: 'example',
          ...
          )
      );
      showOverlayEntry(context, 'example');
    });

Simple Example #

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:tuxin_tutorial_overlay/TutorialOverlayUtil.dart';
import 'package:tuxin_tutorial_overlay/WidgetData.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Tux-In Tutorial Overlay Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Tutorial Overlay Example Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  final GlobalKey buttonKey = GlobalKey();
  final GlobalKey counterKey = GlobalKey();
  double _leftPosition = 0;
  @override
  void initState() {
    SchedulerBinding.instance.addPostFrameCallback((_) {
      createTutorialOverlay(
        context: context,
          tagName: 'example',
          bgColor: Colors.green.withOpacity(
              0.4), // Optional. uses black color with 0.4 opacity by default
          onTap: () => print("TAP"),
          widgetsData: <WidgetData>[
            WidgetData(key: buttonKey, isEnabled: true, padding: 4),
            WidgetData(
                key: counterKey, isEnabled: false, shape: WidgetShape.Rect)
          ],
          description: Text(
            'hello',
            textAlign: TextAlign.center,
            style: TextStyle(decoration: TextDecoration.none),
          ));

      showOverlayEntry(tagName: 'example');
    });

    super.initState();
  }

  void _incrementCounter() {
    setState(() {
      _leftPosition += 10;
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Padding(
                padding: EdgeInsets.fromLTRB(_leftPosition, 0, 0, 0),
                child: Text(
                  '$_counter',
                  key: counterKey,
                  style: Theme.of(context).textTheme.display1,
                ))
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        key: buttonKey,
        child: Icon(Icons.add),
      ),
    );
  }
}

to execute this code see the example app :)

Showcase from example app #

capture

usage of this package in production #

[0.4.3] - 19/06/19

  • added isOverlayBgTransparent optional parameter to allow overlay without a blocking background

[0.4.2] - 16/05/19

  • added hooks to hide and showing overlays (for analytics or what not)

[0.4.1] - 15/05/19

  • removed printing debug information by default
  • added missing new parameters to createTutorialOverlayIfNotExists function

[0.4.0] - 14/05/19

  • added uuid package to distinguish between each overlay with same tag name
  • added animation repeat functionality
  • changed createTutorialOverlay() function to include animation related parameters

[0.3.0] - 12/05/19

  • BuildContext is now required when creating the overlay page instead of when showing it
  • added animation support
  • added default padding for all visible widgets
  • api changes
    - createTutorialOverlay requires a context
    - showOverlayEntry required named parameters and does not require context parameter
    - showOverlayEntry as a new optional parameter redisplayOverlayIfSameTAgName if to redraw the overlay when requested to display an already displayed overlay

[0.2.0] - 08/05/19

  • global keys that are null or not connected to a Widgets are silently ignored instead of throwing an exception
  • detecting position and size change of widgets in order to redraw the overlay
  • added synchronized package dependency to make sure showOverlayEntry is being called synchronized.

[0.1.0] - 28/04/19

  • included onTap event
  • removed context parameter requirement from createTutorialOverlay()
  • breaking changes to API - now uses WidgetData class instead of list of Global Keys.
  • added more shapes - (formerly supported only Oval) now also supports Rect and RRect.
  • added bgColor property to createTutorialOverlay() to allow changing default background color

[0.0.1] - 27/04/19

  • Initial release

example/README.md

tuxin_tutorial_overlay_example #

an example project for the tuxin_tutorial_overlay_example flutter package

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  tuxin_tutorial_overlay: ^0.4.3

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:tuxin_tutorial_overlay/tuxin_tutorial_overlay.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
55
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
78
Learn more about scoring.

We analyzed this package on Aug 16, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.4.0
  • pana: 0.12.19
  • Flutter: 1.7.8+hotfix.4

Platforms

Detected platforms: Flutter

References Flutter, and has no conflicting libraries.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
synchronized ^2.1.0 2.1.0+1
uuid ^2.0.1 2.0.2
Transitive dependencies
charcode 1.1.2
collection 1.14.11 1.14.12
convert 2.1.1
crypto 2.1.1+1
meta 1.1.6 1.1.7
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test