Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Neumorphic AppBar #122

Closed
jaumard opened this issue May 27, 2020 · 14 comments · Fixed by #128
Closed

Neumorphic AppBar #122

jaumard opened this issue May 27, 2020 · 14 comments · Fixed by #128
Labels
enhancement New feature or request widget

Comments

@jaumard
Copy link
Contributor

jaumard commented May 27, 2020

Currently if you try to use the material appBar and put neumorphic button on it it will be weird as the effect is cut by the size of the appBar. Would be nice to have a appBar specific to neumorphic that allow you to do:
Capture d’écran 2020-05-27 à 14 47 39
directly out of the box instead of doing it under Scaffold body manually

@jaumard
Copy link
Contributor Author

jaumard commented May 27, 2020

I find those example of neumorphic appBar
Capture d’écran 2020-05-27 à 14 53 38

@florent37
Copy link
Member

what's your code ?

I think you're on web no ? the web is in beta & should not be used in production, here you have a good example of why :)

a circle path in web have an additional point which is (0, 0), we cannot change this until flutter fix it

@jaumard
Copy link
Contributor Author

jaumard commented May 27, 2020

No no not on web (but I've taken the screenshot on your web sample just to demo) I don't have the code of appbar usage because when I saw that I directly change as you did on the examples and have everything in the body with no app bar

@jaumard
Copy link
Contributor Author

jaumard commented May 27, 2020

Here is a quick sample:

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_neumorphic/flutter_neumorphic.dart';

class HistoryScreen extends StatelessWidget {
  static const route = '/history';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('History'),
        backgroundColor: NeumorphicColors.background,
        elevation: 0,
        actions: <Widget>[NeumorphicButton(child: Icon(Icons.add), onClick: (){

        },)],
      ),
      body: NeumorphicBackground(
        child: Container(),
      ),
    );
  }
}

It gives:

Capture d’écran 2020-05-27 à 15 34 51

With a dedicated appBar we could see the button more properly (with padding on the right, not being cut at the bottom) and we could override the default back button to be neumorphic too

@florent37
Copy link
Member

Yes it's a good widget to add :) can you try to add this into a pull Request ?

Or do you want me to do this ? (I can also ✌️) but you can contribute ;)

@florent37
Copy link
Member

The appbar I used is in the example project, I can reuse it and make it compatible with the ''prefered size widget (appbar inherit from it''

@florent37 florent37 added enhancement New feature or request widget labels May 27, 2020
@jaumard
Copy link
Contributor Author

jaumard commented May 27, 2020

I'm trying to dig a bit this myself by checking the material code, for now I ended up with this:

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_neumorphic/flutter_neumorphic.dart';

const double _kToolbarHeight = kToolbarHeight + 16 * 2;

class NeumorphicAppBar extends StatefulWidget implements PreferredSizeWidget {
  final Widget title;
  final Widget leading;
  final bool centerTitle;
  final List<Widget> actions;
  final bool automaticallyImplyLeading;

  /// The spacing around [title] content on the horizontal axis. This spacing is
  /// applied even if there is no [leading] content or [actions]. If you want
  /// [title] to take all the space available, set this value to 0.0.
  ///
  /// Defaults to [NavigationToolbar.kMiddleSpacing].
  final double titleSpacing;

  @override
  final Size preferredSize;

  NeumorphicAppBar({
    Key key,
    this.title,
    this.actions,
    this.leading,
    this.automaticallyImplyLeading = true,
    this.centerTitle,
    this.titleSpacing = NavigationToolbar.kMiddleSpacing,
  })  : preferredSize = Size.fromHeight(_kToolbarHeight),
        super(key: key);

  @override
  _NeumorphicAppBarState createState() => _NeumorphicAppBarState();

  bool _getEffectiveCenterTitle(ThemeData theme) {
    if (centerTitle != null) return centerTitle;
    assert(theme.platform != null);
    switch (theme.platform) {
      case TargetPlatform.android:
      case TargetPlatform.fuchsia:
      case TargetPlatform.linux:
      case TargetPlatform.windows:
        return false;
      case TargetPlatform.iOS:
      case TargetPlatform.macOS:
        return actions == null || actions.length < 2;
    }
    return null;
  }
}

class _NeumorphicAppBarState extends State<NeumorphicAppBar> {
  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    final ModalRoute<dynamic> parentRoute = ModalRoute.of(context);
    final bool canPop = parentRoute?.canPop ?? false;
    final bool useCloseButton = parentRoute is PageRoute<dynamic> && parentRoute.fullscreenDialog;
    final ScaffoldState scaffold = Scaffold.of(context, nullOk: true);
    final bool hasDrawer = scaffold?.hasDrawer ?? false;
    final bool hasEndDrawer = scaffold?.hasEndDrawer ?? false;

    Widget leading = widget.leading;
    if (leading == null && widget.automaticallyImplyLeading) {
      if (hasDrawer) {
        leading = NeumorphicButton(
          child: const Icon(Icons.menu),
          onClick: _handleDrawerButton,
          //tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
        );
      } else {
        if (canPop)
          leading = NeumorphicButton(
            child: useCloseButton ? const Icon(Icons.close) : const Icon(Icons.arrow_back),
            onClick: () => Navigator.maybePop(context),
          );
      }
    }
    if (leading != null) {
      leading = ConstrainedBox(
        constraints: const BoxConstraints.tightFor(width: kToolbarHeight),
        child: leading,
      );
    }

    Widget title = widget.title;
    if (title != null) {
      bool namesRoute;
      switch (theme.platform) {
        case TargetPlatform.android:
        case TargetPlatform.fuchsia:
        case TargetPlatform.linux:
        case TargetPlatform.windows:
          namesRoute = true;
          break;
        case TargetPlatform.iOS:
        case TargetPlatform.macOS:
          break;
      }

      final AppBarTheme appBarTheme = AppBarTheme.of(context);
      title = DefaultTextStyle(
        style: appBarTheme.textTheme?.headline6 ?? Theme.of(context).textTheme.headline6,
        softWrap: false,
        overflow: TextOverflow.ellipsis,
        child: title,
      );
    }

    Widget actions;
    if (widget.actions != null && widget.actions.isNotEmpty) {
      actions = Row(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: widget.actions,
      );
    } else if (hasEndDrawer) {
      actions = NeumorphicButton(
        child: const Icon(Icons.menu),
        onClick: _handleDrawerButtonEnd,
        //tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
      );
    }
    return NeumorphicBackground(
      child: SafeArea(
        bottom: false,
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: NavigationToolbar(
            leading: leading,
            middle: title,
            trailing: actions,
            centerMiddle: widget._getEffectiveCenterTitle(theme),
            middleSpacing: widget.titleSpacing,
          ),
        ),
      ),
    );
  }

  void _handleDrawerButton() {
    Scaffold.of(context).openDrawer();
  }

  void _handleDrawerButtonEnd() {
    Scaffold.of(context).openEndDrawer();
  }
}

Can be use like:

Scaffold(
      appBar: NeumorphicAppBar(
        title: Text('History'),
        actions: <Widget>[
          NeumorphicButton(
            child: Icon(Icons.add),
            onClick: () {},
          ),
          Container(width: 8,),
          NeumorphicButton(
            child: Icon(Icons.mic_none),
            onClick: () {},
          )
        ],
      ),
....

And give:
Capture d’écran 2020-05-27 à 17 48 08

I kind of like it so far :) I'll check what you did on the example too ^^

@jaumard
Copy link
Contributor Author

jaumard commented May 27, 2020

if you consider good enough at some point I can make a PR to officially add it as part of the package :)

@florent37
Copy link
Member

The code looks really good :) but the ui is strange, but don't know why, maybe the icons are too small or the buttons are too big :) but good work, I think we can add this directly into the project

@florent37
Copy link
Member

Maybe we can add an optional parameter to use circle or roundrect (or directly shape)

@jaumard
Copy link
Contributor Author

jaumard commented May 27, 2020

but the ui is strange, but don't know why, maybe the icons are too small or the buttons are too big :)

I didn't touch anything around that, it's the default size we get out of the box

circle or roundrect

I've think of it, but might be better to manage this from the Theme, (default circle or roundrect), and be able to override it if needed as field.

I'll work to cleanup this a bit and create a PR then :)

@florent37
Copy link
Member

Yes !

@florent37
Copy link
Member

I just updated one thing, I remove the appbar from neumorphic playgreound, just because of one thing : debug

I wanted to only have 1 neumorphic element on this screen, so if we have an issue with neumorphic, we know it's only this widget who have the bug

@jaumard
Copy link
Contributor Author

jaumard commented May 30, 2020

Sure :) I'll add a dedicate test file for app bar on next PR, to show all the possibilities

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request widget
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants