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
482d1aaf
Unverified
Commit
482d1aaf
authored
Apr 24, 2023
by
Tae Hyung Kim
Committed by
GitHub
Apr 24, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Sliver Constrained Cross Axis (#125239)
Reimplements what we reverted here: #125233.
parent
7d9f2082
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
350 additions
and
0 deletions
+350
-0
sliver_constrained_cross_axis.0.dart
...i/lib/widgets/sliver/sliver_constrained_cross_axis.0.dart
+51
-0
sliver_constrained_cross_axis.0_test.dart
.../widgets/sliver/sliver_constrained_cross_axis.0_test.dart
+20
-0
proxy_sliver.dart
packages/flutter/lib/src/rendering/proxy_sliver.dart
+41
-0
sliver.dart
packages/flutter/lib/src/rendering/sliver.dart
+50
-0
sliver.dart
packages/flutter/lib/src/widgets/sliver.dart
+96
-0
sliver_constrained_cross_axis_test.dart
...tter/test/widgets/sliver_constrained_cross_axis_test.dart
+92
-0
No files found.
examples/api/lib/widgets/sliver/sliver_constrained_cross_axis.0.dart
0 → 100644
View file @
482d1aaf
// Copyright 2014 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.
import
'package:flutter/material.dart'
;
void
main
(
)
=>
runApp
(
const
SliverConstrainedCrossAxisExampleApp
());
class
SliverConstrainedCrossAxisExampleApp
extends
StatelessWidget
{
const
SliverConstrainedCrossAxisExampleApp
({
super
.
key
});
@override
Widget
build
(
BuildContext
context
)
{
return
MaterialApp
(
home:
Scaffold
(
appBar:
AppBar
(
title:
const
Text
(
'SliverConstrainedCrossAxis Sample'
)),
body:
const
SliverConstrainedCrossAxisExample
(),
),
);
}
}
class
SliverConstrainedCrossAxisExample
extends
StatelessWidget
{
const
SliverConstrainedCrossAxisExample
({
super
.
key
});
@override
Widget
build
(
BuildContext
context
)
{
return
CustomScrollView
(
slivers:
<
Widget
>[
SliverConstrainedCrossAxis
(
maxExtent:
200
,
sliver:
SliverList
.
builder
(
itemBuilder:
(
BuildContext
context
,
int
index
)
{
return
Container
(
color:
index
.
isEven
?
Colors
.
amber
[
300
]
:
Colors
.
blue
[
300
],
height:
100.0
,
child:
Center
(
child:
Text
(
'Item
$index
'
,
style:
const
TextStyle
(
fontSize:
24
),
),
),
);
},
itemCount:
10
,
),
),
],
);
}
}
examples/api/test/widgets/sliver/sliver_constrained_cross_axis.0_test.dart
0 → 100644
View file @
482d1aaf
// Copyright 2014 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.
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter_api_samples/widgets/sliver/sliver_constrained_cross_axis.0.dart'
as
example
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'SliverConstrainedCrossAxis example'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
SliverConstrainedCrossAxisExampleApp
(),
);
final
RenderSliverList
renderSliverList
=
tester
.
renderObject
(
find
.
byType
(
SliverList
));
expect
(
renderSliverList
.
constraints
.
crossAxisExtent
,
equals
(
200
));
});
}
packages/flutter/lib/src/rendering/proxy_sliver.dart
View file @
482d1aaf
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
import
'dart:math'
;
import
'dart:ui'
as
ui
show
Color
;
import
'dart:ui'
as
ui
show
Color
;
import
'package:flutter/animation.dart'
;
import
'package:flutter/animation.dart'
;
...
@@ -414,3 +415,43 @@ class RenderSliverAnimatedOpacity extends RenderProxySliver with RenderAnimatedO
...
@@ -414,3 +415,43 @@ class RenderSliverAnimatedOpacity extends RenderProxySliver with RenderAnimatedO
child
=
sliver
;
child
=
sliver
;
}
}
}
}
/// Applies a cross-axis constraint to its sliver child.
///
/// This render object takes a [maxExtent] parameter and uses the smaller of
/// [maxExtent] and the parent's [SliverConstraints.crossAxisExtent] as the
/// cross axis extent of the [SliverConstraints] passed to the sliver child.
class
RenderSliverConstrainedCrossAxis
extends
RenderProxySliver
{
/// Creates a render object that constrains the cross axis extent of its sliver child.
///
/// The [maxExtent] parameter must not be null and must be nonnegative.
RenderSliverConstrainedCrossAxis
({
required
double
maxExtent
})
:
_maxExtent
=
maxExtent
,
assert
(
maxExtent
>=
0.0
);
/// The cross axis extent to apply to the sliver child.
///
/// This value must be nonnegative.
double
get
maxExtent
=>
_maxExtent
;
double
_maxExtent
;
set
maxExtent
(
double
value
)
{
if
(
_maxExtent
==
value
)
{
return
;
}
_maxExtent
=
value
;
markNeedsLayout
();
}
@override
void
performLayout
()
{
assert
(
child
!=
null
);
assert
(
maxExtent
>=
0.0
);
child
!.
layout
(
constraints
.
copyWith
(
crossAxisExtent:
min
(
_maxExtent
,
constraints
.
crossAxisExtent
)),
parentUsesSize:
true
,
);
final
SliverGeometry
childLayoutGeometry
=
child
!.
geometry
!;
geometry
=
childLayoutGeometry
.
copyWith
(
crossAxisExtent:
min
(
_maxExtent
,
constraints
.
crossAxisExtent
));
}
}
packages/flutter/lib/src/rendering/sliver.dart
View file @
482d1aaf
...
@@ -560,6 +560,7 @@ class SliverGeometry with Diagnosticable {
...
@@ -560,6 +560,7 @@ class SliverGeometry with Diagnosticable {
double
?
layoutExtent
,
double
?
layoutExtent
,
this
.
maxPaintExtent
=
0.0
,
this
.
maxPaintExtent
=
0.0
,
this
.
maxScrollObstructionExtent
=
0.0
,
this
.
maxScrollObstructionExtent
=
0.0
,
this
.
crossAxisExtent
,
double
?
hitTestExtent
,
double
?
hitTestExtent
,
bool
?
visible
,
bool
?
visible
,
this
.
hasVisualOverflow
=
false
,
this
.
hasVisualOverflow
=
false
,
...
@@ -571,6 +572,36 @@ class SliverGeometry with Diagnosticable {
...
@@ -571,6 +572,36 @@ class SliverGeometry with Diagnosticable {
cacheExtent
=
cacheExtent
??
layoutExtent
??
paintExtent
,
cacheExtent
=
cacheExtent
??
layoutExtent
??
paintExtent
,
visible
=
visible
??
paintExtent
>
0.0
;
visible
=
visible
??
paintExtent
>
0.0
;
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
SliverGeometry
copyWith
({
double
?
scrollExtent
,
double
?
paintExtent
,
double
?
paintOrigin
,
double
?
layoutExtent
,
double
?
maxPaintExtent
,
double
?
maxScrollObstructionExtent
,
double
?
crossAxisExtent
,
double
?
hitTestExtent
,
bool
?
visible
,
bool
?
hasVisualOverflow
,
double
?
cacheExtent
,
})
{
return
SliverGeometry
(
scrollExtent:
scrollExtent
??
this
.
scrollExtent
,
paintExtent:
paintExtent
??
this
.
paintExtent
,
paintOrigin:
paintOrigin
??
this
.
paintOrigin
,
layoutExtent:
layoutExtent
??
this
.
layoutExtent
,
maxPaintExtent:
maxPaintExtent
??
this
.
maxPaintExtent
,
maxScrollObstructionExtent:
maxScrollObstructionExtent
??
this
.
maxScrollObstructionExtent
,
crossAxisExtent:
crossAxisExtent
??
this
.
crossAxisExtent
,
hitTestExtent:
hitTestExtent
??
this
.
hitTestExtent
,
visible:
visible
??
this
.
visible
,
hasVisualOverflow:
hasVisualOverflow
??
this
.
hasVisualOverflow
,
cacheExtent:
cacheExtent
??
this
.
cacheExtent
,
);
}
/// A sliver that occupies no space at all.
/// A sliver that occupies no space at all.
static
const
SliverGeometry
zero
=
SliverGeometry
();
static
const
SliverGeometry
zero
=
SliverGeometry
();
...
@@ -719,6 +750,20 @@ class SliverGeometry with Diagnosticable {
...
@@ -719,6 +750,20 @@ class SliverGeometry with Diagnosticable {
/// * [RenderViewport.cacheExtent] for a description of a viewport's cache area.
/// * [RenderViewport.cacheExtent] for a description of a viewport's cache area.
final
double
cacheExtent
;
final
double
cacheExtent
;
/// The amount of space allocated to the cross axis.
///
/// This value will be typically null unless it is different from
/// [SliverConstraints.crossAxisExtent]. If null, then the cross axis extent of
/// the sliver is assumed to be the same as the [SliverConstraints.crossAxisExtent].
/// This is because slivers typically consume all of the extent that is available
/// in the cross axis.
///
/// See also:
///
/// * [SliverConstrainedCrossAxis] for an example of a sliver which takes up
/// a smaller cross axis extent than the provided constraint.
final
double
?
crossAxisExtent
;
/// Asserts that this geometry is internally consistent.
/// Asserts that this geometry is internally consistent.
///
///
/// Does nothing if asserts are disabled. Always returns true.
/// Does nothing if asserts are disabled. Always returns true.
...
@@ -957,6 +1002,11 @@ class SliverPhysicalParentData extends ParentData {
...
@@ -957,6 +1002,11 @@ class SliverPhysicalParentData extends ParentData {
/// top left visible corner of the sliver.
/// top left visible corner of the sliver.
Offset
paintOffset
=
Offset
.
zero
;
Offset
paintOffset
=
Offset
.
zero
;
/// The [crossAxisFlex] factor to use for this sliver child.
///
/// If null or zero, the child is inflexible and determines its own size in the cross axis.
int
?
crossAxisFlex
;
/// Apply the [paintOffset] to the given [transform].
/// Apply the [paintOffset] to the given [transform].
///
///
/// Used to implement [RenderObject.applyPaintTransform] by slivers that use
/// Used to implement [RenderObject.applyPaintTransform] by slivers that use
...
...
packages/flutter/lib/src/widgets/sliver.dart
View file @
482d1aaf
...
@@ -1365,3 +1365,99 @@ class KeepAlive extends ParentDataWidget<KeepAliveParentDataMixin> {
...
@@ -1365,3 +1365,99 @@ class KeepAlive extends ParentDataWidget<KeepAliveParentDataMixin> {
properties
.
add
(
DiagnosticsProperty
<
bool
>(
'keepAlive'
,
keepAlive
));
properties
.
add
(
DiagnosticsProperty
<
bool
>(
'keepAlive'
,
keepAlive
));
}
}
}
}
/// A sliver that constrains the cross axis extent of its sliver child.
///
/// The [SliverConstrainedCrossAxis] takes a [maxExtent] parameter and uses it as
/// the cross axis extent of the [SliverConstraints] passed to the sliver child.
/// The widget ensures that the [maxExtent] is a nonnegative value.
///
/// This is useful when you want to apply a custom cross-axis extent constraint
/// to a sliver child, as slivers typically consume the full cross axis extent.
///
/// {@tool dartpad}
/// In this sample the [SliverConstrainedCrossAxis] sizes its child so that the
/// cross axis extent takes up less space than the actual viewport.
///
/// ** See code in examples/api/lib/widgets/sliver/sliver_constrained_cross_axis.0.dart **
/// {@end-tool}
class
SliverConstrainedCrossAxis
extends
StatelessWidget
{
/// Creates a sliver that constrains the cross axis extent of its sliver child.
///
/// The [maxExtent] parameter is required and must be nonnegative.
const
SliverConstrainedCrossAxis
({
super
.
key
,
required
this
.
maxExtent
,
required
this
.
sliver
,
});
/// The cross axis extent to apply to the sliver child.
///
/// This value must be nonnegative.
final
double
maxExtent
;
/// The widget below this widget in the tree.
///
/// Must be a sliver.
final
Widget
sliver
;
@override
Widget
build
(
BuildContext
context
)
{
return
_SliverZeroFlexParentDataWidget
(
sliver:
_SliverConstrainedCrossAxis
(
maxExtent:
maxExtent
,
sliver:
sliver
,
)
);
}
}
class
_SliverZeroFlexParentDataWidget
extends
ParentDataWidget
<
SliverPhysicalParentData
>
{
const
_SliverZeroFlexParentDataWidget
({
required
Widget
sliver
,
})
:
super
(
child:
sliver
);
@override
void
applyParentData
(
RenderObject
renderObject
)
{
assert
(
renderObject
.
parentData
is
SliverPhysicalParentData
);
final
SliverPhysicalParentData
parentData
=
renderObject
.
parentData
!
as
SliverPhysicalParentData
;
bool
needsLayout
=
false
;
if
(
parentData
.
crossAxisFlex
!=
0
)
{
parentData
.
crossAxisFlex
=
0
;
needsLayout
=
true
;
}
if
(
needsLayout
)
{
final
AbstractNode
?
targetParent
=
renderObject
.
parent
;
if
(
targetParent
is
RenderObject
)
{
targetParent
.
markNeedsLayout
();
}
}
}
@override
Type
get
debugTypicalAncestorWidgetClass
=>
Widget
;
}
class
_SliverConstrainedCrossAxis
extends
SingleChildRenderObjectWidget
{
const
_SliverConstrainedCrossAxis
({
required
this
.
maxExtent
,
required
Widget
sliver
,
})
:
assert
(
maxExtent
>=
0.0
),
super
(
child:
sliver
);
/// The cross axis extent to apply to the sliver child.
///
/// This value must be nonnegative.
final
double
maxExtent
;
@override
RenderSliverConstrainedCrossAxis
createRenderObject
(
BuildContext
context
)
{
return
RenderSliverConstrainedCrossAxis
(
maxExtent:
maxExtent
);
}
@override
void
updateRenderObject
(
BuildContext
context
,
RenderSliverConstrainedCrossAxis
renderObject
)
{
renderObject
.
maxExtent
=
maxExtent
;
}
}
packages/flutter/test/widgets/sliver_constrained_cross_axis_test.dart
0 → 100644
View file @
482d1aaf
// Copyright 2014 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.
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
const
double
VIEWPORT_HEIGHT
=
500
;
const
double
VIEWPORT_WIDTH
=
300
;
void
main
(
)
{
testWidgets
(
'SliverConstrainedCrossAxis basic test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
_buildSliverConstrainedCrossAxis
(
maxExtent:
50
));
final
RenderBox
box
=
tester
.
renderObject
(
find
.
byType
(
Container
));
expect
(
box
.
size
.
height
,
100
);
expect
(
box
.
size
.
width
,
50
);
final
RenderSliver
sliver
=
tester
.
renderObject
(
find
.
byType
(
SliverToBoxAdapter
));
expect
(
sliver
.
geometry
!.
paintExtent
,
equals
(
100
));
});
testWidgets
(
'SliverConstrainedCrossAxis updates correctly'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
_buildSliverConstrainedCrossAxis
(
maxExtent:
50
));
final
RenderBox
box1
=
tester
.
renderObject
(
find
.
byType
(
Container
));
expect
(
box1
.
size
.
height
,
100
);
expect
(
box1
.
size
.
width
,
50
);
await
tester
.
pumpWidget
(
_buildSliverConstrainedCrossAxis
(
maxExtent:
80
));
final
RenderBox
box2
=
tester
.
renderObject
(
find
.
byType
(
Container
));
expect
(
box2
.
size
.
height
,
100
);
expect
(
box2
.
size
.
width
,
80
);
});
testWidgets
(
'SliverConstrainedCrossAxis uses parent extent if maxExtent is greater'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
_buildSliverConstrainedCrossAxis
(
maxExtent:
400
));
final
RenderBox
box
=
tester
.
renderObject
(
find
.
byType
(
Container
));
expect
(
box
.
size
.
height
,
100
);
expect
(
box
.
size
.
width
,
VIEWPORT_WIDTH
);
});
testWidgets
(
'SliverConstrainedCrossAxis constrains the height when direction is horizontal'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
_buildSliverConstrainedCrossAxis
(
maxExtent:
50
,
scrollDirection:
Axis
.
horizontal
,
));
final
RenderBox
box
=
tester
.
renderObject
(
find
.
byType
(
Container
));
expect
(
box
.
size
.
height
,
50
);
});
testWidgets
(
'SliverConstrainedCrossAxis sets its own flex to 0'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
_buildSliverConstrainedCrossAxis
(
maxExtent:
50
,
));
final
RenderSliver
sliver
=
tester
.
renderObject
(
find
.
byType
(
SliverConstrainedCrossAxis
));
expect
((
sliver
.
parentData
!
as
SliverPhysicalParentData
).
crossAxisFlex
,
equals
(
0
));
});
}
Widget
_buildSliverConstrainedCrossAxis
(
{
required
double
maxExtent
,
Axis
scrollDirection
=
Axis
.
vertical
,
})
{
return
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
Center
(
child:
SizedBox
(
width:
VIEWPORT_WIDTH
,
height:
VIEWPORT_HEIGHT
,
child:
CustomScrollView
(
scrollDirection:
scrollDirection
,
slivers:
<
Widget
>[
SliverConstrainedCrossAxis
(
maxExtent:
maxExtent
,
sliver:
SliverToBoxAdapter
(
child:
scrollDirection
==
Axis
.
vertical
?
Container
(
height:
100
)
:
Container
(
width:
100
),
),
),
],
),
),
),
);
}
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