Preface:

This is the 17th day of my participation in the August More text Challenge. For details, see: August More Text Challenge. To prepare for the August challenge of the nuggets, I’m going to pick 31 components this month that haven’t been introduced before and do a full analysis and attribute introduction. These articles will be used as important material in the collection of the Flutter components. I hope I can stick to it, your support will be my biggest motivation ~

This series Component articles The list of
1.NotificationListener 2.Dismissible 3.Switch
4.Scrollbar 5.ClipPath 6.CupertinoActivityIndicator
7.Opacity 8.FadeTransition 9. AnimatedOpacity
10. FadeInImage 11. Offstage 12. TickerMode
13. Visibility 14. Padding 15. AnimatedContainer
16.CircleAvatar 17.PhysicalShape[this article]

1. Know the PhysicalShape component

Now, if you’ve never used PhysicalShape before, it’s called Physical + Shape. As you can see from the comments, it is used to crop the child components according to the path, and you should think of the ClipPath component. You can also see that this clipping can have a shadow effect.


1. PhysicalShape Basic information

Below is PhysicalShape component class definition and construction method, it can be seen that it inherited from SingleChildRenderObjectWidget. You must pass in the clipper and color parameters when instantiating.

The clipper parameter is of type CustomClipper , which is the same as the clipper parameter in ClipPath.

final CustomClipper<Path> clipper;
Copy the code

In addition, you can specify the shadow depth elevation, shadowColor, and clipBehavior. The default value is no shadow, and the shadow color is black.


2. Use of PhysicalShape

The CustomClipper object is described in detail in the ClipPath Component article. Let’s start with the two required input parameters, clipper and color. Below, crop a circle using the CircleBorder shape, color being the fill color.

class PhysicalShapeDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return  PhysicalShape(
          child: SizedBox(
            width: 80,
            height: 80,
          ),
          clipBehavior: Clip.hardEdge,
          clipper: constShapeBorderClipper( shape: CircleBorder(), ), color: Colors.deepPurpleAccent, ); }}Copy the code

PhysicalShape specifies a shadow by elevation and shadowColor. The effect is as follows:

class PhysicalShapeDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return  PhysicalShape(
          shadowColor: Colors.blueAccent,
          elevation: 3,
          child: SizedBox(
            width: 80,
            height: 80,
          ),
          clipBehavior: Clip.hardEdge,
          clipper: constShapeBorderClipper( shape: CircleBorder(), ), color: Colors.deepPurpleAccent, ); }}Copy the code

3.PhysicalShape Custom shape clipping

Take a look at PhysicalShape using the custom shape clipping from the ClipPath component. Here is the triangle clipping effect of TriangleClipper, you can see that it also has a shadow effect.

class TriangleClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    print(size); Path path = Path() .. moveTo(0, size.height) .. relativeLineTo(size.width,0)
      ..relativeLineTo(-size.width / 2, -size.height) .. close();return path;
  }
  @override
  bool shouldReclip(covariant CustomClipper<dynamic> oldClipper) {
    return true; }}Copy the code

Here is the love path cropping effect:

class LoveClipper extends CustomClipper<Path> {

  @override
  Path getClip(Size size) {
    double fate = 18.5*size.height/100;
    double width = size.width / 2;
    double height = size.height / 4;
    Path path = Path();

    path.moveTo(width, height);
    path.cubicTo(width, height, width + 1.1 * fate, height - 1.5 * fate, width + 2 * fate, height);
    path.cubicTo(width + 2 * fate, height, width + 3.5 * fate, height + 2 * fate, width, height + 4 * fate);

    path.moveTo(width, height);
    path.cubicTo(width, height, width - 1.1 * fate, height - 1.5 * fate, width - 2 * fate, height);
    path.cubicTo(width - 2 * fate, height, width - 3.5 * fate, height + 2 * fate, width, height + 4 * fate);

    return path;
  }

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

Any custom shape can be clipped through the PhysicalShape component and has an influence shadow effect, but the shadow is fixed and the user cannot set the shadow offset. In addition, this clipping, like ClipPath, can be clipped to any component.


Two, PhysicalShape source code simple look

It inherits from SingleChildRenderObjectWidget, will maintain the RenderObject object. You can see that it does that with RenderPhysicalShape. Properties such as color, clipper, and shadow are all input parameters to build RenderPhysicalShape.


In RenderPhysical Shade #paint, the shadow will be drawn first.

The clipper is set to a PhysicalModelLayer object, which means that this object is responsible for clipping.

Overall PhysicalShape is very simple, just an enhanced version of ClipPath, with a shadow effect. Below are the effects of PhysicalShape (left) and ClipPath (right). We can see that PhysicalShape does not have small scissors, indicating that it is not achieved by path clipping of the canvas.

If we trace the path direction of the clipper, we can see that the final path is used in the native method of SceneBuilder#_pushPhysicalShape. So PhysicalShape and ClipPath are fundamentally different implementations.

The use of PhysicalShape here is the end of the introduction, that article to here is the end, thanks for watching, see you tomorrow ~