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

feat: add badge and icon size feature #38

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 91 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# Fluid Navigation Bar


>Many thanks to gskinner for ["The vignettes" showcase](https://flutter.gskinner.com/) presented at Flutter Interact '19 :
They created an awesome creative experience and most of the code in this package comes from
their realisation. I was really impressed by their huge work but the code, even if it was open-sourced,
was not usable as it. So I did some refactoring for maintainability, I extracted some
fields to be able to adapt and skin the widget according to our design and decided to share it.
> Many thanks to gskinner for ["The vignettes" showcase](https://flutter.gskinner.com/) presented at Flutter Interact '19 :
> They created an awesome creative experience and most of the code in this package comes from
> their realisation. I was really impressed by their huge work but the code, even if it was open-sourced,
> was not usable as it. So I did some refactoring for maintainability, I extracted some
> fields to be able to adapt and skin the widget according to our design and decided to share it.
>
>Enjoy
> Enjoy

## Basic Usage

Expand Down Expand Up @@ -35,17 +34,19 @@ The example below shows you the minimal code to use the widget.
);
}
```

(1) Create an instance of `FluidNavBar`
(2) Set the icons, of type `FluidNavBarIcon`, to display in the navigation bar
(3) `FluidNavBarIcon` supports SVG asset or `IconData`
(4) Set the callback to react when the user tap an icon (the callback parameter contains the icon's index)
(4) Set the callback to react when the user tap an icon (the callback parameter contains the icon's index)

![basic usage sample](./doc/basic-usage.gif)

When defining `FluidNavBarIcon` you can provide an SVG asset or an `IconData`. Use the field `svgPath` for an SVG or
the field `icon` for an `IconData`.
When defining `FluidNavBarIcon` you can provide an SVG asset or an `IconData`. Use the field `svgPath` for an SVG or
the field `icon` for an `IconData`.

Example:

Example:
```dart
FluidNavBar(
icons: [
Expand All @@ -58,27 +59,67 @@ FluidNavBar(
backgroundColor: Color(0xFFEC4134),
extras: {"label": "bookmark"}),
],
```
```

**Note:** For backward compatibility (previous to v1.2.0) you can still use the field `iconPath` to set
the SVG asset to use (this is the same behaviour of `svgPath`). But this field has been deprecated and will
be removed in a future version.

## Badge and Icon size Usage

Example:

```dart
FluidNavBar(
icons: [
FluidNavBarIcon(
icon: Icons.bookmark_border,
backgroundColor: Color(0xFFEC4134),
extras: {"label": "bookmark"},
size: 35,
),
FluidNavBarIcon(
icon: Icons.apps,
backgroundColor: Color(0xFFFCBA02),
extras: {"label": "partner"},
badge: 3,
),
FluidNavBarIcon(
svgPath: "assets/calendar-fill.svg",
backgroundColor: Colors.indigo,
extras: {"label": "home"},
badge: 15,
),
],
)
```

![badge and icon size usage sample](./doc/badge-icon-size.gif)

Properties:

| Property | Description |
| ---------------------- | ------------------------------------------------ |
| `badge` | Badge value |
| `badgeBackgroundColor` | Set the background color for the badge container |
| `badgeTextColor` | Set the color for the badge text |
| `size` | Set the icon size |

## How To Style

`FluidNavBar` comes with a default set of styles which are directly inherited from the gskinner showcase.
You can override different properties to adapt the fluid navigation bar to your current design:

![style](./doc/styles.png)

- the bar background color (`Colors.white` by default)
- the icon background color (the same color as the bar background color by default)
- the icon foreground color when it's selected (`Colors.black` by default)
- the icon foreground color when it's unselected (`Colors.grey` by default)
- the bar background color (`Colors.white` by default)
- the icon background color (the same color as the bar background color by default)
- the icon foreground color when it's selected (`Colors.black` by default)
- the icon foreground color when it's unselected (`Colors.grey` by default)

### Global Styles

The easiest way is to define one or more properties in a `FluidNavBatStyle` and set this instance
The easiest way is to define one or more properties in a `FluidNavBatStyle` and set this instance
in the `style` property of the `FluidNavBar`:

```dart
Expand All @@ -95,24 +136,24 @@ FluidNavBar(
iconUnselectedForegroundColor: Colors.black
),
)
```
```

is displayed as:

![global style](./doc/global-style.png)

Properties:
Properties:

| Property | Description |
|-------|------|
| `barBackgroundColor` | Set the background color of the bar |
| `iconBackgroundColor` | Set the background color for all icons |
| `iconSelectedForegroundColor` | Set the foreground color for the selected icon |
| `iconUnselectedForegroundColor` | Set the background color for all unselected icons |
| Property | Description |
| ------------------------------- | ------------------------------------------------- |
| `barBackgroundColor` | Set the background color of the bar |
| `iconBackgroundColor` | Set the background color for all icons |
| `iconSelectedForegroundColor` | Set the foreground color for the selected icon |
| `iconUnselectedForegroundColor` | Set the background color for all unselected icons |

### Local Styles

You can also define some specific styles per icon, by using optional parameters of `FluidNavBarIcon`:
You can also define some specific styles per icon, by using optional parameters of `FluidNavBarIcon`:

```dart
FluidNavBar(
Expand All @@ -135,54 +176,52 @@ is displayed as
_Note: In this example I used also a global style for the foreground color of unselected icons, as I don't want
to set the same color for all icons_

Properties:
Properties:

| Property | Description |
|-------|------|
| `backgroundColor` | Set the background color of the icon |
| `selectedForegroundColor` | Set the foreground color for a selected icon |
| `unselectedForegroundColor` | Set the foreground color for all unselected icons |
| Property | Description |
| --------------------------- | ------------------------------------------------- |
| `backgroundColor` | Set the background color of the icon |
| `selectedForegroundColor` | Set the foreground color for a selected icon |
| `unselectedForegroundColor` | Set the foreground color for all unselected icons |

### Styles Priorities

You can define global styles, local styles, both or no style at all!
You can define global styles, local styles, both or no style at all!

To define the proper style to apply it tries, for each style, to resolve its value in the following order:
1- local style
2- global style
3- default value
when a value is resolved then it applies it to the widget.
1- local style
2- global style
3- default value
when a value is resolved then it applies it to the widget.

For example if you set the global style `iconBackgroundColor` to `Colors.red` and you also
set the local style `backgroundColor` to `Colors.green` for an icon, then it will use the green color
as the local style will be resolved before the global one.


## Other options

There are also few options, you can play with. They are global options and accessible throw `FluidNaBar` fields.

| Property | Description |
|-------|------|
| `animationFactor` | Set the factor to boost or slowdown animation. The default value is 1.0. If you use a value < 1 then the animation will be faster, if you use a value > 1 the animation will be slower |
| `scaleFactor` | Define the factor used by the animation to zoom the selected icon. The default value is 1.2. If the value is > 1 then it is a zoom-in, if you use a value < 1 then it is zoom-out |
| `defaultIndex` | Set to change selected item on start of the application. By default set to 0. |

| Property | Description |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `animationFactor` | Set the factor to boost or slowdown animation. The default value is 1.0. If you use a value < 1 then the animation will be faster, if you use a value > 1 the animation will be slower |
| `scaleFactor` | Define the factor used by the animation to zoom the selected icon. The default value is 1.2. If the value is > 1 then it is a zoom-in, if you use a value < 1 then it is zoom-out |
| `defaultIndex` | Set to change selected item on start of the application. By default set to 0. |

For an `animationFactor` of 2.0 (slower) and a `scaleFactor` of 2.0 (a zoom-in bigger than the default one), the result is:
![other options](./doc/other-options.gif)


## Contributions

Feel free to create an issue if you find a bug or if you need new features. Of course PRs are welcome!
Feel free to create an issue if you find a bug or if you need new features. Of course PRs are welcome!

If you want to contact me on Twitter: @etaix

### Contributors

Many thanks to these contributors:
- Umair M
- Dmitriy Govorov
- Christos Tsortanidis
- Dorbmon
Many thanks to these contributors:

- Umair M
- Dmitriy Govorov
- Christos Tsortanidis
- Dorbmon
Binary file added doc/badge-icon-size.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 24 additions & 12 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,33 @@ class _FluidNavBarDemoState extends State {
bottomNavigationBar: FluidNavBar(
icons: [
FluidNavBarIcon(
svgPath: "assets/home.svg",
backgroundColor: Color(0xFF4285F4),
extras: {"label": "home"}),
svgPath: "assets/home.svg",
backgroundColor: Color(0xFF4285F4),
extras: {"label": "home"},
),
FluidNavBarIcon(
icon: Icons.bookmark_border,
backgroundColor: Color(0xFFEC4134),
extras: {"label": "bookmark"}),
icon: Icons.bookmark_border,
backgroundColor: Color(0xFFEC4134),
extras: {"label": "bookmark"},
size: 35,
),
FluidNavBarIcon(
icon: Icons.apps,
backgroundColor: Color(0xFFFCBA02),
extras: {"label": "partner"}),
icon: Icons.apps,
backgroundColor: Color(0xFFFCBA02),
extras: {"label": "partner"},
badge: 3,
),
FluidNavBarIcon(
svgPath: "assets/conference.svg",
backgroundColor: Color(0xFF34A950),
extras: {"label": "conference"}),
svgPath: "assets/conference.svg",
backgroundColor: Color(0xFF34A950),
extras: {"label": "conference"},
),
FluidNavBarIcon(
svgPath: "assets/calendar-fill.svg",
backgroundColor: Colors.indigo,
extras: {"label": "home"},
badge: 10,
),
],
onChange: _handleNavigationChange,
style: FluidNavBarStyle(iconUnselectedForegroundColor: Colors.white),
Expand Down
37 changes: 18 additions & 19 deletions lib/src/fluid_nav_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -162,18 +162,19 @@ class _FluidNavBarState extends State<FluidNavBar> with TickerProviderStateMixin
(entry) => widget.itemBuilder(
entry.value,
FluidNavBarItem(
entry.value.svgPath ?? entry.value.svgPath,
entry.value.icon,
_currentIndex == entry.key,
() => _handleTap(entry.key),
entry.value.selectedForegroundColor ?? widget.style?.iconSelectedForegroundColor ?? Colors.black,
entry.value.unselectedForegroundColor ?? widget.style?.iconUnselectedForegroundColor ?? Colors.grey,
entry.value.backgroundColor ??
widget.style?.iconBackgroundColor ??
widget.style?.barBackgroundColor ??
Colors.white,
widget.scaleFactor,
widget.animationFactor,
badge: entry.value.badge,
badgeBackgroundColor: entry.value.badgeBackgroundColor,
badgeTextColor: entry.value.badgeTextColor,
size: entry.value.size,
svgPath: entry.value.svgPath,
icon: entry.value.icon,
selected: _currentIndex == entry.key,
onTap: () => _handleTap(entry.key),
selectedForegroundColor: entry.value.selectedForegroundColor ?? widget.style?.iconSelectedForegroundColor ?? Colors.black,
unselectedForegroundColor: entry.value.unselectedForegroundColor ?? widget.style?.iconUnselectedForegroundColor ?? Colors.grey,
backgroundColor: entry.value.backgroundColor ?? widget.style?.iconBackgroundColor ?? widget.style?.barBackgroundColor ?? Colors.white,
scaleFactor: widget.scaleFactor,
animationFactor: widget.animationFactor,
),
),
)
Expand Down Expand Up @@ -253,15 +254,13 @@ class _BackgroundCurvePainter extends CustomPainter {

final radius = Tween<double>(begin: _radiusTop, end: _radiusBottom).transform(norm);
// Point colinear to the top edge of the background pane
final anchorControlOffset =
Tween<double>(begin: radius * _horizontalControlTop, end: radius * _horizontalControlBottom)
.transform(LinearPointCurve(0.5, 0.75).transform(norm));
final anchorControlOffset = Tween<double>(begin: radius * _horizontalControlTop, end: radius * _horizontalControlBottom)
.transform(LinearPointCurve(0.5, 0.75).transform(norm));
// Point that slides up and down depending on distance for the target x position
final dipControlOffset = Tween<double>(begin: radius * _pointControlTop, end: radius * _pointControlBottom)
.transform(LinearPointCurve(0.5, 0.8).transform(norm));
final dipControlOffset =
Tween<double>(begin: radius * _pointControlTop, end: radius * _pointControlBottom).transform(LinearPointCurve(0.5, 0.8).transform(norm));
final y = Tween<double>(begin: _topY, end: _bottomY).transform(LinearPointCurve(0.2, 0.7).transform(norm));
final dist =
Tween<double>(begin: _topDistance, end: _bottomDistance).transform(LinearPointCurve(0.5, 0.0).transform(norm));
final dist = Tween<double>(begin: _topDistance, end: _bottomDistance).transform(LinearPointCurve(0.5, 0.0).transform(norm));
final x0 = _x - dist / 2;
final x1 = _x + dist / 2;

Expand Down
16 changes: 16 additions & 0 deletions lib/src/fluid_nav_bar_icon.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ import 'package:flutter/cupertino.dart';
/// * [FluidNavBar]

class FluidNavBarIcon {
/// The badge amount
final int? badge;

// The background color of the badge container
final Color? badgeBackgroundColor;

// The color used to badge text
final Color? badgeTextColor;

// The icon or svg size
final double? size;

/// The path of the SVG asset
@deprecated
final String? iconPath;
Expand All @@ -30,6 +42,10 @@ class FluidNavBarIcon {
final Map<String, dynamic>? extras;

FluidNavBarIcon({
this.size,
this.badge,
this.badgeBackgroundColor,
this.badgeTextColor,
this.iconPath,
this.svgPath,
this.icon,
Expand Down
Loading