颤振位置堆栈小部件在中心
Posted
技术标签:
【中文标题】颤振位置堆栈小部件在中心【英文标题】:Flutter position stack widget in center 【发布时间】:2018-11-21 23:31:53 【问题描述】:我在堆栈中有小部件,所以我想将我的按钮栏放在堆栈的底部中心,但没有任何效果。小部件只是粘在左侧。这是我的代码。
new Positioned(
bottom: 40.0,
child: new Container(
margin: const EdgeInsets.all(16.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Align(
alignment: Alignment.bottomCenter,
child: new ButtonBar(
alignment: MainAxisAlignment.center,
children: <Widget>[
new OutlineButton(
onPressed: ()
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new LoginPage()));
,
child: new Text(
"Login",
style: new TextStyle(color: Colors.white),
),
),
new RaisedButton(
color: Colors.white,
onPressed: ()
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
new RegistrationPage()));
,
child: new Text(
"Register",
style: new TextStyle(color: Colors.black),
),
)
],
),
)
],
),
),
)
我已经尝试了每个中心对齐方式,请帮助
【问题讨论】:
您在 Column 上尝试过mainAxisSize: MainAxisSize.min
吗?并通过删除 Align
小部件
是的,我试过@RémiRousselet,它仍然向左对齐
【参考方案1】:
它可以像 Positioned.center 一样工作 您确定小部件的中心并设置小部件和点的相同中心。
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:math' as math;
class AlignPositioned extends SingleChildRenderObjectWidget
const AlignPositioned(
Key? key,
this.alignment = Alignment.center,
required this.centerPoint,
this.widthFactor,
this.heightFactor,
Widget? child,
) : assert(widthFactor == null || widthFactor >= 0.0),
assert(heightFactor == null || heightFactor >= 0.0),
super(key: key, child: child);
final AlignmentGeometry alignment;
final Offset centerPoint;
final double? widthFactor;
final double? heightFactor;
@override
_RenderPositionedBox createRenderObject(BuildContext context)
return _RenderPositionedBox(
alignment: alignment,
widthFactor: widthFactor,
heightFactor: heightFactor,
textDirection: Directionality.maybeOf(context),
centerPoint: this.centerPoint,
);
@override
void updateRenderObject(
BuildContext context, _RenderPositionedBox renderObject)
renderObject
..alignment = alignment
..widthFactor = widthFactor
..heightFactor = heightFactor
..textDirection = Directionality.maybeOf(context)
..centerPoint = centerPoint;
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties)
super.debugFillProperties(properties);
properties
.add(DiagnosticsProperty<AlignmentGeometry>('alignment', alignment));
properties
.add(DoubleProperty('widthFactor', widthFactor, defaultValue: null));
properties
.add(DoubleProperty('heightFactor', heightFactor, defaultValue: null));
class _RenderPositionedBox extends RenderAligningShiftedBox
Offset centerPoint;
_RenderPositionedBox(
RenderBox? child,
double? widthFactor,
double? heightFactor,
AlignmentGeometry alignment = Alignment.center,
TextDirection? textDirection,
required this.centerPoint,
) : assert(widthFactor == null || widthFactor >= 0.0),
assert(heightFactor == null || heightFactor >= 0.0),
_widthFactor = widthFactor,
_heightFactor = heightFactor,
super(child: child, alignment: alignment, textDirection: textDirection);
double? get widthFactor => _widthFactor;
double? _widthFactor;
set widthFactor(double? value)
assert(value == null || value >= 0.0);
if (_widthFactor == value) return;
_widthFactor = value;
markNeedsLayout();
set alignment(AlignmentGeometry value)
super.alignment = value;
_resolvedAlignment = alignment.resolve(textDirection);
double? get heightFactor => _heightFactor;
double? _heightFactor;
late Alignment _resolvedAlignment = alignment.resolve(textDirection);
set heightFactor(double? value)
assert(value == null || value >= 0.0);
if (_heightFactor == value) return;
_heightFactor = value;
markNeedsLayout();
@override
Size computeDryLayout(BoxConstraints constraints)
final bool shrinkWrapWidth =
_widthFactor != null || constraints.maxWidth == double.infinity;
final bool shrinkWrapHeight =
_heightFactor != null || constraints.maxHeight == double.infinity;
if (child != null)
final Size childSize = child!.getDryLayout(constraints.loosen());
return constraints.constrain(Size(
shrinkWrapWidth
? childSize.width * (_widthFactor ?? 1.0)
: double.infinity,
shrinkWrapHeight
? childSize.height * (_heightFactor ?? 1.0)
: double.infinity,
));
return constraints.constrain(Size(
shrinkWrapWidth ? 0.0 : double.infinity,
shrinkWrapHeight ? 0.0 : double.infinity,
));
@override
void performLayout()
final BoxConstraints constraints = this.constraints;
final bool shrinkWrapWidth =
_widthFactor != null || constraints.maxWidth == double.infinity;
final bool shrinkWrapHeight =
_heightFactor != null || constraints.maxHeight == double.infinity;
if (child != null)
child!.layout(constraints.loosen(), parentUsesSize: true);
size = constraints.constrain(Size(
shrinkWrapWidth
? child!.size.width * (_widthFactor ?? 1.0)
: double.infinity,
shrinkWrapHeight
? child!.size.height * (_heightFactor ?? 1.0)
: double.infinity,
));
final BoxParentData childParentData = child!.parentData! as BoxParentData;
final moveX = _resolvedAlignment.x - 1;
final moveY = _resolvedAlignment.y - 1;
log(_resolvedAlignment.y.toString());
childParentData.offset = this.centerPoint +
Offset(
child!.size.width / 2 * moveX,
child!.size.height / 2 * moveY,
);
// log(_resolvedAlignment.x.toString());
// log(_resolvedAlignment.y.toString());
// _resolvedAlignment.alongOffset(size - child!.size as Offset);
else
size = constraints.constrain(Size(
shrinkWrapWidth ? 0.0 : double.infinity,
shrinkWrapHeight ? 0.0 : double.infinity,
));
@override
void debugPaintSize(PaintingContext context, Offset offset)
super.debugPaintSize(context, offset);
assert(()
final Paint paint;
if (child != null && !child!.size.isEmpty)
final Path path;
paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 1.0
..color = const Color(0xFFFFFF00);
path = Path();
final BoxParentData childParentData =
child!.parentData! as BoxParentData;
if (childParentData.offset.dy > 0.0)
// vertical alignment arrows
final double headSize =
math.min(childParentData.offset.dy * 0.2, 10.0);
path
..moveTo(offset.dx + size.width / 2.0, offset.dy)
..relativeLineTo(0.0, childParentData.offset.dy - headSize)
..relativeLineTo(headSize, 0.0)
..relativeLineTo(-headSize, headSize)
..relativeLineTo(-headSize, -headSize)
..relativeLineTo(headSize, 0.0)
..moveTo(offset.dx + size.width / 2.0, offset.dy + size.height)
..relativeLineTo(0.0, -childParentData.offset.dy + headSize)
..relativeLineTo(headSize, 0.0)
..relativeLineTo(-headSize, -headSize)
..relativeLineTo(-headSize, headSize)
..relativeLineTo(headSize, 0.0);
context.canvas.drawPath(path, paint);
if (childParentData.offset.dx > 0.0)
// horizontal alignment arrows
final double headSize =
math.min(childParentData.offset.dx * 0.2, 10.0);
path
..moveTo(offset.dx, offset.dy + size.height / 2.0)
..relativeLineTo(childParentData.offset.dx - headSize, 0.0)
..relativeLineTo(0.0, headSize)
..relativeLineTo(headSize, -headSize)
..relativeLineTo(-headSize, -headSize)
..relativeLineTo(0.0, headSize)
..moveTo(offset.dx + size.width, offset.dy + size.height / 2.0)
..relativeLineTo(-childParentData.offset.dx + headSize, 0.0)
..relativeLineTo(0.0, headSize)
..relativeLineTo(-headSize, -headSize)
..relativeLineTo(headSize, -headSize)
..relativeLineTo(0.0, headSize);
context.canvas.drawPath(path, paint);
else
paint = Paint()..color = const Color(0x90909090);
context.canvas.drawRect(offset & size, paint);
return true;
());
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties)
super.debugFillProperties(properties);
properties
.add(DoubleProperty('widthFactor', _widthFactor, ifNull: 'expand'));
properties
.add(DoubleProperty('heightFactor', _heightFactor, ifNull: 'expand'));
【讨论】:
【参考方案2】:对于到达这里但无法解决问题的任何人,我曾经通过将左右都设置为 0 来使我的小部件水平居中,如下所示:
Stack(
children: <Widget>[
Positioned(
top: 100,
left: 0,
right: 0,
child: Text("Search",
style: TextStyle(
color: Color(0xff757575),
fontWeight: FontWeight.w700,
fontFamily: "Roboto",
fontStyle: FontStyle.normal,
fontSize: 56.0,
),
textAlign: TextAlign.center,
),
),
]
)
【讨论】:
你能解释一下为什么需要左值和右值吗? Web中常用的一种做法。 ? 现在这就是我所说的简单解决方案!谢谢老哥【参考方案3】:可能是最优雅的方式。
您可以简单地使用Stack
中的alignment
选项
child: Stack(
alignment: Alignment.center
)
【讨论】:
确实,这是最优雅的方式。 完美运行,不会像 Positioned.fill 那样拉伸内容 迄今为止最好的答案!!可能是因为最近在 Stack 小部件中添加了此功能 确实,这应该是最佳答案。干得好! 是的,太棒了。【参考方案4】:Stack
允许您将元素堆叠在一起,数组中的最后一个元素具有最高优先级。您可以使用Align
、Positioned
或Container
来定位堆栈的子级。
对齐
通过使用Alignment
设置对齐来移动小部件,它具有topCenter
、bottomRight 等静态属性。或者您可以完全控制并设置Alignment(1.0, -1.0)
,它的 x,y 值范围为 1.0 到 -1.0,其中 (0,0) 为屏幕中心。
Stack(
children: [
Align(
alignment: Alignment.topCenter,
child: Container(
height: 80,
width: 80, color: Colors.blueAccent
),
),
Align(
alignment: Alignment.center,
child: Container(
height: 80,
width: 80, color: Colors.deepPurple
),
),
Container(
alignment: Alignment.bottomCenter,
// alignment: Alignment(1.0, -1.0),
child: Container(
height: 80,
width: 80, color: Colors.amber
),
)
]
)
【讨论】:
很好的解释,应该被接受。【参考方案5】:对我来说最好的方法是使用Align
。
我需要在封面图片的底部中心制作用户的头像。
return Container(
height: 220,
color: Colors.red,
child: Stack(
children: [
Container(
height: 160,
color: Colors.yellow,
),
Align(
alignment: Alignment.bottomCenter,
child: UserProfileImage(),
),
],
),
);
这就像一个魅力。
【讨论】:
【参考方案6】:看看我想出的这个解决方案
Positioned( child: SizedBox( child: CircularProgressIndicator(), width: 50, height: 50,), left: MediaQuery.of(context).size.width / 2 - 25);
【讨论】:
【参考方案7】:删除所有内容,但这个:
Align(
alignment: Alignment.bottomCenter,
child: new ButtonBar(
alignment: MainAxisAlignment.center,
children: <Widget>[
new OutlineButton(
onPressed: ()
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new LoginPage()));
,
child: new Text(
"Login",
style: new TextStyle(color: Colors.white),
),
),
new RaisedButton(
color: Colors.white,
onPressed: ()
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
new RegistrationPage()));
,
child: new Text(
"Register",
style: new TextStyle(color: Colors.black),
),
)
],
),
)
在我的理论中,额外的Container
正在摧毁它。我建议您通过添加 Padding
来包围它:
Padding(
padding: EdgeInsets.only(bottom: 20.0),
child: Align...
),
这对我来说似乎比Positioned
更合理,而且我不太理解你的Column
只有一个孩子。
【讨论】:
哇,谢谢,老实说,我从来不知道 Align 可以将小部件放置在 Stack 中【参考方案8】:感谢以上所有答案,我想分享一些在某些情况下可能会派上用场的东西。那么让我们看看当你使用Positioned:( right: 0.0, left:0.0, bottom:0.0)
时会发生什么:
Padding(
padding: const EdgeInsets.all(4.0),
child: Stack(
children: <Widget>[
Positioned(
bottom: 0.0,
right: 0.0,
left: 0.0,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Container(
color: Colors.blue,
child: Center(
child: Text('Hello',
style: TextStyle(color: Color(0xffF6C37F),
fontSize: 46, fontWeight: FontWeight.bold),),
)
),
)
),
],
),
),
这将是上述代码的输出:
如您所见,即使您不想要它并且您只想让容器包裹其子项,它也会用容器填充整个宽度。因此,为此您可以尝试以下技巧:
Padding(
padding: const EdgeInsets.all(4.0),
child: Stack(
children: <Widget>[
Positioned(
bottom: 0.0,
right: 0.0,
left: 0.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Container(
color: Colors.blue,
child: Text('Hello',
style: TextStyle(color: Color(0xffF6C37F),
fontSize: 46, fontWeight: FontWeight.bold),)
),
),
Container(),
],
)
),
],
),
),
【讨论】:
【参考方案9】:您可以在Stack
内使用Positioned.fill
和Align
:
Stack(
children: <Widget>[
Positioned.fill(
child: Align(
alignment: Alignment.centerRight,
child: ....
),
),
],
),
【讨论】:
@JoãoAbrantes 在调用 Positioned.fill() 时,您将获得完整尺寸(它将填充视图),然后 Align 可以在其中做任何它想做的事情。如果您将 Align 替换为具有红色背景的容器,则堆栈将变为红色。【参考方案10】:你也可以试试这个:
Center(
child: Stack(
children: [],
),
)
【讨论】:
【参考方案11】:您可以在堆栈内使用 Align 更改定位:
Align(
alignment: Alignment.bottomCenter,
child: ... ,
),
有关 Stack 的更多信息:Exploring Stack
【讨论】:
【参考方案12】:问题是容器的尺寸尽可能小。
只需将width:
发送给容器(红色)即可。
width: MediaQuery.of(context).size.width
new Positioned(
bottom: 0.0,
child: new Container(
width: MediaQuery.of(context).size.width,
color: Colors.red,
margin: const EdgeInsets.all(0.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Align(
alignment: Alignment.bottomCenter,
child: new ButtonBar(
alignment: MainAxisAlignment.center,
children: <Widget>[
new OutlineButton(
onPressed: null,
child: new Text(
"Login",
style: new TextStyle(color: Colors.white),
),
),
new RaisedButton(
color: Colors.white,
onPressed: null,
child: new Text(
"Register",
style: new TextStyle(color: Colors.black),
),
)
],
),
)
],
),
),
),
【讨论】:
为什么不在这里使用列/行? 有不同的解决方案来达到预期的结果。我的回答是试图解释为什么 OP 提供的解决方案不起作用。以上是关于颤振位置堆栈小部件在中心的主要内容,如果未能解决你的问题,请参考以下文章