15 | 组合与自绘,我该选用何种方式自定义Widget?
该思维导图由 AI 生成,仅供参考
组装
- 深入了解
- 翻译
- 解释
- 总结
Flutter中自定义Widget有两种方式:组合和自绘。组合是通过将基础Widget组装成高级别的Widget,提高控件的复用性,而自绘则是根据特殊需求在画板上绘制界面。文章通过一个App Store升级项UI的例子,详细介绍了如何通过组装方式自定义控件。首先定义了数据结构UpdateItemModel,然后按照子Widget的摆放方向,分别拆解了UI的垂直和水平布局结构。在拆解的基础上,详细讲解了控件间的边距设置、文本伸缩规则、图片圆角实现等关键步骤。最终通过组合方式完成了升级项UI的定制。这种从上到下、从左到右拆解UI的布局结构的方法对于以组装方式自定义UI非常有用。 在自绘部分,文章介绍了Flutter中自绘控件的实现方式。通过CustomPaint容器和CustomPainter,可以实现自定义的绘制逻辑,例如绘制饼图等不规则的视图。CustomPainter的paint方法中,通过Canvas与Paint的配合,可以实现定制化的绘制逻辑。自绘控件的实现并不复杂,可以通过画笔和画布实现更丰富的功能。 总结来说,Flutter提供了组装与自绘两种自定义Widget的方式,来满足对视图的自定义需求。组合方式适用于将目标视图分解成各个UI小元素,而自绘方式则适用于实现少数通过组合难以实现的需求。在自定义UI时,需要将目标视图化繁为简,拆解成小控件,然后再思考如何将这些小控件串联起来。这种思维方式类似于学习新知识的过程,需要将复杂的知识化繁为简,逐个攻破。 通过本文的学习,读者可以了解到组合和自绘这两种自定义Widget的具体使用方法,并在实际应用中体会它们在不同场景下的优劣势。同时,文章还留下了两道思考题,可以帮助读者进一步巩固所学知识。 Overall, the article provides a comprehensive overview of customizing widgets in Flutter through composition and custom painting, offering practical examples and thought-provoking exercises for readers to deepen their understanding.
《Flutter 核心技术与实战》,新⼈⾸单¥59
全部留言(33)
- 最新
- 精选
- 吴小安大前端的界面不是提倡尽量减少图层的数量?这样一直嵌套下去图层似乎太多,这些布局的控件是不是不算图层?不参与渲染?
作者回复: 1.大部分都是非可视的容器,并不参与绘制;对于非透明的视图叠加,Flutter在绘制完毕后会做图层合并的
2019-08-0114 - 和小胖关于第二道思考题目的解决方法,请老师看一下: //绘制自定义view,其中画笔 paint ,画布 canvas,而 CustomPainter 负责具体的绘制逻辑处理 class WheelPainter extends CustomPainter { List<double> _list; List<Color> _listColor; double _total; //总份数 WheelPainter(this._list, this._listColor); @override void paint(Canvas canvas, Size size) { double wheelSize = min(size.width, size.height) / 2; //饼图的尺寸 //用一个矩形框来包裹饼图 Rect boundingRect = Rect.fromCircle( center: Offset(wheelSize, wheelSize), radius: wheelSize); //求出数组中所有数值的和 _total = _list.reduce((value, element) => value + element); print("总份额是:$_total"); //求出每一份所占的角度 double radius = (2 * pi) / _total; //求出每一份的弧度 print("总角度是${2 * pi},每份额角度是:$radius"); //循环绘制每一份扇形 for (int i = 0; i < _list.length; i++) { // 求出初始角度 double startRadius; if (i == 0) { startRadius = 0; } else { startRadius = _list.sublist(0, i).reduce((value, element) => value + element) * radius; } //求出滑过角度,即当前份额乘以每份所占角度 double sweepRadius = radius * _list[i]; print("起始角度:$startRadius,划过角度:$sweepRadius"); /// 绘制扇形,第一个参数是绘制矩形所在的矩形,第二个参数是起始角度,第三个参数是矩形划过的角度 /// 第三个参数代表扇形是否是实心,否则就只是绘制边框是空心的,最后一个参数是画笔 canvas.drawArc(boundingRect, startRadius, sweepRadius, true, getPaintByColor(_listColor[i])); } } //根据不同的 color 来获取对应的画笔 Paint getPaintByColor(Color color) { Paint paint = Paint(); paint.color = color; return paint; } //判断是否需要重绘 @override bool shouldRepaint(CustomPainter oldDelegate) => oldDelegate != this; } Padding getCustomPaint() { return Padding( padding: EdgeInsets.all(10), child: CustomPaint( size: Size(200, 200), painter: WheelPainter( List.of([1.0, 2.0, 3.0, 4.0, 20]), List.of([ Colors.red, Colors.blue, Colors.green, Colors.amber, Colors.black54 ])), )); }
作者回复: 很厉害👍!
2019-09-05412 - wanggw功能算是差不多实现了,但是还存在一个核心的问题不知道应该解决,就是我怎么获取Text展示文本的行数,我需要行数才能控制 more 按钮的显示和隐藏,否则我默认超过2行显示 more 按钮,当文本只有1行的时候,more 按钮也显示了😂。暂时还没找到解决方案。这是我写的例子:https://github.com/wanggw911/flutter_hello/blob/master/lib/widget/Listview02.dart
作者回复: 如果想简单点,可以预估一个文本长度(比如100),超过这个文本长度的两行文字,统一都展示“More”按钮;如果想精确点,算文本高度可以用TextPainter。具体用法可以参考auto_size_text控件:https://github.com/leisim/auto_size_text
2019-08-2235 - davidzhou我的思路这样,先自定义一个statefulwidget,里面用过一个变量控制两个text,因为text是statelesswidget,无法动态去刷新,一个widget设置Maxlines=2,另一个不设置,more是一个floatbutton,点击事件里面实现setstate改变先前定义的变量就行了
作者回复: 赞
2019-08-0124 - 獸丶老师,Flutter代码规范方面会讲吗,如果代码全写在一个Dart文件里,有点太冗杂了,还是说遵循SRP,一个类一个Dart文件?
作者回复: 后面会捎带讲一点点
2019-08-023 - zzz请问下,再混合开发的场景下,module类型的对于root Widget,我们必须使用MaterialApp或者CupertinoApp二选一么?如果不使用这两个基础的widgetApp,除了不能享受封装好的Theme、封装好的Widget组件这些便利外,是否有无法实现的基础功能(比如在iOS中的右滑返回等等)? 同时想问下目前国内很多App在安卓上的表现都不是Material风格的,同时也不完全是Cupertino风格,所以在实际应用中,主流的做法是使用 MaterialApp/CupertinoApp/完全自定义 这三种的哪一种呢?以及在开发过程中的是否有什么弊端呢?
作者回复: MaterialApp和CupertinoApp封装了一些基本的App功能,比如导航栈管理、屏幕管理,国际化,以及对应的脚手架等,自己实现没有必要也基本不可能。样式就是一个配置而已,你可以自己定义不同平台的配置规则(具体参考夜间模式这一节)。另外他俩对Android/iOS的关键设计差异(如导航栏样式、状态栏样式、弹窗样式等),在框架内就进行了区分实现,所以如果你不定制样式,也无需过多担心在iOS上长得太像Android。
2019-10-0832 - Neil 陈荣老师,我想绘制一个围棋游戏的棋盘,并在上面实现落子、提子等各种操作。大致估计了一下,如果用组合的方案,算上棋子,棋盘,各种线,至少会有接近400个 widget. 这种情况下性能会有问题吗?我想知道 widget 数量一般在多少以内采用组合不会出现性能问题,这个有没有一个指导性的最佳实践?如果一上来就用自绘的方案的话,担心各种操作的交互功能不容易实现。谢谢!
作者回复: 没啥问题,组件比较多的情况下,唯一需要关注的是限制界面的刷新范围,可以参考37节分享,用重绘边界去提前做一些缓存。
2019-12-1121 - 毛哥来了我是用Builder(builder: (Buildcontext context){})来创建description那个Text组件,然后就可以通过context.size.height获取Text的高度,然后就能判断按钮何时展示了
作者回复: 赞
2019-10-2431 - 浣熊特工队请问老师,more按钮那里的左右渐隐是怎么实现的啊,我用TextOverflow.fade是向下渐隐的啊
作者回复: 可以看下这个issue:https://github.com/flutter/flutter/issues/13631 另外这种效果可以考虑用Button遮挡来实现
2019-09-0321 - 🌙如果说尽量使用stateless,但是只要需要交互都必须是stateful吧?怎么尽量来使用成stateless呢?
作者回复: 把组件拆小
2019-08-231