Skip to content
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
95 changes: 67 additions & 28 deletions lib/navigation_dot_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,29 @@ import 'package:flutter/material.dart';
class BottomNavigationDotBar extends StatefulWidget{

final List<BottomNavigationDotBarItem> items;
final Color activeColor;
final Color color;

const BottomNavigationDotBar({@required this.items, this.activeColor, this.color, Key key}): super(key: key);
final Color? activeColor;
final Color? color;
final int initialPosition;
final double? elevation;
final BorderRadiusGeometry? border;
final EdgeInsetsGeometry? padding;
final int? animationSpeed;
final CircleAvatar? indicator;
final bool useThemeColors;

const BottomNavigationDotBar({
required this.items,
this.activeColor,
this.color,
this.initialPosition = 0,
this.elevation,
this.border,
this.padding,
this.animationSpeed,
this.indicator,
this.useThemeColors = false,
Key? key
}): super(key: key);

@override
State<StatefulWidget> createState() => _BottomNavigationDotBarState();
Expand All @@ -18,31 +37,49 @@ class BottomNavigationDotBar extends StatefulWidget{
class _BottomNavigationDotBarState extends State<BottomNavigationDotBar>{

GlobalKey _keyBottomBar = GlobalKey();
double _numPositionBase, _numDifferenceBase, _positionLeftIndicatorDot;
int _indexPageSelected = 0;
Color _color, _activeColor;
double _numPositionBase = 0.0;
double _numDifferenceBase = 0.0;
double? _positionLeftIndicatorDot;
int _indexPageSelected = 1;
Color? _color;
Color? _activeColor;

double? _elevation;
BorderRadiusGeometry? _border;
EdgeInsetsGeometry? _padding;
int? _animationSpeed;
CircleAvatar? _indicator;

@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
_elevation = widget.elevation ?? 5;
_border = widget.border ?? BorderRadius.circular(10);
_padding = widget.padding ?? EdgeInsets.fromLTRB(10, 0, 10, 5);
_animationSpeed = widget.animationSpeed ?? 400;
_indicator = widget.indicator ?? CircleAvatar(radius: 2.5, backgroundColor: widget.useThemeColors ? _activeColor : Colors.black);
WidgetsBinding.instance!.addPostFrameCallback(_afterLayout);
super.initState();
}

_afterLayout(_) {
_indexPageSelected = widget.initialPosition;
_color = widget.color ?? Colors.black45;
_activeColor = widget.activeColor ?? Theme.of(context).primaryColor;
final sizeBottomBar = (_keyBottomBar.currentContext.findRenderObject() as RenderBox).size;

final sizeBottomBar = (_keyBottomBar.currentContext!.findRenderObject() as RenderBox).size;
_numPositionBase = ((sizeBottomBar.width / widget.items.length));
_numDifferenceBase = (_numPositionBase - (_numPositionBase / 2) + 2);
setState(() { _positionLeftIndicatorDot = _numPositionBase - _numDifferenceBase; });
setState(() {
_activeColor = widget.activeColor ?? Theme.of(context).primaryColor;
_positionLeftIndicatorDot = (_numPositionBase * (_indexPageSelected+1))-_numDifferenceBase;
});
}

@override
Widget build(BuildContext context) => Container (
padding: EdgeInsets.fromLTRB(5, 0, 5, 5),
padding: _padding,
child: Material(
elevation: 5,
borderRadius: BorderRadius.circular(10),
elevation: _elevation!,
borderRadius: _border,
child: Container(
padding: EdgeInsets.symmetric(vertical: 12),
child: Stack(
Expand All @@ -56,8 +93,8 @@ class _BottomNavigationDotBarState extends State<BottomNavigationDotBar>{
),
),
AnimatedPositioned(
child: CircleAvatar(radius: 2.5, backgroundColor: _activeColor),
duration: Duration(milliseconds: 400),
child: _indicator!,
duration: Duration(milliseconds: _animationSpeed!),
curve: Curves.fastOutSlowIn,
left: _positionLeftIndicatorDot,
bottom: 0
Expand All @@ -69,7 +106,7 @@ class _BottomNavigationDotBarState extends State<BottomNavigationDotBar>{
);

List<_NavigationIconButton> _createNavigationIconButtonList(Map<int, BottomNavigationDotBarItem> mapItem){
List<_NavigationIconButton> children = List<_NavigationIconButton>();
List<_NavigationIconButton> children = [];
mapItem.forEach((index, item) =>
children.add(_NavigationIconButton(item.icon, (index == _indexPageSelected) ? _activeColor : _color,item.onTap,() { _changeOptionBottomBar(index); }))
);
Expand All @@ -78,7 +115,9 @@ class _BottomNavigationDotBarState extends State<BottomNavigationDotBar>{

void _changeOptionBottomBar(int indexPageSelected){
if(indexPageSelected != _indexPageSelected){
setState(() { _positionLeftIndicatorDot = (_numPositionBase * (indexPageSelected+1))-_numDifferenceBase; });
setState(() {
_positionLeftIndicatorDot = (_numPositionBase * (indexPageSelected+1))-_numDifferenceBase;
});
_indexPageSelected = indexPageSelected;
}
}
Expand All @@ -88,19 +127,19 @@ class _BottomNavigationDotBarState extends State<BottomNavigationDotBar>{
class BottomNavigationDotBarItem{
final IconData icon;
final NavigationIconButtonTapCallback onTap;
const BottomNavigationDotBarItem({@required this.icon, this.onTap}) : assert(icon != null);
const BottomNavigationDotBarItem({required this.icon, required this.onTap}) : assert(icon != null);
}

typedef NavigationIconButtonTapCallback = void Function();

class _NavigationIconButton extends StatefulWidget {

final IconData _icon;
final Color _colorIcon;
final Color? _colorIcon;
final NavigationIconButtonTapCallback _onTapInternalButton;
final NavigationIconButtonTapCallback _onTapExternalButton;

const _NavigationIconButton(this._icon, this._colorIcon, this._onTapInternalButton, this._onTapExternalButton, {Key key}): super(key: key);
const _NavigationIconButton(this._icon, this._colorIcon, this._onTapInternalButton, this._onTapExternalButton, {Key? key}): super(key: key);

@override
_NavigationIconButtonState createState() => _NavigationIconButtonState();
Expand All @@ -109,37 +148,37 @@ class _NavigationIconButton extends StatefulWidget {

class _NavigationIconButtonState extends State<_NavigationIconButton> with SingleTickerProviderStateMixin {

AnimationController _controller;
Animation _scaleAnimation;
AnimationController? _controller;
Animation<double>? _scaleAnimation;
double _opacityIcon = 1;

@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: Duration(milliseconds: 200));
_scaleAnimation = Tween<double>(begin: 1, end: 0.93).animate(_controller);
_scaleAnimation = Tween<double>(begin: 1, end: 0.93).animate(_controller!.view);
}

@override
Widget build(BuildContext context) => GestureDetector(
onTapDown: (_) {
_controller.forward();
_controller!.forward();
setState(() { _opacityIcon = 0.7; });
},
onTapUp: (_) {
_controller.reverse();
_controller!.reverse();
setState(() { _opacityIcon = 1; });
},
onTapCancel: () {
_controller.reverse();
_controller!.reverse();
setState(() { _opacityIcon = 1; });
},
onTap: () {
widget._onTapInternalButton();
widget._onTapExternalButton();
},
child: ScaleTransition(
scale: _scaleAnimation,
scale: _scaleAnimation!,
child: AnimatedOpacity(
opacity: _opacityIcon,
duration: Duration(milliseconds: 200),
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ author: Juan Junior Chauca Flores <tiocoding@gmail.com>
homepage: https://github.com/TioCoding/flutter_navigation_dot_bar

environment:
sdk: ">=2.0.0-dev.68.0 <3.0.0"
sdk: '>=2.12.0 <3.0.0'

dependencies:
flutter:
Expand Down