bubble_showcase 0.2.0+2

  • Readme
  • Changelog
  • Example
  • Installing
  • 85

BubbleShowcase #

BubbleShowcase is a small but powerful flutter package that allows you to highlight specific parts of your app (to explain them to the user for instance) or to showcase your app new features.

Preview

Getting Started #

This package is easy to use. Take a look at the following snippet (which is using speech_bubble) :

BubbleShowcase(
  bubbleShowcaseId: 'my_bubble_showcase',
  bubbleShowcaseVersion: 1,
  bubbleSlides: [
    RelativeBubbleSlide(
      widgetKey: widgetToHighlightKey,
      child: RelativeBubbleSlideChild(
        direction: AxisDirection.right,
        widget: SpeechBubble(
          nipLocation: NipLocation.LEFT,
          color: Colors.blue,
          child: Padding(
            padding: EdgeInsets.all(10),
            child: Text(
              'This is a new cool feature !',
              style: TextStyle(color: Colors.white),
            ),
          ),
        ),
      ),
    ),
  ],
  child: MyMainWidget(),
);

It creates a BubbleShowcase widget with only one BubbleSlide. This slide will highlight the widget that holds the key widgetToHighlightKey. The speech bubble will be placed on the right of the widget.

BubbleShowcase is not limited to highlight a specific widget. You can also highlight a specific part of your app by its coordinates :

BubbleShowcase(
  bubbleShowcaseId: 'my_bubble_showcase',
  bubbleShowcaseVersion: 1,
  bubbleSlides: [
    AbsoluteBubbleSlide(
      positionCalculator: (size) => Position(
        top: 0,
        right: 0,
        bottom: 0,
        left: 0,
      ),
      child: AbsoluteBubbleSlideChild(
        positionCalculator: (size) => Position(
          top: 0,
          left: 0,
        ),
        widget: SpeechBubble(
          nipLocation: NipLocation.LEFT,
          color: Colors.blue,
          child: Padding(
            padding: EdgeInsets.all(10),
            child: Text(
              'This is the top left corner of your app.',
              style: TextStyle(color: Colors.white),
            ),
          ),
        ),
      ),
    ),
  ],
  child: MyMainWidget(),
);

This will display the speech bubble on the top left corner of your app.

Options #

The showcase #

The showcase is where everything begins. Let's see the available options :

  • bubbleShowcaseId The showcase identifier. Must be unique across the app as it is used as a saving mean; for instance when the showcase should not be reopened (required).
  • bubbleShowcaseVersion The showcase version. Increase it when you update the showcase, this allows to redisplay the it to the user if doNotReopenOnClose is set to true (required).
  • doNotReopenOnClose Whether this showcase should be reopened once closed.
  • bubbleSlides The slides to display (required & must not be empty).
  • child The widget to display below the slides. It should be your app main widget.
  • counterText The current slide counter text. :i targets the current slide number and :n targets the maximum slide number.
  • showCloseButton Whether to show a little close button on the top left of the slide.

The slides #

The slides is what is highlighting a specific part of your app. There are two main categories of positioning : Absolute and Relative. Here is a little summary :

PositionClass nameUse caseSpecific options
AbsoluteAbsoluteBubbleSlideYou want to position your slide according to a x, y position on the screen and not a specific widget.positionCalculator The function that calculates the slide position on the screen.
RelativeRelativeBubbleSlideYou want to position your slide according to a specific widget.widgetKey The global key that the target widget is holding.

All slides have these options in common :

  • shape The slide shape (available are Rectangle, RoundedRectangle, Oval and Circle but you can add a custom one by extending the Shape class).
  • boxShadow The slide box shadow (containing the color, the blur radius, the spread radius, ...).
  • child The slide child, see below (required).

The slides children #

Slides children are what are displayed according to what you are highlighting (it can be a speech bubble for example). The same positioning system is also available for children :

PositionClass nameUse caseSpecific options
AbsoluteAbsoluteBubbleSlideChildYou want to position the child according to a x, y position on the screen and not the highlighted part of the screen.positionCalculator The function that calculates the child position on the screen.
RelativeRelativeBubbleSlideChildYou want to position the child according to the highlighted zone.direction Where to position the child compared to the highlighted zone.

All children have these options in common :

  • widget The widget to display (required).

But you have a lot of other options ! Don't hesitate to check the API Reference or the Github repo.

Contributions #

You have a lot of options to contribute to this project ! You can :

[0.2.0+2] - 2020-02-28 #

  • Bugs fixed.
  • Some refactoring.

[0.2.0+1] - 2019-12-29 #

  • Fixed an error in the README.md.

[0.2.0] - 2019-12-29 #

  • A lot of refactoring.
  • Updated license (now MIT licensed).
  • Improved the README.md.
  • Updated dependencies.

[0.1.0] - 2019-08-24 #

  • First public release.

example/lib/main.dart

import 'package:bubble_showcase/bubble_showcase.dart';
import 'package:flutter/material.dart';
import 'package:speech_bubble/speech_bubble.dart';

/// First plugin test method.
void main() => runApp(_BubbleShowcaseDemoApp());

/// The demo material app.
class _BubbleShowcaseDemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(
        title: 'Bubble Showcase Demo',
        home: Scaffold(
          appBar: AppBar(
            title: Text('Bubble Showcase Demo'),
          ),
          body: _BubbleShowcaseDemoWidget(),
        ),
      );
}

/// The main demo widget.
class _BubbleShowcaseDemoWidget extends StatelessWidget {
  /// The title text global key.
  final GlobalKey _titleKey = GlobalKey();

  /// The first button global key.
  final GlobalKey _firstButtonKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    TextStyle textStyle = Theme.of(context).textTheme.body1.copyWith(
          color: Colors.white,
        );
    return BubbleShowcase(
      bubbleShowcaseId: 'my_bubble_showcase',
      bubbleShowcaseVersion: 1,
      bubbleSlides: [
        _firstSlide(textStyle),
        _secondSlide(textStyle),
        _thirdSlide(textStyle),
      ],
      child: _BubbleShowcaseDemoChild(_titleKey, _firstButtonKey),
    );
  }

  /// Creates the first slide.
  BubbleSlide _firstSlide(TextStyle textStyle) => RelativeBubbleSlide(
        widgetKey: _titleKey,
        child: RelativeBubbleSlideChild(
          widget: Padding(
            padding: EdgeInsets.only(top: 2),
            child: SpeechBubble(
              nipLocation: NipLocation.TOP,
              color: Colors.blue,
              child: Padding(
                padding: EdgeInsets.all(10),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Text(
                      'That\'s cool !',
                      style: textStyle.copyWith(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    Text(
                      'This is my brand new title !',
                      style: textStyle,
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      );

  /// Creates the second slide.
  BubbleSlide _secondSlide(TextStyle textStyle) => AbsoluteBubbleSlide(
        positionCalculator: (size) => Position(
          top: 0,
          right: 0,
          left: 0,
          bottom: size.height,
        ),
        child: RelativeBubbleSlideChild(
          widget: SpeechBubble(
            nipLocation: NipLocation.LEFT,
            color: Colors.teal,
            child: Padding(
              padding: EdgeInsets.all(10),
              child: Text(
                'Look at me pointing absolutely nothing.\n(Or maybe that\'s an hidden navigation bar !)',
                style: textStyle,
              ),
            ),
          ),
          direction: AxisDirection.right,
        ),
      );

  /// Creates the third slide.
  BubbleSlide _thirdSlide(TextStyle textStyle) => RelativeBubbleSlide(
        widgetKey: _firstButtonKey,
        shape: Oval(
          spreadRadius: 15,
        ),
        child: RelativeBubbleSlideChild(
          widget: Padding(
            padding: EdgeInsets.only(top: 10),
            child: SpeechBubble(
              nipLocation: NipLocation.TOP,
              color: Colors.purple,
              child: Padding(
                padding: EdgeInsets.all(10),
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Padding(
                      padding: EdgeInsets.only(right: 5),
                      child: Icon(
                        Icons.info_outline,
                        color: Colors.white,
                      ),
                    ),
                    Expanded(
                      child: Text(
                        'As said, this button is new.\nOh, and this one is oval by the way.',
                        style: textStyle,
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      );
}

/// The main demo widget child.
class _BubbleShowcaseDemoChild extends StatelessWidget {
  /// The title text global key.
  final GlobalKey _titleKey;

  /// The first button global key.
  final GlobalKey _firstButtonKey;

  /// Creates a new bubble showcase demo child instance.
  _BubbleShowcaseDemoChild(this._titleKey, this._firstButtonKey);

  @override
  Widget build(BuildContext context) => Padding(
        padding: EdgeInsets.symmetric(
          vertical: 40,
          horizontal: 20,
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Container(
              child: Text(
                'Bubble Showcase',
                key: _titleKey,
                style: Theme.of(context).textTheme.display1,
                textAlign: TextAlign.center,
              ),
              width: MediaQuery.of(context).size.width,
            ),
            Padding(
              padding: EdgeInsets.only(top: 30),
              child: RaisedButton(
                child: Text('This button is NEW !'),
                key: _firstButtonKey,
                onPressed: () {},
              ),
            ),
            RaisedButton(
              child: Text('This button is old, please don\'t pay attention.'),
              onPressed: () {},
            )
          ],
        ),
      );
}

Use this package as a library

1. Depend on it

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


dependencies:
  bubble_showcase: ^0.2.0+2

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:bubble_showcase/bubble_showcase.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
70
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]
85
Learn more about scoring.

We analyzed this package on Apr 7, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6
  • Flutter: 1.12.13+hotfix.8

Health suggestions

Format lib/bubble_showcase.dart.

Run flutter format to format lib/bubble_showcase.dart.

Format lib/src/shape.dart.

Run flutter format to format lib/src/shape.dart.

Format lib/src/showcase.dart.

Run flutter format to format lib/src/showcase.dart.

Format lib/src/slide.dart.

Run flutter format to format lib/src/slide.dart.

Format lib/src/utils.dart.

Run flutter format to format lib/src/utils.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
shared_preferences ^0.5.6 0.5.6+3
Transitive dependencies
collection 1.14.11 1.14.12
flutter_web_plugins 0.0.0
meta 1.1.8
shared_preferences_macos 0.0.1+6
shared_preferences_platform_interface 1.0.3
shared_preferences_web 0.1.2+4
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
pedantic ^1.9.0