簡體   English   中英

通過 (path.quadraticBezierTo) Flutter 從頂部為容器制作半圈

[英]make half circle from top for Container by (path.quadraticBezierTo) Flutter

我正在嘗試如下圖所示的形狀...

在此處輸入圖像描述

我不知道如何使它像圖像一樣...

我的代碼...

ClipPath(
    clipper: MyClipper(),
    child: Container(
    margin: EdgeInsets.only(top: size.height * 0.6),
    height: 500,
    width: size.width,
    color: Colors.white,
    ),
),

第一次嘗試我在(0,1)上提出了第一點......

class MyClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    var path = Path();

    path.moveTo(0, size.height);

    path.lineTo(0, size.height * 0.2);
//    path.lineTo(size.width, size.height);
//    path.lineTo(size.width, size.height * 0.5);

    path.quadraticBezierTo(size.width / 2, 0, size.width, size.height * 0.2);

    path.lineTo(size.width, size.height);

    path.close();
    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) {
    return true;
  }
}

第二次嘗試,我在(0,0.5)上提出了第一點......

class MyClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    var path = Path();

    path.moveTo(0, size.height * 0.5);

    path.quadraticBezierTo(size.width / 2, 0, size.width, size.height * 0.5);
    
    path.lineTo(size.width, size.height);
    path.lineTo(0, size.height);

    path.close();
    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) {
    return false;
  }
}

我知道鋤頭從底部做,但我不知道如何做

請我需要對答案的解釋

您可以在下面復制粘貼運行完整代碼
可以參考https://blog.usejournal.com/how-to-draw-custom-shapes-in-flutter-aa197bda94bf

對 C 做二次貝塞爾曲線,以 B 作為控制。

在此處輸入圖像描述

代碼片段

Path getClip(Size size) {
    var path = Path();

    path.moveTo(0.0, height);
    path.quadraticBezierTo(
        size.width / 2, size.height * 0.2, size.width, size.height - height);
    path.lineTo(size.width, 0.0);
    path.lineTo(0.0, 0.0);

    path.close();

    return path;
  }

在此處輸入圖像描述

完整代碼

import 'package:flutter/material.dart';

class ClipPainter extends CustomPainter {
  final CustomClipper<Path> clipper;

  ClipPainter(this.clipper);

  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint();
    paint.color = Colors.blue[800];
    paint.style = PaintingStyle.fill;
    canvas.drawPath(clipper.getClip(size), paint);
  }

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

class ArcClipper extends CustomClipper<Path> {
  ArcClipper(this.height);

  ///The height of the arc
  final double height;

  @override
  Path getClip(Size size) {
    var path = Path();

    path.moveTo(0.0, height);
    path.quadraticBezierTo(
        size.width / 2, size.height * 0.2, size.width, size.height - height);
    path.lineTo(size.width, 0.0);
    path.lineTo(0.0, 0.0);

    path.close();

    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) {
    ArcClipper oldie = oldClipper as ArcClipper;
    return height != oldie.height;
  }
}

class Arc extends StatelessWidget {
  const Arc({
    Key key,
    @required this.height,
    @required this.child,
  }) : super(key: key);

  /// The widget which one of [edge]s is going to be clippddddded as arc
  final Widget child;

  ///The height of the arc
  final double height;

  @override
  Widget build(BuildContext context) {
    var clipper = ArcClipper(height);
    return CustomPaint(
      painter: ClipPainter(clipper),
      child: ClipPath(
        clipper: clipper,
        child: child,
      ),
    );
  }
}

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

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

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Test'),
        ),
        body: Center(
            child: Container(
          width: 100,
          height: 100,
          decoration: BoxDecoration(
            border: Border.all(),
          ),
          child: Arc(
              height: 50,
              child: Container(
                  decoration: BoxDecoration(
                    border: Border.all(),
                  ),
                  width: 100,
                  height: 100)),
        )));
  }
}

解決方案是當我刪除margin時效果很好。

我使用margin的原因是因為我希望我的Container位於屏幕底部,我通過Positioned: bottom: 0 inside Stack回復了margin


Stack(
 children: <Widget>[
   Positioned(
     bottom: 0,
     child: ClipPath(
     clipper: MyClipper(),
     child: Container(
//       margin: EdgeInsets.only(top: size.height * 0.5),
         height: size.height * 0.45,
         width: size.width,
         color: Colors.white,
         ),
      ),
   ),
 ]
),

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM