1
+ using System ;
2
+ using System . Collections . Generic ;
3
+ using Unity . UIWidgets . animation ;
4
+ using Unity . UIWidgets . foundation ;
5
+ using Unity . UIWidgets . painting ;
6
+ using Unity . UIWidgets . ui ;
7
+ using Unity . UIWidgets . widgets ;
8
+
9
+ namespace Unity . UIWidgets . cupertino {
10
+ public class CupertinoPageScaffold : StatefulWidget {
11
+ /// Creates a layout for pages with a navigation bar at the top.
12
+ public CupertinoPageScaffold (
13
+ Widget child ,
14
+ Key key = null ,
15
+ ObstructingPreferredSizeWidget navigationBar = null ,
16
+ Color backgroundColor = null ,
17
+ bool resizeToAvoidBottomInset = true
18
+ ) : base ( key : key ) {
19
+ D . assert ( child != null ) ;
20
+ D . assert ( resizeToAvoidBottomInset != null ) ;
21
+
22
+ this . child = child ;
23
+ this . navigationBar = navigationBar ;
24
+ this . backgroundColor = backgroundColor ;
25
+ this . resizeToAvoidBottomInset = resizeToAvoidBottomInset ;
26
+ }
27
+
28
+ public readonly ObstructingPreferredSizeWidget navigationBar ;
29
+ public readonly Widget child ;
30
+ public readonly Color backgroundColor ;
31
+ public readonly bool resizeToAvoidBottomInset ;
32
+
33
+
34
+ public override State createState ( ) {
35
+ return new _CupertinoPageScaffoldState ( ) ;
36
+ }
37
+ }
38
+
39
+ class _CupertinoPageScaffoldState : State < CupertinoPageScaffold > {
40
+ public readonly ScrollController _primaryScrollController = new ScrollController ( ) ;
41
+
42
+ void _handleStatusBarTap ( ) {
43
+ // Only act on the scroll controller if it has any attached scroll positions.
44
+ if ( this . _primaryScrollController . hasClients ) {
45
+ this . _primaryScrollController . animateTo (
46
+ 0.0f ,
47
+ duration : new TimeSpan ( 0 , 0 , 0 , 0 , 500 ) ,
48
+ curve : Curves . linearToEaseOut
49
+ ) ;
50
+ }
51
+ }
52
+
53
+ public override Widget build ( BuildContext context ) {
54
+ List < Widget > stacked = new List < Widget > ( ) ;
55
+
56
+ Widget paddedContent = this . widget . child ;
57
+
58
+ MediaQueryData existingMediaQuery = MediaQuery . of ( context ) ;
59
+ if ( this . widget . navigationBar != null ) {
60
+ float topPadding = this . widget . navigationBar . preferredSize . height + existingMediaQuery . padding . top ;
61
+
62
+ float bottomPadding = this . widget . resizeToAvoidBottomInset
63
+ ? existingMediaQuery . viewInsets . bottom
64
+ : 0.0f ;
65
+
66
+ EdgeInsets newViewInsets = this . widget . resizeToAvoidBottomInset
67
+ ? existingMediaQuery . viewInsets . copyWith ( bottom : 0.0f )
68
+ : existingMediaQuery . viewInsets ;
69
+
70
+ bool fullObstruction =
71
+ this . widget . navigationBar . fullObstruction == false
72
+ ? CupertinoTheme . of ( context ) . barBackgroundColor . alpha == 0xFF
73
+ : this . widget . navigationBar . fullObstruction ;
74
+
75
+ if ( fullObstruction ) {
76
+ paddedContent = new MediaQuery (
77
+ data : existingMediaQuery
78
+ . removePadding ( removeTop : true )
79
+ . copyWith (
80
+ viewInsets : newViewInsets
81
+ ) ,
82
+ child : new Padding (
83
+ padding : EdgeInsets . only ( top : topPadding , bottom : bottomPadding ) ,
84
+ child : paddedContent
85
+ )
86
+ ) ;
87
+ }
88
+ else {
89
+ paddedContent = new MediaQuery (
90
+ data : existingMediaQuery . copyWith (
91
+ padding : existingMediaQuery . padding . copyWith (
92
+ top : topPadding
93
+ ) ,
94
+ viewInsets : newViewInsets
95
+ ) ,
96
+ child : new Padding (
97
+ padding : EdgeInsets . only ( bottom : bottomPadding ) ,
98
+ child : paddedContent
99
+ )
100
+ ) ;
101
+ }
102
+ }
103
+
104
+ stacked . Add ( new PrimaryScrollController (
105
+ controller : this . _primaryScrollController ,
106
+ child : paddedContent
107
+ ) ) ;
108
+
109
+ if ( this . widget . navigationBar != null ) {
110
+ stacked . Add ( new Positioned (
111
+ top : 0.0f ,
112
+ left : 0.0f ,
113
+ right : 0.0f ,
114
+ child : this . widget . navigationBar
115
+ ) ) ;
116
+ }
117
+
118
+ stacked . Add ( new Positioned (
119
+ top : 0.0f ,
120
+ left : 0.0f ,
121
+ right : 0.0f ,
122
+ height : existingMediaQuery . padding . top ,
123
+ child : new GestureDetector (
124
+ onTap : this . _handleStatusBarTap
125
+ )
126
+ )
127
+ ) ;
128
+
129
+ return new DecoratedBox (
130
+ decoration : new BoxDecoration (
131
+ color : this . widget . backgroundColor ?? CupertinoTheme . of ( context ) . scaffoldBackgroundColor
132
+ ) ,
133
+ child : new Stack (
134
+ children : stacked
135
+ )
136
+ ) ;
137
+ }
138
+ }
139
+
140
+ public abstract class ObstructingPreferredSizeWidget : PreferredSizeWidget {
141
+ public bool fullObstruction { get ; }
142
+ }
143
+ }
0 commit comments