乐趣区

关于flutter:Flutter-实战各种各样形状的组件

老孟导读 :Flutter 中很多组件都有一个叫做shape 的属性,类型是 ShapeBorder,比方Button 类、Card等组件,shape示意控件的形态,零碎曾经为咱们提供了很多形态,对于没有此属性的组件,能够应用 Clip 类组件进行裁减。

BeveledRectangleBorder

斜角矩形边框,用法如下:

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

如果设置的半径比控件还大,就会变成 菱形

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

同理,如果半径设置为 0,就是矩形。

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

Border

Border 容许独自设置每一个边上的线条款式.

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

设置全副

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: () {},
      )

BorderDirectional

BorderDirectionalBorder 根本一样,区别就是 BorderDirectional 带有浏览方向,大部分国家浏览是从左到右,但有的国家是从右到左的,比方阿拉伯等。

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

CircleBorder

圆形

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

ContinuousRectangleBorder

间断的圆角矩形,直线和圆角平滑间断的过渡,和 RoundedRectangleBorder 相比,圆角成果会小一些。

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

RoundedRectangleBorder

圆角矩形

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

StadiumBorder

相似 足球场 的形态,两边圆形,两头矩形

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

OutlineInputBorder

带外边框

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

UnderlineInputBorder

下划线边框

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

ClipRect

ClipRect 组件应用矩形裁剪子组件,通常状况下,ClipRect 作用于 CustomPaintCustomSingleChildLayoutCustomMultiChildLayoutAlignCenterOverflowBoxSizedOverflowBox 组件,例如 ClipRect 作用于 Align,能够仅显示上半局部,代码如下:

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

全图成果:

<img src=”https://img-blog.csdnimg.cn/20200324160500474.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70″ style=”zoom:50%;” />

裁剪成果:

<img src=”https://img-blog.csdnimg.cn/20200324160537832.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70″ style=”zoom:50%;” />

clipper参数定义裁剪规定,上面具体介绍。

clipBehavior参数定义了裁剪的形式,只有子控件超出父控件的范畴才有裁剪的说法,各个形式阐明如下:

  • none:不裁剪,零碎默认值,如果子组件不超出边界,此值没有任何性能耗费。
  • hardEdge:裁剪但不利用抗锯齿,速度比 none 慢一点,但比其余形式快。
  • antiAlias:裁剪而且抗锯齿,此形式看起来更平滑,比 antiAliasWithSaveLayer 快,比 hardEdge 慢,通常用于解决圆形和弧形裁剪。
  • antiAliasWithSaveLayer:裁剪、抗锯齿而且有一个缓冲区,此形式很慢,用到的状况比拟少。

ClipRRect

ClipRRect 组件能够对子组件进行圆角裁剪,默认圆角半径为 0,留神 ClipRRect 有 2 个 R,不是下面介绍的 ClipRect。

用法如下:

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

成果如图:

<img src=”https://img-blog.csdnimg.cn/20200324160615913.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70″ style=”zoom:50%;” />

ClipOval

ClipOval 裁剪为椭圆形,椭圆形的大小为正切父组件,因而如果父组件为正方形,切出来是圆形,用法如下:

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

成果如下:

<img src=”https://img-blog.csdnimg.cn/20200324160734820.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70″ style=”zoom:50%;” />

ClipPath

ClipPath 组件依据门路进行裁剪,咱们自定义裁剪门路也能够应用零碎提供的,用法如下:

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

shape参数是 ShapeBorder 类型,零碎曾经定义了很多形态,介绍如下:

  • RoundedRectangleBorder:圆角矩形
  • ContinuousRectangleBorder:直线和圆角平滑间断的过渡,和 RoundedRectangleBorder 相比,圆角成果会小一些。
  • StadiumBorder:相似于足球场的形态,两端半圆。
  • BeveledRectangleBorder:斜角矩形。成果如图:

    <img src=”https://img-blog.csdnimg.cn/20200324160806686.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70″ style=”zoom:50%;” />

  • CircleBorder:圆形。

CustomClipper

CustomClipper 并不是一个组件,而是一个 abstract(形象) 类,应用 CustomClipper 能够绘制出任何咱们想要的形态,比方三角形,代码如下:

@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,
        ),
      ),
    ),
  );
}

自定义 TrianglePath 代码如下:

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;}
}

成果如下:

<img src=”https://img-blog.csdnimg.cn/20200324160835511.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70″ style=”zoom:50%;” />

咱们还能够绘制五角星,代码如下:

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;}
}

scale参数示意距离的点到圆心的缩放比例,五角星成果如下:

<img src=”https://img-blog.csdnimg.cn/2020032416085643.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70″ style=”zoom:50%;” />

上面用动画动静设置scale,代码如下:

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,
              ),
            );
          }),
    );
  }
}

成果如下:

交换

老孟 Flutter 博客地址(330 个控件用法):http://laomengit.com

欢送退出 Flutter 交换群(微信:laomengit)、关注公众号【老孟 Flutter】:

退出移动版