Phe*_*ter 6 flutter flutter-sliver flutter-renderflex-error
我有一个包含视频的 SliverPersistentHeader。此视图所需的行为是,当用户向上滚动时,视图应覆盖或最小化视频的大小。视频标题是一个包含 Chewie 视频播放器的小部件。所需的行为会达到某个点,此时我会出现像素溢出,如该动画所示:
当滚动到达某个点时,视频无法再调整大小,从而导致渲染溢出。所需的行为是视频继续调整大小直到消失,或者捕获错误并从视图中隐藏或删除视频。呈现此滚动视图的代码是:
Widget buildScollView(GenericScreenModel model) {
return CustomScrollView(
slivers: [
StandardHeader(),
SliverFillRemaining(
child: Container(
// color: Colors.transparent,
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
),
borderRadius: BorderRadius.only(topRight: radius, topLeft: radius)),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Text(model.model?.getContentText ?? 'Empty'),
)),
)
],
);
}
Run Code Online (Sandbox Code Playgroud)
StandardHeader 类是一个包含 Chewie 视频的简单小部件。
class _StandardHeaderState extends State<StandardHeader> {
@override
Widget build(BuildContext context) {
return SliverPersistentHeader(
floating: true,
delegate: Delegate(
Colors.blue,
'Header Title',
),
pinned: true,
);
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法捕获此错误并隐藏视频播放器?任何人都可以帮忙解决这个问题或向我指出资源吗?谢谢!
问题似乎与 Chewie 和/或视频播放器小部件有关。如果标题的高度小于播放器所需的高度,则会发生溢出。
您可以通过使用 来达到所需的效果SingleChildRenderObjectWidget。我添加了一个不透明因素,您可以轻松删除它,这给了它(在我看来)额外的触感。
我将这个小部件命名为:ClipBelowHeight
输出:
来源:
ClipBelowHeight是通过使用参数将子项的高度限制为不会溢出的高度来SingleChildRenderObjectWidget添加所需的效果。clipHeight它将其子项垂直居中(在本例中为 Chewie 播放器)。
performLayout要了解更多信息,请阅读and方法内的注释paint。
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class ClipBelowHeight extends SingleChildRenderObjectWidget {
const ClipBelowHeight({
super.key,
super.child,
required this.clipHeight,
required this.opacityFactor,
});
/// The minimum height the [child] must have, as well as the height at which
/// clipping begins.
final double clipHeight;
/// The opacity factor to apply when the height decreases.
final double opacityFactor;
@override
RenderObject createRenderObject(BuildContext context) {
return RenderClipBelowHeight(clipHeight: clipHeight, factor: opacityFactor);
}
@override
void updateRenderObject(
BuildContext context,
RenderClipBelowHeight renderObject,
) {
renderObject
..clipHeight = clipHeight
..factor = opacityFactor;
}
}
class RenderClipBelowHeight extends RenderBox with RenderObjectWithChildMixin {
RenderClipBelowHeight({required double clipHeight, required double factor})
: _clipHeight = clipHeight,
_factor = factor;
double _clipHeight;
double get clipHeight => _clipHeight;
set clipHeight(double value) {
assert(value >= .0);
if (_clipHeight == value) return;
_clipHeight = value;
markNeedsLayout();
}
double _factor;
double get factor => _factor;
set factor(double value) {
assert(value >= .0);
if (_factor == value) return;
_factor = value;
markNeedsLayout();
}
@override
bool get sizedByParent => false;
@override
void performLayout() {
/// The child contraints depend on whether [constraints.maxHeight] is less
/// than [clipHeight]. This RenderObject's responsibility is to ensure that
/// the child's height is never below [clipHeight], because when the
/// child's height is below [clipHeight], then there will be visual
/// overflow.
final childConstraints = constraints.maxHeight < _clipHeight
? BoxConstraints.tight(Size(constraints.maxWidth, _clipHeight))
: constraints;
(child as RenderBox).layout(childConstraints, parentUsesSize: true);
size = Size(constraints.maxWidth, constraints.maxHeight);
}
@override
void paint(PaintingContext context, Offset offset) {
final theChild = child as RenderBox;
/// Clip the painted area to [size], which allows the [child] height to
/// be greater than [size] without overflowing.
context.pushClipRect(
true,
offset,
Offset.zero & size,
(PaintingContext context, Offset offset) {
/// (optional) Set the opacity by applying the specified factor.
context.pushOpacity(
offset,
/// The opacity begins to take effect at approximately half [size].
((255.0 + 128.0) * _factor).toInt(),
(context, offset) {
/// Ensure the child remains centered vertically based on [size].
final centeredOffset =
Offset(.0, (size.height - theChild.size.height) / 2.0);
context.paintChild(theChild, centeredOffset + offset);
},
);
},
);
}
@override
bool hitTestChildren(BoxHitTestResult result, {required Offset position}) {
final theChild = child as RenderBox;
var childParentData = theChild.parentData as BoxParentData;
final isHit = result.addWithPaintOffset(
offset: childParentData.offset,
position: position,
hitTest: (BoxHitTestResult result, Offset transformed) {
assert(transformed == position - childParentData.offset);
return theChild.hitTest(result, position: transformed);
},
);
return isHit;
}
@override
Size computeDryLayout(BoxConstraints constraints) => constraints.biggest;
@override
double computeMinIntrinsicWidth(double height) =>
(child as RenderBox).getMinIntrinsicWidth(height);
@override
double computeMaxIntrinsicWidth(double height) =>
(child as RenderBox).getMaxIntrinsicWidth(height);
@override
double computeMinIntrinsicHeight(double width) =>
(child as RenderBox).getMinIntrinsicHeight(width);
@override
double computeMaxIntrinsicHeight(double width) =>
(child as RenderBox).getMaxIntrinsicHeight(width);
}
Run Code Online (Sandbox Code Playgroud)
使用该ClipBelowHeight小部件的小部件是您的标头委托。这个小部件应该是不言自明的,我认为您能够理解它。
class Delegate extends SliverPersistentHeaderDelegate {
Delegate(this.color, this.player);
final Color color;
final Chewie player;
@override
Widget build(
BuildContext context,
double shrinkOffset,
bool overlapsContent,
) {
return Container(
color: color,
child: ClipBelowHeight(
clipHeight: 80.0,
opacityFactor: 1.0 - shrinkOffset / maxExtent,
child: player,
),
);
}
@override
double get maxExtent => 150.0;
@override
double get minExtent => .0;
@override
bool shouldRebuild(Delegate oldDelegate) {
return color != oldDelegate.color || player != oldDelegate.player;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
589 次 |
| 最近记录: |