Flutter applying shadows to CustomPainted widget

3,600

Solution 1

As @pskink mentioned, there is a method of canvas called drawShadow

so changing my drawing method for my shadowPath to :

canvas.drawShadow(shadowPath, Colors.black, 2.0, true);

Will solve the problem and the output will be something like this : Final Image

Thanks for everyone !!

Solution 2

An easier way I found was to offset the path

canvas.drawShadow(path.shift(Offset(0, -5)), Colors.black, 2.0, true);
Share:
3,600
isa türk
Author by

isa türk

Updated on December 12, 2022

Comments

  • isa türk
    isa türk over 1 year

    Introduction

    I draw a custom Tab-bar using Flutter's CustomPaint Widget it looks like this: Shape Image

    In Addition, this is the code I used to draw the widget :

    class TabBarPainter extends CustomPainter {
      final Color paintColor = Colors.redAccent 
      @override
      void paint(Canvas canvas, Size size) {
        /// the thing that I called as a deleter circle is an imaginary circle that I used to delete a semicircle from my rectangular shape
    
        var diameter = 80; /// X value is the diameter(R) of the deleter circle;
        double topSpace = 2;
        double startCurve = (size.width-diameter)/2; /// Start point of the curve
        double endCurve = startCurve+diameter; // End Point of the curve
    
    
         /// Some math about my cubic bezier curve
        double xValueInset = diameter * 0.05; 
        double yValueOffset = (diameter/2) * 4.0 / 3.0; 
    
        Path path = Path();
    
        Paint paint = Paint();
    
        /// Points to make a semicircle approximation using Bezier Curve
        var firstendPoint = new Offset(endCurve, topSpace);
        var controlPoint1  = new Offset(startCurve+xValueInset,yValueOffset+topSpace);
        var controlPoint2  = new Offset((diameter-xValueInset)+startCurve,yValueOffset+topSpace);
    
        //! Start sketching Shape
        path.moveTo(0.0,topSpace);
        path.lineTo(startCurve, topSpace);
        path.cubicTo(controlPoint1.dx, controlPoint1.dy,
        controlPoint2.dx, controlPoint2.dy,
        firstendPoint.dx, firstendPoint.dy);
        path.lineTo(size.width, topSpace);
        path.lineTo(size.width, size.height);
        path.lineTo(0.0, size.height);
        path.close();
        //! End sketching Shape
    
        paint.color = paintColor;
    
        canvas.drawPath(path, paint);
    
      }
    
      @override
      bool shouldRepaint(TabBarPainter oldDelegate) =>  oldDelegate != this;
    }
    

    Experimenting

    I want to apply a shodow on my CustomDrawen Shape so I tried 2 methods:

    First Method: I used a classical container and boxshadow to shadow it and it looked like this: Shape Image shadow Applied I used the following code :

    Container(
      decoration: BoxDecoration(
        boxShadow: [
          BoxShadow(
            color : Colors.black.withOpacity(0.30),
            blurRadius: 3,
            ffset: new Offset(0, -3)
          )
        ]
      ),
      child: CustomPaint(           
        painter: TabBarPainter(),
      ),
    

    Second Method : I drew a similar black colored(opacity(0.15)) shape and it looked like this:

    Shape with a sub shape approximating the shadow

    I added the following code to my CustomPainter in order to draw this shape:

    final Color shadowColor = Colors.black.withOpacity(0.15);
    
    Path shadowPath = Path();
    Paint shadowPaint = Paint();
    
    /// Points to make a semicircle approximation using Bezier Curve
    
    var shadowfirstendPoint = new Offset(endCurve-topSpace, 0.0);
    var shadowcontrolPoint1  = new Offset(startCurve+xValueInset+topSpace,yValueOffset);
    var shadowcontrolPoint2  = new Offset((diameter-xValueInset)+startCurve-topSpace,yValueOffset);
    
    //! Start sketching Shadow   
    shadowPath.lineTo(startCurve+topSpace, 0.0);
    shadowPath.cubicTo(shadowcontrolPoint1.dx, shadowcontrolPoint1.dy,
    shadowcontrolPoint2.dx, shadowcontrolPoint2.dy,
    shadowfirstendPoint.dx, shadowfirstendPoint.dy);
    shadowPath.lineTo(size.width, 0.0);
    shadowPath.lineTo(size.width, size.height);
    shadowPath.lineTo(0.0, size.height);
    shadowPath.close();
    
    //! End Sketching Shadow
    shadowPaint.color = shadowColor;
    canvas.drawPath(shadowPath, shadowPaint);
    

    Problem

    In the first method, blank area - at the top center of widget - was filled with shadow

    In the second method, shadow was not realistic because even though it had low opacity, it did not had a blur and I could not find a method to make it blurred

    Conclusion

    I need another way to properly shadow my widget or add blur to my shadow-like custom drawn shape

    Since flutter is doing this to every type of widget they created, it seems possible

    I would be thankful to any kind of helper

    Regards

    • pskink
      pskink almost 5 years
      use drawShadow method to draw a shadow
  • Florian K
    Florian K over 2 years
    Thank you ! Elevation can be set to customize spread