Untitled
unknown
dart
2 years ago
6.2 kB
4
Indexable
import 'package:flutter/material.dart'; import 'package:meta/meta.dart'; import 'src/nav_button.dart'; import 'src/nav_custom_painter.dart'; typedef _LetIndexPage = bool Function(int value); class CurvedNavigationBar extends StatefulWidget { final List<Widget> items; final int index; final Color color; final Color? buttonBackgroundColor; final Color backgroundColor; final ValueChanged<int>? onTap; final _LetIndexPage letIndexChange; final Curve animationCurve; final Duration animationDuration; final double height; CurvedNavigationBar({ Key? key, required this.items, this.index = 0, this.color = Colors.white, this.buttonBackgroundColor, this.backgroundColor = Colors.blueAccent, this.onTap, _LetIndexPage? letIndexChange, this.animationCurve = Curves.easeOut, this.animationDuration = const Duration(milliseconds: 600), this.height = 75.0, }) : letIndexChange = letIndexChange ?? ((_) => true), assert(items != null), assert(items.length >= 1), assert(0 <= index && index < items.length), assert(0 <= height && height <= 75.0), super(key: key); @override CurvedNavigationBarState createState() => CurvedNavigationBarState(); } class CurvedNavigationBarState extends State<CurvedNavigationBar> with SingleTickerProviderStateMixin { late double _startingPos; int _endingIndex = 0; late double _pos; double _buttonHide = 0; late Widget _icon; late AnimationController _animationController; late int _length; @override void initState() { super.initState(); _icon = widget.items[widget.index]; _length = widget.items.length; _pos = widget.index / _length; _startingPos = widget.index / _length; _animationController = AnimationController(vsync: this, value: _pos); _animationController.addListener(() { setState(() { _pos = _animationController.value; final endingPos = _endingIndex / widget.items.length; final middle = (endingPos + _startingPos) / 2; if ((endingPos - _pos).abs() < (_startingPos - _pos).abs()) { _icon = widget.items[_endingIndex]; } _buttonHide = (1 - ((middle - _pos) / (_startingPos - middle)).abs()).abs(); }); }); } @override void didUpdateWidget(CurvedNavigationBar oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.index != widget.index) { final newPosition = widget.index / _length; _startingPos = _pos; _endingIndex = widget.index; _animationController.animateTo(newPosition, duration: widget.animationDuration, curve: widget.animationCurve); } } @override void dispose() { _animationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; print(widget.index); return Container( height: widget.height, color: widget.backgroundColor, child: Stack( clipBehavior: Clip.none, alignment: Alignment.bottomCenter, children: <Widget>[ Positioned( bottom: -40 - (75.0 - widget.height), left: Directionality.of(context) == TextDirection.rtl ? null : _pos * size.width, right: Directionality.of(context) == TextDirection.rtl ? _pos * size.width : null, width: size.width / _length, child: Center( child: Transform.translate( offset: Offset( 0, -(1 - _buttonHide) * 80, ), child: Material( // elevation: 50, color: widget.buttonBackgroundColor ?? widget.color, // borderRadius: widget.index != 0 && widget.index != 4 // ? const BorderRadius.only( // topLeft: Radius.circular(15), // topRight: Radius.circular(15), // ) // : const BorderRadius.only( // topLeft: Radius.circular(0), // topRight: Radius.circular(0), // ), type: MaterialType.circle, child: Padding( padding: const EdgeInsets.all(8.0), child: _icon, ), ), ), ), ), Positioned( left: 0, right: 0, bottom: 0 - (75.0 - widget.height), child: CustomPaint( painter: NavCustomPainter(_pos, _length, Colors.transparent, Directionality.of(context)), child: Container( height: 75.0, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(15), topRight: Radius.circular(15), ), // border: Border.all(color: Colors.black), ), ), ), ), Positioned( left: 0, right: 0, bottom: 0 - (75.0 - widget.height), child: SizedBox( height: 100.0, child: Row( children: widget.items.map((item) { return NavButton( onTap: _buttonTap, position: _pos, length: _length, index: widget.items.indexOf(item), child: Center(child: item), ); }).toList())), ), ], ), ); } void setPage(int index) { _buttonTap(index); } void _buttonTap(int index) { if (!widget.letIndexChange(index)) { return; } if (widget.onTap != null) { widget.onTap!(index); } final newPosition = index / _length; setState(() { _startingPos = _pos; _endingIndex = index; _animationController.animateTo(newPosition, duration: widget.animationDuration, curve: widget.animationCurve); }); } }
Editor is loading...