我试图让我的用户界面显示两个按钮,其中一个按钮与另一个按钮稍微重叠,位于全角卡片的中间。 因为 Stack 的宽度仅与其非定位子级一样宽,所以我添加了一个宽度为 double.INFINITY 的 SizedBox 的非定位子级,以给我一个画布来放置按钮,但我不知道该放什么作为 SizedBox 的高度。 理想情况下,我希望无论用户使用手机还是平板电脑,这个小部件都能适当调整自身大小,因此我宁愿将 SizedBox 高度设置为按钮当前大小的基础,而不是仅仅硬编码一个数字。
有没有办法找到给定现有小部件的大小? 如果不是,如何确定需要在多种屏幕尺寸上看起来不错的对象的高度?
示例代码:
new Card(
child: new Stack(
children: <Widget>[
new SizedBox(
width: double.INFINITY,
),
new Positioned(
left: 1.0,
child: getButtonOne(),
),
new Positioned(
right: 1.0,
child: getButtonTwo(),
),
],
),
),
简短的答案是否定的,因为在构建函数时,小部件尚未布局,因此它们没有尺寸。
更长的答案是,要实现自定义布局效果,您可以使用自定义布局生成器,尽管在您的情况下这没有帮助,因为自定义布局生成器无法根据其子级调整自身大小。下一个级别是直接构建一个自定义渲染对象,这正是 Stack、Row 和 Column 等的实际含义。然后你就可以做任何你想做的事情,布局方面。
在 Flutter 中,渲染完成后无法直接获取 widget 的大小,因为 Flutter 的渲染过程是异步的。但是,您可以使用多种策略来实现有效定位具有重叠样式的按钮的目标,同时确保不同屏幕尺寸的响应能力。
LayoutBuilder
您可以使用
LayoutBuilder
小部件获取父小部件的约束,并使用它来调整按钮的大小。这允许您根据可用空间动态调整布局。
import 'package:flutter/material.dart';
class OverlappingButtons extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Card(
elevation: 4,
child: LayoutBuilder(
builder: (context, constraints) {
// Determine the size of the buttons dynamically
double buttonWidth = constraints.maxWidth * 0.4; // 40% of the card width
double buttonHeight = 50; // Set a fixed height for the buttons
return Stack(
alignment: Alignment.center,
children: [
Positioned(
top: 0,
child: SizedBox(
width: buttonWidth,
height: buttonHeight,
child: ElevatedButton(
onPressed: () {},
child: Text('Button 1'),
),
),
),
Positioned(
top: buttonHeight * 0.3, // Overlap 30% of the button height
child: SizedBox(
width: buttonWidth,
height: buttonHeight,
child: ElevatedButton(
onPressed: () {},
child: Text('Button 2'),
),
),
),
],
);
},
),
),
),
);
}
}
void main() {
runApp(MaterialApp(
home: OverlappingButtons(),
));
}
MediaQuery
另一种选择是使用
MediaQuery
获取屏幕的尺寸并据此进行计算。
import 'package:flutter/material.dart';
class OverlappingButtons extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Get screen size
final size = MediaQuery.of(context).size;
return Scaffold(
body: Center(
child: Card(
elevation: 4,
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
top: 0,
child: SizedBox(
width: size.width * 0.4, // 40% of the screen width
height: 50, // Fixed height for the button
child: ElevatedButton(
onPressed: () {},
child: Text('Button 1'),
),
),
),
Positioned(
top: 15, // Overlap the buttons by adjusting this value
child: SizedBox(
width: size.width * 0.4,
height: 50,
child: ElevatedButton(
onPressed: () {},
child: Text('Button 2'),
),
),
),
],
),
),
),
);
}
}
void main() {
runApp(MaterialApp(
home: OverlappingButtons(),
));
}