forked from toly1994328/FlutterUnit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtoly_app_bar.dart
155 lines (132 loc) · 4.2 KB
/
toly_app_bar.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import 'package:flutter/material.dart';
import 'package:flutter_unit/app/res/cons.dart';
import 'package:flutter_unit/components/permanent/circle.dart';
class TolyAppBar extends StatefulWidget implements PreferredSizeWidget {
final Function(int, Color) onItemClick;
@override
_TolyAppBarState createState() => _TolyAppBarState();
final Size preferredSize;
final int selectIndex;
TolyAppBar({this.onItemClick, this.preferredSize, this.selectIndex = 0});
}
const _kBorderRadius = BorderRadius.only(
bottomLeft: Radius.circular(15),
bottomRight: Radius.circular(15),
);
const _kTabTextStyle = TextStyle(color: Colors.white, shadows: [
const Shadow(color: Colors.black, offset: Offset(0.5, 0.5), blurRadius: 0.5)
]);
class _TolyAppBarState extends State<TolyAppBar>
with SingleTickerProviderStateMixin {
double _width = 0;
int _selectIndex = 0;
List<int> colors = Cons.tabColors;
List info = Cons.tabs;
AnimationController _controller;
@override
void initState() {
_controller = AnimationController(
duration: const Duration(milliseconds: 300), vsync: this)
..addListener(_render)
..addStatusListener(_listenStatus);
_selectIndex = widget.selectIndex;
super.initState();
}
void _render() {
setState(() {});
}
void _listenStatus(AnimationStatus status) {
if (status == AnimationStatus.completed) {
setState(() {});
}
}
int get nextIndex => (_selectIndex + 1) % colors.length;
@override
Widget build(BuildContext context) {
_width = MediaQuery.of(context).size.width / colors.length;
return Container(
alignment: Alignment.center,
child: Flow(
delegate: TolyAppBarDelegate(
_selectIndex, _controller.value, widget.preferredSize.height),
children: [
...colors
.map((e) => GestureDetector(
onTap: () => _onTap(e), child: _buildChild(e)))
.toList(),
...colors.map((e) => Circle(
color: Color(e),
radius: 6,
))
]),
);
}
Widget _buildChild(int color) => Container(
alignment: const Alignment(0, 0.4),
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: _selectIndex == colors.indexOf(color)
? Colors.transparent
: Color(colors[_selectIndex]),
offset: Offset(1, 1),
blurRadius: 2)
], color: Color(color), borderRadius: _kBorderRadius),
height: widget.preferredSize.height + 20,
width: _width,
child: Text(
info[colors.indexOf(color)],
style: _kTabTextStyle,
),
);
_onTap(int color) {
setState(() {
_controller.reset();
_controller.forward();
_selectIndex = colors.indexOf(color);
if (widget.onItemClick != null)
widget.onItemClick(_selectIndex, Color(color));
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
class TolyAppBarDelegate extends FlowDelegate {
final int selectIndex;
final double factor;
final double height;
TolyAppBarDelegate(this.selectIndex, this.factor, this.height);
@override
void paintChildren(FlowPaintingContext context) {
double ox = 0;
double obx = 0;
for (int i = 0; i < context.childCount / 2; i++) {
var cSize = context.getChildSize(i);
if (i == selectIndex) {
context.paintChild(i,
transform: Matrix4.translationValues(ox, 20.0 * factor - 20, 0.0));
ox += cSize.width;
} else {
context.paintChild(i,
transform: Matrix4.translationValues(ox, -20, 0.0));
ox += cSize.width;
}
}
for (int i = (context.childCount / 2).floor();
i < context.childCount;
i++) {
if (i - (context.childCount / 2).floor() == selectIndex) {
obx += context.getChildSize(0).width;
} else {
context.paintChild(i,
transform: Matrix4.translationValues(
obx + context.getChildSize(0).width / 2 - 5, height + 5, 0));
obx += context.getChildSize(0).width;
}
}
}
@override
bool shouldRepaint(FlowDelegate oldDelegate) => true;
}