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
e766ae74
Unverified
Commit
e766ae74
authored
Nov 26, 2019
by
Dan Field
Committed by
GitHub
Nov 26, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Automatically caching viewport (#45327)
parent
84ce3f60
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
217 additions
and
13 deletions
+217
-13
viewport.dart
packages/flutter/lib/src/rendering/viewport.dart
+74
-11
viewport.dart
packages/flutter/lib/src/widgets/viewport.dart
+11
-1
rendering_tester.dart
packages/flutter/test/rendering/rendering_tester.dart
+0
-1
viewport_caching_test.dart
packages/flutter/test/rendering/viewport_caching_test.dart
+127
-0
viewport_test.dart
packages/flutter/test/rendering/viewport_test.dart
+5
-0
No files found.
packages/flutter/lib/src/rendering/viewport.dart
View file @
e766ae74
...
...
@@ -15,6 +15,14 @@ import 'object.dart';
import
'sliver.dart'
;
import
'viewport_offset.dart'
;
/// The unit of measurement for a [Viewport.cacheExtent].
enum
CacheExtentStyle
{
/// Treat the [Viewport.cacheExtent] as logical pixels.
pixel
,
/// Treat the [Viewport.cacheExtent] as a multiplier of the main axis extent.
viewport
,
}
/// An interface for render objects that are bigger on the inside.
///
/// Some render objects, such as [RenderViewport], present a portion of their
...
...
@@ -75,6 +83,7 @@ abstract class RenderAbstractViewport extends RenderObject {
///
/// * [RenderViewportBase.cacheExtent] for a definition of the cache extent.
@protected
@visibleForTesting
static
const
double
defaultCacheExtent
=
250.0
;
}
...
...
@@ -160,14 +169,18 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
@required
AxisDirection
crossAxisDirection
,
@required
ViewportOffset
offset
,
double
cacheExtent
,
CacheExtentStyle
cacheExtentStyle
=
CacheExtentStyle
.
pixel
,
})
:
assert
(
axisDirection
!=
null
),
assert
(
crossAxisDirection
!=
null
),
assert
(
offset
!=
null
),
assert
(
axisDirectionToAxis
(
axisDirection
)
!=
axisDirectionToAxis
(
crossAxisDirection
)),
assert
(
cacheExtentStyle
!=
null
),
assert
(
cacheExtent
!=
null
||
cacheExtentStyle
==
CacheExtentStyle
.
pixel
),
_axisDirection
=
axisDirection
,
_crossAxisDirection
=
crossAxisDirection
,
_offset
=
offset
,
_cacheExtent
=
cacheExtent
??
RenderAbstractViewport
.
defaultCacheExtent
;
_cacheExtent
=
cacheExtent
??
RenderAbstractViewport
.
defaultCacheExtent
,
_cacheExtentStyle
=
cacheExtentStyle
;
@override
void
describeSemanticsConfiguration
(
SemanticsConfiguration
config
)
{
...
...
@@ -272,6 +285,34 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
markNeedsLayout
();
}
/// This value is set during layout based on the [CacheExtentStyle].
///
/// When the style is [CacheExtentStyle.viewport], it is the main axis extent
/// of the viewport multiplied by the requested cache extent, which is still
/// expressed in pixels.
double
_calculatedCacheExtent
;
/// {@template flutter.rendering.viewport.cacheExtentStyle}
/// Controls how the [cacheExtent] is interpreted.
///
/// If set to [CacheExtentStyle.pixels], the [cacheExtent] will be treated as
/// a logical pixels.
///
/// If set to [CacheExtentStyle.viewport], the [cacheExtent] will be treated
/// as a multiplier for the main axis extent of the viewport. In this case,
/// the [cacheExtent] must not be null.
/// {@endtemplate}
CacheExtentStyle
get
cacheExtentStyle
=>
_cacheExtentStyle
;
CacheExtentStyle
_cacheExtentStyle
;
set
cacheExtentStyle
(
CacheExtentStyle
value
)
{
assert
(
value
!=
null
);
if
(
value
==
_cacheExtentStyle
)
{
return
;
}
_cacheExtentStyle
=
value
;
markNeedsLayout
();
}
@override
void
attach
(
PipelineOwner
owner
)
{
super
.
attach
(
owner
);
...
...
@@ -494,20 +535,25 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
@override
Rect
describeSemanticsClip
(
RenderSliver
child
)
{
assert
(
axis
!=
null
);
assert
(
axis
!=
null
);
if
(
_calculatedCacheExtent
==
null
)
{
return
semanticBounds
;
}
switch
(
axis
)
{
case
Axis
.
vertical
:
return
Rect
.
fromLTRB
(
semanticBounds
.
left
,
semanticBounds
.
top
-
c
acheExtent
,
semanticBounds
.
top
-
_calculatedC
acheExtent
,
semanticBounds
.
right
,
semanticBounds
.
bottom
+
c
acheExtent
,
semanticBounds
.
bottom
+
_calculatedC
acheExtent
,
);
case
Axis
.
horizontal
:
return
Rect
.
fromLTRB
(
semanticBounds
.
left
-
c
acheExtent
,
semanticBounds
.
left
-
_calculatedC
acheExtent
,
semanticBounds
.
top
,
semanticBounds
.
right
+
c
acheExtent
,
semanticBounds
.
right
+
_calculatedC
acheExtent
,
semanticBounds
.
bottom
,
);
}
...
...
@@ -1076,11 +1122,19 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
List
<
RenderSliver
>
children
,
RenderSliver
center
,
double
cacheExtent
,
CacheExtentStyle
cacheExtentStyle
=
CacheExtentStyle
.
pixel
,
})
:
assert
(
anchor
!=
null
),
assert
(
anchor
>=
0.0
&&
anchor
<=
1.0
),
assert
(
cacheExtentStyle
!=
CacheExtentStyle
.
viewport
||
cacheExtent
!=
null
),
_anchor
=
anchor
,
_center
=
center
,
super
(
axisDirection:
axisDirection
,
crossAxisDirection:
crossAxisDirection
,
offset:
offset
,
cacheExtent:
cacheExtent
)
{
super
(
axisDirection:
axisDirection
,
crossAxisDirection:
crossAxisDirection
,
offset:
offset
,
cacheExtent:
cacheExtent
,
cacheExtentStyle:
cacheExtentStyle
,
)
{
addAll
(
children
);
if
(
center
==
null
&&
firstChild
!=
null
)
_center
=
firstChild
;
...
...
@@ -1337,8 +1391,17 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
final
double
reverseDirectionRemainingPaintExtent
=
centerOffset
.
clamp
(
0.0
,
mainAxisExtent
);
final
double
forwardDirectionRemainingPaintExtent
=
(
mainAxisExtent
-
centerOffset
).
clamp
(
0.0
,
mainAxisExtent
);
final
double
fullCacheExtent
=
mainAxisExtent
+
2
*
cacheExtent
;
final
double
centerCacheOffset
=
centerOffset
+
cacheExtent
;
switch
(
cacheExtentStyle
)
{
case
CacheExtentStyle
.
pixel
:
_calculatedCacheExtent
=
cacheExtent
;
break
;
case
CacheExtentStyle
.
viewport
:
_calculatedCacheExtent
=
mainAxisExtent
*
cacheExtent
;
break
;
}
final
double
fullCacheExtent
=
mainAxisExtent
+
2
*
_calculatedCacheExtent
;
final
double
centerCacheOffset
=
centerOffset
+
_calculatedCacheExtent
;
final
double
reverseDirectionRemainingCacheExtent
=
centerCacheOffset
.
clamp
(
0.0
,
fullCacheExtent
);
final
double
forwardDirectionRemainingCacheExtent
=
(
fullCacheExtent
-
centerCacheOffset
).
clamp
(
0.0
,
fullCacheExtent
);
...
...
@@ -1357,7 +1420,7 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
growthDirection:
GrowthDirection
.
reverse
,
advance:
childBefore
,
remainingCacheExtent:
reverseDirectionRemainingCacheExtent
,
cacheOrigin:
(
mainAxisExtent
-
centerOffset
).
clamp
(-
c
acheExtent
,
0.0
),
cacheOrigin:
(
mainAxisExtent
-
centerOffset
).
clamp
(-
_calculatedC
acheExtent
,
0.0
),
);
if
(
result
!=
0.0
)
return
-
result
;
...
...
@@ -1375,7 +1438,7 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
growthDirection:
GrowthDirection
.
forward
,
advance:
childAfter
,
remainingCacheExtent:
forwardDirectionRemainingCacheExtent
,
cacheOrigin:
centerOffset
.
clamp
(-
c
acheExtent
,
0.0
),
cacheOrigin:
centerOffset
.
clamp
(-
_calculatedC
acheExtent
,
0.0
),
);
}
...
...
packages/flutter/lib/src/widgets/viewport.dart
View file @
e766ae74
...
...
@@ -57,10 +57,13 @@ class Viewport extends MultiChildRenderObjectWidget {
@required
this
.
offset
,
this
.
center
,
this
.
cacheExtent
,
this
.
cacheExtentStyle
=
CacheExtentStyle
.
pixel
,
List
<
Widget
>
slivers
=
const
<
Widget
>[],
})
:
assert
(
offset
!=
null
),
assert
(
slivers
!=
null
),
assert
(
center
==
null
||
slivers
.
where
((
Widget
child
)
=>
child
.
key
==
center
).
length
==
1
),
assert
(
cacheExtentStyle
!=
null
),
assert
(
cacheExtentStyle
!=
CacheExtentStyle
.
viewport
||
cacheExtent
!=
null
),
super
(
key:
key
,
children:
slivers
);
/// The direction in which the [offset]'s [ViewportOffset.pixels] increases.
...
...
@@ -112,6 +115,9 @@ class Viewport extends MultiChildRenderObjectWidget {
/// {@macro flutter.rendering.viewport.cacheExtent}
final
double
cacheExtent
;
/// {@macro flutter.rendering.viewport.cacheExtentStyle}
final
CacheExtentStyle
cacheExtentStyle
;
/// Given a [BuildContext] and an [AxisDirection], determine the correct cross
/// axis direction.
///
...
...
@@ -140,6 +146,7 @@ class Viewport extends MultiChildRenderObjectWidget {
anchor:
anchor
,
offset:
offset
,
cacheExtent:
cacheExtent
,
cacheExtentStyle:
cacheExtentStyle
,
);
}
...
...
@@ -150,7 +157,8 @@ class Viewport extends MultiChildRenderObjectWidget {
..
crossAxisDirection
=
crossAxisDirection
??
Viewport
.
getDefaultCrossAxisDirection
(
context
,
axisDirection
)
..
anchor
=
anchor
..
offset
=
offset
..
cacheExtent
=
cacheExtent
;
..
cacheExtent
=
cacheExtent
..
cacheExtentStyle
=
cacheExtentStyle
;
}
@override
...
...
@@ -168,6 +176,8 @@ class Viewport extends MultiChildRenderObjectWidget {
}
else
if
(
children
.
isNotEmpty
&&
children
.
first
.
key
!=
null
)
{
properties
.
add
(
DiagnosticsProperty
<
Key
>(
'center'
,
children
.
first
.
key
,
tooltip:
'implicit'
));
}
properties
.
add
(
DiagnosticsProperty
<
double
>(
'cacheExtent'
,
cacheExtent
));
properties
.
add
(
DiagnosticsProperty
<
CacheExtentStyle
>(
'cacheExtentStyle'
,
cacheExtentStyle
));
}
}
...
...
packages/flutter/test/rendering/rendering_tester.dart
View file @
e766ae74
...
...
@@ -190,7 +190,6 @@ class TestCallbackPainter extends CustomPainter {
bool
shouldRepaint
(
TestCallbackPainter
oldPainter
)
=>
true
;
}
class
RenderSizedBox
extends
RenderBox
{
RenderSizedBox
(
this
.
_size
);
...
...
packages/flutter/test/rendering/viewport_caching_test.dart
0 → 100644
View file @
e766ae74
// Copyright 2019 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is separate from viewport_test.dart because we can't use both
// testWidgets and rendering_tester in the same file - testWidgets will
// initialize a binding, which rendering_tester will attempt to re-initialize
// (or vice versa).
import
'package:flutter/rendering.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'rendering_tester.dart'
;
void
main
(
)
{
const
double
width
=
800
;
const
double
height
=
600
;
Rect
rectExpandedOnAxis
(
double
value
)
=>
Rect
.
fromLTRB
(
0.0
,
0.0
-
value
,
width
,
height
+
value
);
List
<
RenderSliver
>
children
;
setUp
(()
{
children
=
<
RenderSliver
>[
RenderSliverToBoxAdapter
(
child:
RenderSizedBox
(
const
Size
(
800
,
400
)),
),
];
});
test
(
'Cache extent - null, pixels'
,
()
async
{
final
RenderViewport
renderViewport
=
RenderViewport
(
crossAxisDirection:
AxisDirection
.
left
,
offset:
ViewportOffset
.
zero
(),
children:
children
,
);
layout
(
renderViewport
,
phase:
EnginePhase
.
flushSemantics
);
expect
(
renderViewport
.
describeSemanticsClip
(
null
),
rectExpandedOnAxis
(
RenderAbstractViewport
.
defaultCacheExtent
),
);
});
test
(
'Cache extent - 0, pixels'
,
()
async
{
final
RenderViewport
renderViewport
=
RenderViewport
(
crossAxisDirection:
AxisDirection
.
left
,
offset:
ViewportOffset
.
zero
(),
cacheExtent:
0.0
,
children:
children
,
);
layout
(
renderViewport
,
phase:
EnginePhase
.
flushSemantics
);
expect
(
renderViewport
.
describeSemanticsClip
(
null
),
rectExpandedOnAxis
(
0.0
));
});
test
(
'Cache extent - 500, pixels'
,
()
async
{
final
RenderViewport
renderViewport
=
RenderViewport
(
crossAxisDirection:
AxisDirection
.
left
,
offset:
ViewportOffset
.
zero
(),
cacheExtent:
500.0
,
children:
children
,
);
layout
(
renderViewport
,
phase:
EnginePhase
.
flushSemantics
);
expect
(
renderViewport
.
describeSemanticsClip
(
null
),
rectExpandedOnAxis
(
500.0
));
});
test
(
'Cache extent - nullx viewport'
,
()
async
{
await
expectLater
(()
=>
RenderViewport
(
crossAxisDirection:
AxisDirection
.
left
,
offset:
ViewportOffset
.
zero
(),
cacheExtent:
null
,
cacheExtentStyle:
CacheExtentStyle
.
viewport
,
children:
children
,
),
throwsAssertionError
);
});
test
(
'Cache extent - 0x viewport'
,
()
async
{
final
RenderViewport
renderViewport
=
RenderViewport
(
crossAxisDirection:
AxisDirection
.
left
,
offset:
ViewportOffset
.
zero
(),
cacheExtent:
0.0
,
cacheExtentStyle:
CacheExtentStyle
.
viewport
,
children:
children
,
);
layout
(
renderViewport
);
expect
(
renderViewport
.
describeSemanticsClip
(
null
),
rectExpandedOnAxis
(
0
));
});
test
(
'Cache extent - .5x viewport'
,
()
async
{
final
RenderViewport
renderViewport
=
RenderViewport
(
crossAxisDirection:
AxisDirection
.
left
,
offset:
ViewportOffset
.
zero
(),
cacheExtent:
.
5
,
cacheExtentStyle:
CacheExtentStyle
.
viewport
,
children:
children
,
);
layout
(
renderViewport
);
expect
(
renderViewport
.
describeSemanticsClip
(
null
),
rectExpandedOnAxis
(
height
/
2
));
});
test
(
'Cache extent - 1x viewport'
,
()
async
{
final
RenderViewport
renderViewport
=
RenderViewport
(
crossAxisDirection:
AxisDirection
.
left
,
offset:
ViewportOffset
.
zero
(),
cacheExtent:
1.0
,
cacheExtentStyle:
CacheExtentStyle
.
viewport
,
children:
children
,
);
layout
(
renderViewport
);
expect
(
renderViewport
.
describeSemanticsClip
(
null
),
rectExpandedOnAxis
(
height
));
});
test
(
'Cache extent - 2.5x viewport'
,
()
async
{
final
RenderViewport
renderViewport
=
RenderViewport
(
crossAxisDirection:
AxisDirection
.
left
,
offset:
ViewportOffset
.
zero
(),
cacheExtent:
2.5
,
cacheExtentStyle:
CacheExtentStyle
.
viewport
,
children:
children
,
);
layout
(
renderViewport
);
expect
(
renderViewport
.
describeSemanticsClip
(
null
),
rectExpandedOnAxis
(
height
*
2.5
));
});
}
packages/flutter/test/rendering/viewport_test.dart
View file @
e766ae74
...
...
@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is separate from viewport_caching_test.dart because we can't use
// both testWidgets and rendering_tester in the same file - testWidgets will
// initialize a binding, which rendering_tester will attempt to re-initialize
// (or vice versa).
import
'dart:ui'
;
import
'package:flutter_test/flutter_test.dart'
;
...
...
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