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
da27d674
Unverified
Commit
da27d674
authored
Mar 19, 2018
by
Ian Hickson
Committed by
GitHub
Mar 19, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move dialogs when keyboard pops up (#15426)
Fixes #7032
parent
076594b3
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
229 additions
and
24 deletions
+229
-24
dialog.dart
packages/flutter/lib/src/material/dialog.dart
+37
-13
media_query.dart
packages/flutter/lib/src/widgets/media_query.dart
+91
-6
dialog_test.dart
packages/flutter/test/material/dialog_test.dart
+52
-3
media_query_test.dart
packages/flutter/test/widgets/media_query_test.dart
+49
-2
No files found.
packages/flutter/lib/src/material/dialog.dart
View file @
da27d674
...
...
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:ui'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/widgets.dart'
;
...
...
@@ -38,6 +39,8 @@ class Dialog extends StatelessWidget {
const
Dialog
({
Key
key
,
this
.
child
,
this
.
insetAnimationDuration
:
const
Duration
(
milliseconds:
100
),
this
.
insetAnimationCurve
:
Curves
.
decelerate
,
})
:
super
(
key:
key
);
/// The widget below this widget in the tree.
...
...
@@ -45,25 +48,46 @@ class Dialog extends StatelessWidget {
/// {@macro flutter.widgets.child}
final
Widget
child
;
/// The duration of the animation to show when the system keyboard intrudes
/// into the space that the dialog is placed in.
///
/// Defaults to 100 milliseconds.
final
Duration
insetAnimationDuration
;
/// The curve to use for the animation shown when the system keyboard intrudes
/// into the space that the dialog is placed in.
///
/// Defaults to [Curves.fastOutSlowIn].
final
Curve
insetAnimationCurve
;
Color
_getColor
(
BuildContext
context
)
{
return
Theme
.
of
(
context
).
dialogBackgroundColor
;
}
@override
Widget
build
(
BuildContext
context
)
{
return
new
Center
(
child:
new
Container
(
margin:
const
EdgeInsets
.
symmetric
(
horizontal:
40.0
,
vertical:
24.0
),
child:
new
ConstrainedBox
(
constraints:
const
BoxConstraints
(
minWidth:
280.0
),
child:
new
Material
(
elevation:
24.0
,
color:
_getColor
(
context
),
type:
MaterialType
.
card
,
child:
child
)
)
)
return
new
AnimatedPadding
(
padding:
MediaQuery
.
of
(
context
).
viewInsets
+
const
EdgeInsets
.
symmetric
(
horizontal:
40.0
,
vertical:
24.0
),
duration:
insetAnimationDuration
,
curve:
insetAnimationCurve
,
child:
new
MediaQuery
.
removeViewInsets
(
removeLeft:
true
,
removeTop:
true
,
removeRight:
true
,
removeBottom:
true
,
context:
context
,
child:
new
Center
(
child:
new
ConstrainedBox
(
constraints:
const
BoxConstraints
(
minWidth:
280.0
),
child:
new
Material
(
elevation:
24.0
,
color:
_getColor
(
context
),
type:
MaterialType
.
card
,
child:
child
,
),
),
),
),
);
}
}
...
...
packages/flutter/lib/src/widgets/media_query.dart
View file @
da27d674
...
...
@@ -140,7 +140,7 @@ class MediaQueryData {
);
}
/// Creates a copy of this media query data but with the given
padding
s
/// Creates a copy of this media query data but with the given
[padding]
s
/// replaced with zero.
///
/// The `removeLeft`, `removeTop`, `removeRight`, and `removeBottom` arguments
...
...
@@ -153,6 +153,7 @@ class MediaQueryData {
/// from the ambient [MediaQuery].
/// * [SafeArea], which both removes the padding from the [MediaQuery] and
/// adds a [Padding] widget.
/// * [removeViewInsets], the same thing but for [viewInsets].
MediaQueryData
removePadding
({
bool
removeLeft:
false
,
bool
removeTop:
false
,
...
...
@@ -176,6 +177,41 @@ class MediaQueryData {
);
}
/// Creates a copy of this media query data but with the given [viewInsets]
/// replaced with zero.
///
/// The `removeLeft`, `removeTop`, `removeRight`, and `removeBottom` arguments
/// must not be null. If all four are false (the default) then this
/// [MediaQueryData] is returned unmodified.
///
/// See also:
///
/// * [new MediaQuery.removeViewInsets], which uses this method to remove
/// padding from the ambient [MediaQuery].
/// * [removePadding], the same thing but for [padding].
MediaQueryData
removeViewInsets
({
bool
removeLeft:
false
,
bool
removeTop:
false
,
bool
removeRight:
false
,
bool
removeBottom:
false
,
})
{
if
(!(
removeLeft
||
removeTop
||
removeRight
||
removeBottom
))
return
this
;
return
new
MediaQueryData
(
size:
size
,
devicePixelRatio:
devicePixelRatio
,
textScaleFactor:
textScaleFactor
,
padding:
padding
,
viewInsets:
viewInsets
.
copyWith
(
left:
removeLeft
?
0.0
:
null
,
top:
removeTop
?
0.0
:
null
,
right:
removeRight
?
0.0
:
null
,
bottom:
removeBottom
?
0.0
:
null
,
),
alwaysUse24HourFormat:
alwaysUse24HourFormat
,
);
}
@override
bool
operator
==(
Object
other
)
{
if
(
other
.
runtimeType
!=
runtimeType
)
...
...
@@ -194,9 +230,14 @@ class MediaQueryData {
@override
String
toString
()
{
return
'
$runtimeType
(size:
$size
, devicePixelRatio:
$devicePixelRatio
, '
'textScaleFactor:
$textScaleFactor
, padding:
$padding
, '
'viewInsets:
$viewInsets
, alwaysUse24HourFormat:
$alwaysUse24HourFormat
)'
;
return
'
$runtimeType
('
'size:
$size
, '
'devicePixelRatio:
$devicePixelRatio
, '
'textScaleFactor:
$textScaleFactor
, '
'padding:
$padding
, '
'viewInsets:
$viewInsets
, '
'alwaysUse24HourFormat:
$alwaysUse24HourFormat
'
')'
;
}
}
...
...
@@ -236,8 +277,8 @@ class MediaQuery extends InheritedWidget {
/// the given context, but removes the specified paddings.
///
/// This should be inserted into the widget tree when the [MediaQuery] padding
/// is consumed
in such a way that the padding is no longer exposed to its
/// descendents or siblings.
/// is consumed
by a widget in such a way that the padding is no longer
///
exposed to the widget's
descendents or siblings.
///
/// The [context] argument is required, must not be null, and must have a
/// [MediaQuery] in scope.
...
...
@@ -253,6 +294,8 @@ class MediaQuery extends InheritedWidget {
///
/// * [SafeArea], which both removes the padding from the [MediaQuery] and
/// adds a [Padding] widget.
/// * [MediaQueryData.padding], the affected property of the [MediaQueryData].
/// * [new removeViewInsets], the same thing but for removing view insets.
factory
MediaQuery
.
removePadding
({
Key
key
,
@required
BuildContext
context
,
...
...
@@ -274,6 +317,48 @@ class MediaQuery extends InheritedWidget {
);
}
/// Creates a new [MediaQuery] that inherits from the ambient [MediaQuery] from
/// the given context, but removes the specified view insets.
///
/// This should be inserted into the widget tree when the [MediaQuery] view
/// insets are consumed by a widget in such a way that the view insets are no
/// longer exposed to the widget's descendents or siblings.
///
/// The [context] argument is required, must not be null, and must have a
/// [MediaQuery] in scope.
///
/// The `removeLeft`, `removeTop`, `removeRight`, and `removeBottom` arguments
/// must not be null. If all four are false (the default) then the returned
/// [MediaQuery] reuses the ambient [MediaQueryData] unmodified, which is not
/// particularly useful.
///
/// The [child] argument is required and must not be null.
///
/// See also:
///
/// * [MediaQueryData.viewInsets], the affected property of the [MediaQueryData].
/// * [new removePadding], the same thing but for removing paddings.
factory
MediaQuery
.
removeViewInsets
({
Key
key
,
@required
BuildContext
context
,
bool
removeLeft:
false
,
bool
removeTop:
false
,
bool
removeRight:
false
,
bool
removeBottom:
false
,
@required
Widget
child
,
})
{
return
new
MediaQuery
(
key:
key
,
data:
MediaQuery
.
of
(
context
).
removeViewInsets
(
removeLeft:
removeLeft
,
removeTop:
removeTop
,
removeRight:
removeRight
,
removeBottom:
removeBottom
,
),
child:
child
,
);
}
/// Contains information about the current media.
///
/// For example, the [MediaQueryData.size] property contains the width and
...
...
packages/flutter/test/material/dialog_test.dart
View file @
da27d674
...
...
@@ -242,8 +242,9 @@ void main() {
semantics
.
dispose
();
});
testWidgets
(
'Dialogs removes MediaQuery padding'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Dialogs removes MediaQuery padding
and view insets
'
,
(
WidgetTester
tester
)
async
{
BuildContext
outerContext
;
BuildContext
routeContext
;
BuildContext
dialogContext
;
await
tester
.
pumpWidget
(
new
Localizations
(
...
...
@@ -255,6 +256,7 @@ void main() {
child:
new
MediaQuery
(
data:
const
MediaQueryData
(
padding:
const
EdgeInsets
.
all
(
50.0
),
viewInsets:
const
EdgeInsets
.
only
(
left:
25.0
,
bottom:
75.0
),
),
child:
new
Navigator
(
onGenerateRoute:
(
_
)
{
...
...
@@ -273,14 +275,61 @@ void main() {
context:
outerContext
,
barrierDismissible:
false
,
builder:
(
BuildContext
context
)
{
dialogContext
=
context
;
return
new
Container
();
routeContext
=
context
;
return
new
Dialog
(
child:
new
Builder
(
builder:
(
BuildContext
context
)
{
dialogContext
=
context
;
return
const
Placeholder
();
},
),
);
},
);
await
tester
.
pump
();
expect
(
MediaQuery
.
of
(
outerContext
).
padding
,
const
EdgeInsets
.
all
(
50.0
));
expect
(
MediaQuery
.
of
(
routeContext
).
padding
,
EdgeInsets
.
zero
);
expect
(
MediaQuery
.
of
(
dialogContext
).
padding
,
EdgeInsets
.
zero
);
expect
(
MediaQuery
.
of
(
outerContext
).
viewInsets
,
const
EdgeInsets
.
only
(
left:
25.0
,
bottom:
75.0
));
expect
(
MediaQuery
.
of
(
routeContext
).
viewInsets
,
const
EdgeInsets
.
only
(
left:
25.0
,
bottom:
75.0
));
expect
(
MediaQuery
.
of
(
dialogContext
).
viewInsets
,
EdgeInsets
.
zero
);
});
testWidgets
(
'Dialog widget insets by viewInsets'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
MediaQuery
(
data:
const
MediaQueryData
(
viewInsets:
const
EdgeInsets
.
fromLTRB
(
10.0
,
20.0
,
30.0
,
40.0
),
),
child:
const
Dialog
(
child:
const
Placeholder
(),
),
),
);
expect
(
tester
.
getRect
(
find
.
byType
(
Placeholder
)),
new
Rect
.
fromLTRB
(
10.0
+
40.0
,
20.0
+
24.0
,
800.0
-
(
40.0
+
30.0
),
600.0
-
(
24.0
+
40.0
)),
);
await
tester
.
pumpWidget
(
const
MediaQuery
(
data:
const
MediaQueryData
(
viewInsets:
const
EdgeInsets
.
fromLTRB
(
0.0
,
0.0
,
0.0
,
0.0
),
),
child:
const
Dialog
(
child:
const
Placeholder
(),
),
),
);
expect
(
// no change because this is an animation
tester
.
getRect
(
find
.
byType
(
Placeholder
)),
new
Rect
.
fromLTRB
(
10.0
+
40.0
,
20.0
+
24.0
,
800.0
-
(
40.0
+
30.0
),
600.0
-
(
24.0
+
40.0
)),
);
await
tester
.
pump
(
const
Duration
(
seconds:
1
));
expect
(
// animation finished
tester
.
getRect
(
find
.
byType
(
Placeholder
)),
new
Rect
.
fromLTRB
(
40.0
,
24.0
,
800.0
-
40.0
,
600.0
-
24.0
),
);
});
}
packages/flutter/test/widgets/media_query_test.dart
View file @
da27d674
...
...
@@ -96,9 +96,9 @@ void main() {
builder:
(
BuildContext
context
)
{
return
new
MediaQuery
.
removePadding
(
context:
context
,
removeLeft:
true
,
removeTop:
true
,
removeRight:
true
,
removeLeft:
true
,
removeBottom:
true
,
child:
new
Builder
(
builder:
(
BuildContext
context
)
{
...
...
@@ -107,7 +107,8 @@ void main() {
}
),
);
}),
},
),
)
);
...
...
@@ -118,4 +119,50 @@ void main() {
expect
(
unpadded
.
viewInsets
,
viewInsets
);
expect
(
unpadded
.
alwaysUse24HourFormat
,
true
);
});
testWidgets
(
'MediaQuery.removeViewInsets removes specified viewInsets'
,
(
WidgetTester
tester
)
async
{
const
Size
size
=
const
Size
(
2.0
,
4.0
);
const
double
devicePixelRatio
=
2.0
;
const
double
textScaleFactor
=
1.2
;
const
EdgeInsets
padding
=
const
EdgeInsets
.
only
(
top:
5.0
,
right:
6.0
,
left:
7.0
,
bottom:
8.0
);
const
EdgeInsets
viewInsets
=
const
EdgeInsets
.
only
(
top:
1.0
,
right:
2.0
,
left:
3.0
,
bottom:
4.0
);
MediaQueryData
unpadded
;
await
tester
.
pumpWidget
(
new
MediaQuery
(
data:
const
MediaQueryData
(
size:
size
,
devicePixelRatio:
devicePixelRatio
,
textScaleFactor:
textScaleFactor
,
padding:
padding
,
viewInsets:
viewInsets
,
alwaysUse24HourFormat:
true
,
),
child:
new
Builder
(
builder:
(
BuildContext
context
)
{
return
new
MediaQuery
.
removeViewInsets
(
context:
context
,
removeLeft:
true
,
removeTop:
true
,
removeRight:
true
,
removeBottom:
true
,
child:
new
Builder
(
builder:
(
BuildContext
context
)
{
unpadded
=
MediaQuery
.
of
(
context
);
return
new
Container
();
}
),
);
},
),
)
);
expect
(
unpadded
.
size
,
size
);
expect
(
unpadded
.
devicePixelRatio
,
devicePixelRatio
);
expect
(
unpadded
.
textScaleFactor
,
textScaleFactor
);
expect
(
unpadded
.
padding
,
padding
);
expect
(
unpadded
.
viewInsets
,
EdgeInsets
.
zero
);
expect
(
unpadded
.
alwaysUse24HourFormat
,
true
);
});
}
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