Flutter - 试图实现这种复杂的布局
Flutter - Trying to achieve this complex layout
我正在尝试实现如下的Flutter布局(如图所示)
我想并排放置两个图像,我知道可以使用 Row 轻松实现,但我想要的是按形状将两个图像分开(如图所示)。另外,我知道使用 CustomClipper,但我想不出实现它的方法。
如果有人能帮助我,我将不胜感激。提前致谢。
您可以按以下顺序使用 stack
和 3 children 作为第一部分:
- 用于放置雷电(或任何您喜欢的路径)颜色的容器
- I区的第一张图片
- II区的第二张图片
将每个图像包装成具有特定 CustomClipper<Path>
的 ClipPath
:目标是将图像裁剪到应该显示的一侧 with 一个 "padding" 与另一个剪刀。在中间,您将有一个没有图像被剪裁的区域,因此将显示堆栈中的第一个小部件。
这里是完整的源代码:
import 'package:flutter/material.dart';
main() async {
runApp(
MaterialApp(
home: Scaffold(body: ComplexLayoutApp()),
),
);
}
class ComplexLayoutApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(children: [
Expanded(child: Part1()),
Expanded(child: Part2()),
]);
}
}
class Part1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Stack(fit: StackFit.expand, children: [
Container(
color: Colors.black87,
),
ClipPath(
clipper: Area1CustomClipper(),
child: Image.network(
'https://picsum.photos/seed/area1/400/100',
fit: BoxFit.fill,
)),
ClipPath(
clipper: Area2CustomClipper(),
child: Image.network(
'https://picsum.photos/400/300',
fit: BoxFit.fill,
))
]);
}
}
class Part2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(child: Text("Part II")),
],
);
}
}
const double offset = 0.34;
class Area1CustomClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
Path path = Path();
path.moveTo(4*size.width/8, 0);
path.lineTo((4-offset)*size.width/8, (4)*size.height/8);
path.lineTo((4)*size.width/8, (4)*size.height/8);
path.lineTo(size.width/2, size.height);
path.lineTo(0, size.height);
path.lineTo(0, 0);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
class Area2CustomClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
Path path = Path();
path.moveTo(4*size.width/8, 0);
path.lineTo((4)*size.width/8, (4-offset)*size.height/8);
path.lineTo((4+offset)*size.width/8, (4 - offset)*size.height/8);
path.lineTo(size.width/2, size.height);
path.lineTo(size.width, size.height);
path.lineTo(size.width, 0);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
我正在尝试实现如下的Flutter布局(如图所示)
我想并排放置两个图像,我知道可以使用 Row 轻松实现,但我想要的是按形状将两个图像分开(如图所示)。另外,我知道使用 CustomClipper,但我想不出实现它的方法。
如果有人能帮助我,我将不胜感激。提前致谢。
您可以按以下顺序使用 stack
和 3 children 作为第一部分:
- 用于放置雷电(或任何您喜欢的路径)颜色的容器
- I区的第一张图片
- II区的第二张图片
将每个图像包装成具有特定 CustomClipper<Path>
的 ClipPath
:目标是将图像裁剪到应该显示的一侧 with 一个 "padding" 与另一个剪刀。在中间,您将有一个没有图像被剪裁的区域,因此将显示堆栈中的第一个小部件。
这里是完整的源代码:
import 'package:flutter/material.dart';
main() async {
runApp(
MaterialApp(
home: Scaffold(body: ComplexLayoutApp()),
),
);
}
class ComplexLayoutApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(children: [
Expanded(child: Part1()),
Expanded(child: Part2()),
]);
}
}
class Part1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Stack(fit: StackFit.expand, children: [
Container(
color: Colors.black87,
),
ClipPath(
clipper: Area1CustomClipper(),
child: Image.network(
'https://picsum.photos/seed/area1/400/100',
fit: BoxFit.fill,
)),
ClipPath(
clipper: Area2CustomClipper(),
child: Image.network(
'https://picsum.photos/400/300',
fit: BoxFit.fill,
))
]);
}
}
class Part2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(child: Text("Part II")),
],
);
}
}
const double offset = 0.34;
class Area1CustomClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
Path path = Path();
path.moveTo(4*size.width/8, 0);
path.lineTo((4-offset)*size.width/8, (4)*size.height/8);
path.lineTo((4)*size.width/8, (4)*size.height/8);
path.lineTo(size.width/2, size.height);
path.lineTo(0, size.height);
path.lineTo(0, 0);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
class Area2CustomClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
Path path = Path();
path.moveTo(4*size.width/8, 0);
path.lineTo((4)*size.width/8, (4-offset)*size.height/8);
path.lineTo((4+offset)*size.width/8, (4 - offset)*size.height/8);
path.lineTo(size.width/2, size.height);
path.lineTo(size.width, size.height);
path.lineTo(size.width, 0);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}