如何使用Flutter实现这种复杂的布局

时间:2019-11-09 15:37:51

标签: flutter flutter-layout clipper

我正在尝试实现以下Flutter布局(如图所示)。

enter image description here

我想并排放置两个图像,我知道使用Row可以轻松实现两个图像,但是我想要的是按形状将两个图像分开(如图所示)。另外,我知道使用CustomClipper,但我想不出一种方法来实现此目的。

如果有人可以帮助我,我将非常感激。预先感谢。

1 个答案:

答案 0 :(得分:2)

对于第一部分,您可以将stack用于有3个孩子的顺序: -雷电(或您喜欢的任何路径)颜色的容器 -第I区的第一张图片 -第二区的第二张图片

使用特定的ClipPath将每张图片包装到CustomClipper<Path>中:目标是使用将其裁剪到应在其显示的一侧 与其他快船队。在中间,您将有一个区域,其中没有图像被裁剪,因此将显示堆栈中的第一个窗口小部件。

这是完整的源代码:

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;
}

它会产生以下UI: enter image description here