gizmos_hud 0.0.1-alpha.1

  • Readme
  • Changelog
  • Example
  • Installing
  • 73

gizmos_hud #

badge-pubdev badge-platforms badge-language badge-license

badge-sponsors badge-githubsponsors badge-patreon

badge-twitter badge-twitter-gizmosdev

A Flutter package for displaying custom HUDs, Toasts, Pop-Ups, Dialogs or other screen overlays. Any widget can be displayed, in any position on the screen for a completely customized interface.

Installation #

To use this package, add gizmos_hud as a dependency in your pubspec.yaml file.

dependencies:
  gizmos_hud: any

Import the library #

import 'package:gizmos_hud/gizmos_hud.dart';

Usage #

For each overlay you want to use in your app, create a Hud instance.

To display the Hud, call the show(). To hide it, call hide().

show() #

Parameter: context required #

The context is the BuildContext that will be used to present the hud. Depending on where/how you're displaying the hud, this won't likely be the context for the current build() method. Because we want the hud to have access to the full screen, you need to pass in the context for the top most page.

Parameter: child required #

The child parameter is the Widget to be displayed.

Parameter: position #

The position parameter determines where the hud is displayed. There are four options:

HudPosition.top

For HudPosition.top, the top parameter becomes the offset (defaults to 100) from the top of the context. You must also pass in either a width with an optional left or right value, or omit width and specify both left and right values. height is also required.

HudPosition.bottom

For HudPosition.bottom, the bottom parameter becomes the offset (defaults to 100) from the bottom of the context. You must also pass in either a width with an optional left or right value, or omit width and specify both left and right values. height is also required.

HudPosition.center

For HudPosition.center, width and height are required, top, bottom, left, right should be omitted.

HudPosition.custom

For a position of HudPosition.custom, the positional parameters are passed directly to a Position Widget.

Parameter: duration #

Set a duration to have the hud automatically fade out after that duration has passed. Omit duration to have the overlay stay on screen until programmatically dismissed by calling the hide() method.

Parameter: isBlocking #

Set isBlocking to true to create a full screen background behind the hud that blocks user interaction.

Parameter: backgroundColor #

backgroundColor specifies the colour to display behind the hud. Currently this is ignored if isBlocking is set to true, however I expect that to change in a later version.

Parameter: hudDecoration #

Use hudDecoration to display a custom BoxDecoration as the background of the hud. There are two default hudDecorations included that you can use: Hud.defaultDarkHudDecoration and Hud.defaultLightHudDecoration

Parameter: hudColor #

The hudColor parameter can be used as a shortcut to create a basic hudDecoration.

Parameter: left/top/right/bottom/width/height #

These parameters are related to position above.

hide() #

The only parameter in hide() is the optional boolean animated that specifies whether or not to animate (fade out) the Hud. This defaults to true.

Samples #

iOS Demo Android Demo

Example #

fancyToastHud.show(
  context: topBuildContext,
  child: child,
  hudDecoration: fancyHudDecoration,
  position: HudPosition.top,
  duration: Duration(seconds: 3),
  width: 280,
  height: 50,
  top: 120,
);

Please see the example app in this package for a full example.

Notes #

  • This is my first Flutter package, and I'm still learning the Flutter way of doing things so a lot of this package may change. Please send me suggestions/bug fixes.
  • Some initial questions:
    • Is there a better way to get the topBuildContext?
    • Is there a better way to handle the fade in/out, rather than using the delay/markNeedsBuild process?

gizmosdev-logo gizmos.dev #

0.0.1-alpha.1 - 2020/04/19 #

  • Initial pre-release

example/lib/main.dart

//
//  gizmos_hud
//
//  Copyright (c) 2020, Dave Wood.
//  All rights reserved.
//  Use of this source code is governed by a BSD-style license that can be
//  found in the LICENSE file.
//

import 'dart:math';

import 'package:flutter/material.dart';

import 'huds.dart';
import 'fancy_toast_details.dart';

// Keep a reference to the top level BuildContext so our Huds can easily be
// displayed on top of everything, regardless of the navigation in place, or
// how deep we are in a navigation stack.
/// Global reference to our top level buildContext.
BuildContext topBuildContext;
MyCustomHuds huds = MyCustomHuds();

/// Whether to randomize which fancy toast to display. This is just so I can
/// disable the randomness when recording the demo videos
var randomizeFancyToasts = true;

/// Main app widget
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'gizmos_hud Examples',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'gizmos_hud Examples'),
    );
  }
}

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

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

/// State for the HomePage
class _MyHomePageState extends State<MyHomePage> {
  final _scrollController = ScrollController();

  /// Variable to keep track of the previous fancy message to avoid dups.
  static int previousIndex = -1;

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  /// Convenience method to make consistent looking buttons
  Widget sample(
      {@required String title,
      String info,
      @required VoidCallback show,
      VoidCallback hide}) {
    // layout/size calculations
    var mediaQuery = MediaQuery.of(context);
    var contextWidth = mediaQuery.size.width;

    // magic numbers etc
    var buttonLength = 50.0;
    var marginLength = 4.0;
    var buttonColor = Colors.grey.withOpacity(0.5);

    var showButton = InkWell(
        splashColor: Colors.blue,
        onTap: show,
        child: Container(
          width: buttonLength,
          height: buttonLength,
          margin: EdgeInsets.all(marginLength),
          color: buttonColor,
          child: Icon(Icons.play_arrow, color: Colors.black),
        ));

    var hideButton = (hide != null)
        ? InkWell(
            splashColor: Colors.blue,
            onTap: hide,
            child: Container(
              width: buttonLength,
              height: buttonLength,
              margin: EdgeInsets.all(marginLength),
              color: buttonColor,
              child: Icon(Icons.stop, color: Colors.black),
            ))
        : SizedBox(
            width: buttonLength + marginLength * 2,
            height: buttonLength + marginLength * 2,
          );

    var buttons = Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        showButton,
        hideButton,
      ],
    );

    var header = Text(
      title,
      style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
      maxLines: 1,
    );

    var body = Container(
      width: (contextWidth - (buttonLength * 2) - (marginLength * 4)) * 0.9,
      child: Text(
        info,
        style: TextStyle(color: Colors.grey, fontWeight: FontWeight.normal),
        maxLines: 10,
        softWrap: true,
      ),
    );

    var row = Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      mainAxisSize: MainAxisSize.max,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        body,
        buttons,
      ],
    );

    var column = Column(
      mainAxisAlignment: MainAxisAlignment.start,
      mainAxisSize: MainAxisSize.max,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        header,
        row,
      ],
    );

    var container = Container(
      color: Colors.transparent,
      margin: EdgeInsets.all(marginLength),
      padding: EdgeInsets.all(marginLength),
      child: column,
    );

    return container;
  }

  @override
  Widget build(BuildContext context) {
    topBuildContext = context;

    /// List of our example buttons
    var children = List<Widget>();

    /// Toast
    children.add(sample(
      title: 'Simple Toast Message',
      info: 'A toast message that appears near the bottom of the screen, and '
          'disappears 3 seconds later. It can be hidden early if needed.',
      show: () {
        huds.showToast('Our simple toast message!');

        // Tool for recording demo videos
        if (!randomizeFancyToasts) {
          // Reset order
          previousIndex = -1;
        }
      },
      hide: () {
        huds.hideToast();
      },
    ));

    /// Fancy Toast
    children.add(sample(
      title: 'Fancy Toast Message',
      info: 'A toast message with an icon that appears near the top of the '
          'screen, and disappears 3 seconds later. It can be hidden early if '
          'needed.',
      show: () {
        var randomToasts = List<FancyToastDetails>();

        // Create a few random toasts to pick from
        randomToasts.add(
          FancyToastDetails(
            message: 'Please file any bugs you see',
            backgroundColor: Colors.blue,
            icon: Icon(
              Icons.bug_report,
              color: Colors.yellow,
            ),
          ),
        );
        randomToasts.add(
          FancyToastDetails(
            message: 'Payment successful',
            backgroundColor: Colors.green,
            icon: Icon(
              Icons.monetization_on,
              color: Colors.white,
            ),
          ),
        );
        randomToasts.add(
          FancyToastDetails(
            message: 'Warning: Battery low',
            backgroundColor: Colors.orange,
            icon: Icon(
              Icons.battery_alert,
              color: Colors.white,
            ),
          ),
        );
        randomToasts.add(
          FancyToastDetails(
            message: 'Error: Unable to reach the Internet',
            backgroundColor: Colors.red,
            icon: Icon(
              Icons.offline_bolt,
              color: Colors.black,
            ),
          ),
        );

        var randIndex = Random().nextInt(randomToasts.length);
        if (randomizeFancyToasts) {
          while (randIndex == previousIndex) {
            randIndex = Random().nextInt(randomToasts.length);
          }
        } else {
          // Tool for recording demo videos
          randIndex = previousIndex + 1;
          if (randIndex >= randomToasts.length) {
            randIndex = 0;
          }
        }
        previousIndex = randIndex;

        FancyToastDetails details = randomToasts[randIndex];

        huds.showFancyToast(
          details.message,
          icon: details.icon,
          backgroundColor: details.backgroundColor,
        );
      },
      hide: () {
        huds.hideFancyToast();
      },
    ));

    /// Busy
    children.add(sample(
      title: 'Non-Blocking Activity Indicator',
      info:
          'A non-blocking, indeterminate activity indicator. Appears on screen '
          'until dismissed, here with the hide button, but in practise it would'
          ' be dismissed when the long running task completes. gizmos_hud can '
          'create a blocking Activity Indicator, by passing `true` to '
          '`isBlocking`, but it\'s not as interesting for a demo.',
      show: () {
        huds.showBusy();
      },
      hide: () {
        huds.hideBusy();
      },
    ));

    /// Dialog
    children.add(sample(
      title: 'Custom Dialog',
      info: 'This presents a custom, blocking dialog widget. It includes a '
          'button that allows the user to dismiss the dialog after they\'ve '
          'read the contents. The dialog could have other options for the user,'
          ' offer a choice, or trigger a series of dialogs, perhaps as an '
          'on-boarding process.',
      show: () {
        huds.showDialog('A Custom Dialog',
            'Please submit feature requests, and or improvements to the package\'s Github page.');
      },
    ));

    /// Confetti
    children.add(sample(
      title: 'Confetti!',
      info: 'An overlay with a transparent, animated GIF covering the full '
          'screen. It automatically disappears 3 seconds later, but can be '
          'hidden early if needed. Because it\'s a full screen image however, '
          'it blocks the interface, so there\'s no hide button here to test '
          'with.',
      show: () {
        huds.showConfetti();
      },
    ));

    var header = Container(
      color: Colors.blue.withOpacity(0.2),
      height: 40.0,
      child: Center(
          child: Text('Visit https://gizmos.dev/ for more information.')),
    );

    var listView = ListView(
      controller: _scrollController,
      physics: const AlwaysScrollableScrollPhysics(),
      children: children,
    );

    var scrollView = Expanded(
        child: Scrollbar(
      controller: _scrollController,
      child: listView,
    ));

    var column = Column(
        mainAxisAlignment: MainAxisAlignment.start,
        mainAxisSize: MainAxisSize.max,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          header,
          scrollView,
        ]);

    var body = column;

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: body,
    );
  }
}

/// Run the app.
void main() => runApp(MyApp());

Use this package as a library

1. Depend on it

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


dependencies:
  gizmos_hud: ^0.0.1-alpha.1

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:gizmos_hud/gizmos_hud.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
52
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
85
Overall:
Weighted score of the above. [more]
73
Learn more about scoring.

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

  • Dart: 2.8.4
  • pana: 0.13.15
  • Flutter: 1.17.5

Analysis suggestions

Package not compatible with SDK dart

Because:

  • gizmos_hud that is a package requiring null.

Maintenance suggestions

Package is pre-v0.1 release. (-10 points)

While nothing is inherently wrong with versions of 0.0.*, it might mean that the author is still experimenting with the general direction of the API.

Package is pre-release. (-5 points)

Pre-release versions should be used with caution; their API can change in breaking ways.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.12 1.14.13
meta 1.1.8 1.2.2
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8 2.1.0-nullsafety
Dev dependencies
flutter_test