Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
7f3485e3
Unverified
Commit
7f3485e3
authored
Mar 27, 2019
by
xster
Committed by
GitHub
Mar 27, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Let CupertinoPageScaffold have tap status bar to scroll to top (#29946)
parent
0b687122
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
102 additions
and
14 deletions
+102
-14
page_scaffold.dart
packages/flutter/lib/src/cupertino/page_scaffold.dart
+50
-14
scaffold_test.dart
packages/flutter/test/cupertino/scaffold_test.dart
+52
-0
No files found.
packages/flutter/lib/src/cupertino/page_scaffold.dart
View file @
7f3485e3
...
...
@@ -16,7 +16,7 @@ import 'theme.dart';
/// * [CupertinoTabScaffold], a similar widget for tabbed applications.
/// * [CupertinoPageRoute], a modal page route that typically hosts a
/// [CupertinoPageScaffold] with support for iOS-style page transitions.
class
CupertinoPageScaffold
extends
State
less
Widget
{
class
CupertinoPageScaffold
extends
State
ful
Widget
{
/// Creates a layout for pages with a navigation bar at the top.
const
CupertinoPageScaffold
({
Key
key
,
...
...
@@ -61,32 +61,51 @@ class CupertinoPageScaffold extends StatelessWidget {
/// Defaults to true and cannot be null.
final
bool
resizeToAvoidBottomInset
;
@override
_CupertinoPageScaffoldState
createState
()
=>
_CupertinoPageScaffoldState
();
}
class
_CupertinoPageScaffoldState
extends
State
<
CupertinoPageScaffold
>
{
final
ScrollController
_primaryScrollController
=
ScrollController
();
void
_handleStatusBarTap
()
{
// Only act on the scroll controller if it has any attached scroll positions.
if
(
_primaryScrollController
.
hasClients
)
{
_primaryScrollController
.
animateTo
(
0.0
,
// Eyeballed from iOS.
duration:
const
Duration
(
milliseconds:
500
),
curve:
Curves
.
linearToEaseOut
,
);
}
}
@override
Widget
build
(
BuildContext
context
)
{
final
List
<
Widget
>
stacked
=
<
Widget
>[];
Widget
paddedContent
=
child
;
if
(
navigationBar
!=
null
)
{
final
MediaQueryData
existingMediaQuery
=
MediaQuery
.
of
(
context
);
Widget
paddedContent
=
widget
.
child
;
final
MediaQueryData
existingMediaQuery
=
MediaQuery
.
of
(
context
);
if
(
widget
.
navigationBar
!=
null
)
{
// TODO(xster): Use real size after partial layout instead of preferred size.
// https://github.com/flutter/flutter/issues/12912
final
double
topPadding
=
navigationBar
.
preferredSize
.
height
+
existingMediaQuery
.
padding
.
top
;
widget
.
navigationBar
.
preferredSize
.
height
+
existingMediaQuery
.
padding
.
top
;
// Propagate bottom padding and include viewInsets if appropriate
final
double
bottomPadding
=
resizeToAvoidBottomInset
final
double
bottomPadding
=
widget
.
resizeToAvoidBottomInset
?
existingMediaQuery
.
viewInsets
.
bottom
:
0.0
;
final
EdgeInsets
newViewInsets
=
resizeToAvoidBottomInset
final
EdgeInsets
newViewInsets
=
widget
.
resizeToAvoidBottomInset
// The insets are consumed by the scaffolds and no longer exposed to
// the descendant subtree.
?
existingMediaQuery
.
viewInsets
.
copyWith
(
bottom:
0.0
)
:
existingMediaQuery
.
viewInsets
;
final
bool
fullObstruction
=
navigationBar
.
fullObstruction
??
CupertinoTheme
.
of
(
context
).
barBackgroundColor
.
alpha
==
0xFF
;
widget
.
navigationBar
.
fullObstruction
??
CupertinoTheme
.
of
(
context
).
barBackgroundColor
.
alpha
==
0xFF
;
// If navigation bar is opaquely obstructing, directly shift the main content
// down. If translucent, let main content draw behind navigation bar but hint the
...
...
@@ -101,7 +120,7 @@ class CupertinoPageScaffold extends StatelessWidget {
),
child:
Padding
(
padding:
EdgeInsets
.
only
(
top:
topPadding
,
bottom:
bottomPadding
),
child:
child
,
child:
paddedContent
,
),
);
}
else
{
...
...
@@ -114,27 +133,44 @@ class CupertinoPageScaffold extends StatelessWidget {
),
child:
Padding
(
padding:
EdgeInsets
.
only
(
bottom:
bottomPadding
),
child:
child
,
child:
paddedContent
,
),
);
}
}
// The main content being at the bottom is added to the stack first.
stacked
.
add
(
paddedContent
);
stacked
.
add
(
PrimaryScrollController
(
controller:
_primaryScrollController
,
child:
paddedContent
,
));
if
(
navigationBar
!=
null
)
{
if
(
widget
.
navigationBar
!=
null
)
{
stacked
.
add
(
Positioned
(
top:
0.0
,
left:
0.0
,
right:
0.0
,
child:
navigationBar
,
child:
widget
.
navigationBar
,
));
}
// Add a touch handler the size of the status bar on top of all contents
// to handle scroll to top by status bar taps.
stacked
.
add
(
Positioned
(
top:
0.0
,
left:
0.0
,
right:
0.0
,
height:
existingMediaQuery
.
padding
.
top
,
child:
GestureDetector
(
excludeFromSemantics:
true
,
onTap:
_handleStatusBarTap
,
),
),
);
return
DecoratedBox
(
decoration:
BoxDecoration
(
color:
backgroundColor
??
CupertinoTheme
.
of
(
context
).
scaffoldBackgroundColor
,
color:
widget
.
backgroundColor
??
CupertinoTheme
.
of
(
context
).
scaffoldBackgroundColor
,
),
child:
Stack
(
children:
stacked
,
...
...
packages/flutter/test/cupertino/scaffold_test.dart
View file @
7f3485e3
...
...
@@ -343,4 +343,56 @@ testWidgets('Opaque bar pushes contents down', (WidgetTester tester) async {
final
BoxDecoration
decoration
=
decoratedBox
.
decoration
;
expect
(
decoration
.
color
,
const
Color
(
0xFF010203
));
});
testWidgets
(
'Lists in CupertinoPageScaffold scroll to the top when status bar tapped'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
CupertinoApp
(
builder:
(
BuildContext
context
,
Widget
child
)
{
// Acts as a 20px status bar at the root of the app.
return
MediaQuery
(
data:
MediaQuery
.
of
(
context
).
copyWith
(
padding:
const
EdgeInsets
.
only
(
top:
20
)),
child:
child
,
);
},
home:
CupertinoPageScaffold
(
// Default nav bar is translucent.
navigationBar:
const
CupertinoNavigationBar
(
middle:
Text
(
'Title'
),
),
child:
ListView
.
builder
(
itemExtent:
50
,
itemBuilder:
(
BuildContext
context
,
int
index
)
=>
Text
(
index
.
toString
()),
),
),
),
);
// Top media query padding 20 + translucent nav bar 44.
expect
(
tester
.
getTopLeft
(
find
.
text
(
'0'
)).
dy
,
64
);
expect
(
tester
.
getTopLeft
(
find
.
text
(
'6'
)).
dy
,
364
);
await
tester
.
fling
(
find
.
text
(
'5'
),
// Find some random text on the screen.
const
Offset
(
0
,
-
200
),
20
,
);
await
tester
.
pumpAndSettle
();
expect
(
tester
.
getTopLeft
(
find
.
text
(
'6'
)).
dy
,
moreOrLessEquals
(
166.833
,
epsilon:
0.1
));
expect
(
tester
.
getTopLeft
(
find
.
text
(
'12'
)).
dy
,
moreOrLessEquals
(
466.8333333333334
,
epsilon:
0.1
));
// The media query top padding is 20. Tapping at 20 should do nothing.
await
tester
.
tapAt
(
const
Offset
(
400
,
20
));
await
tester
.
pumpAndSettle
();
expect
(
tester
.
getTopLeft
(
find
.
text
(
'6'
)).
dy
,
moreOrLessEquals
(
166.833
,
epsilon:
0.1
));
expect
(
tester
.
getTopLeft
(
find
.
text
(
'12'
)).
dy
,
moreOrLessEquals
(
466.8333333333334
,
epsilon:
0.1
));
// Tap 1 pixel higher.
await
tester
.
tapAt
(
const
Offset
(
400
,
19
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
500
));
expect
(
tester
.
getTopLeft
(
find
.
text
(
'0'
)).
dy
,
64
);
expect
(
tester
.
getTopLeft
(
find
.
text
(
'6'
)).
dy
,
364
);
expect
(
find
.
text
(
'12'
),
findsNothing
);
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment