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
c5996629
Unverified
Commit
c5996629
authored
Mar 16, 2018
by
Hans Muller
Committed by
GitHub
Mar 16, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added a Backdrop demo to the Gallery (#15579)
parent
dd0acea1
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
417 additions
and
6 deletions
+417
-6
backdrop_demo.dart
...ples/flutter_gallery/lib/demo/material/backdrop_demo.dart
+402
-0
material.dart
examples/flutter_gallery/lib/demo/material/material.dart
+1
-0
item.dart
examples/flutter_gallery/lib/gallery/item.dart
+7
-0
theme.dart
examples/flutter_gallery/lib/gallery/theme.dart
+3
-3
example_code_display_test.dart
examples/flutter_gallery/test/example_code_display_test.dart
+2
-3
smoke_test.dart
examples/flutter_gallery/test/smoke_test.dart
+2
-0
No files found.
examples/flutter_gallery/lib/demo/material/backdrop_demo.dart
0 → 100644
View file @
c5996629
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:math'
as
math
;
import
'package:flutter/material.dart'
;
// This demo displays one Category at a time. The backdrop show a list
// of all of the categories and the selected category is displayed
// (CategoryView) on top of the backdrop.
class
Category
{
const
Category
({
this
.
title
,
this
.
assets
});
final
String
title
;
final
List
<
String
>
assets
;
}
const
List
<
Category
>
allCategories
=
const
<
Category
>[
const
Category
(
title:
'Home'
,
assets:
const
<
String
>[
'shrine/products/clock.png'
,
'shrine/products/teapot.png'
,
'shrine/products/radio.png'
,
'shrine/products/lawn_chair.png'
,
'shrine/products/chair.png'
,
],
),
const
Category
(
title:
'Red'
,
assets:
const
<
String
>[
'shrine/products/popsicle.png'
,
'shrine/products/brush.png'
,
'shrine/products/lipstick.png'
,
'shrine/products/backpack.png'
,
],
),
const
Category
(
title:
'Sport'
,
assets:
const
<
String
>[
'shrine/products/helmet.png'
,
'shrine/products/beachball.png'
,
'shrine/products/flippers.png'
,
'shrine/products/surfboard.png'
,
],
),
const
Category
(
title:
'Shoes'
,
assets:
const
<
String
>[
'shrine/products/chucks.png'
,
'shrine/products/green-shoes.png'
,
'shrine/products/heels.png'
,
'shrine/products/flippers.png'
,
],
),
const
Category
(
title:
'Vision'
,
assets:
const
<
String
>[
'shrine/products/sunnies.png'
,
'shrine/products/binoculars.png'
,
'shrine/products/fish_bowl.png'
,
],
),
const
Category
(
title:
'Everything'
,
assets:
const
<
String
>[
'shrine/products/radio.png'
,
'shrine/products/sunnies.png'
,
'shrine/products/clock.png'
,
'shrine/products/popsicle.png'
,
'shrine/products/lawn_chair.png'
,
'shrine/products/chair.png'
,
'shrine/products/heels.png'
,
'shrine/products/green-shoes.png'
,
'shrine/products/teapot.png'
,
'shrine/products/chucks.png'
,
'shrine/products/brush.png'
,
'shrine/products/fish_bowl.png'
,
'shrine/products/lipstick.png'
,
'shrine/products/backpack.png'
,
'shrine/products/helmet.png'
,
'shrine/products/beachball.png'
,
'shrine/products/binoculars.png'
,
'shrine/products/flippers.png'
,
'shrine/products/surfboard.png'
,
],
),
];
class
CategoryView
extends
StatelessWidget
{
const
CategoryView
({
Key
key
,
this
.
category
})
:
super
(
key:
key
);
final
Category
category
;
@override
Widget
build
(
BuildContext
context
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
return
new
ListView
(
key:
new
PageStorageKey
<
Category
>(
category
),
padding:
const
EdgeInsets
.
symmetric
(
vertical:
16.0
,
horizontal:
64.0
,
),
children:
category
.
assets
.
map
<
Widget
>((
String
asset
)
{
return
new
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
children:
<
Widget
>[
new
Card
(
child:
new
Container
(
width:
144.0
,
alignment:
Alignment
.
center
,
child:
new
Column
(
children:
<
Widget
>[
new
Image
.
asset
(
asset
,
package:
'flutter_gallery_assets'
,
fit:
BoxFit
.
contain
,
),
new
Container
(
padding:
const
EdgeInsets
.
only
(
bottom:
16.0
),
alignment:
AlignmentDirectional
.
center
,
child:
new
Text
(
asset
,
style:
theme
.
textTheme
.
caption
,
),
),
],
),
),
),
const
SizedBox
(
height:
24.0
),
],
);
}).
toList
(),
);
}
}
// One BackdropPanel is visible at a time. It's stacked on top of the
// the BackdropDemo.
class
BackdropPanel
extends
StatelessWidget
{
const
BackdropPanel
({
Key
key
,
this
.
onTap
,
this
.
onVerticalDragUpdate
,
this
.
onVerticalDragEnd
,
this
.
title
,
this
.
child
,
})
:
super
(
key:
key
);
final
VoidCallback
onTap
;
final
GestureDragUpdateCallback
onVerticalDragUpdate
;
final
GestureDragEndCallback
onVerticalDragEnd
;
final
Widget
title
;
final
Widget
child
;
@override
Widget
build
(
BuildContext
context
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
return
new
Material
(
elevation:
2.0
,
borderRadius:
const
BorderRadius
.
only
(
topLeft:
const
Radius
.
circular
(
16.0
),
topRight:
const
Radius
.
circular
(
16.0
),
),
child:
new
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
children:
<
Widget
>[
new
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
onVerticalDragUpdate:
onVerticalDragUpdate
,
onVerticalDragEnd:
onVerticalDragEnd
,
onTap:
onTap
,
child:
new
Container
(
height:
48.0
,
padding:
const
EdgeInsetsDirectional
.
only
(
start:
16.0
),
alignment:
AlignmentDirectional
.
centerStart
,
child:
new
DefaultTextStyle
(
style:
theme
.
textTheme
.
subhead
,
child:
title
,
),
),
),
const
Divider
(
height:
1.0
),
new
Expanded
(
child:
child
),
],
),
);
}
}
// Cross fades between 'Select a Category' and 'Asset Viewer'.
class
BackdropTitle
extends
AnimatedWidget
{
const
BackdropTitle
({
Key
key
,
Listenable
listenable
,
})
:
super
(
key:
key
,
listenable:
listenable
);
@override
Widget
build
(
BuildContext
context
)
{
final
Animation
<
double
>
animation
=
listenable
;
return
new
DefaultTextStyle
(
style:
Theme
.
of
(
context
).
primaryTextTheme
.
title
,
softWrap:
false
,
overflow:
TextOverflow
.
ellipsis
,
child:
new
Stack
(
children:
<
Widget
>[
new
Opacity
(
opacity:
new
CurvedAnimation
(
parent:
new
ReverseAnimation
(
animation
),
curve:
const
Interval
(
0.5
,
1.0
),
).
value
,
child:
const
Text
(
'Select a Category'
),
),
new
Opacity
(
opacity:
new
CurvedAnimation
(
parent:
animation
,
curve:
const
Interval
(
0.5
,
1.0
),
).
value
,
child:
const
Text
(
'Asset Viewer'
),
),
],
),
);
}
}
// This widget is essentially the backdrop itself.
class
BackdropDemo
extends
StatefulWidget
{
static
const
String
routeName
=
'/material/backdrop'
;
@override
_BackdropDemoState
createState
()
=>
new
_BackdropDemoState
();
}
class
_BackdropDemoState
extends
State
<
BackdropDemo
>
with
SingleTickerProviderStateMixin
{
final
GlobalKey
_backdropKey
=
new
GlobalKey
(
debugLabel:
'Backdrop'
);
AnimationController
_controller
;
Category
_category
=
allCategories
[
0
];
@override
void
initState
()
{
super
.
initState
();
_controller
=
new
AnimationController
(
duration:
const
Duration
(
milliseconds:
300
),
value:
1.0
,
vsync:
this
,
);
}
@override
void
dispose
()
{
_controller
.
dispose
();
super
.
dispose
();
}
void
_changeCategory
(
Category
category
)
{
setState
(()
{
_category
=
category
;
_controller
.
fling
(
velocity:
2.0
);
});
}
bool
get
_backdropPanelVisible
{
final
AnimationStatus
status
=
_controller
.
status
;
return
status
==
AnimationStatus
.
completed
||
status
==
AnimationStatus
.
forward
;
}
void
_toggleBackdropPanelVisibility
()
{
_controller
.
fling
(
velocity:
_backdropPanelVisible
?
-
2.0
:
2.0
);
}
double
get
_backdropHeight
{
final
RenderBox
renderBox
=
_backdropKey
.
currentContext
.
findRenderObject
();
return
renderBox
.
size
.
height
;
}
// By design: the panel can only be opened with a swipe. To close the panel
// the user must either tap its heading or the backdrop's menu icon.
void
_handleDragUpdate
(
DragUpdateDetails
details
)
{
if
(
_controller
.
isAnimating
||
_controller
.
status
==
AnimationStatus
.
completed
)
return
;
_controller
.
value
-=
details
.
primaryDelta
/
(
_backdropHeight
??
details
.
primaryDelta
);
}
void
_handleDragEnd
(
DragEndDetails
details
)
{
if
(
_controller
.
isAnimating
||
_controller
.
status
==
AnimationStatus
.
completed
)
return
;
final
double
flingVelocity
=
details
.
velocity
.
pixelsPerSecond
.
dy
/
_backdropHeight
;
if
(
flingVelocity
<
0.0
)
_controller
.
fling
(
velocity:
math
.
max
(
2.0
,
-
flingVelocity
));
else
if
(
flingVelocity
>
0.0
)
_controller
.
fling
(
velocity:
math
.
min
(-
2.0
,
-
flingVelocity
));
else
_controller
.
fling
(
velocity:
_controller
.
value
<
0.5
?
-
2.0
:
2.0
);
}
// Stacks a BackdropPanel, which displays the selected category, on top
// of the backdrop. The categories are displayed with ListTiles. Just one
// can be selected at a time. This is a LayoutWidgetBuild function because
// we need to know how big the BackdropPanel will be to set up its
// animation.
Widget
_buildStack
(
BuildContext
context
,
BoxConstraints
constraints
)
{
const
double
panelTitleHeight
=
48.0
;
final
Size
panelSize
=
constraints
.
biggest
;
final
double
panelTop
=
panelSize
.
height
-
panelTitleHeight
;
final
Animation
<
RelativeRect
>
panelAnimation
=
new
RelativeRectTween
(
begin:
new
RelativeRect
.
fromLTRB
(
0.0
,
panelTop
,
0.0
,
panelTop
-
panelSize
.
height
),
end:
const
RelativeRect
.
fromLTRB
(
0.0
,
0.0
,
0.0
,
0.0
),
).
animate
(
new
CurvedAnimation
(
parent:
_controller
,
curve:
Curves
.
linear
,
),
);
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
List
<
Widget
>
backdropItems
=
allCategories
.
map
<
Widget
>((
Category
category
)
{
final
bool
selected
=
category
==
_category
;
return
new
Material
(
shape:
const
RoundedRectangleBorder
(
borderRadius:
const
BorderRadius
.
all
(
const
Radius
.
circular
(
4.0
)),
),
color:
selected
?
Colors
.
white
.
withOpacity
(
0.25
)
:
Colors
.
transparent
,
child:
new
ListTile
(
title:
new
Text
(
category
.
title
),
selected:
selected
,
onTap:
()
{
_changeCategory
(
category
);
},
),
);
}).
toList
()
..
add
(
const
SizedBox
(
height:
8.0
))
..
add
(
new
Align
(
alignment:
AlignmentDirectional
.
centerStart
,
child:
new
BackButton
(
color:
Colors
.
white
.
withOpacity
(
0.5
))
),
);
return
new
Container
(
key:
_backdropKey
,
color:
theme
.
primaryColor
,
child:
new
Stack
(
children:
<
Widget
>[
new
ListTileTheme
(
iconColor:
theme
.
primaryIconTheme
.
color
,
textColor:
theme
.
primaryTextTheme
.
title
.
color
.
withOpacity
(
0.6
),
selectedColor:
theme
.
primaryTextTheme
.
title
.
color
,
child:
new
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16.0
),
child:
new
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
children:
backdropItems
,
),
),
),
new
PositionedTransition
(
rect:
panelAnimation
,
child:
new
BackdropPanel
(
onTap:
_toggleBackdropPanelVisibility
,
onVerticalDragUpdate:
_handleDragUpdate
,
onVerticalDragEnd:
_handleDragEnd
,
title:
new
Text
(
_category
.
title
),
child:
new
CategoryView
(
category:
_category
),
),
),
],
),
);
}
@override
Widget
build
(
BuildContext
context
)
{
return
new
Scaffold
(
appBar:
new
AppBar
(
elevation:
0.0
,
leading:
new
IconButton
(
onPressed:
_toggleBackdropPanelVisibility
,
icon:
new
AnimatedIcon
(
icon:
AnimatedIcons
.
close_menu
,
progress:
_controller
.
view
,
),
),
title:
new
BackdropTitle
(
listenable:
_controller
.
view
,
),
),
body:
new
LayoutBuilder
(
builder:
_buildStack
,
),
);
}
}
examples/flutter_gallery/lib/demo/material/material.dart
View file @
c5996629
...
...
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
export
'backdrop_demo.dart'
;
export
'bottom_navigation_demo.dart'
;
export
'buttons_demo.dart'
;
export
'cards_demo.dart'
;
...
...
examples/flutter_gallery/lib/gallery/item.dart
View file @
c5996629
...
...
@@ -81,6 +81,13 @@ List<GalleryItem> _buildGalleryItems() {
buildRoute:
(
BuildContext
context
)
=>
const
VideoDemo
(),
),
// Material Components
new
GalleryItem
(
title:
'Backdrop'
,
subtitle:
'Select a front layer from back layer'
,
category:
'Material Components'
,
routeName:
BackdropDemo
.
routeName
,
buildRoute:
(
BuildContext
context
)
=>
new
BackdropDemo
(),
),
new
GalleryItem
(
title:
'Bottom navigation'
,
subtitle:
'Bottom navigation with cross-fading views'
,
...
...
examples/flutter_gallery/lib/gallery/theme.dart
View file @
c5996629
...
...
@@ -11,16 +11,16 @@ class GalleryTheme {
final
ThemeData
theme
;
}
const
int
_kPurplePrimaryValue
=
0xFF6200EE
;
const
MaterialColor
_kPurpleSwatch
=
const
MaterialColor
(
500
,
_kPurplePrimaryValue
,
const
<
int
,
Color
>
{
50
:
const
Color
(
0xFFF2E7FE
),
100
:
const
Color
(
0xFFD7B7FD
),
200
:
const
Color
(
0xFFBB86FC
),
300
:
const
Color
(
0xFF9E55FC
),
400
:
const
Color
(
0xFF7F22FD
),
500
:
const
Color
(
0xFF6200EE
),
600
:
const
Color
(
0xFF4B00D1
),
500
:
const
Color
(
_kPurplePrimaryValue
),
700
:
const
Color
(
0xFF3700B3
),
800
:
const
Color
(
0xFF270096
),
900
:
const
Color
(
0xFF190078
),
...
...
examples/flutter_gallery/test/example_code_display_test.dart
View file @
c5996629
...
...
@@ -23,9 +23,8 @@ void main() {
final
Offset
allDemosOrigin
=
tester
.
getTopRight
(
find
.
text
(
'Demos'
));
final
Finder
button
=
find
.
text
(
'Buttons'
);
while
(
button
.
evaluate
().
isEmpty
)
{
await
tester
.
dragFrom
(
allDemosOrigin
,
const
Offset
(
0.0
,
-
100.0
));
await
tester
.
pump
();
// start the scroll
await
tester
.
pump
(
const
Duration
(
seconds:
1
));
await
tester
.
dragFrom
(
allDemosOrigin
,
const
Offset
(
0.0
,
-
200.0
));
await
tester
.
pumpAndSettle
();
}
// Launch the buttons demo and then prove that showing the example
...
...
examples/flutter_gallery/test/smoke_test.dart
View file @
c5996629
...
...
@@ -128,6 +128,8 @@ Future<Null> runSmokeTest(WidgetTester tester) async {
final
Finder
finder
=
findGalleryItemByRouteName
(
tester
,
routeName
);
Scrollable
.
ensureVisible
(
tester
.
element
(
finder
),
alignment:
0.5
);
await
tester
.
pumpAndSettle
();
if
(
routeName
==
'/material/backdrop'
)
continue
;
await
smokeDemo
(
tester
,
routeName
);
tester
.
binding
.
debugAssertNoTransientCallbacks
(
'A transient callback was still active after leaving route
$routeName
'
);
}
...
...
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