1
+ using System . Collections . Generic ;
2
+ using Unity . UIWidgets . foundation ;
3
+ using Unity . UIWidgets . gestures ;
4
+ using Unity . UIWidgets . painting ;
5
+ using Unity . UIWidgets . rendering ;
6
+ using Unity . UIWidgets . ui ;
7
+ using Unity . UIWidgets . widgets ;
8
+ using TextStyle = Unity . UIWidgets . painting . TextStyle ;
9
+
10
+ namespace Unity . UIWidgets . cupertino {
11
+ class BottomAppBarUtils {
12
+ public const float _kTabBarHeight = 50.0f ;
13
+ public static readonly Color _kDefaultTabBarBorderColor = new Color ( 0x4C000000 ) ;
14
+ }
15
+
16
+
17
+ public class CupertinoTabBar : StatelessWidget {
18
+ public CupertinoTabBar (
19
+ Key key = null ,
20
+ List < BottomNavigationBarItem > items = null ,
21
+ ValueChanged < int > onTap = null ,
22
+ int currentIndex = 0 ,
23
+ Color backgroundColor = null ,
24
+ Color activeColor = null ,
25
+ Color inactiveColor = null ,
26
+ float iconSize = 30.0f ,
27
+ Border border = null
28
+ ) : base ( key : key ) {
29
+ D . assert ( items != null ) ;
30
+ D . assert ( items . Count >= 2 ,
31
+ ( ) => "Tabs need at least 2 items to conform to Apple's HIG"
32
+ ) ;
33
+ D . assert ( 0 <= currentIndex && currentIndex < items . Count ) ;
34
+ D . assert ( inactiveColor != null ) ;
35
+ this . items = items ;
36
+ this . onTap = onTap ;
37
+ this . currentIndex = currentIndex ;
38
+
39
+ this . backgroundColor = backgroundColor ;
40
+ this . activeColor = activeColor ;
41
+ this . inactiveColor = inactiveColor ?? CupertinoColors . inactiveGray ;
42
+ this . iconSize = iconSize ;
43
+ this . border = border ?? new Border (
44
+ top : new BorderSide (
45
+ color : BottomAppBarUtils . _kDefaultTabBarBorderColor ,
46
+ width : 0.0f , // One physical pixel.
47
+ style : BorderStyle . solid
48
+ )
49
+ ) ;
50
+ }
51
+
52
+ public readonly List < BottomNavigationBarItem > items ;
53
+
54
+ public readonly ValueChanged < int > onTap ;
55
+
56
+ public readonly int currentIndex ;
57
+
58
+ public readonly Color backgroundColor ;
59
+
60
+ public readonly Color activeColor ;
61
+
62
+ public readonly Color inactiveColor ;
63
+
64
+ public readonly float iconSize ;
65
+
66
+ public readonly Border border ;
67
+
68
+ public Size preferredSize {
69
+ get { return Size . fromHeight ( BottomAppBarUtils . _kTabBarHeight ) ; }
70
+ }
71
+
72
+ public bool opaque ( BuildContext context ) {
73
+ Color backgroundColor =
74
+ this . backgroundColor ?? CupertinoTheme . of ( context ) . barBackgroundColor ;
75
+ return backgroundColor . alpha == 0xFF ;
76
+ }
77
+
78
+ public override Widget build ( BuildContext context ) {
79
+ float bottomPadding = MediaQuery . of ( context ) . padding . bottom ;
80
+
81
+ Widget result = new DecoratedBox (
82
+ decoration : new BoxDecoration (
83
+ border : this . border ,
84
+ color : this . backgroundColor ?? CupertinoTheme . of ( context ) . barBackgroundColor
85
+ ) ,
86
+ child : new SizedBox (
87
+ height : BottomAppBarUtils . _kTabBarHeight + bottomPadding ,
88
+ child : IconTheme . merge ( // Default with the inactive state.
89
+ data : new IconThemeData (
90
+ color : this . inactiveColor ,
91
+ size : this . iconSize
92
+ ) ,
93
+ child : new DefaultTextStyle ( // Default with the inactive state.
94
+ style : CupertinoTheme . of ( context ) . textTheme . tabLabelTextStyle
95
+ . copyWith ( color : this . inactiveColor ) ,
96
+ child : new Padding (
97
+ padding : EdgeInsets . only ( bottom : bottomPadding ) ,
98
+ child : new Row (
99
+ crossAxisAlignment : CrossAxisAlignment . end ,
100
+ children : this . _buildTabItems ( context )
101
+ )
102
+ )
103
+ )
104
+ )
105
+ )
106
+ ) ;
107
+
108
+ if ( ! this . opaque ( context ) ) {
109
+ result = new ClipRect (
110
+ child : new BackdropFilter (
111
+ filter : ImageFilter . blur ( sigmaX : 10.0f , sigmaY : 10.0f ) ,
112
+ child : result
113
+ )
114
+ ) ;
115
+ }
116
+
117
+ return result ;
118
+ }
119
+
120
+ List < Widget > _buildTabItems ( BuildContext context ) {
121
+ List < Widget > result = new List < Widget > { } ;
122
+
123
+ for ( int index = 0 ; index < this . items . Count ; index += 1 ) {
124
+ bool active = index == this . currentIndex ;
125
+ result . Add (
126
+ this . _wrapActiveItem (
127
+ context ,
128
+ new Expanded (
129
+ child : new GestureDetector (
130
+ behavior : HitTestBehavior . opaque ,
131
+ onTap : this . onTap == null ? null : ( GestureTapCallback ) ( ( ) => { this . onTap ( index ) ; } ) ,
132
+ child : new Padding (
133
+ padding : EdgeInsets . only ( bottom : 4.0f ) ,
134
+ child : new Column (
135
+ mainAxisAlignment : MainAxisAlignment . end ,
136
+ children : this . _buildSingleTabItem ( this . items [ index ] , active )
137
+ )
138
+ )
139
+ )
140
+ ) ,
141
+ active : active
142
+ )
143
+ ) ;
144
+ }
145
+
146
+ return result ;
147
+ }
148
+
149
+ List < Widget > _buildSingleTabItem ( BottomNavigationBarItem item , bool active ) {
150
+ List < Widget > components = new List < Widget > {
151
+ new Expanded (
152
+ child : new Center ( child : active ? item . activeIcon : item . icon )
153
+ )
154
+ } ;
155
+
156
+ if ( item . title != null ) {
157
+ components . Add ( item . title ) ;
158
+ }
159
+
160
+ return components ;
161
+ }
162
+
163
+ Widget _wrapActiveItem ( BuildContext context , Widget item , bool active ) {
164
+ if ( ! active ) {
165
+ return item ;
166
+ }
167
+
168
+ Color activeColor = this . activeColor ?? CupertinoTheme . of ( context ) . primaryColor ;
169
+ return IconTheme . merge (
170
+ data : new IconThemeData ( color : activeColor ) ,
171
+ child : DefaultTextStyle . merge (
172
+ style : new TextStyle ( color : activeColor ) ,
173
+ child : item
174
+ )
175
+ ) ;
176
+ }
177
+
178
+ public CupertinoTabBar copyWith (
179
+ Key key = null ,
180
+ List < BottomNavigationBarItem > items = null ,
181
+ Color backgroundColor = null ,
182
+ Color activeColor = null ,
183
+ Color inactiveColor = null ,
184
+ float ? iconSize = null ,
185
+ Border border = null ,
186
+ int ? currentIndex = null ,
187
+ ValueChanged < int > onTap = null
188
+ ) {
189
+ return new CupertinoTabBar (
190
+ key : key ?? this . key ,
191
+ items : items ?? this . items ,
192
+ backgroundColor : backgroundColor ?? this . backgroundColor ,
193
+ activeColor : activeColor ?? this . activeColor ,
194
+ inactiveColor : inactiveColor ?? this . inactiveColor ,
195
+ iconSize : iconSize ?? this . iconSize ,
196
+ border : border ?? this . border ,
197
+ currentIndex : currentIndex ?? this . currentIndex ,
198
+ onTap : onTap ?? this . onTap
199
+ ) ;
200
+ }
201
+ }
202
+ }
0 commit comments