[Flutter actual combat] various shapes of components

Lao Meng's introduction : Many components in Flutter have a shapeproperty called , the type is ShapeBorder, such as Button class, Card and other components, shaperepresenting the shape of the control. The system has provided us with many shapes. For components without this property, you can use Clip Class components are cut.

BeveledRectangleBorder

Bevel rectangular border, usage is as follows:

RaisedButton(
  shape: BeveledRectangleBorder(
      side: BorderSide(width: 1, color: Colors.red),
      borderRadius: BorderRadius.circular(10)),
  child: Text('老孟'),
  onPressed: () {},
)

image-20200522172909192

If you set a radius larger than the control, it will become a diamond :

 3RaisedButton(
  shape: BeveledRectangleBorder(
      side: BorderSide(width: 1, color: Colors.red),
      borderRadius: BorderRadius.circular(100)),
  child: Text('老孟'),
  onPressed: () {},
)

image-20200522173147073

Similarly, if the radius is set to 0, it is a rectangle.

RaisedButton(
  shape: BeveledRectangleBorder(
      side: BorderSide(width: 1, color: Colors.red),
      borderRadius: BorderRadius.circular(0)),
  child: Text('老孟'),
  onPressed: () {},
)

image-20200522173458904

Border

Border allows the line style on each side to be individually set.

RaisedButton(
  shape: Border(
    top: BorderSide(color: Colors.red,width: 2)
  ),
  child: Text('老孟'),
  onPressed: () {},
)

image-20200522173801387

Set all

RaisedButton(
        shape: Border(
          top: BorderSide(color: Colors.red,width: 10),
          right: BorderSide(color: Colors.blue,width: 10),
          bottom: BorderSide(color: Colors.yellow,width: 10),
          left: BorderSide(color: Colors.green,width: 10),
        ),
        child: Text('老孟'),
        onPressed: () {},
      )

image-20200522182443777

BorderDirectional

BorderDirectional and Border essentially the same, the difference is BorderDirectional with reading direction, reading from left to right in most countries, but some countries are right to left, such as Arabic and so on.

RaisedButton(
  shape: BorderDirectional(
    start: BorderSide(color: Colors.red,width: 2),
    end: BorderSide(color: Colors.blue,width: 2),
  ),
  child: Text('老孟'),
  onPressed: () {},
)

image-20200522182150780

CircleBorder

Round

RaisedButton(
  shape: CircleBorder(side: BorderSide(color: Colors.red)),
  child: Text('老孟'),
  onPressed: () {},
)

image-20200522182549205

ContinuousRectangleBorder

A continuous rounded rectangle, a smooth and continuous transition between straight lines and rounded corners, has a smaller rounded corner effect compared to RoundedRectangleBorder.

RaisedButton(
  shape: ContinuousRectangleBorder(
      side: BorderSide(color: Colors.red),
      borderRadius: BorderRadius.circular(20)),
  child: Text('老孟'),
  onPressed: () {},
)

image-20200522182922984

RoundedRectangleBorder

Rounded Rectangle

RaisedButton(
  shape: RoundedRectangleBorder(
      side: BorderSide(color: Colors.red),
      borderRadius: BorderRadius.circular(10)),
  child: Text('老孟'),
  onPressed: () {},
)

image-20200522183032650

StadiumBorder

Similar to the shape of a football field , round on both sides, rectangular in the middle

RaisedButton(
  shape: StadiumBorder(
      side: BorderSide(color: Colors.red),),
  child: Text('老孟'),
  onPressed: () {},
)

image-20200522183814823

OutlineInputBorder

With outer border

RaisedButton(
  shape: OutlineInputBorder(
    borderSide: BorderSide(color: Colors.red),
    borderRadius: BorderRadius.circular(10),
  ),
  child: Text('老孟'),
  onPressed: () {},
)

image-20200522184044810

UnderlineInputBorder

Underline border

RaisedButton(
  shape: UnderlineInputBorder(
    borderSide: BorderSide(color: Colors.red),
  ),
  child: Text('老孟'),
  onPressed: () {},
)

image-20200522184216659

ClipRect

ClipRect rectangular cropping assembly subassembly, usually, clipRect acting CustomPaint, CustomSingleChildLayout, CustomMultiChildLayout, Align, Center, OverflowBox, SizedOverflowBoxcomponents such as the Align clipRect acts on, only the upper half portion may be displayed, as follows:

ClipRect(
  child: Align(
    alignment: Alignment.topCenter,
    heightFactor: 0.5,
    child: Container(
      height: 150,
      width: 150,
      child: Image.asset(
        'images/1.png',
        fit: BoxFit.cover,
      ),
    ),
  ),
)

Full image effect:

Cutting effect:

clipperThe parameters define the cutting rules, which are described in detail below.

clipBehaviorThe parameter defines the cutting method. Only the child control is beyond the scope of the parent control can be cut. Each method is explained as follows:

  • none: No clipping, the system default value. If the subcomponent does not exceed the boundary, this value has no performance consumption.
  • hardEdge: Crop without applying anti-aliasing, which is noneslower than other methods, but faster than other methods.
  • antiAlias: cropping and anti-aliasing, this method looks smoother, antiAliasWithSaveLayerfaster than hardEdgeslower, usually used to handle circular and arc-shaped cropping.
  • antiAliasWithSaveLayer: cropping, anti-aliasing, and a buffer. This method is very slow and is rarely used.

ClipRRect

The ClipRRect component can round corners of the sub-components. The default corner radius is 0. Note that ClipRRect has 2 Rs, not the ClipRect described above.

The usage is as follows:

ClipRRect(
  borderRadius: BorderRadius.circular(20),
  child: Container(
    height: 150,
    width: 150,
    child: Image.asset(
      'images/1.png',
      fit: BoxFit.cover,
    ),
  ),
)

The effect is as follows:

ClipOval

ClipOval is cut into an ellipse, and the size of the ellipse is tangent to the parent component, so if the parent component is square, the cut out is a circle. The usage is as follows:

ClipOval(
  child: Container(
    height: 150,
    width: 250,
    child: Image.asset(
      'images/1.png',
      fit: BoxFit.cover,
    ),
  ),
)

The effect is as follows:

ClipPath

The ClipPath component cuts according to the path. We can also use the custom clipping path provided by the system. The usage is as follows:

ClipPath.shape(
  shape: StadiumBorder(),
  child: Container(
    height: 150,
    width: 250,
    child: Image.asset(
      'images/1.png',
      fit: BoxFit.cover,
    ),
  ),
)

shapeThe parameter is of the ShapeBorder type. The system has defined many shapes. The introduction is as follows:

  • RoundedRectangleBorder: rounded rectangle

  • ContinuousRectangleBorder: A smooth and continuous transition between straight lines and rounded corners. Compared with RoundedRectangleBorder, the rounded corners have a smaller effect.

  • StadiumBorder: Similar to the shape of a football field, with semicircles at both ends.

  • BeveledRectangleBorder: Beveled rectangle. The effect is as follows:

  • CircleBorder: Circle.

CustomClipper

CustomClipper is not a component, but an abstract(abstract) class. Using CustomClipper, we can draw any shape we want, such as a triangle. The code is as follows:

@override
Widget build(BuildContext context) {
  return Center(
    child: ClipPath(
      clipper: TrianglePath(),
      child: Container(
        height: 150,
        width: 250,
        child: Image.asset(
          'images/1.png',
          fit: BoxFit.cover,
        ),
      ),
    ),
  );
}

The custom TrianglePath code is as follows:

class TrianglePath extends CustomClipper<Path>{
  @override
  Path getClip(Size size) {
    var path = Path();
    path.moveTo(size.width/2, 0);
    path.lineTo(0, size.height);
    path.lineTo(size.width, size.height);
    return path;
  }

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

The effect is as follows:

We can also draw a five-pointed star, the code is as follows:

class StarPath extends CustomClipper<Path> {
  StarPath({this.scale = 2.5});

  final double scale;

  double perDegree = 36;

  /// 角度转弧度公式
  double degree2Radian(double degree) {
    return (pi * degree / 180);
  }

  @override
  Path getClip(Size size) {
    var R = min(size.width / 2, size.height / 2);
    var r = R / scale;
    var x = size.width / 2;
    var y = size.height / 2;

    var path = Path();
    path.moveTo(x, y - R);
    path.lineTo(x - sin(degree2Radian(perDegree)) * r,
        y - cos(degree2Radian(perDegree)) * r);
    path.lineTo(x - sin(degree2Radian(perDegree * 2)) * R,
        y - cos(degree2Radian(perDegree * 2)) * R);
    path.lineTo(x - sin(degree2Radian(perDegree * 3)) * r,
        y - cos(degree2Radian(perDegree * 3)) * r);
    path.lineTo(x - sin(degree2Radian(perDegree * 4)) * R,
        y - cos(degree2Radian(perDegree * 4)) * R);
    path.lineTo(x - sin(degree2Radian(perDegree * 5)) * r,
        y - cos(degree2Radian(perDegree * 5)) * r);
    path.lineTo(x - sin(degree2Radian(perDegree * 6)) * R,
        y - cos(degree2Radian(perDegree * 6)) * R);
    path.lineTo(x - sin(degree2Radian(perDegree * 7)) * r,
        y - cos(degree2Radian(perDegree * 7)) * r);
    path.lineTo(x - sin(degree2Radian(perDegree * 8)) * R,
        y - cos(degree2Radian(perDegree * 8)) * R);
    path.lineTo(x - sin(degree2Radian(perDegree * 9)) * r,
        y - cos(degree2Radian(perDegree * 9)) * r);
    path.lineTo(x - sin(degree2Radian(perDegree * 10)) * R,
        y - cos(degree2Radian(perDegree * 10)) * R);
    return path;
  }

  @override
  bool shouldReclip(StarPath oldClipper) {
    return oldClipper.scale != this.scale;
  }
}

scaleThe parameter represents the zoom ratio from the point of the interval to the center of the circle. The effect of the five-pointed star is as follows:

The following is dynamically set with animation scale, the code is as follows:

class StartClip extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _StartClipState();
}

class _StartClipState extends State<StartClip>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation _animation;

  @override
  void initState() {
    _controller =
        AnimationController(duration: Duration(seconds: 2), vsync: this)
          ..addStatusListener((status) {
            if (status == AnimationStatus.completed) {
              _controller.reverse();
            } else if (status == AnimationStatus.dismissed) {
              _controller.forward();
            }
          });
    _animation = Tween(begin: 1.0, end: 4.0).animate(_controller);
    _controller.forward();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: AnimatedBuilder(
          animation: _animation,
          builder: (context, child) {
            return ClipPath(
              clipper: StarPath(scale: _animation.value),
              child: Container(
                height: 150,
                width: 150,
                color: Colors.red,
              ),
            );
          }),
    );
  }
}

The effect is as follows:

communicate with

Laomeng Flutter blog address (330 control usage): http://laomengit.com

Welcome to join the Flutter exchange group (WeChat: laomengit) and follow the public account [Lao Meng Flutter]:

Guess you like

Origin blog.csdn.net/mengks1987/article/details/108481200