前言:
这是我参与8月更文挑战的第 27 天,活动详情查看:8月更文挑战。为应掘金的八月更文挑战
,我准备在本月挑选 31
个以前没有介绍过的组件,进行全面分析和属性介绍。这些文章将来会作为 Flutter 组件集录
的重要素材。希望可以坚持下去,你的支持将是我最大的动力~
| 本系列 | 组件文章 | 列表 | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | 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 | 18.Divider | | 19.Flexible、Expanded 和 Spacer | 20.Card | 21.SizedBox | | 22.ConstrainedBox | 23.Stack | 24.Positioned | | 25.OverflowBox | 26.SizedOverflowBox | 27. DecoratedBox |
1.认识 DecoratedBox 组件
DecoratedBox
组件可能单独使用的频率不是很高,因为它被集成在了 Container
组件中,但装饰的使用方式是共通的,源码中说 DecoratedBox
会在其孩子的前景或背景上绘制 Decoration
装饰对象。这说明 Decoration
才是装饰的重点,我们需要了解或自定义 Decoration
。
下面是 DecoratedBox
组件类的定义
和 构造方法
,可以看出它继承自 SingleChildRenderObjectWidget
。构造时必须传入尺寸 decoration
参数,可以传入 position
入参。
decoration
成员的类型是 Decoration
,表示装饰对象。position
成员的类型是 DecorationPosition
枚举,表示在前景绘制还是在背景绘制。
```dart final Decoration decoration; final DecorationPosition position;
enum DecorationPosition { background, foreground, } ```
2.认识 Decoration 及其子类
首先需要注意的是: Decoration
是一个抽象类,无法直接实例化使用。
Flutter
框架中提供了四个实现类,其中 BoxDecoration
是我们最常用的。
比如下面通过 BoxDecoration
的 borderRadius
可以指定装饰的圆角,通过 color
指定填充的颜色。
```dart DecoratedBox( decoration: BoxDecoration( color: Colors.orangeAccent, borderRadius: BorderRadius.only( topLeft: Radius.circular(20), bottomRight: Radius.circular(20), bottomLeft: Radius.circular(5), topRight: Radius.circular(5), ), ), child: buildContent(), );
Widget buildContent() { return SizedBox( width: 80, height: 80, child: Icon(Icons.android, size: 50, color: Colors.white), ); } ```
下面是 BoxDecoration
的构造方法,可以看出除了圆角和颜色,还有很多入参,比如背景图片
、边线
、阴影
、渐变
、形状
等。
如下装饰,有红色史诗碎片那味了:
dart BoxDecoration( color: Colors.transparent, borderRadius: BorderRadius.only( topLeft: Radius.circular(20), bottomRight: Radius.circular(20), bottomLeft: Radius.circular(5), topRight: Radius.circular(5), ), border: Border.all(color: Colors.red, width: 2), image: DecorationImage( image: AssetImage('assets/images/bg_6.jpeg'), fit: BoxFit.cover, ), boxShadow: [ const BoxShadow( color: Colors.red, offset: Offset.zero, blurRadius: 2, spreadRadius: 2), ] ),
另外还有一个 ShapeDecoration
子类,顾名思义,它可以进行一些形状的处理。其中入参必须传入 ShapeBorder
类型的 shape
参数。关于 ShapeBorder
,详见 : 《Path在手,天下我有》
如下,通过一个 Flutter 自带的 CircleBorder
来测试一下:
dart DecoratedBox( position: DecorationPosition.background, decoration: ShapeDecoration( shape: CircleBorder(), shadows: const [BoxShadow( color: Colors.red, offset: Offset.zero, blurRadius: 2, spreadRadius: 2)], image: DecorationImage( image: AssetImage('assets/images/bg_6.jpeg'), fit: BoxFit.cover, ), ), child: buildContent(), );
3.自定义装饰
很多人问过我,如何加虚线边框。本质上就是在问如何通过绘制虚线,通过 DecoratedBox
装饰而已。在我发布的 dash_painter 包中有实现虚线装饰,就以此来讲述一下如何自定义装饰
。
dart dependencies: ... dash_painter: ^1.0.2
```dart import 'package:dashpainter/dashdecoration.dart';
DecoratedBox( decoration: DashDecoration( pointWidth: 2, step: 5, pointCount: 1, radius: Radius.circular(15), gradient: SweepGradient(colors: [ Colors.blue, Colors.red, Colors.yellow, Colors.green ])), child: buildContent(), );
Widget buildContent() { return SizedBox( width: 70, height: 70, child: Icon( Icons.add, color: Colors.orangeAccent, size: 40), ); } ```
下面看一下 DashDecoration
的源码实现,首先定义可配置的参数,通过构造函数初始化。
在 DashDecoration
中必须实现抽象方法 createBoxPainter
,返回一个 BoxPainter
对象。
然后继承 BoxPainter
,将配置对象传进来,在 paint
里画就完事了。本身流程很简单,关键在于如何绘制。在 《Flutter 绘制指南 - 妙笔生花》 小册中系统地介绍了 Flutter 绘制相关的基础知识,感兴趣的可以看一看。
4. DecoratedBox 的源码实现
DecoratedBox
继承自 SingleChildRenderObjectWidget
,内部维护 RenderDecoratedBox
渲染对象来实现装饰功能。
核心代码是下面的 paint
方法,执行绘制。其中 super.paint(context, offset);
是绘制子组件,可见 background
是在绘制孩子前绘制,也就是作为背景,孩子在前面。而 foreground
会覆盖在孩子前面,也就是前景。画笔是通过 _decoration#createBoxPainter
创建的,也就是那个 BoxPainter
对象。
那本文到这里就结束了,谢谢观看,明天见~