如何在 flutter 中构建手绘边框线或框?

How to build hand-drawn border line or boxes in flutter?

我如何建立如下图所示的徒手边框线?

想实现这个形象:

但我只知道构建简单的 straight/rounded 边框,

像这样:

代码:

// CORNER ROUNDED BORDER DROP DOWN:

 _buildDropDownField() {
    return Container(
      padding: const EdgeInsets.only(left: 8, right: 8),
      alignment: Alignment.center,
      height: 60,
      width: MediaQuery.of(context).size.width,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(10),
        border: Border.all(
            color: Colors.black),
        // color:Colors.white,
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          selectedTopic == null
              ? Text(
                  "Select Topic",
                  style: TextStyle(
                      color:  Colors.black),
                )
              : Text(
                  selectedTopic.title,
                  style: TextStyle(
                    color:
                         Colors.black,
                  ),
                ),
          DropdownButton<TopicModel>(
                  underline: Container(),
                  dropdownColor: Colors.white,
                  icon: Icon(Icons.arrow_drop_down),
                  items: TOPICS.map((TopicModel value) {
                    return new DropdownMenuItem<TopicModel>(
                      value: value,
                      child: new Text(
                        value.title,
                        style: TextStyle(color: Colors.black),
                      ),
                    );
                  }).toList(),
                  onChanged: (val) {
                    setState(() {
                     selectedTopic = val;
                    });
                  },
                )
        ],
      ),
    );
  }

//CORNER ROUNDED BORDER TEXT FIELD:

new TextFormField(
                  controller: _option1Controller,
                  decoration: new InputDecoration(
                      // suffixText: "2",
                      border: new OutlineInputBorder(
                        borderRadius: const BorderRadius.all(
                          const Radius.circular(10.0),
                        ),
                      ),
                      filled: true,
                      hintStyle: new TextStyle(color: Colors.grey[800]),
                      hintText: "Option 1",
                      labelText: "Option 1",
                      fillColor: Colors.white70),
                  validator: (value) {
                    if (value.isEmpty) {
                      return 'Can\'t not be empty';
                    }
                    return null;
                  },
                ),

我认为 CustomPainter 可以做到这一点。但只知道画一些形状,比如环形、圆形、直线、正方形、长方形。

自定义画家直线:

class DrawCustomShape extends CustomPainter{
  @override
  void paint(Canvas canvas, Size size) {
       
      var paint = Paint();
      paint.color = Colors.red;
      paint.strokeWidth = 5;
      
      canvas.drawLine(
        Offset(0, size.height / 2),
        Offset(size.width, size.height / 2),
        paint,
      );

      
    }

  
    @override
    bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }

}

Circle With Custom painter:


class DrawCustomShape extends CustomPainter{
  @override
  void paint(Canvas canvas, Size size) {
     var paint = Paint();
      paint.color = Colors.amber;
      paint.strokeWidth = 5;
  
      paint.color = Colors.blue;
      paint.style = PaintingStyle.stroke;
      canvas.drawCircle(Offset(size.width/2, size.height/2), size.width/4, paint);
      
    }

  
    @override
    bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }

}

我找到了把我们的手绘图canvas转成dart代码的工具(Flutter Shape Maker),真是太棒了

示例代码:


import 'package:flutter/material.dart';



void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Sample(),
    );
  }
}

class Sample extends StatefulWidget {
  @override
  _SampleState createState() => _SampleState();
}

class _SampleState extends State<Sample> {
 TextEditingController controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          automaticallyImplyLeading: false,
          title: Text(
            "Custom painter",
          ),
          centerTitle: true,
        ),
        body: Center(
          child: Container(
            padding:const EdgeInsets.all(
                  10
                ) ,
            width: MediaQuery.of(context).size.width,
            child: CustomPaint(
              size: Size(
                  MediaQuery.of(context).size.width,
                  (MediaQuery.of(context).size.width * 0.1111111111111111)
                      .toDouble()),
              painter: RPSCustomPainter(),
              child: Container(
                padding: const EdgeInsets.only(
                  left: 10,
                  right: 10,
                ),
                child: TextField(
                  controller: controller,
                  decoration: InputDecoration(
                      hintText: "type", border: InputBorder.none),
                ),
              ),
            ),
          ),
        ));
  }
}

class RPSCustomPainter extends CustomPainter{
  
  @override
  void paint(Canvas canvas, Size size) {
    
    

  Paint paint_0 = new Paint()
      ..color = Color.fromARGB(255, 33, 150, 243)
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2;
     
         
    Path path_0 = Path();
    path_0.moveTo(size.width*0.0022222,size.height*0.0400000);
    path_0.lineTo(size.width*0.0055556,size.height*0.0400000);
    path_0.lineTo(size.width*0.1455556,size.height*0.0500000);
    path_0.lineTo(size.width*0.2800000,size.height*0.0700000);
    path_0.lineTo(size.width*0.4211111,size.height*0.0300000);
    path_0.lineTo(size.width*0.5455556,size.height*0.0500000);
    path_0.lineTo(size.width*0.6611111,size.height*0.0600000);
    path_0.lineTo(size.width*0.7911111,size.height*0.0600000);
    path_0.lineTo(size.width*0.9077778,size.height*0.0700000);
    path_0.lineTo(size.width*0.9744444,size.height*0.0500000);
    path_0.lineTo(size.width*0.9933333,size.height*0.0700000);
    path_0.lineTo(size.width*0.9977778,size.height*0.9300000);
    path_0.lineTo(size.width*0.8611111,size.height*0.9400000);
    path_0.lineTo(size.width*0.7266667,size.height*0.9500000);
    path_0.lineTo(size.width*0.4844444,size.height*0.9500000);
    path_0.lineTo(size.width*0.2955556,size.height*0.9600000);
    path_0.lineTo(size.width*0.1344444,size.height*0.9600000);
    path_0.lineTo(size.width*0.0033333,size.height*0.9400000);
    path_0.lineTo(size.width*0.0077778,size.height*0.5200000);
    path_0.lineTo(size.width*0.0022222,size.height*0.0600000);

    canvas.drawPath(path_0, paint_0);
  
    
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
  
}

输出:

给你测试dartPad

说真的,真的很棒:)