赵走x博客
网站访问量:151872
首页
书籍
软件
工具
古诗词
搜索
登录
75、插件开发:iOS端API实现
64、文件操作
85、图片加载原理与缓存
84、Flutter运行机制-从启动到显示
83、RenderObject和RenderBox
82、Element与BuildContext
81、Flutter UI系统
80、国际化常见问题
79、使用Intl包
78、实现Localizations
77、让App支持多语言
76、Texture和PlatformView
73、开发Flutter插件
72、插件开发:平台通道简介
71、开发Package
70、Json转Dart Model类
69、使用Socket API
68、使用WebSockets
67、实例:Http分块下载
66、Http请求-Dio http库
65、通过HttpClient发起HTTP请求
63、自绘实例:圆形背景渐变进度条
62、自绘组件 (CustomPaint与Canvas)
61、组合实例:TurnBox
60、组合现有组件
59、自定义组件方法简介
58、动画过渡组件
57、通用"切换动画"组件(AnimatedSwitcher)
56、交织动画
55、Hero动画
54、自定义路由切换动画
53、动画基本结构及状态监听
51、动画
50、通知(Notification)
49、全局事件总线
48、手势识别
47、原始指针事件处理
46、事件处理与通知
45、对话框详解
44、异步UI更新(FutureBuilder、StreamBuilder)
43、颜色和主题
42、跨组件状态共享(Provider)
41、数据共享(InheritedWidget)
40、导航返回拦截(WillPopScope)
39、功能型Widget简介
38、滚动监听及控制
37、CustomScrollView
36、GridView
35、ListView
34、SingleChildScrollView
33、可滚动组件简介
32、剪裁(Clip)
31、Scaffold、TabBar、底部导航
30、Container
29、变换(Transform)
28、装饰容器DecoratedBox
27、尺寸限制类容器
26、填充(Padding)
25、容器类Widget
24、对齐与相对定位(Align)
23、层叠布局 Stack、Positioned
22、流式布局
21、弹性布局(Flex)
20、线性布局(Row和Column)
19、布局类组件简介
18、进度指示器
17、输入框及表单
16、单选开关和复选框
15、图片及ICON
14、按钮
13、文本、字体样式
12、状态管理
11、Widget简介
10、Flutter异常捕获
9、调试Flutter应用
8、资源管理
7、包管理
6、路由管理
5、第一个Flutter应该:计数器应用示例
4、Dart语言简介
3、搭建Flutter开发环境
2、初识Flutter
1、移动开发技术简介
60、组合现有组件
资源编号:76212
Flutter实战
书籍
热度:93
在Flutter中页面UI通常都是由一些低阶别的组件组合而成,当我们需要封装一些通用组件时,应该首先考虑是否可以通过组合其它组件来实现,如果可以,则应优先使用组合,因为直接通过现有组件拼装会非常简单、灵活、高效。
在Flutter中页面UI通常都是由一些低阶别的组件组合而成,当我们需要封装一些通用组件时,应该首先考虑是否可以通过组合其它组件来实现,如果可以,则应优先使用组合,因为直接通过现有组件拼装会非常简单、灵活、高效。 # 示例:自定义渐变按钮 Flutter Material组件库中的按钮默认不支持渐变背景,为了实现渐变背景按钮,我们自定义一个GradientButton组件,它需要支持一下功能: * 背景支持渐变色 * 手指按下时有涟漪效果 * 可以支持圆角 我们先来看看最终要实现的效果(图10-1):  我们DecoratedBox可以支持背景色渐变和圆角,InkWell在手指按下有涟漪效果,所以我们可以通过组合DecoratedBox和InkWell来实现GradientButton,代码如下: ``` import 'package:flutter/material.dart'; class GradientButton extends StatelessWidget { GradientButton({ this.colors, this.width, this.height, this.onPressed, this.borderRadius, @required this.child, }); // 渐变色数组 final List
colors; // 按钮宽高 final double width; final double height; final Widget child; final BorderRadius borderRadius; //点击回调 final GestureTapCallback onPressed; @override Widget build(BuildContext context) { ThemeData theme = Theme.of(context); //确保colors数组不空 List
_colors = colors ?? [theme.primaryColor, theme.primaryColorDark ?? theme.primaryColor]; return DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient(colors: _colors), borderRadius: borderRadius, ), child: Material( type: MaterialType.transparency, child: InkWell( splashColor: _colors.last, highlightColor: Colors.transparent, borderRadius: borderRadius, onTap: onPressed, child: ConstrainedBox( constraints: BoxConstraints.tightFor(height: height, width: width), child: Center( child: Padding( padding: const EdgeInsets.all(8.0), child: DefaultTextStyle( style: TextStyle(fontWeight: FontWeight.bold), child: child, ), ), ), ), ), ), ); } } ``` 可以看到GradientButton是由DecoratedBox、Padding、Center、InkWell等组件组合而成。当然上面的代码只是一个示例,作为一个按钮它还并不完整,比如没有禁用状态,读者可以根据实际需要来完善。 # 使用GradientButton ``` import 'package:flutter/material.dart'; import '../widgets/index.dart'; class GradientButtonRoute extends StatefulWidget { @override _GradientButtonRouteState createState() => _GradientButtonRouteState(); } class _GradientButtonRouteState extends State
{ @override Widget build(BuildContext context) { return Container( child: Column( children:
[ GradientButton( colors: [Colors.orange, Colors.red], height: 50.0, child: Text("Submit"), onPressed: onTap, ), GradientButton( height: 50.0, colors: [Colors.lightGreen, Colors.green[700]], child: Text("Submit"), onPressed: onTap, ), GradientButton( height: 50.0, colors: [Colors.lightBlue[300], Colors.blueAccent], child: Text("Submit"), onPressed: onTap, ), ], ), ); } onTap() { print("button click"); } } ``` # 总结 通过组合的方式定义组件和我们之前写界面并无差异,不过在抽离出单独的组件时我们要考虑代码规范性,如必要参数要用@required 标注,对于可选参数在特定场景需要判空或设置默认值等。这是由于使用者大多时候可能不了解组件的内部细节,所以为了保证代码健壮性,我们需要在用户错误地使用组件时能够兼容或报错提示(使用assert断言函数)。