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
24fadf49
Commit
24fadf49
authored
Jan 05, 2016
by
Adam Barth
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1070 from abarth/scrollable_list2
Introduce ScrollableList2
parents
c8ac09a5
99bca282
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
426 additions
and
173 deletions
+426
-173
media_query.dart
examples/widgets/media_query.dart
+5
-4
rendering.dart
packages/flutter/lib/rendering.dart
+1
-0
grid.dart
packages/flutter/lib/src/rendering/grid.dart
+10
-78
list.dart
packages/flutter/lib/src/rendering/list.dart
+86
-0
viewport.dart
packages/flutter/lib/src/rendering/viewport.dart
+63
-0
scrollable_grid.dart
packages/flutter/lib/src/widgets/scrollable_grid.dart
+22
-91
scrollable_list.dart
packages/flutter/lib/src/widgets/scrollable_list.dart
+124
-0
virtual_viewport.dart
packages/flutter/lib/src/widgets/virtual_viewport.dart
+113
-0
widgets.dart
packages/flutter/lib/widgets.dart
+2
-0
No files found.
examples/widgets/media_query.dart
View file @
24fadf49
...
...
@@ -72,13 +72,14 @@ class MediaQueryExample extends StatelessComponent {
items
.
add
(
new
AdaptiveItem
(
"Item
$i
"
));
if
(
MediaQuery
.
of
(
context
).
size
.
width
<
_gridViewBreakpoint
)
{
return
new
Block
(
items
.
map
((
AdaptiveItem
item
)
=>
item
.
toListItem
()).
toList
()
return
new
ScrollableList2
(
itemExtent:
50.0
,
children:
items
.
map
((
AdaptiveItem
item
)
=>
item
.
toListItem
()).
toList
()
);
}
else
{
return
new
ScrollableGrid
(
children:
items
.
map
((
AdaptiveItem
item
)
=>
item
.
toCard
()).
toList
(
),
delegate:
new
MaxTileWidthGridDelegate
(
maxTileWidth:
_maxTileWidth
)
delegate:
new
MaxTileWidthGridDelegate
(
maxTileWidth:
_maxTileWidth
),
children:
items
.
map
((
AdaptiveItem
item
)
=>
item
.
toCard
()).
toList
(
)
);
}
}
...
...
packages/flutter/lib/rendering.dart
View file @
24fadf49
...
...
@@ -18,6 +18,7 @@ export 'src/rendering/flex.dart';
export
'src/rendering/grid.dart'
;
export
'src/rendering/image.dart'
;
export
'src/rendering/layer.dart'
;
export
'src/rendering/list.dart'
;
export
'src/rendering/node.dart'
;
export
'src/rendering/object.dart'
;
export
'src/rendering/overflow.dart'
;
...
...
packages/flutter/lib/src/rendering/grid.dart
View file @
24fadf49
...
...
@@ -6,8 +6,7 @@ import 'dart:typed_data';
import
'box.dart'
;
import
'object.dart'
;
import
'package:vector_math/vector_math_64.dart'
;
import
'viewport.dart'
;
bool
_debugIsMonotonic
(
List
<
double
>
offsets
)
{
bool
result
=
true
;
...
...
@@ -314,8 +313,7 @@ class GridParentData extends ContainerBoxParentDataMixin<RenderBox> {
///
/// Additionally, grid layout materializes all of its children, which makes it
/// most useful for grids containing a moderate number of tiles.
class
RenderGrid
extends
RenderBox
with
ContainerRenderObjectMixin
<
RenderBox
,
GridParentData
>,
RenderBoxContainerDefaultsMixin
<
RenderBox
,
GridParentData
>
{
class
RenderGrid
extends
RenderVirtualViewport
<
GridParentData
>
{
RenderGrid
({
List
<
RenderBox
>
children
,
GridDelegate
delegate
,
...
...
@@ -323,11 +321,11 @@ class RenderGrid extends RenderBox with ContainerRenderObjectMixin<RenderBox, Gr
int
virtualChildCount
,
Offset
paintOffset:
Offset
.
zero
,
LayoutCallback
callback
})
:
_delegate
=
delegate
,
_virtualChildBase
=
virtualChildBase
,
_virtualChildCount
=
virtualChildCoun
t
,
_paintOffset
=
paintOffset
,
_callback
=
callback
{
})
:
_delegate
=
delegate
,
_virtualChildBase
=
virtualChildBase
,
super
(
virtualChildCount:
virtualChildCount
,
paintOffset:
paintOffse
t
,
callback:
callback
)
{
assert
(
delegate
!=
null
);
addAll
(
children
);
}
...
...
@@ -360,49 +358,6 @@ class RenderGrid extends RenderBox with ContainerRenderObjectMixin<RenderBox, Gr
markNeedsLayout
();
}
/// The total number of virtual children in the grid.
///
/// When asking the delegate for the grid specification, the grid will use
/// this number of children, which can be larger than the actual number of
/// children of this render object.
///
/// If the this value is null, the grid will use the actual child count of
/// this render object.
int
get
virtualChildCount
=>
_virtualChildCount
??
childCount
;
int
_virtualChildCount
;
void
set
virtualChildCount
(
int
value
)
{
if
(
_virtualChildCount
==
value
)
return
;
_virtualChildCount
=
value
;
markNeedsLayout
();
}
/// The offset at which to paint the first tile.
///
/// Note: you can modify this property from within [callback], if necessary.
Offset
get
paintOffset
=>
_paintOffset
;
Offset
_paintOffset
;
void
set
paintOffset
(
Offset
value
)
{
assert
(
value
!=
null
);
if
(
value
==
_paintOffset
)
return
;
_paintOffset
=
value
;
markNeedsPaint
();
}
/// Called during [layout] to determine the grid's children.
///
/// Typically the callback will mutate the child list appropriately, for
/// example so the child list contains only visible children.
LayoutCallback
get
callback
=>
_callback
;
LayoutCallback
_callback
;
void
set
callback
(
LayoutCallback
value
)
{
if
(
value
==
_callback
)
return
;
_callback
=
value
;
markNeedsLayout
();
}
void
setupParentData
(
RenderBox
child
)
{
if
(
child
.
parentData
is
!
GridParentData
)
child
.
parentData
=
new
GridParentData
();
...
...
@@ -447,17 +402,13 @@ class RenderGrid extends RenderBox with ContainerRenderObjectMixin<RenderBox, Gr
}
}
bool
_hasVisualOverflow
=
false
;
void
performLayout
()
{
_updateGridSpecification
();
Size
gridSize
=
_specification
.
gridSize
;
size
=
constraints
.
constrain
(
gridSize
);
if
(
gridSize
.
width
>
size
.
width
||
gridSize
.
height
>
size
.
height
)
_hasVisualOverflow
=
true
;
if
(
_
callback
!=
null
)
invokeLayoutCallback
(
_
callback
);
if
(
callback
!=
null
)
invokeLayoutCallback
(
callback
);
double
gridTopPadding
=
_specification
.
padding
.
top
;
double
gridLeftPadding
=
_specification
.
padding
.
left
;
...
...
@@ -492,29 +443,10 @@ class RenderGrid extends RenderBox with ContainerRenderObjectMixin<RenderBox, Gr
tileTop
+
placement
.
padding
.
top
);
++
childIndex
;
childIndex
+=
1
;
assert
(
child
.
parentData
==
childParentData
);
child
=
childParentData
.
nextSibling
;
}
}
void
applyPaintTransform
(
RenderBox
child
,
Matrix4
transform
)
{
super
.
applyPaintTransform
(
child
,
transform
.
translate
(
paintOffset
));
}
bool
hitTestChildren
(
HitTestResult
result
,
{
Point
position
})
{
return
defaultHitTestChildren
(
result
,
position:
position
+
-
paintOffset
);
}
void
_paintContents
(
PaintingContext
context
,
Offset
offset
)
{
defaultPaint
(
context
,
offset
+
paintOffset
);
}
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
if
(
_hasVisualOverflow
)
context
.
pushClipRect
(
needsCompositing
,
offset
,
Point
.
origin
&
size
,
_paintContents
);
else
_paintContents
(
context
,
offset
);
}
}
packages/flutter/lib/src/rendering/list.dart
0 → 100644
View file @
24fadf49
// Copyright 2015 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
'box.dart'
;
import
'object.dart'
;
import
'viewport.dart'
;
/// Parent data for use with [RenderList].
class
ListParentData
extends
ContainerBoxParentDataMixin
<
RenderBox
>
{
}
class
RenderList
extends
RenderVirtualViewport
<
ListParentData
>
{
RenderList
({
List
<
RenderBox
>
children
,
double
itemExtent
,
int
virtualChildCount
,
Offset
paintOffset:
Offset
.
zero
,
LayoutCallback
callback
})
:
_itemExtent
=
itemExtent
,
super
(
virtualChildCount:
virtualChildCount
,
paintOffset:
paintOffset
,
callback:
callback
)
{
assert
(
itemExtent
!=
null
);
addAll
(
children
);
}
double
get
itemExtent
=>
_itemExtent
;
double
_itemExtent
;
void
set
itemExtent
(
double
newValue
)
{
assert
(
newValue
!=
null
);
if
(
_itemExtent
==
newValue
)
return
;
_itemExtent
=
newValue
;
markNeedsLayout
();
}
void
setupParentData
(
RenderBox
child
)
{
if
(
child
.
parentData
is
!
ListParentData
)
child
.
parentData
=
new
ListParentData
();
}
double
get
_preferredMainAxisExtent
=>
itemExtent
*
virtualChildCount
;
double
getMinIntrinsicWidth
(
BoxConstraints
constraints
)
{
assert
(
constraints
.
isNormalized
);
return
constraints
.
constrainWidth
(
0.0
);
}
double
getMaxIntrinsicWidth
(
BoxConstraints
constraints
)
{
assert
(
constraints
.
isNormalized
);
return
constraints
.
constrainWidth
(
0.0
);
}
double
getMinIntrinsicHeight
(
BoxConstraints
constraints
)
{
assert
(
constraints
.
isNormalized
);
return
constraints
.
constrainHeight
(
_preferredMainAxisExtent
);
}
double
getMaxIntrinsicHeight
(
BoxConstraints
constraints
)
{
assert
(
constraints
.
isNormalized
);
return
constraints
.
constrainHeight
(
_preferredMainAxisExtent
);
}
void
performLayout
()
{
double
height
=
_preferredMainAxisExtent
;
size
=
new
Size
(
constraints
.
maxWidth
,
constraints
.
constrainHeight
(
height
));
if
(
callback
!=
null
)
invokeLayoutCallback
(
callback
);
BoxConstraints
innerConstraints
=
new
BoxConstraints
.
tightFor
(
width:
size
.
width
,
height:
itemExtent
);
int
childIndex
=
0
;
RenderBox
child
=
firstChild
;
while
(
child
!=
null
)
{
child
.
layout
(
innerConstraints
);
final
ListParentData
childParentData
=
child
.
parentData
;
childParentData
.
offset
=
new
Offset
(
0.0
,
childIndex
*
itemExtent
);
childIndex
+=
1
;
assert
(
child
.
parentData
==
childParentData
);
child
=
childParentData
.
nextSibling
;
}
}
}
packages/flutter/lib/src/rendering/viewport.dart
View file @
24fadf49
...
...
@@ -178,3 +178,66 @@ class RenderViewport extends RenderBox with RenderObjectWithChildMixin<RenderBox
return
false
;
}
}
abstract
class
RenderVirtualViewport
<
T
extends
ContainerBoxParentDataMixin
<
RenderBox
>>
extends
RenderBox
with
ContainerRenderObjectMixin
<
RenderBox
,
T
>,
RenderBoxContainerDefaultsMixin
<
RenderBox
,
T
>
{
RenderVirtualViewport
({
int
virtualChildCount
,
Offset
paintOffset
,
LayoutCallback
callback
})
:
_virtualChildCount
=
virtualChildCount
,
_paintOffset
=
paintOffset
,
_callback
=
callback
;
int
get
virtualChildCount
=>
_virtualChildCount
??
childCount
;
int
_virtualChildCount
;
void
set
virtualChildCount
(
int
value
)
{
if
(
_virtualChildCount
==
value
)
return
;
_virtualChildCount
=
value
;
markNeedsLayout
();
}
/// The offset at which to paint the first item.
///
/// Note: you can modify this property from within [callback], if necessary.
Offset
get
paintOffset
=>
_paintOffset
;
Offset
_paintOffset
;
void
set
paintOffset
(
Offset
value
)
{
assert
(
value
!=
null
);
if
(
value
==
_paintOffset
)
return
;
_paintOffset
=
value
;
markNeedsPaint
();
}
/// Called during [layout] to determine the grid's children.
///
/// Typically the callback will mutate the child list appropriately, for
/// example so the child list contains only visible children.
LayoutCallback
get
callback
=>
_callback
;
LayoutCallback
_callback
;
void
set
callback
(
LayoutCallback
value
)
{
if
(
value
==
_callback
)
return
;
_callback
=
value
;
markNeedsLayout
();
}
void
applyPaintTransform
(
RenderBox
child
,
Matrix4
transform
)
{
super
.
applyPaintTransform
(
child
,
transform
.
translate
(
paintOffset
));
}
bool
hitTestChildren
(
HitTestResult
result
,
{
Point
position
})
{
return
defaultHitTestChildren
(
result
,
position:
position
+
-
paintOffset
);
}
void
_paintContents
(
PaintingContext
context
,
Offset
offset
)
{
defaultPaint
(
context
,
offset
+
paintOffset
);
}
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
context
.
pushClipRect
(
needsCompositing
,
offset
,
Point
.
origin
&
size
,
_paintContents
);
}
}
packages/flutter/lib/src/widgets/scrollable_grid.dart
View file @
24fadf49
...
...
@@ -4,9 +4,9 @@
import
'dart:math'
as
math
;
import
'basic.dart'
;
import
'framework.dart'
;
import
'scrollable.dart'
;
import
'virtual_viewport.dart'
;
import
'package:flutter/animation.dart'
;
import
'package:flutter/rendering.dart'
;
...
...
@@ -38,11 +38,11 @@ class ScrollableGrid extends Scrollable {
final
GridDelegate
delegate
;
final
List
<
Widget
>
children
;
ScrollableState
createState
()
=>
new
_ScrollableGrid
();
ScrollableState
createState
()
=>
new
_ScrollableGrid
State
();
}
class
_ScrollableGrid
extends
ScrollableState
<
ScrollableGrid
>
{
ScrollBehavior
createScrollBehavior
()
=>
new
Overscroll
WhenScrollable
Behavior
();
class
_ScrollableGrid
State
extends
ScrollableState
<
ScrollableGrid
>
{
ScrollBehavior
createScrollBehavior
()
=>
new
OverscrollBehavior
();
ExtentScrollBehavior
get
scrollBehavior
=>
super
.
scrollBehavior
;
void
_handleExtentsChanged
(
double
contentExtent
,
double
containerExtent
)
{
...
...
@@ -65,9 +65,7 @@ class _ScrollableGrid extends ScrollableState<ScrollableGrid> {
}
}
typedef
void
ExtentsChangedCallback
(
double
contentExtent
,
double
containerExtent
);
class
GridViewport
extends
RenderObjectWidget
{
class
GridViewport
extends
VirtualViewport
{
GridViewport
({
Key
key
,
this
.
startOffset
,
...
...
@@ -87,6 +85,7 @@ class GridViewport extends RenderObjectWidget {
}
// TODO(abarth): This function should go somewhere more general.
// See https://github.com/dart-lang/collection/pull/16
int
_lowerBound
(
List
sortedList
,
var
value
,
{
int
begin:
0
})
{
int
current
=
begin
;
int
count
=
sortedList
.
length
-
current
;
...
...
@@ -103,82 +102,31 @@ int _lowerBound(List sortedList, var value, { int begin: 0 }) {
return
current
;
}
class
_GridViewportElement
extends
RenderObjec
tElement
<
GridViewport
>
{
class
_GridViewportElement
extends
VirtualViewpor
tElement
<
GridViewport
>
{
_GridViewportElement
(
GridViewport
widget
)
:
super
(
widget
);
double
_contentExtent
;
double
_containerExtent
;
RenderGrid
get
renderObject
=>
super
.
renderObject
;
int
get
materializedChildBase
=>
_materializedChildBase
;
int
_materializedChildBase
;
int
_materializedChildCount
;
List
<
Element
>
_materializedChildren
=
const
<
Element
>[];
int
get
materializedChildCount
=>
_materializedChildCount
;
int
_materializedChildCount
;
GridSpecification
_specification
;
double
get
repaintOffsetBase
=>
_repaintOffsetBase
;
double
_repaintOffsetBase
;
double
_repaintOffsetLimit
;
RenderGrid
get
renderObject
=>
super
.
renderObject
;
void
visitChildren
(
ElementVisitor
visitor
)
{
if
(
_materializedChildren
==
null
)
return
;
for
(
Element
child
in
_materializedChildren
)
visitor
(
child
);
}
void
mount
(
Element
parent
,
dynamic
newSlot
)
{
super
.
mount
(
parent
,
newSlot
);
renderObject
.
callback
=
layout
;
_updateRenderObject
();
}
void
unmount
()
{
renderObject
.
callback
=
null
;
super
.
unmount
();
}
void
update
(
GridViewport
newWidget
)
{
super
.
update
(
newWidget
);
_updateRenderObject
();
if
(!
renderObject
.
needsLayout
)
_materializeChildren
();
}
void
_updatePaintOffset
()
{
renderObject
.
paintOffset
=
new
Offset
(
0.0
,
-(
widget
.
startOffset
-
_repaintOffsetBase
));
}
double
get
repaintOffsetLimit
=>
_repaintOffsetLimit
;
double
_repaintOffsetLimit
;
void
_
updateRenderObject
()
{
void
updateRenderObject
()
{
renderObject
.
delegate
=
widget
.
delegate
;
renderObject
.
virtualChildCount
=
widget
.
children
.
length
;
if
(
_specification
!=
null
)
{
_updatePaintOffset
();
// If we don't already need layout, we need to request a layout if the
// viewport has shifted to expose a new row.
if
(!
renderObject
.
needsLayout
)
{
if
(
_repaintOffsetBase
!=
null
&&
widget
.
startOffset
<
_repaintOffsetBase
)
renderObject
.
markNeedsLayout
();
else
if
(
_repaintOffsetLimit
!=
null
&&
widget
.
startOffset
+
_containerExtent
>
_repaintOffsetLimit
)
renderObject
.
markNeedsLayout
();
}
}
super
.
updateRenderObject
();
}
void
_materializeChildren
()
{
assert
(
_materializedChildBase
!=
null
);
assert
(
_materializedChildCount
!=
null
);
List
<
Widget
>
newWidgets
=
new
List
<
Widget
>(
_materializedChildCount
);
for
(
int
i
=
0
;
i
<
_materializedChildCount
;
++
i
)
{
int
childIndex
=
_materializedChildBase
+
i
;
Widget
child
=
widget
.
children
[
childIndex
];
Key
key
=
new
ValueKey
(
child
.
key
??
childIndex
);
newWidgets
[
i
]
=
new
RepaintBoundary
(
key:
key
,
child:
child
);
}
_materializedChildren
=
updateChildren
(
_materializedChildren
,
newWidgets
);
}
double
_contentExtent
;
double
_containerExtent
;
GridSpecification
_specification
;
void
layout
(
BoxConstraints
constraints
)
{
_specification
=
renderObject
.
specification
;
...
...
@@ -188,13 +136,12 @@ class _GridViewportElement extends RenderObjectElement<GridViewport> {
int
materializedRowBase
=
math
.
max
(
0
,
_lowerBound
(
_specification
.
rowOffsets
,
widget
.
startOffset
)
-
1
);
int
materializedRowLimit
=
math
.
min
(
_specification
.
rowCount
,
_lowerBound
(
_specification
.
rowOffsets
,
widget
.
startOffset
+
containerExtent
));
_materializedChildBase
=
materializedRowBase
*
_specification
.
columnCount
;
_materializedChildCount
=
math
.
min
(
widget
.
children
.
length
,
materializedRowLimit
*
_specification
.
columnCount
)
-
_materializedChildBase
;
_materializedChildBase
=
(
materializedRowBase
*
_specification
.
columnCount
).
clamp
(
0
,
widget
.
children
.
length
)
;
_materializedChildCount
=
(
materializedRowLimit
*
_specification
.
columnCount
).
clamp
(
0
,
widget
.
children
.
length
)
-
_materializedChildBase
;
_repaintOffsetBase
=
_specification
.
rowOffsets
[
materializedRowBase
];
_repaintOffsetLimit
=
_specification
.
rowOffsets
[
materializedRowLimit
];
_updatePaintOffset
();
BuildableElement
.
lockState
(
_materializeChildren
);
super
.
layout
(
constraints
);
if
(
contentExtent
!=
_contentExtent
||
containerExtent
!=
_containerExtent
)
{
_contentExtent
=
contentExtent
;
...
...
@@ -202,20 +149,4 @@ class _GridViewportElement extends RenderObjectElement<GridViewport> {
widget
.
onExtentsChanged
(
_contentExtent
,
_containerExtent
);
}
}
void
insertChildRenderObject
(
RenderObject
child
,
Element
slot
)
{
RenderObject
nextSibling
=
slot
?.
renderObject
;
renderObject
.
add
(
child
,
before:
nextSibling
);
}
void
moveChildRenderObject
(
RenderObject
child
,
Element
slot
)
{
assert
(
child
.
parent
==
renderObject
);
RenderObject
nextSibling
=
slot
?.
renderObject
;
renderObject
.
move
(
child
,
before:
nextSibling
);
}
void
removeChildRenderObject
(
RenderObject
child
)
{
assert
(
child
.
parent
==
renderObject
);
renderObject
.
remove
(
child
);
}
}
packages/flutter/lib/src/widgets/scrollable_list.dart
0 → 100644
View file @
24fadf49
// Copyright 2015 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
'framework.dart'
;
import
'scrollable.dart'
;
import
'virtual_viewport.dart'
;
import
'package:flutter/animation.dart'
;
import
'package:flutter/rendering.dart'
;
class
ScrollableList2
extends
Scrollable
{
ScrollableList2
({
Key
key
,
double
initialScrollOffset
,
ScrollListener
onScroll
,
SnapOffsetCallback
snapOffsetCallback
,
double
snapAlignmentOffset:
0.0
,
this
.
itemExtent
,
this
.
children
})
:
super
(
key:
key
,
initialScrollOffset:
initialScrollOffset
,
// TODO(abarth): Support horizontal offsets.
scrollDirection:
ScrollDirection
.
vertical
,
onScroll:
onScroll
,
snapOffsetCallback:
snapOffsetCallback
,
snapAlignmentOffset:
snapAlignmentOffset
);
final
double
itemExtent
;
final
List
<
Widget
>
children
;
ScrollableState
createState
()
=>
new
_ScrollableList2State
();
}
class
_ScrollableList2State
extends
ScrollableState
<
ScrollableList2
>
{
ScrollBehavior
createScrollBehavior
()
=>
new
OverscrollBehavior
();
ExtentScrollBehavior
get
scrollBehavior
=>
super
.
scrollBehavior
;
void
_handleExtentsChanged
(
double
contentExtent
,
double
containerExtent
)
{
setState
(()
{
scrollTo
(
scrollBehavior
.
updateExtents
(
contentExtent:
contentExtent
,
containerExtent:
containerExtent
,
scrollOffset:
scrollOffset
));
});
}
Widget
buildContent
(
BuildContext
context
)
{
return
new
ListViewport
(
startOffset:
scrollOffset
,
itemExtent:
config
.
itemExtent
,
onExtentsChanged:
_handleExtentsChanged
,
children:
config
.
children
);
}
}
class
ListViewport
extends
VirtualViewport
{
ListViewport
({
Key
key
,
this
.
startOffset
,
this
.
itemExtent
,
this
.
onExtentsChanged
,
this
.
children
});
final
double
startOffset
;
final
double
itemExtent
;
final
ExtentsChangedCallback
onExtentsChanged
;
final
List
<
Widget
>
children
;
RenderList
createRenderObject
()
=>
new
RenderList
(
itemExtent:
itemExtent
);
_ListViewportElement
createElement
()
=>
new
_ListViewportElement
(
this
);
}
class
_ListViewportElement
extends
VirtualViewportElement
<
ListViewport
>
{
_ListViewportElement
(
ListViewport
widget
)
:
super
(
widget
);
RenderList
get
renderObject
=>
super
.
renderObject
;
int
get
materializedChildBase
=>
_materializedChildBase
;
int
_materializedChildBase
;
int
get
materializedChildCount
=>
_materializedChildCount
;
int
_materializedChildCount
;
double
get
repaintOffsetBase
=>
_repaintOffsetBase
;
double
_repaintOffsetBase
;
double
get
repaintOffsetLimit
=>
_repaintOffsetLimit
;
double
_repaintOffsetLimit
;
void
updateRenderObject
()
{
renderObject
.
itemExtent
=
widget
.
itemExtent
;
super
.
updateRenderObject
();
}
double
_contentExtent
;
double
_containerExtent
;
void
layout
(
BoxConstraints
constraints
)
{
double
contentExtent
=
widget
.
itemExtent
*
widget
.
children
.
length
;
double
containerExtent
=
renderObject
.
size
.
height
;
_materializedChildBase
=
(
widget
.
startOffset
~/
widget
.
itemExtent
).
clamp
(
0
,
widget
.
children
.
length
);
int
materializedChildLimit
=
((
widget
.
startOffset
+
containerExtent
)
/
widget
.
itemExtent
).
ceil
().
clamp
(
0
,
widget
.
children
.
length
);
_materializedChildCount
=
materializedChildLimit
-
_materializedChildBase
;
_repaintOffsetBase
=
_materializedChildBase
*
widget
.
itemExtent
;
_repaintOffsetLimit
=
materializedChildLimit
*
widget
.
itemExtent
;
super
.
layout
(
constraints
);
if
(
contentExtent
!=
_contentExtent
||
containerExtent
!=
_containerExtent
)
{
_contentExtent
=
contentExtent
;
_containerExtent
=
containerExtent
;
widget
.
onExtentsChanged
(
_contentExtent
,
_containerExtent
);
}
}
}
packages/flutter/lib/src/widgets/virtual_viewport.dart
0 → 100644
View file @
24fadf49
// Copyright 2015 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
'basic.dart'
;
import
'framework.dart'
;
import
'package:flutter/rendering.dart'
;
typedef
void
ExtentsChangedCallback
(
double
contentExtent
,
double
containerExtent
);
abstract
class
VirtualViewport
extends
RenderObjectWidget
{
double
get
startOffset
;
List
<
Widget
>
get
children
;
}
abstract
class
VirtualViewportElement
<
T
extends
VirtualViewport
>
extends
RenderObjectElement
<
T
>
{
VirtualViewportElement
(
T
widget
)
:
super
(
widget
);
int
get
materializedChildBase
;
int
get
materializedChildCount
;
double
get
repaintOffsetBase
;
double
get
repaintOffsetLimit
;
List
<
Element
>
_materializedChildren
=
const
<
Element
>[];
RenderVirtualViewport
get
renderObject
=>
super
.
renderObject
;
void
visitChildren
(
ElementVisitor
visitor
)
{
if
(
_materializedChildren
==
null
)
return
;
for
(
Element
child
in
_materializedChildren
)
visitor
(
child
);
}
void
mount
(
Element
parent
,
dynamic
newSlot
)
{
super
.
mount
(
parent
,
newSlot
);
renderObject
.
callback
=
layout
;
updateRenderObject
();
}
void
unmount
()
{
renderObject
.
callback
=
null
;
super
.
unmount
();
}
void
update
(
T
newWidget
)
{
super
.
update
(
newWidget
);
updateRenderObject
();
if
(!
renderObject
.
needsLayout
)
_materializeChildren
();
}
void
_updatePaintOffset
()
{
renderObject
.
paintOffset
=
renderObject
.
paintOffset
=
new
Offset
(
0.0
,
-(
widget
.
startOffset
-
repaintOffsetBase
));
}
void
updateRenderObject
()
{
renderObject
.
virtualChildCount
=
widget
.
children
.
length
;
if
(
repaintOffsetBase
!=
null
)
{
_updatePaintOffset
();
// If we don't already need layout, we need to request a layout if the
// viewport has shifted to expose new children.
if
(!
renderObject
.
needsLayout
)
{
if
(
repaintOffsetBase
!=
null
&&
widget
.
startOffset
<
repaintOffsetBase
)
renderObject
.
markNeedsLayout
();
else
if
(
repaintOffsetLimit
!=
null
&&
widget
.
startOffset
+
renderObject
.
size
.
height
>
repaintOffsetLimit
)
renderObject
.
markNeedsLayout
();
}
}
}
void
layout
(
BoxConstraints
constraints
)
{
assert
(
repaintOffsetBase
!=
null
);
assert
(
repaintOffsetLimit
!=
null
);
_updatePaintOffset
();
BuildableElement
.
lockState
(
_materializeChildren
);
}
void
_materializeChildren
()
{
int
base
=
materializedChildBase
;
int
count
=
materializedChildCount
;
assert
(
base
!=
null
);
assert
(
count
!=
null
);
List
<
Widget
>
newWidgets
=
new
List
<
Widget
>(
count
);
for
(
int
i
=
0
;
i
<
count
;
++
i
)
{
int
childIndex
=
base
+
i
;
Widget
child
=
widget
.
children
[
childIndex
];
Key
key
=
new
ValueKey
(
child
.
key
??
childIndex
);
newWidgets
[
i
]
=
new
RepaintBoundary
(
key:
key
,
child:
child
);
}
_materializedChildren
=
updateChildren
(
_materializedChildren
,
newWidgets
);
}
void
insertChildRenderObject
(
RenderObject
child
,
Element
slot
)
{
RenderObject
nextSibling
=
slot
?.
renderObject
;
renderObject
.
add
(
child
,
before:
nextSibling
);
}
void
moveChildRenderObject
(
RenderObject
child
,
Element
slot
)
{
assert
(
child
.
parent
==
renderObject
);
RenderObject
nextSibling
=
slot
?.
renderObject
;
renderObject
.
move
(
child
,
before:
nextSibling
);
}
void
removeChildRenderObject
(
RenderObject
child
)
{
assert
(
child
.
parent
==
renderObject
);
renderObject
.
remove
(
child
);
}
}
packages/flutter/lib/widgets.dart
View file @
24fadf49
...
...
@@ -33,10 +33,12 @@ export 'src/widgets/placeholder.dart';
export
'src/widgets/routes.dart'
;
export
'src/widgets/scrollable.dart'
;
export
'src/widgets/scrollable_grid.dart'
;
export
'src/widgets/scrollable_list.dart'
;
export
'src/widgets/statistics_overlay.dart'
;
export
'src/widgets/status_transitions.dart'
;
export
'src/widgets/title.dart'
;
export
'src/widgets/transitions.dart'
;
export
'src/widgets/unique_component.dart'
;
export
'src/widgets/virtual_viewport.dart'
;
export
'package:vector_math/vector_math_64.dart'
show
Matrix4
;
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