Flutter开发3:UI功能控件集合

2022-05-05  本文已影响0人  十二栗子

一、SafeArea

用于在屏幕安全区中显示布局。当我们没有使用Scaffold或未设置AppBar时,页面的布局会伸展到系统状态栏下,如果我们不需要这种沉浸式状态栏效果,那么就可以使用SafeArea跳过状态栏区域(包括底部导航栏)。
用法就是,用SafeArea包裹展示容器

SafeArea(
        child: Container()
)

二、显示与隐藏

Visibility 属性

属性名 类型 简介
replacement Widget 不可见时显示的控件,仅当maintainState为false时有效
visible bool 子控件是否可见
maintainState bool 不可见时是否维持状态
maintainAnimation bool 不可见时是否维持子控件动画
maintainSize bool 不可见时是否保留空间
maintainInteractivity bool 不可见时是否保留交互性
 Wrap(
              children: [
                Offstage(offstage: true, child: TextButton(onPressed: (){}, child: const Text('社会心理学'))),
                Visibility(visible: false, child: TextButton(onPressed: (){}, child: const Text('发展心理学'))),
                TextButton(onPressed: (){}, child: const Text('变态心理学')),
                TextButton(onPressed: (){}, child: const Text('健康心理学')),
                TextButton(onPressed: (){}, child: const Text('咨询心理学')),
              ],
            ),

三、裁剪

//剪裁为内切椭圆
ClipOval(
              child: Image.asset('assets/img/nezha1.jpeg'),
            ),
//剪裁为圆角矩形
ClipRRect(borderRadius: BorderRadius.circular(15),child: Image.asset('assets/img/nezha1.jpeg'),),
            const SizedBox(height: 10,),

//圆形头像
const Center(
              child: CircleAvatar(
                backgroundImage: NetworkImage(
                    'https://c-ssl.duitang.com/uploads/item/201810/07/20181007131933_qhjkl.thumb.1000_0.jpg'),
                maxRadius: 100,
              ),
            ),
            const SizedBox(height: 10,),

//昵称头像
const Center(
              child: CircleAvatar(
                child: Text('洋哥'),
                backgroundColor: Colors.blueAccent,
                maxRadius: 30,
              ),
            ),
20220429113053.jpg

路径剪裁

ClipPath(
              clipper: MyClipper(),
              child: Container(
                width: 400,
                height: 300,
                decoration: const BoxDecoration(
                    color: Color(0xff622F74),
                    gradient: LinearGradient(
                        colors: [Colors.red, Colors.yellow],
                        begin: Alignment.centerRight,
                        end: Alignment(-1.0, -1.0))),
              ),
            ),
class MyClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    var path = Path();
    path.lineTo(0, 300);
    path.lineTo(400, 150);
    path.lineTo(400, 0);
    path.close();
    return path;
  }

  @override
  bool shouldReclip(covariant CustomClipper oldClipper) {
    return false;
  }
}
20220429113521.jpg

四、变换 Transform

Transform可以对子控件做一系列变换操作。需要注意的是,它的变换是在绘制阶段进行的,而不是布局(layout)阶段,因此无论对子控件应用何种变换,其占用空间的大小和在屏幕上的位置都是在一开始确定的,不会变化的。

常用变换

命名构造方法如下

平移

  double dx = 0;
  double dy = 0;
Container(
              color: Colors.purpleAccent,
              child: Transform.translate(offset: Offset(dx, dy),
                child: const Text("走么No加油💪🏻"),

              ),
            ),
            TextButton(onPressed: (){
              setState(() {
                dx++;
                dy++;
              });
            }, child: const Text('点我移动')),
            TextButton(onPressed: (){
              setState(() {
                dx--;
                dy--;
              });
            }, child: const Text('点我回位')),

旋转

double PI = 2;
Container(
              color: Colors.yellow,
              child: Transform.rotate(angle:pi/PI,
                child: const Text("看我旋转"),

              ),
            ),
            TextButton(onPressed: (){
              setState(() {
                PI++;
              });
            }, child: const Text('点我旋转')),
            TextButton(onPressed: (){
              setState(() {
                PI--;
              });
            }, child: const Text('点我旋转')),

使用默认构造方法时,transform属性是必传,此时需要使用 Matrix4 类作为 4D 矩阵

import 'package:vector_math/vector_math_64.dart' as v;
Container(
              color: Colors.blue,
              child: Transform(
                transform: Matrix4.translation(v.Vector3(5,5,0)),
                child: const Text('会当凌绝顶,一览众山小'),
              ),
            ),

Matrix4 的常用构造方法

直接使用Matrix4 的命名构造方法还是有些繁琐,还涉及到导入一些数学库,因此真正推荐的写法是使用identity构造方法来初始化一个Matrix4对象,然后调用对应的功能方法,示例如下

Container(
              color: Colors.pinkAccent,
              child: Transform(
                transform: Matrix4.identity()
                  ..translate(5.0,5.0,0.0),
                child: const Text('会当凌绝顶,一览众山小'),
              ),
            ),

通过这种链式调用,在后面连续调用其他变换方法,可同时组合多种变换。
需要注意,斜切变换只能使用命名构造方法实现

Container(
              color: Colors.lightBlue,
              child: Transform(
                transform: Matrix4.skewY(-pi/18),
                child: const Text('会当凌绝顶,一览众山小'),
              ),
            ),

注意,除了直接使用Transform控件,还可以通过设置Container的transform属性来实现同样的变换功能,其用法与Transform相同。

20220429143223.jpg

五、MediaQuery

MediaQuery主要用于查询媒体相关的数据,使用MediaQuery.of(context)可返回一个MediaQueryData类型的数据,通常不会直接将MediaQuery作为一个控件使用,但它也可以作为Widget控件树中的控件使用。

MediaQueryData 的属性
属性名 类型 简介
size Size 获取屏幕宽、高。单位为逻辑像素,非物理像素。物理像素 = size*devicePixelRatio
devicePixelRatio double 设备像素比(密度)。单位逻辑像素对应的物理像素数量
textScaleFactor double 单位逻辑像素的字体像素数,若设为1.5,则放大50%
platformBrightness Brightness 平台当前亮度模式(iOS夜间模式、安卓9以上支持)
viewInsets EdgeInsets 被系统遮挡的部分,通常指键盘。viewInsets.bottom表示键盘的高度
padding EdgeInsets 被系统遮挡的部分,此处指“刘海屏”和安卓底部导航栏高度
viewPadding EdgeInsets 被系统遮挡的部分,独立于padding和viewInsets,通常是全屏
systemGestureInsets EdgeInsets 沿着屏幕边缘的区域,系统在这里消耗某些输入事件,并阻止将这些事件传递给APP。APP应避免将手势检测器定位在系统手势识别的区域内
physicalDepth double 设备的最大深度(主要在Fuchsia系统上设置)
alwaysUse24HourFormat bool 是否是24小时制
accessibleNavigation bool 否使用TalkBack或VoiceOver等辅助功能与程序进行交互
invertColors bool 是否支持颜色反转
highContrast bool 仅iOS 13以上支持。通过“设置”->“辅助功能”->“增加对比度”
disableAnimations bool 平台是否要求尽可能禁用或减少动画
boldText bool 平台是否要求使用粗体
orientation Orientation 是横屏还是竖屏

需要注意,MediaQuery必须在MaterialApp的作用域下使用,即在MaterialApp控件之后使用。

下面是iPhone 12 mini的模拟器打印数据

    // 屏幕大小
    Size mSize = MediaQuery.of(context).size;
    debugPrint(mSize.width.toString()); // 375.0
    debugPrint(mSize.height.toString()); // 812.0

    // 密度
    double mRatio = MediaQuery.of(context).devicePixelRatio;
    debugPrint(mRatio.toString()); // 3.0

    // 设备真实像素
    double width = mSize.width * mRatio;
    double heigth = mSize.height * mRatio;
    debugPrint(width.toString()); // 1125.0
    debugPrint(heigth.toString()); // 2436.0

    //上下边距 (状态栏 和 内置导航键)
    double topPadding = MediaQuery.of(context).padding.top;
    double bottomPadding = MediaQuery.of(context).padding.bottom;
    debugPrint(topPadding.toString()); // 50.0
    debugPrint(bottomPadding.toString()); // 34.0

六、返回拦截 WillPopScope*

Flutter中可以通过WillPopScope来实现返回按钮(iOS上的滑动返回)拦截。

WillPopScope中的onWillPop属性是一个回调函数,当用户点击返回按钮时会被调用(或手势操作)。该回调需要返回一个Future对象,如果返回的Future最终值为false时,则当前路由不出栈(不会返回);最终值为true时,当前路由出栈退出。可以通过这个回调来决定是否退出。

WillPopScope(
        onWillPop: () async {
          if (_lastPressedAt == null ||
              DateTime.now().difference(_lastPressedAt) > Duration(seconds: 1)) {
            //两次点击间隔超过1秒则重新计时
            _lastPressedAt = DateTime.now();
            return false;
          }
          return true;
        },
        child: Container(
          alignment: Alignment.center,
          child: Text("1秒内连续点击两次返回键才退出"),
        )
    );

七、Builder

使用一个闭包来创建Widget。它的主要用途有两个

获取某个控件中的上下文对象(BuildContext)
使用一个函数来构建Widget,这样可以在构建前做一些初始化操作

// 以下局部主题修改不生效,则需要使用Builder获取正确的上下文对象。
MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.orange,
        primaryColor: Colors.orange,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text(
            "Flutter",
            style: TextStyle(color: Theme.of(context).accentColor),
          ),
        ),
        body: Container(
          alignment: Alignment.center,
          child: Theme(
            data: Theme.of(context).copyWith(primaryColor: Colors.red),
            child: Text(
              "测试",
              style: TextStyle(color: Theme.of(context).primaryColor),
            ),
          ),
        ),
      ),
    );

八、模糊处理 BackdropFilter

该控件主要用于模糊处理,它不仅可以处理图片,也可以处理任意的其他控件。但通常不建议使用模糊处理,对渲染性能影响很大。

模糊图层使用 ImageFilter.blur 设置模糊度,一般是在 0.0-10.0 之间,数值越大模糊度越高,超过 10.0 时完全不可见。另外蒙层还需要设置一个色值,通常可使用 withOpacity 方法设置透明度,一般是在 0.0-1.0 之间。

Stack(
              alignment: Alignment.center,
              children: <Widget>[
                SizedBox(
                  width: 300,
                  height: 400,
                  child: Image.network('https://c-ssl.duitang.com/uploads/item/201810/07/20181007131933_qhjkl.thumb.1000_0.jpg'),
                ),
                BackdropFilter(
                  filter: ImageFilter.blur(sigmaX: 2.0,sigmaY: 1.0),
                  child: Center(
                    child: Container(
                      height: 200,
                      width: 100,
                      color: Colors.red.withOpacity(0),
                    ),
                  ),
                )
              ],
            ),

九、截图 RepaintBoundary*

可用于截取当前屏幕的Widget的截图,只需要套在想要截图的控件的外层。如要获取全屏截图,将RepaintBoundary包裹在最外层即可。

十、主题 Theme

Theme 控件为Material APP 定义了主题数据(ThemeData)。在Flutter 中已预定义了一系列的主题,许多控件或部分或全部应用了这些主题,因此当更改了预定义主题后,所有使用了这些主题的Widget也都会发生相应的变化。

Theme 主要描述了应用程序的颜色和排版选择。主题分为两种:

MaterialApp(
    title: title,
    theme: ThemeData(
         primaryColor: Colors.red,
         ///...
    ),
);
// 对于修改主题的控件,使用Theme包裹
Theme(
    data: ThemeData(
        accentColor: Colors.yellow,
        //...
    ),
    child: Text('Hello World'),
);

如需获取主题,可使用如下方式

Container(
    color: Theme.of(context).accentColor,
    chile: Text(
        'Text with a background color',
        style: Theme.of(context).textTheme.title,
    ),
);

有时候我们不想要覆盖所有的主题属性,这时候可以扩展父主题

Theme(
  /// 使用 copyWith 找到并扩展父主题
  data: Theme.of(context).copyWith(accentColor: Colors.yellow),
  child: FloatingActionButton(
    onPressed: null,
    child: Icon(Icons.add),
  ),
);

Flutter 中主要通过ThemeData去保存应用的主题及样式等信息,因此需要重点了解该类的属性。

属性名 类型 简介
brightness Brightness 应用的整体主题亮度(可用于适配夜间模式)
primarySwatch MaterialColor Material 定义的主题颜色样本。它是具有十种颜色阴影的颜色样本
primaryColor Color 主色,决定导航栏颜色
primaryColorBrightness Brightness primaryColor的亮度
primaryColorLight Color primaryColor的较浅版本
primaryColorDark Color primaryColor的较深版本
accentColor Color 小控件的前景色(按钮、文本、覆盖边缘效果等)
accentColorBrightness Brightness accentColor的亮度
canvasColor Color MaterialType.canvas 的默认颜色
scaffoldBackgroundColor Color 为Scaffold下的Material默认色,用于app的背景色
bottomAppBarColor Color bottomAppBarColor的默认颜色
cardColor Color 用在卡片(Card)上的Material的颜色
dividerColor Color Divider和PopupMenuDivider的颜色,也用于ListTile之间、DataTable的行之间等
highlightColor Color 用于溅墨动画或指示菜单被选中时的高亮颜色
splashColor Color 溅墨效果颜色(水波纹)
splashFactory InteractiveInkFeatureFactory 定义InkWall和InkResponse的外观
selectedRowColor Color 高亮选定行的颜色
unselectedWidgetColor Color 用于处于非活动(但已启用)状态的小控件的颜色。例如未选中的复选框
disabledColor Color 禁用状态下小控件的颜色
buttonColor Color RaisedButtons使用的默认填充色
buttonTheme ButtonThemeData 定义按钮部件的默认配置
secondaryHeaderColor Color 选定行时PaginatedDataTable标题的颜色
textSelectionColor Color 文本框(如TextField)中文本被选中的颜色
cursorColor Color 文本框中光标的颜色
textSelectionHandleColor Color 用于调整当前选定文本部分的句柄的颜色
backgroundColor Color 与primaryColor形成对比的颜色,例如用作进度条的剩余部分
dialogBackgroundColor Color Dialog的背景色
indicatorColor Color TabBar中选中的指示器颜色
hintColor Color 用于提示文本或占位符文本的颜色,例如在TextField中
errorColor Color 用于输入验证错误的颜色,例如在TextField中
toggleableActiveColor Color 用于突出显示Switch、Radio和Checkbox等可切换小部件的活动状态的颜色
fontFamily String 字体类型
textTheme TextTheme 与卡片和画布对比的文本颜色
primaryTextTheme TextTheme 与primaryColor形成对比的文本主题
accentTextTheme TextTheme 与accentColor形成对比的文本主题
inputDecorationTheme InputDecorationTheme InputDecorator、TextField和TextFormField的默认InputDecoration值基于此主题
iconTheme IconThemeData 与卡片和画布颜色形成对比的图标主题
primaryIconTheme IconThemeData 与primaryColor形成对比的图标主题
accentIconTheme IconThemeData 与accentColor形成对比的图标主题
sliderTheme SliderThemeData 用于呈现Slider的颜色和形状
tabBarTheme TabBarTheme 用于自定义选项卡指示器的大小、形状和颜色的主题
cardTheme CardTheme Card的颜色和样式
chipTheme ChipThemeData Chip的颜色和样式
platform TargetPlatform 小控件应该适应目标的平台,应该被用来根据平台的约定来样式化UI元素
materialTapTargetSize MaterialTapTargetSize 配置某些Material部件的命中测试大小
pageTransitionsTheme PageTransitionsTheme 每个目标平台的默认MaterialPageRoute转换
appBarTheme AppBarTheme 用于自定义Appbar的颜色、高度、亮度、iconTheme和textTheme的主题
bottomAppBarTheme BottomAppBarTheme 自定义BottomAppBar的形状、高度和颜色的主题
colorScheme ColorScheme 一组13种颜色,可用于配置大多数组件的颜色属性
dialogTheme DialogTheme 自定义Dialog的主题形状
typography Typography 用于配置TextTheme、primaryTextTheme和accentTextTheme的颜色和几何文本主题值
cupertinoOverrideTheme CupertinoThemeData 用来覆盖Cupertino主题的样式
/// 判断当前是否是夜间模式
bool isDarkMode(BuildContext context){
    return Theme.of(context).brightness == Brightness.dark;
}

十一、异步 UI*

1.FutureBuilder
2.StreamBuilder

上一篇下一篇

猜你喜欢

热点阅读