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
efd5aea0
Commit
efd5aea0
authored
Feb 09, 2016
by
Adam Barth
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1736 from abarth/scroll_anchor3
Add scroll anchor for Block
parents
a82b8963
f0276d09
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
136 additions
and
22 deletions
+136
-22
viewport.dart
packages/flutter/lib/src/rendering/viewport.dart
+64
-11
basic.dart
packages/flutter/lib/src/widgets/basic.dart
+18
-10
scrollable.dart
packages/flutter/lib/src/widgets/scrollable.dart
+5
-1
block_test.dart
packages/flutter/test/widget/block_test.dart
+49
-0
No files found.
packages/flutter/lib/src/rendering/viewport.dart
View file @
efd5aea0
...
@@ -14,6 +14,33 @@ enum ViewportAnchor {
...
@@ -14,6 +14,33 @@ enum ViewportAnchor {
end
,
end
,
}
}
class
ViewportDimensions
{
const
ViewportDimensions
({
this
.
contentSize
:
Size
.
zero
,
this
.
containerSize
:
Size
.
zero
});
static
const
ViewportDimensions
zero
=
const
ViewportDimensions
();
final
Size
contentSize
;
final
Size
containerSize
;
bool
get
_debugHasAtLeastOneCommonDimension
{
return
contentSize
.
width
==
containerSize
.
width
||
contentSize
.
height
==
containerSize
.
height
;
}
Offset
getAbsolutePaintOffset
({
Offset
paintOffset
,
ViewportAnchor
anchor
})
{
assert
(
_debugHasAtLeastOneCommonDimension
);
switch
(
anchor
)
{
case
ViewportAnchor
.
start
:
return
paintOffset
;
case
ViewportAnchor
.
end
:
return
paintOffset
+
(
containerSize
-
contentSize
);
}
}
}
abstract
class
HasScrollDirection
{
abstract
class
HasScrollDirection
{
Axis
get
scrollDirection
;
Axis
get
scrollDirection
;
}
}
...
@@ -27,9 +54,11 @@ class RenderViewportBase extends RenderBox implements HasScrollDirection {
...
@@ -27,9 +54,11 @@ class RenderViewportBase extends RenderBox implements HasScrollDirection {
RenderViewportBase
(
RenderViewportBase
(
Offset
paintOffset
,
Offset
paintOffset
,
Axis
scrollDirection
,
Axis
scrollDirection
,
ViewportAnchor
scrollAnchor
,
Painter
overlayPainter
Painter
overlayPainter
)
:
_paintOffset
=
paintOffset
,
)
:
_paintOffset
=
paintOffset
,
_scrollDirection
=
scrollDirection
,
_scrollDirection
=
scrollDirection
,
_scrollAnchor
=
scrollAnchor
,
_overlayPainter
=
overlayPainter
{
_overlayPainter
=
overlayPainter
{
assert
(
paintOffset
!=
null
);
assert
(
paintOffset
!=
null
);
assert
(
scrollDirection
!=
null
);
assert
(
scrollDirection
!=
null
);
...
@@ -76,6 +105,17 @@ class RenderViewportBase extends RenderBox implements HasScrollDirection {
...
@@ -76,6 +105,17 @@ class RenderViewportBase extends RenderBox implements HasScrollDirection {
markNeedsLayout
();
markNeedsLayout
();
}
}
ViewportAnchor
get
scrollAnchor
=>
_scrollAnchor
;
ViewportAnchor
_scrollAnchor
;
void
set
scrollAnchor
(
ViewportAnchor
value
)
{
assert
(
value
!=
null
);
if
(
value
==
_scrollAnchor
)
return
;
_scrollAnchor
=
value
;
markNeedsPaint
();
markNeedsSemanticsUpdate
();
}
Painter
get
overlayPainter
=>
_overlayPainter
;
Painter
get
overlayPainter
=>
_overlayPainter
;
Painter
_overlayPainter
;
Painter
_overlayPainter
;
void
set
overlayPainter
(
Painter
value
)
{
void
set
overlayPainter
(
Painter
value
)
{
...
@@ -99,16 +139,25 @@ class RenderViewportBase extends RenderBox implements HasScrollDirection {
...
@@ -99,16 +139,25 @@ class RenderViewportBase extends RenderBox implements HasScrollDirection {
_overlayPainter
?.
detach
();
_overlayPainter
?.
detach
();
}
}
Offset
get
_paintOffsetRoundedToIntegerDevicePixels
{
ViewportDimensions
get
dimensions
=>
_dimensions
;
ViewportDimensions
_dimensions
=
ViewportDimensions
.
zero
;
void
set
dimensions
(
ViewportDimensions
value
)
{
assert
(
debugDoingThisLayout
);
_dimensions
=
value
;
}
Offset
get
_effectivePaintOffset
{
final
double
devicePixelRatio
=
ui
.
window
.
devicePixelRatio
;
final
double
devicePixelRatio
=
ui
.
window
.
devicePixelRatio
;
int
dxInDevicePixels
=
(
_paintOffset
.
dx
*
devicePixelRatio
).
round
();
int
dxInDevicePixels
=
(
_paintOffset
.
dx
*
devicePixelRatio
).
round
();
int
dyInDevicePixels
=
(
_paintOffset
.
dy
*
devicePixelRatio
).
round
();
int
dyInDevicePixels
=
(
_paintOffset
.
dy
*
devicePixelRatio
).
round
();
return
new
Offset
(
dxInDevicePixels
/
devicePixelRatio
,
return
_dimensions
.
getAbsolutePaintOffset
(
dyInDevicePixels
/
devicePixelRatio
);
paintOffset:
new
Offset
(
dxInDevicePixels
/
devicePixelRatio
,
dyInDevicePixels
/
devicePixelRatio
),
anchor:
_scrollAnchor
);
}
}
void
applyPaintTransform
(
RenderBox
child
,
Matrix4
transform
)
{
void
applyPaintTransform
(
RenderBox
child
,
Matrix4
transform
)
{
final
Offset
effectivePaintOffset
=
_
paintOffsetRoundedToIntegerDevicePixels
;
final
Offset
effectivePaintOffset
=
_
effectivePaintOffset
;
super
.
applyPaintTransform
(
child
,
transform
.
translate
(
effectivePaintOffset
.
dx
,
effectivePaintOffset
.
dy
));
super
.
applyPaintTransform
(
child
,
transform
.
translate
(
effectivePaintOffset
.
dx
,
effectivePaintOffset
.
dy
));
}
}
...
@@ -126,8 +175,9 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin<
...
@@ -126,8 +175,9 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin<
RenderBox
child
,
RenderBox
child
,
Offset
paintOffset:
Offset
.
zero
,
Offset
paintOffset:
Offset
.
zero
,
Axis
scrollDirection:
Axis
.
vertical
,
Axis
scrollDirection:
Axis
.
vertical
,
ViewportAnchor
scrollAnchor:
ViewportAnchor
.
start
,
Painter
overlayPainter
Painter
overlayPainter
})
:
super
(
paintOffset
,
scrollDirection
,
overlayPainter
)
{
})
:
super
(
paintOffset
,
scrollDirection
,
scrollAnchor
,
overlayPainter
)
{
this
.
child
=
child
;
this
.
child
=
child
;
}
}
...
@@ -183,8 +233,10 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin<
...
@@ -183,8 +233,10 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin<
size
=
constraints
.
constrain
(
child
.
size
);
size
=
constraints
.
constrain
(
child
.
size
);
final
BoxParentData
childParentData
=
child
.
parentData
;
final
BoxParentData
childParentData
=
child
.
parentData
;
childParentData
.
offset
=
Offset
.
zero
;
childParentData
.
offset
=
Offset
.
zero
;
dimensions
=
new
ViewportDimensions
(
containerSize:
size
,
contentSize:
child
.
size
);
}
else
{
}
else
{
performResize
();
performResize
();
dimensions
=
new
ViewportDimensions
(
containerSize:
size
);
}
}
}
}
...
@@ -195,7 +247,7 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin<
...
@@ -195,7 +247,7 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin<
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
if
(
child
!=
null
)
{
if
(
child
!=
null
)
{
final
Offset
effectivePaintOffset
=
_
paintOffsetRoundedToIntegerDevicePixels
;
final
Offset
effectivePaintOffset
=
_
effectivePaintOffset
;
void
paintContents
(
PaintingContext
context
,
Offset
offset
)
{
void
paintContents
(
PaintingContext
context
,
Offset
offset
)
{
context
.
paintChild
(
child
,
offset
+
effectivePaintOffset
);
context
.
paintChild
(
child
,
offset
+
effectivePaintOffset
);
...
@@ -211,7 +263,7 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin<
...
@@ -211,7 +263,7 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin<
}
}
Rect
describeApproximatePaintClip
(
RenderObject
child
)
{
Rect
describeApproximatePaintClip
(
RenderObject
child
)
{
if
(
child
!=
null
&&
_shouldClipAtPaintOffset
(
_
paintOffsetRoundedToIntegerDevicePixels
))
if
(
child
!=
null
&&
_shouldClipAtPaintOffset
(
_
effectivePaintOffset
))
return
Point
.
origin
&
size
;
return
Point
.
origin
&
size
;
return
null
;
return
null
;
}
}
...
@@ -219,7 +271,7 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin<
...
@@ -219,7 +271,7 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin<
bool
hitTestChildren
(
HitTestResult
result
,
{
Point
position
})
{
bool
hitTestChildren
(
HitTestResult
result
,
{
Point
position
})
{
if
(
child
!=
null
)
{
if
(
child
!=
null
)
{
assert
(
child
.
parentData
is
BoxParentData
);
assert
(
child
.
parentData
is
BoxParentData
);
Point
transformed
=
position
+
-
_
paintOffsetRoundedToIntegerDevicePixels
;
Point
transformed
=
position
+
-
_
effectivePaintOffset
;
return
child
.
hitTest
(
result
,
position:
transformed
);
return
child
.
hitTest
(
result
,
position:
transformed
);
}
}
return
false
;
return
false
;
...
@@ -234,10 +286,11 @@ abstract class RenderVirtualViewport<T extends ContainerBoxParentDataMixin<Rende
...
@@ -234,10 +286,11 @@ abstract class RenderVirtualViewport<T extends ContainerBoxParentDataMixin<Rende
LayoutCallback
callback
,
LayoutCallback
callback
,
Offset
paintOffset:
Offset
.
zero
,
Offset
paintOffset:
Offset
.
zero
,
Axis
scrollDirection:
Axis
.
vertical
,
Axis
scrollDirection:
Axis
.
vertical
,
ViewportAnchor
scrollAnchor:
ViewportAnchor
.
start
,
Painter
overlayPainter
Painter
overlayPainter
})
:
_virtualChildCount
=
virtualChildCount
,
})
:
_virtualChildCount
=
virtualChildCount
,
_callback
=
callback
,
_callback
=
callback
,
super
(
paintOffset
,
scrollDirection
,
overlayPainter
);
super
(
paintOffset
,
scrollDirection
,
scrollAnchor
,
overlayPainter
);
int
get
virtualChildCount
=>
_virtualChildCount
;
int
get
virtualChildCount
=>
_virtualChildCount
;
int
_virtualChildCount
;
int
_virtualChildCount
;
...
@@ -262,11 +315,11 @@ abstract class RenderVirtualViewport<T extends ContainerBoxParentDataMixin<Rende
...
@@ -262,11 +315,11 @@ abstract class RenderVirtualViewport<T extends ContainerBoxParentDataMixin<Rende
}
}
bool
hitTestChildren
(
HitTestResult
result
,
{
Point
position
})
{
bool
hitTestChildren
(
HitTestResult
result
,
{
Point
position
})
{
return
defaultHitTestChildren
(
result
,
position:
position
+
-
_
paintOffsetRoundedToIntegerDevicePixels
);
return
defaultHitTestChildren
(
result
,
position:
position
+
-
_
effectivePaintOffset
);
}
}
void
_paintContents
(
PaintingContext
context
,
Offset
offset
)
{
void
_paintContents
(
PaintingContext
context
,
Offset
offset
)
{
defaultPaint
(
context
,
offset
+
_
paintOffsetRoundedToIntegerDevicePixels
);
defaultPaint
(
context
,
offset
+
_
effectivePaintOffset
);
_overlayPainter
?.
paint
(
context
,
offset
);
_overlayPainter
?.
paint
(
context
,
offset
);
}
}
...
...
packages/flutter/lib/src/widgets/basic.dart
View file @
efd5aea0
...
@@ -65,6 +65,7 @@ export 'package:flutter/rendering.dart' show
...
@@ -65,6 +65,7 @@ export 'package:flutter/rendering.dart' show
TextStyle
,
TextStyle
,
TransferMode
,
TransferMode
,
ValueChanged
,
ValueChanged
,
ViewportAnchor
,
VoidCallback
;
VoidCallback
;
...
@@ -796,8 +797,9 @@ class Baseline extends OneChildRenderObjectWidget {
...
@@ -796,8 +797,9 @@ class Baseline extends OneChildRenderObjectWidget {
class
Viewport
extends
OneChildRenderObjectWidget
{
class
Viewport
extends
OneChildRenderObjectWidget
{
Viewport
({
Viewport
({
Key
key
,
Key
key
,
this
.
scrollDirection
:
Axis
.
vertical
,
this
.
paintOffset
:
Offset
.
zero
,
this
.
paintOffset
:
Offset
.
zero
,
this
.
scrollDirection
:
Axis
.
vertical
,
this
.
scrollAnchor
:
ViewportAnchor
.
start
,
this
.
overlayPainter
,
this
.
overlayPainter
,
Widget
child
Widget
child
})
:
super
(
key:
key
,
child:
child
)
{
})
:
super
(
key:
key
,
child:
child
)
{
...
@@ -805,6 +807,11 @@ class Viewport extends OneChildRenderObjectWidget {
...
@@ -805,6 +807,11 @@ class Viewport extends OneChildRenderObjectWidget {
assert
(
paintOffset
!=
null
);
assert
(
paintOffset
!=
null
);
}
}
/// The offset at which to paint the child.
///
/// The offset can be non-zero only in the [scrollDirection].
final
Offset
paintOffset
;
/// The direction in which the child is permitted to be larger than the viewport
/// The direction in which the child is permitted to be larger than the viewport
///
///
/// If the viewport is scrollable in a particular direction (e.g., vertically),
/// If the viewport is scrollable in a particular direction (e.g., vertically),
...
@@ -812,26 +819,27 @@ class Viewport extends OneChildRenderObjectWidget {
...
@@ -812,26 +819,27 @@ class Viewport extends OneChildRenderObjectWidget {
/// that direction (e.g., the child can be as tall as it wants).
/// that direction (e.g., the child can be as tall as it wants).
final
Axis
scrollDirection
;
final
Axis
scrollDirection
;
/// The offset at which to paint the child.
final
ViewportAnchor
scrollAnchor
;
///
/// The offset can be non-zero only in the [scrollDirection].
final
Offset
paintOffset
;
/// Paints an overlay over the viewport.
/// Paints an overlay over the viewport.
///
///
/// Often used to paint scroll bars.
/// Often used to paint scroll bars.
final
Painter
overlayPainter
;
final
Painter
overlayPainter
;
RenderViewport
createRenderObject
()
=>
new
RenderViewport
(
RenderViewport
createRenderObject
()
{
scrollDirection:
scrollDirection
,
return
new
RenderViewport
(
paintOffset:
paintOffset
,
paintOffset:
paintOffset
,
overlayPainter:
overlayPainter
scrollDirection:
scrollDirection
,
);
scrollAnchor:
scrollAnchor
,
overlayPainter:
overlayPainter
);
}
void
updateRenderObject
(
RenderViewport
renderObject
,
Viewport
oldWidget
)
{
void
updateRenderObject
(
RenderViewport
renderObject
,
Viewport
oldWidget
)
{
// Order dependency: RenderViewport validates scrollOffset based on scrollDirection.
// Order dependency: RenderViewport validates scrollOffset based on scrollDirection.
renderObject
renderObject
..
scrollDirection
=
scrollDirection
..
scrollDirection
=
scrollDirection
..
scrollAnchor
=
scrollAnchor
..
paintOffset
=
paintOffset
..
paintOffset
=
paintOffset
..
overlayPainter
=
overlayPainter
;
..
overlayPainter
=
overlayPainter
;
}
}
...
...
packages/flutter/lib/src/widgets/scrollable.dart
View file @
efd5aea0
...
@@ -520,8 +520,9 @@ class _ScrollableViewportState extends ScrollableState<ScrollableViewport> {
...
@@ -520,8 +520,9 @@ class _ScrollableViewportState extends ScrollableState<ScrollableViewport> {
return
new
SizeObserver
(
return
new
SizeObserver
(
onSizeChanged:
_handleViewportSizeChanged
,
onSizeChanged:
_handleViewportSizeChanged
,
child:
new
Viewport
(
child:
new
Viewport
(
scrollDirection:
config
.
scrollDirection
,
paintOffset:
scrollOffsetToPixelDelta
(
scrollOffset
),
paintOffset:
scrollOffsetToPixelDelta
(
scrollOffset
),
scrollDirection:
config
.
scrollDirection
,
scrollAnchor:
config
.
scrollAnchor
,
child:
new
SizeObserver
(
child:
new
SizeObserver
(
onSizeChanged:
_handleChildSizeChanged
,
onSizeChanged:
_handleChildSizeChanged
,
child:
config
.
child
child:
config
.
child
...
@@ -541,6 +542,7 @@ class Block extends StatelessComponent {
...
@@ -541,6 +542,7 @@ class Block extends StatelessComponent {
this
.
padding
,
this
.
padding
,
this
.
initialScrollOffset
,
this
.
initialScrollOffset
,
this
.
scrollDirection
:
Axis
.
vertical
,
this
.
scrollDirection
:
Axis
.
vertical
,
this
.
scrollAnchor
:
ViewportAnchor
.
start
,
this
.
onScroll
,
this
.
onScroll
,
this
.
scrollableKey
this
.
scrollableKey
})
:
super
(
key:
key
)
{
})
:
super
(
key:
key
)
{
...
@@ -552,6 +554,7 @@ class Block extends StatelessComponent {
...
@@ -552,6 +554,7 @@ class Block extends StatelessComponent {
final
EdgeDims
padding
;
final
EdgeDims
padding
;
final
double
initialScrollOffset
;
final
double
initialScrollOffset
;
final
Axis
scrollDirection
;
final
Axis
scrollDirection
;
final
ViewportAnchor
scrollAnchor
;
final
ScrollListener
onScroll
;
final
ScrollListener
onScroll
;
final
Key
scrollableKey
;
final
Key
scrollableKey
;
...
@@ -563,6 +566,7 @@ class Block extends StatelessComponent {
...
@@ -563,6 +566,7 @@ class Block extends StatelessComponent {
key:
scrollableKey
,
key:
scrollableKey
,
initialScrollOffset:
initialScrollOffset
,
initialScrollOffset:
initialScrollOffset
,
scrollDirection:
scrollDirection
,
scrollDirection:
scrollDirection
,
scrollAnchor:
scrollAnchor
,
onScroll:
onScroll
,
onScroll:
onScroll
,
child:
contents
child:
contents
);
);
...
...
packages/flutter/test/widget/block_test.dart
View file @
efd5aea0
...
@@ -66,4 +66,53 @@ void main() {
...
@@ -66,4 +66,53 @@ void main() {
tester
.
dispatchEvent
(
pointer
.
up
(),
target
);
tester
.
dispatchEvent
(
pointer
.
up
(),
target
);
});
});
});
});
test
(
'Scroll anchor'
,
()
{
testWidgets
((
WidgetTester
tester
)
{
int
first
=
0
;
int
second
=
0
;
Widget
buildBlock
(
ViewportAnchor
scrollAnchor
)
{
return
new
Block
(
key:
new
UniqueKey
(),
scrollAnchor:
scrollAnchor
,
children:
<
Widget
>[
new
GestureDetector
(
onTap:
()
{
++
first
;
},
child:
new
Container
(
height:
2000.0
,
// more than 600, the height of the test area
decoration:
new
BoxDecoration
(
backgroundColor:
new
Color
(
0xFF00FF00
)
)
)
),
new
GestureDetector
(
onTap:
()
{
++
second
;
},
child:
new
Container
(
height:
2000.0
,
// more than 600, the height of the test area
decoration:
new
BoxDecoration
(
backgroundColor:
new
Color
(
0xFF0000FF
)
)
)
)
]
);
}
tester
.
pumpWidget
(
buildBlock
(
ViewportAnchor
.
end
));
tester
.
pump
();
// for SizeObservers
Point
target
=
const
Point
(
200.0
,
200.0
);
tester
.
tapAt
(
target
);
expect
(
first
,
equals
(
0
));
expect
(
second
,
equals
(
1
));
tester
.
pumpWidget
(
buildBlock
(
ViewportAnchor
.
start
));
tester
.
pump
();
// for SizeObservers
tester
.
tapAt
(
target
);
expect
(
first
,
equals
(
1
));
expect
(
second
,
equals
(
1
));
});
});
}
}
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