如何使用 ClipPath 得到这种类型的设计布局?

How to use ClipPath to get this type of design layout?

为了TextFormField的这种设计布局,我挠了挠头很长时间,但失败了!

TextFormField

注意反海峡线。我在 Internet 上进一步搜索此布局后得出结论,我可以使用自定义剪辑器或剪辑路径来存档此类布局。但我只是一个学习 flutter 的初学者,之前从未使用过自定义剪辑器,我不知道如何使用它。请帮忙。

我想你可以使用 CustomPainter :

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: CustomPaint(
            painter: MyPainter(),
            child: // your TextField with style so we don't see the borders etc...
          ),
        ),
      ),
    );
  }
}

class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
      // draw your rectangle from points here
  }

  // no need to repaint it because your shape is static
  @override
  bool shouldRepaint(Sky oldDelegate) => false;
  @override
  bool shouldRebuildSemantics(Sky oldDelegate) => false;
}

这里是 link CustomPainter 的基础知识:link


更新:

这是带有显示 TextField 的小部件的书面代码,当然还有您的自定义形状:

class MainScreen extends StatefulWidget {
  @override
  _MainScreenState createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  // implementation of your custom active borders
  bool emailActive = false;
  FocusNode? emailNode;

  @override
  void initState() {
    super.initState();
    emailNode = FocusScopeNode()
      ..addListener(() {
        setState(() {
          emailActive = emailNode!.hasFocus;
        });
        print(emailActive);
      });
  }

  @override
  Widget build(BuildContext context) {
    final Size size = MediaQuery.of(context).size;
    final double width = size.width * 0.8;
    final double height = width * 0.15;

    return Scaffold(
      appBar: AppBar(
        title: Text('First screen'),
      ),
      body: Center(
        child: Container(
          height: height,
          width: width,
          child: Stack(
            children: [
              Center(
                // your shape
                child: CustomPaint(
                  painter: _TextFieldPainter(width, height, emailActive),
                ),
              ),
              Container(
                height: height,
                width: width,
                padding: const EdgeInsets.symmetric(horizontal: 10.0),
                child: Row(
                  children: [
                    Container(
                      width: 35,
                      padding: const EdgeInsets.only(
                          top: 5.0), // so it's aligned with the textfield
                      child: Icon(Icons.email_rounded),
                    ),
                    Container(
                      width: width - 35 - 20, // width - iconSize - padding
                      child: TextField(
                        decoration: InputDecoration(
                          hintText: 'Email id',
                          focusedBorder: InputBorder
                              .none, // so there is no border below the text field
                        ),
                        focusNode: emailNode,
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class _TextFieldPainter extends CustomPainter {
  final double width;
  final double height;
  final bool active;

  _TextFieldPainter(this.width, this.height, this.active);

  @override
  void paint(Canvas canvas, Size size) {
    // The starting values so it's centered properly
    final double startX = width / -2;
    final double startY = height / -2;

    // Where you set the color etc...
    final Paint paint = Paint()
      ..color = active
          ? Colors.green
          : Colors.black // where you change the color wether it's active or not
      ..strokeWidth = 1.0;

    // Drawing the shape
    canvas.drawLine(
        Offset(startX, startY + 5.0), Offset(startX + width, startY), paint);
    canvas.drawLine(Offset(startX + width, startY),
        Offset(startX + width, startY + height), paint);
    canvas.drawLine(Offset(startX + width, startY + height),
        Offset(startX - 5.0, startY + height), paint);
    canvas.drawLine(Offset(startX - 5.0, startY + height),
        Offset(startX, startY + 5.0), paint);
  }

  // no need to repaint it here since there is no dynamic values
  @override
  bool shouldRepaint(_TextFieldPainter oldDelegate) => false;

  @override
  bool shouldRebuildSemantics(_TextFieldPainter oldDelegate) => false;
}

您只需对密码 TextField 执行相同的操作即可。

这是它的样子: