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
54d95416
Commit
54d95416
authored
Mar 03, 2017
by
Hans Muller
Committed by
GitHub
Mar 03, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added a gallery animation demo (#8547)
parent
baaa2e67
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
864 additions
and
4 deletions
+864
-4
all.dart
examples/flutter_gallery/lib/demo/all.dart
+1
-0
home.dart
examples/flutter_gallery/lib/demo/animation/home.dart
+533
-0
sections.dart
examples/flutter_gallery/lib/demo/animation/sections.dart
+143
-0
widgets.dart
examples/flutter_gallery/lib/demo/animation/widgets.dart
+158
-0
animation_demo.dart
examples/flutter_gallery/lib/demo/animation_demo.dart
+16
-0
item.dart
examples/flutter_gallery/lib/gallery/item.dart
+7
-0
transitions_perf_test.dart
...es/flutter_gallery/test_driver/transitions_perf_test.dart
+1
-0
scroll_position.dart
packages/flutter/lib/src/widgets/scroll_position.dart
+5
-4
No files found.
examples/flutter_gallery/lib/demo/all.dart
View file @
54d95416
...
...
@@ -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
'animation_demo.dart'
;
export
'calculator_demo.dart'
;
export
'colors_demo.dart'
;
export
'contacts_demo.dart'
;
...
...
examples/flutter_gallery/lib/demo/animation/home.dart
0 → 100644
View file @
54d95416
// Copyright 2017 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.
// Based on https://material.uplabs.com/posts/google-newsstand-navigation-pattern
// See also: https://material-motion.github.io/material-motion/documentation/
import
'dart:math'
as
math
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'sections.dart'
;
import
'widgets.dart'
;
const
Color
_kAppBackgroundColor
=
const
Color
(
0xFF353662
);
// This app's contents start out at _kHeadingMaxHeight and they function like
// an appbar. Initially the appbar occupies most of the screen and its section
// headings are laid out in a column. By the time its height has been
// reduced to _kAppBarMidHeight, its layout is horizontal, only one section
// heading is visible, and the section's list of details is visible below the
// heading. The appbar's height can be reduced to no more than _kAppBarMinHeight.
const
double
_kAppBarMinHeight
=
90.0
;
const
double
_kAppBarMidHeight
=
256.0
;
// The AppBar's max height depends on the screen, see _AnimationDemoHomeState._buildBody()
// Initially occupies the same space as the status bar and gets smaller as
// the primary scrollable scrolls upwards.
// TODO(hansmuller): it would be worth adding something like this to the framework.
class
_RenderStatusBarPaddingSliver
extends
RenderSliver
{
_RenderStatusBarPaddingSliver
({
double
maxHeight
,
double
scrollFactor
,
})
:
_maxHeight
=
maxHeight
,
_scrollFactor
=
scrollFactor
{
assert
(
maxHeight
!=
null
&&
maxHeight
>=
0.0
);
assert
(
scrollFactor
!=
null
&&
scrollFactor
>=
1.0
);
}
// The height of the status bar
double
get
maxHeight
=>
_maxHeight
;
double
_maxHeight
;
set
maxHeight
(
double
value
)
{
assert
(
maxHeight
!=
null
&&
maxHeight
>=
0.0
);
if
(
_maxHeight
==
value
)
return
;
_maxHeight
=
value
;
markNeedsLayout
();
}
// That rate at which this renderer's height shrinks when the scroll
// offset changes.
double
get
scrollFactor
=>
_scrollFactor
;
double
_scrollFactor
;
set
scrollFactor
(
double
value
)
{
assert
(
scrollFactor
!=
null
&&
scrollFactor
>=
1.0
);
if
(
_scrollFactor
==
value
)
return
;
_scrollFactor
=
value
;
markNeedsLayout
();
}
@override
void
performLayout
()
{
final
double
height
=
(
maxHeight
-
constraints
.
scrollOffset
/
scrollFactor
).
clamp
(
0.0
,
maxHeight
);
geometry
=
new
SliverGeometry
(
paintExtent:
math
.
min
(
height
,
constraints
.
remainingPaintExtent
),
scrollExtent:
maxHeight
,
maxPaintExtent:
maxHeight
,
);
}
}
class
_StatusBarPaddingSliver
extends
SingleChildRenderObjectWidget
{
_StatusBarPaddingSliver
({
Key
key
,
@required
this
.
maxHeight
,
this
.
scrollFactor
:
5.0
,
})
:
super
(
key:
key
)
{
assert
(
maxHeight
!=
null
&&
maxHeight
>=
0.0
);
assert
(
scrollFactor
!=
null
&&
scrollFactor
>=
1.0
);
}
final
double
maxHeight
;
final
double
scrollFactor
;
@override
_RenderStatusBarPaddingSliver
createRenderObject
(
BuildContext
context
)
{
return
new
_RenderStatusBarPaddingSliver
(
maxHeight:
maxHeight
,
scrollFactor:
scrollFactor
,
);
}
@override
void
updateRenderObject
(
BuildContext
context
,
_RenderStatusBarPaddingSliver
renderObject
)
{
renderObject
..
maxHeight
=
maxHeight
..
scrollFactor
=
scrollFactor
;
}
@override
void
debugFillDescription
(
List
<
String
>
description
)
{
super
.
debugFillDescription
(
description
);
description
.
add
(
'maxHeight:
$maxHeight
'
);
description
.
add
(
'scrollFactor:
$scrollFactor
'
);
}
}
class
_SliverAppBarDelegate
extends
SliverPersistentHeaderDelegate
{
_SliverAppBarDelegate
({
@required
this
.
minHeight
,
@required
this
.
maxHeight
,
@required
this
.
child
,
});
final
double
minHeight
;
final
double
maxHeight
;
final
Widget
child
;
@override
double
get
minExtent
=>
minHeight
;
@override
double
get
maxExtent
=>
math
.
max
(
maxHeight
,
minHeight
);
@override
Widget
build
(
BuildContext
context
,
double
shrinkOffset
,
bool
overlapsContent
)
{
return
new
SizedBox
.
expand
(
child:
child
);
}
@override
bool
shouldRebuild
(
_SliverAppBarDelegate
oldDelegate
)
{
return
maxHeight
!=
oldDelegate
.
maxHeight
||
minHeight
!=
oldDelegate
.
minHeight
||
child
!=
oldDelegate
.
child
;
}
@override
String
toString
()
=>
'_SliverAppBarDelegate'
;
}
// Arrange the section titles, indicators, and cards. The cards are only included when
// the layout is transitioning between vertical and horizontal. Once the layout is
// horizontal the cards are laid out by a PageView.
//
// The layout of the section cards, titles, and indicators is defined by the
// two 0.0-1.0 "t" parameters, both of which are based on the layout's height:
// - tColumnToRow
// 0.0 when height is maxHeight and the layout is a column
// 1.0 when the height is midHeight and the layout is a row
// - tCollapsed
// 0.0 when height is midHeight and the layout is a row
// 1.0 when height is minHeight and the layout is a (still) row
//
// minHeight < midHeight < maxHeight
//
// The general approach here is to compute the column layout and row size
// and position of each element and then interpolate between them using
// tColumnToRow. Once tColumnToRow reaches 1.0, the layout changes are
// defined by tCollapsed. As tCollapsed increases the titles spread out
// until only one title is visible and the indicators cluster together
// until they're all visible.
class
_AllSectionsLayout
extends
MultiChildLayoutDelegate
{
_AllSectionsLayout
({
this
.
tColumnToRow
,
this
.
tCollapsed
,
this
.
cardCount
,
this
.
selectedIndex
,
});
final
double
tColumnToRow
;
final
double
tCollapsed
;
final
int
cardCount
;
final
double
selectedIndex
;
Rect
_interpolateRect
(
Rect
begin
,
Rect
end
)
{
return
Rect
.
lerp
(
begin
,
end
,
tColumnToRow
);
}
Point
_interpolatePoint
(
Point
begin
,
Point
end
)
{
return
Point
.
lerp
(
begin
,
end
,
tColumnToRow
);
}
@override
void
performLayout
(
Size
size
)
{
final
double
columnCardX
=
size
.
width
/
5.0
;
final
double
columnCardWidth
=
size
.
width
-
columnCardX
;
final
double
columnCardHeight
=
size
.
height
/
cardCount
;
final
double
rowCardWidth
=
size
.
width
;
double
columnCardY
=
0.0
;
double
rowCardX
=
-(
selectedIndex
*
rowCardWidth
);
// When tCollapsed > 0 the titles spread apart
final
double
columnTitleX
=
size
.
width
/
10.0
;
final
double
rowTitleWidth
=
size
.
width
*
((
1
+
tCollapsed
)
/
2.25
);
double
rowTitleX
=
(
size
.
width
-
rowTitleWidth
)
/
2.0
-
selectedIndex
*
rowTitleWidth
;
// When tCollapsed > 0, the indicators move closer together
//final double rowIndicatorWidth = 48.0 + (1.0 - tCollapsed) * (rowTitleWidth - 48.0);
final
double
paddedSectionIndicatorWidth
=
kSectionIndicatorWidth
+
8.0
;
final
double
rowIndicatorWidth
=
paddedSectionIndicatorWidth
+
(
1.0
-
tCollapsed
)
*
(
rowTitleWidth
-
paddedSectionIndicatorWidth
);
double
rowIndicatorX
=
(
size
.
width
-
rowIndicatorWidth
)
/
2.0
-
selectedIndex
*
rowIndicatorWidth
;
// Compute the size and origin of each card, title, and indicator for the maxHeight
// "column" layout, and the midHeight "row" layout. The actual layout is just the
// interpolated value between the column and row layouts for t.
for
(
int
index
=
0
;
index
<
cardCount
;
index
++)
{
// Layout the card for index.
final
Rect
columnCardRect
=
new
Rect
.
fromLTWH
(
columnCardX
,
columnCardY
,
columnCardWidth
,
columnCardHeight
);
final
Rect
rowCardRect
=
new
Rect
.
fromLTWH
(
rowCardX
,
0.0
,
rowCardWidth
,
size
.
height
);
final
Rect
cardRect
=
_interpolateRect
(
columnCardRect
,
rowCardRect
);
final
String
cardId
=
'card
$index
'
;
if
(
hasChild
(
cardId
))
{
// Add a small horizontal gap between the cards.
final
Rect
insetRect
=
new
Rect
.
fromLTWH
(
cardRect
.
left
+
0.5
,
cardRect
.
top
,
cardRect
.
width
-
1.0
,
cardRect
.
height
);
layoutChild
(
cardId
,
new
BoxConstraints
.
tight
(
insetRect
.
size
));
positionChild
(
cardId
,
insetRect
.
topLeft
.
toOffset
());
}
// Layout the title for index.
final
Size
titleSize
=
layoutChild
(
'title
$index
'
,
new
BoxConstraints
.
loose
(
cardRect
.
size
));
final
double
columnTitleY
=
columnCardRect
.
centerLeft
.
y
-
titleSize
.
height
/
2.0
;
final
double
rowTitleY
=
rowCardRect
.
centerLeft
.
y
-
titleSize
.
height
/
2.0
;
final
double
centeredRowTitleX
=
rowTitleX
+
(
rowTitleWidth
-
titleSize
.
width
)
/
2.0
;
final
Point
columnTitleOrigin
=
new
Point
(
columnTitleX
,
columnTitleY
);
final
Point
rowTitleOrigin
=
new
Point
(
centeredRowTitleX
,
rowTitleY
);
final
Point
titleOrigin
=
_interpolatePoint
(
columnTitleOrigin
,
rowTitleOrigin
);
positionChild
(
'title
$index
'
,
titleOrigin
.
toOffset
());
// Layout the selection indicator for index.
final
Size
indicatorSize
=
layoutChild
(
'indicator
$index
'
,
new
BoxConstraints
.
loose
(
cardRect
.
size
));
final
double
columnIndicatorX
=
cardRect
.
centerRight
.
x
-
indicatorSize
.
width
-
16.0
;
final
double
columnIndicatorY
=
cardRect
.
bottomRight
.
y
-
indicatorSize
.
height
-
16.0
;
final
Point
columnIndicatorOrigin
=
new
Point
(
columnIndicatorX
,
columnIndicatorY
);
final
Rect
titleRect
=
new
Rect
.
fromPoints
(
titleOrigin
,
titleSize
.
bottomRight
(
titleOrigin
));
final
double
centeredRowIndicatorX
=
rowIndicatorX
+
(
rowIndicatorWidth
-
indicatorSize
.
width
)
/
2.0
;
final
double
rowIndicatorY
=
titleRect
.
bottomCenter
.
y
+
16.0
;
final
Point
rowIndicatorOrigin
=
new
Point
(
centeredRowIndicatorX
,
rowIndicatorY
);
final
Point
indicatorOrigin
=
_interpolatePoint
(
columnIndicatorOrigin
,
rowIndicatorOrigin
);
positionChild
(
'indicator
$index
'
,
indicatorOrigin
.
toOffset
());
columnCardY
+=
columnCardHeight
;
rowCardX
+=
rowCardWidth
;
rowTitleX
+=
rowTitleWidth
;
rowIndicatorX
+=
rowIndicatorWidth
;
}
}
@override
bool
shouldRelayout
(
_AllSectionsLayout
oldDelegate
)
{
return
tColumnToRow
!=
oldDelegate
.
tColumnToRow
||
cardCount
!=
oldDelegate
.
cardCount
||
selectedIndex
!=
oldDelegate
.
selectedIndex
;
}
}
class
_AllSectionsView
extends
StatelessWidget
{
_AllSectionsView
({
Key
key
,
this
.
sections
,
this
.
selectedIndex
,
this
.
minHeight
,
this
.
midHeight
,
this
.
maxHeight
,
this
.
sectionCards
:
const
<
Widget
>[],
})
:
super
(
key:
key
)
{
assert
(
sections
!=
null
);
assert
(
sectionCards
!=
null
);
assert
(
sectionCards
.
length
==
sections
.
length
);
assert
(
selectedIndex
>=
0.0
&&
selectedIndex
<
sections
.
length
.
toDouble
());
}
final
List
<
Section
>
sections
;
final
double
selectedIndex
;
final
double
minHeight
;
final
double
midHeight
;
final
double
maxHeight
;
final
List
<
Widget
>
sectionCards
;
double
_selectedIndexDelta
(
int
index
)
{
return
(
index
.
toDouble
()
-
selectedIndex
).
abs
().
clamp
(
0.0
,
1.0
);
}
Widget
_build
(
BuildContext
context
,
BoxConstraints
constraints
)
{
final
Size
size
=
constraints
.
biggest
;
// The layout's progress from from a column to a row. Its value is
// 0.0 when size.height equals the maxHeight, 1.0 when the size.height
// equals the midHeight.
// The layout's progress from from a column to a row. Its value is
// 0.0 when size.height equals the maxHeight, 1.0 when the size.height
// equals the midHeight.
final
double
tColumnToRow
=
1.0
-
((
size
.
height
-
midHeight
)
/
(
maxHeight
-
midHeight
)).
clamp
(
0.0
,
1.0
);
// The layout's progress from from the midHeight row layout to
// a minHeight row layout. Its value is 0.0 when size.height equals
// midHeight and 1.0 when size.height equals minHeight.
final
double
tCollapsed
=
1.0
-
((
size
.
height
-
minHeight
)
/
(
midHeight
-
minHeight
)).
clamp
(
0.0
,
1.0
);
double
_indicatorOpacity
(
int
index
)
{
return
1.0
-
_selectedIndexDelta
(
index
)
*
tColumnToRow
*
0.5
;
}
double
_titleOpacity
(
int
index
)
{
return
1.0
-
_selectedIndexDelta
(
index
)
*
tColumnToRow
*
0.5
;
}
double
_titleScale
(
int
index
)
{
return
1.0
-
_selectedIndexDelta
(
index
)
*
tColumnToRow
*
0.15
;
}
final
List
<
Widget
>
children
=
new
List
<
Widget
>.
from
(
sectionCards
);
for
(
int
index
=
0
;
index
<
sections
.
length
;
index
++)
{
final
Section
section
=
sections
[
index
];
children
.
add
(
new
LayoutId
(
id:
'title
$index
'
,
child:
new
SectionTitle
(
section:
section
,
scale:
_titleScale
(
index
),
opacity:
_titleOpacity
(
index
),
),
));
}
for
(
int
index
=
0
;
index
<
sections
.
length
;
index
++)
{
children
.
add
(
new
LayoutId
(
id:
'indicator
$index
'
,
child:
new
SectionIndicator
(
opacity:
_indicatorOpacity
(
index
),
),
));
}
return
new
CustomMultiChildLayout
(
delegate:
new
_AllSectionsLayout
(
tColumnToRow:
tColumnToRow
,
tCollapsed:
tCollapsed
,
cardCount:
sections
.
length
,
selectedIndex:
selectedIndex
,
),
children:
children
,
);
}
@override
Widget
build
(
BuildContext
context
)
{
return
new
LayoutBuilder
(
builder:
_build
);
}
}
class
AnimationDemoHome
extends
StatefulWidget
{
AnimationDemoHome
({
Key
key
})
:
super
(
key:
key
);
static
const
String
routeName
=
'/animation'
;
@override
_AnimationDemoHomeState
createState
()
=>
new
_AnimationDemoHomeState
();
}
class
_AnimationDemoHomeState
extends
State
<
AnimationDemoHome
>
{
final
ScrollController
_scrollController
=
new
ScrollController
();
final
PageController
_headingPageController
=
new
PageController
();
final
PageController
_detailsPageController
=
new
PageController
();
double
_selectedIndex
=
0.0
;
@override
Widget
build
(
BuildContext
context
)
{
return
new
Scaffold
(
backgroundColor:
_kAppBackgroundColor
,
body:
new
Builder
(
// Insert an element so that _buildBody can find the PrimaryScrollController.
builder:
(
BuildContext
context
)
=>
_buildBody
(
context
),
),
);
}
void
_maybeScroll
(
double
midScrollOffset
,
int
pageIndex
,
double
xOffset
)
{
const
Duration
duration
=
const
Duration
(
milliseconds:
400
);
const
Curve
curve
=
Curves
.
fastOutSlowIn
;
if
(
_scrollController
.
offset
<
midScrollOffset
)
{
// Scroll the overall list to the point where only one section card shows.
// At the same time scroll the PageViews to the page at pageIndex.
_headingPageController
.
animateToPage
(
pageIndex
,
curve:
curve
,
duration:
duration
);
_scrollController
.
animateTo
(
midScrollOffset
,
curve:
curve
,
duration:
duration
);
}
else
{
// One one section card is showing: scroll one page forward or back.
final
double
centerX
=
_headingPageController
.
position
.
viewportDimension
/
2.0
;
final
int
newPageIndex
=
xOffset
>
centerX
?
pageIndex
+
1
:
pageIndex
-
1
;
_headingPageController
.
animateToPage
(
newPageIndex
,
curve:
curve
,
duration:
duration
);
}
}
bool
_handlePageNotification
(
ScrollNotification
notification
,
PageController
leader
,
PageController
follower
)
{
if
(
notification
.
depth
==
0
&&
notification
is
ScrollUpdateNotification
)
{
setState
(()
{
_selectedIndex
=
leader
.
page
;
});
if
(
follower
.
page
!=
leader
.
page
)
follower
.
position
.
jumpTo
(
leader
.
position
.
pixels
,
settle:
false
);
}
return
false
;
}
Iterable
<
Widget
>
_detailItemsFor
(
Section
section
)
{
final
Iterable
<
Widget
>
detailItems
=
section
.
details
.
map
((
SectionDetail
detail
)
{
return
new
SectionDetailView
(
detail:
detail
);
});
return
ListItem
.
divideItems
(
context:
context
,
items:
detailItems
).
map
((
Widget
item
)
{
return
new
SliverToBoxAdapter
(
child:
item
);
});
}
Iterable
<
Widget
>
_allHeadingItems
(
double
maxHeight
,
double
midScrollOffset
)
{
final
List
<
Widget
>
sectionCards
=
<
Widget
>[];
for
(
int
index
=
0
;
index
<
allSections
.
length
;
index
++)
{
sectionCards
.
add
(
new
LayoutId
(
id:
'card
$index
'
,
child:
new
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
child:
new
SectionCard
(
section:
allSections
[
index
]),
onTapUp:
(
TapUpDetails
details
)
{
final
double
xOffset
=
details
.
globalPosition
.
x
;
setState
(()
{
_maybeScroll
(
midScrollOffset
,
index
,
xOffset
);
});
}
),
));
}
final
List
<
Widget
>
headings
=
<
Widget
>[];
for
(
int
index
=
0
;
index
<
allSections
.
length
;
index
++)
{
headings
.
add
(
new
Container
(
decoration:
new
BoxDecoration
(
backgroundColor:
_kAppBackgroundColor
),
child:
new
FractionalTranslation
(
translation:
new
FractionalOffset
(
_selectedIndex
-
index
,
0.0
),
child:
new
ClipRect
(
child:
new
_AllSectionsView
(
sections:
allSections
,
selectedIndex:
_selectedIndex
,
minHeight:
_kAppBarMinHeight
,
midHeight:
_kAppBarMidHeight
,
maxHeight:
maxHeight
,
sectionCards:
sectionCards
,
),
),
),
)
);
}
return
headings
;
}
Widget
_buildBody
(
BuildContext
context
)
{
final
MediaQueryData
mediaQueryData
=
MediaQuery
.
of
(
context
);
final
double
statusBarHeight
=
mediaQueryData
.
padding
.
top
;
final
double
screenHeight
=
mediaQueryData
.
size
.
height
;
final
double
appBarMaxHeight
=
screenHeight
-
statusBarHeight
;
// The scrolloffset that reveals the appBarMidHeight appbar.
final
double
appBarMidScrollOffset
=
statusBarHeight
+
appBarMaxHeight
-
_kAppBarMidHeight
;
return
new
SizedBox
.
expand
(
child:
new
Stack
(
children:
<
Widget
>[
new
CustomScrollView
(
controller:
_scrollController
,
slivers:
<
Widget
>[
// Start out below the status bar, gradually move to the top of the screen.
new
_StatusBarPaddingSliver
(
maxHeight:
statusBarHeight
,
scrollFactor:
7.0
,
),
// Section Headings
new
SliverPersistentHeader
(
pinned:
true
,
delegate:
new
_SliverAppBarDelegate
(
minHeight:
_kAppBarMinHeight
,
maxHeight:
appBarMaxHeight
,
child:
new
NotificationListener
<
ScrollNotification
>(
onNotification:
(
ScrollNotification
notification
)
{
return
_handlePageNotification
(
notification
,
_headingPageController
,
_detailsPageController
);
},
child:
new
PageView
(
controller:
_headingPageController
,
children:
_allHeadingItems
(
appBarMaxHeight
,
appBarMidScrollOffset
),
),
),
),
),
// Details
new
SliverToBoxAdapter
(
child:
new
SizedBox
(
height:
610.0
,
child:
new
NotificationListener
<
ScrollNotification
>(
onNotification:
(
ScrollNotification
notification
)
{
return
_handlePageNotification
(
notification
,
_detailsPageController
,
_headingPageController
);
},
child:
new
PageView
(
controller:
_detailsPageController
,
children:
allSections
.
map
((
Section
section
)
{
return
new
CustomScrollView
(
slivers:
_detailItemsFor
(
section
).
toList
(),
);
}).
toList
(),
),
),
),
),
],
),
new
Positioned
(
top:
statusBarHeight
,
left:
0.0
,
child:
new
IconTheme
(
data:
new
IconThemeData
(
color:
Colors
.
white
),
child:
new
BackButton
(),
),
),
],
),
);
}
}
examples/flutter_gallery/lib/demo/animation/sections.dart
0 → 100644
View file @
54d95416
// Copyright 2017 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.
// Raw data for the animation demo.
import
'package:flutter/material.dart'
;
const
Color
_mariner
=
const
Color
(
0xFF3B5F8F
);
const
Color
_mediumPurple
=
const
Color
(
0xFF8266D4
);
const
Color
_tomato
=
const
Color
(
0xFFF95B57
);
const
Color
_mySin
=
const
Color
(
0xFFF3A646
);
const
Color
_deepCerise
=
const
Color
(
0xFFD93F9B
);
class
SectionDetail
{
const
SectionDetail
({
this
.
title
,
this
.
subtitle
,
this
.
imageAsset
});
final
String
title
;
final
String
subtitle
;
final
String
imageAsset
;
}
class
Section
{
const
Section
({
this
.
title
,
this
.
backgroundAsset
,
this
.
leftColor
,
this
.
rightColor
,
this
.
details
});
final
String
title
;
final
String
backgroundAsset
;
final
Color
leftColor
;
final
Color
rightColor
;
final
List
<
SectionDetail
>
details
;
@override
bool
operator
==(
Object
other
)
{
if
(
other
is
!
Section
)
return
false
;
final
Section
otherSection
=
other
;
return
title
==
otherSection
.
title
;
}
@override
int
get
hashCode
=>
title
.
hashCode
;
}
// TODO(hansmuller): replace the SectionDetail images and text. Get rid of
// the const vars like _eyeglassesDetail and insert a variety of titles and
// image SectionDetails in the allSections list.
const
SectionDetail
_eyeglassesDetail
=
const
SectionDetail
(
imageAsset:
'packages/flutter_gallery_assets/shrine/products/sunnies.png'
,
title:
'Flutter enables interactive animation'
,
subtitle:
'3K views - 5 days'
,
);
const
SectionDetail
_eyeglassesImageDetail
=
const
SectionDetail
(
imageAsset:
'packages/flutter_gallery_assets/shrine/products/sunnies.png'
,
);
const
SectionDetail
_seatingDetail
=
const
SectionDetail
(
imageAsset:
'packages/flutter_gallery_assets/shrine/products/lawn_chair.png'
,
title:
'Flutter enables interactive animation'
,
subtitle:
'3K views - 5 days'
,
);
const
SectionDetail
_seatingImageDetail
=
const
SectionDetail
(
imageAsset:
'packages/flutter_gallery_assets/shrine/products/lawn_chair.png'
,
);
const
SectionDetail
_decorationDetail
=
const
SectionDetail
(
imageAsset:
'packages/flutter_gallery_assets/shrine/products/lipstick.png'
,
title:
'Flutter enables interactive animation'
,
subtitle:
'3K views - 5 days'
,
);
const
SectionDetail
_decorationImageDetail
=
const
SectionDetail
(
imageAsset:
'packages/flutter_gallery_assets/shrine/products/lipstick.png'
,
);
const
SectionDetail
_protectionDetail
=
const
SectionDetail
(
imageAsset:
'packages/flutter_gallery_assets/shrine/products/helmet.png'
,
title:
'Flutter enables interactive animation'
,
subtitle:
'3K views - 5 days'
,
);
const
SectionDetail
_protectionImageDetail
=
const
SectionDetail
(
imageAsset:
'packages/flutter_gallery_assets/shrine/products/helmet.png'
,
);
final
List
<
Section
>
allSections
=
<
Section
>[
const
Section
(
title:
'EYEGLASSES'
,
leftColor:
_mediumPurple
,
rightColor:
_mariner
,
backgroundAsset:
'packages/flutter_gallery_assets/shrine/products/sunnies.png'
,
details:
const
<
SectionDetail
>[
_eyeglassesDetail
,
_eyeglassesImageDetail
,
_eyeglassesDetail
,
_eyeglassesDetail
,
_eyeglassesDetail
,
_eyeglassesDetail
,
],
),
const
Section
(
title:
'SEATING'
,
leftColor:
_tomato
,
rightColor:
_mediumPurple
,
backgroundAsset:
'packages/flutter_gallery_assets/shrine/products/lawn_chair.png'
,
details:
const
<
SectionDetail
>[
_seatingDetail
,
_seatingImageDetail
,
_seatingDetail
,
_seatingDetail
,
_seatingDetail
,
_seatingDetail
,
],
),
const
Section
(
title:
'DECORATION'
,
leftColor:
_mySin
,
rightColor:
_tomato
,
backgroundAsset:
'packages/flutter_gallery_assets/shrine/products/lipstick.png'
,
details:
const
<
SectionDetail
>[
_decorationDetail
,
_decorationImageDetail
,
_decorationDetail
,
_decorationDetail
,
_decorationDetail
,
_decorationDetail
,
],
),
const
Section
(
title:
'PROTECTION'
,
leftColor:
Colors
.
white
,
rightColor:
_tomato
,
backgroundAsset:
'packages/flutter_gallery_assets/shrine/products/helmet.png'
,
details:
const
<
SectionDetail
>[
_protectionDetail
,
_protectionImageDetail
,
_protectionDetail
,
_protectionDetail
,
_protectionDetail
,
_protectionDetail
,
],
),
];
examples/flutter_gallery/lib/demo/animation/widgets.dart
0 → 100644
View file @
54d95416
// Copyright 2017 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
'package:flutter/material.dart'
;
import
'sections.dart'
;
const
double
kSectionIndicatorWidth
=
32.0
;
// The card for a single section. Displays the section's gradient and background image.
class
SectionCard
extends
StatelessWidget
{
SectionCard
({
Key
key
,
this
.
section
})
:
super
(
key:
key
)
{
assert
(
section
!=
null
);
}
final
Section
section
;
@override
Widget
build
(
BuildContext
context
)
{
return
new
Padding
(
padding:
const
EdgeInsets
.
only
(
bottom:
1.0
),
child:
new
DecoratedBox
(
decoration:
new
BoxDecoration
(
borderRadius:
new
BorderRadius
.
circular
(
4.0
),
gradient:
new
LinearGradient
(
begin:
FractionalOffset
.
topLeft
,
end:
FractionalOffset
.
topRight
,
colors:
<
Color
>[
section
.
leftColor
,
section
.
rightColor
,
],
),
),
child:
new
Opacity
(
opacity:
0.075
,
child:
new
Image
.
asset
(
section
.
backgroundAsset
,
fit:
ImageFit
.
cover
,
),
),
),
);
}
}
// The title is rendered with two overlapping text widgets that are vertically
// offset a little. It's supposed to look sort-of 3D.
class
SectionTitle
extends
StatelessWidget
{
static
const
TextStyle
sectionTitleStyle
=
const
TextStyle
(
fontFamily:
'Raleway'
,
inherit:
false
,
fontSize:
24.0
,
fontWeight:
FontWeight
.
w500
,
color:
Colors
.
white
,
textBaseline:
TextBaseline
.
alphabetic
,
);
static
final
TextStyle
sectionTitleShadowStyle
=
sectionTitleStyle
.
copyWith
(
color:
const
Color
(
0x19000000
),
);
SectionTitle
({
Key
key
,
this
.
section
,
this
.
scale
,
this
.
opacity
})
:
super
(
key:
key
)
{
assert
(
section
!=
null
);
assert
(
scale
!=
null
);
assert
(
opacity
!=
null
&&
opacity
>=
0.0
&&
opacity
<=
1.0
);
}
final
Section
section
;
final
double
scale
;
final
double
opacity
;
@override
Widget
build
(
BuildContext
context
)
{
return
new
IgnorePointer
(
child:
new
Opacity
(
opacity:
opacity
,
child:
new
Transform
(
transform:
new
Matrix4
.
identity
()..
scale
(
scale
),
alignment:
FractionalOffset
.
center
,
child:
new
Stack
(
children:
<
Widget
>[
new
Positioned
(
top:
4.0
,
child:
new
Text
(
section
.
title
,
style:
sectionTitleShadowStyle
),
),
new
Text
(
section
.
title
,
style:
sectionTitleStyle
),
],
),
),
),
);
}
}
// Small horizontal bar that indicates the selected section.
class
SectionIndicator
extends
StatelessWidget
{
SectionIndicator
({
Key
key
,
this
.
opacity
:
1.0
})
:
super
(
key:
key
);
final
double
opacity
;
@override
Widget
build
(
BuildContext
context
)
{
return
new
IgnorePointer
(
child:
new
Container
(
width:
kSectionIndicatorWidth
,
height:
3.0
,
decoration:
new
BoxDecoration
(
backgroundColor:
Colors
.
white
.
withOpacity
(
opacity
),
),
),
);
}
}
// Display a single SectionDetail.
class
SectionDetailView
extends
StatelessWidget
{
SectionDetailView
({
Key
key
,
this
.
detail
})
:
super
(
key:
key
)
{
assert
(
detail
!=
null
&&
detail
.
imageAsset
!=
null
);
assert
((
detail
.
imageAsset
??
detail
.
title
)
!=
null
);
}
final
SectionDetail
detail
;
@override
Widget
build
(
BuildContext
context
)
{
final
Widget
image
=
new
DecoratedBox
(
decoration:
new
BoxDecoration
(
borderRadius:
new
BorderRadius
.
circular
(
6.0
),
backgroundImage:
new
BackgroundImage
(
image:
new
AssetImage
(
detail
.
imageAsset
),
fit:
ImageFit
.
cover
,
alignment:
FractionalOffset
.
center
,
),
),
);
Widget
item
;
if
(
detail
.
title
==
null
&&
detail
.
subtitle
==
null
)
{
item
=
new
Container
(
height:
240.0
,
padding:
const
EdgeInsets
.
all
(
16.0
),
child:
image
,
);
}
else
{
item
=
new
ListItem
(
title:
new
Text
(
detail
.
title
),
subtitle:
new
Text
(
detail
.
subtitle
),
leading:
new
SizedBox
(
width:
32.0
,
height:
32.0
,
child:
image
),
);
}
return
new
DecoratedBox
(
decoration:
new
BoxDecoration
(
backgroundColor:
Colors
.
grey
[
200
]),
child:
item
,
);
}
}
examples/flutter_gallery/lib/demo/animation_demo.dart
0 → 100644
View file @
54d95416
// Copyright 2017 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
'package:flutter/material.dart'
;
import
'animation/home.dart'
;
class
AnimationDemo
extends
StatelessWidget
{
AnimationDemo
({
Key
key
})
:
super
(
key:
key
);
static
const
String
routeName
=
'/animation'
;
@override
Widget
build
(
BuildContext
context
)
=>
new
AnimationDemoHome
();
}
examples/flutter_gallery/lib/gallery/item.dart
View file @
54d95416
...
...
@@ -67,6 +67,13 @@ final List<GalleryItem> kAllGalleryItems = <GalleryItem>[
routeName:
ContactsDemo
.
routeName
,
buildRoute:
(
BuildContext
context
)
=>
new
ContactsDemo
(),
),
new
GalleryItem
(
title:
'Animation'
,
subtitle:
'Section organizer'
,
category:
'Demos'
,
routeName:
AnimationDemo
.
routeName
,
buildRoute:
(
BuildContext
context
)
=>
new
AnimationDemo
(),
),
// Material Components
new
GalleryItem
(
title:
'Bottom navigation'
,
...
...
examples/flutter_gallery/test_driver/transitions_perf_test.dart
View file @
54d95416
...
...
@@ -18,6 +18,7 @@ final List<String> demoTitles = <String>[
'Pesto'
,
'Shrine'
,
'Contact profile'
,
'Animation'
,
// Material Components
'Bottom navigation'
,
'Buttons'
,
...
...
packages/flutter/lib/src/widgets/scroll_position.dart
View file @
54d95416
...
...
@@ -215,9 +215,9 @@ class ScrollPosition extends ViewportOffset {
/// scroll notifications will be dispatched. No overscroll notifications can
/// be generated by this method.
///
/// I
mmediately after the jump, a ballistic activity is started, in case the
/// value was out of range.
void
jumpTo
(
double
value
)
{
/// I
f settle is true then, immediately after the jump, a ballistic activity
///
is started, in case the
value was out of range.
void
jumpTo
(
double
value
,
{
bool
settle:
true
}
)
{
beginIdleActivity
();
if
(
_pixels
!=
value
)
{
final
double
oldPixels
=
_pixels
;
...
...
@@ -227,6 +227,7 @@ class ScrollPosition extends ViewportOffset {
state
.
dispatchNotification
(
activity
.
createScrollUpdateNotification
(
state
,
_pixels
-
oldPixels
));
state
.
dispatchNotification
(
activity
.
createScrollEndNotification
(
state
));
}
if
(
settle
)
beginBallisticActivity
(
0.0
);
}
...
...
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