Flutter Tips

总结flutter开发中遇到的问题,持续更新中...

溢出的解决方法

  1. 使用Column包裹在SingleChildScrollView
    SingleChildScrollView(
      child: Column(children: children),
    )
  1. 改成 ListView
    ListView(
      children: children
    )
  1. 使用两者的组合Column和ListView时,使用Expanded或者给ListView一个固定高度
    Column(
      children: [
        ...children.take(2).toList(), // show first 2 children in Column
        Expanded(
          child: ListView(
            children: children.getRange(3, children.length).toList(),
          ), // And rest of them in ListView
        ),
      ],
    )

动画

Flutter 中缩放、旋转、透明渐变动画的 API 如下:

缩放动画
ScaleTransition:可以将 Widget 平滑地缩放。
AnimatedContainer:可以平滑地调整 Widget 的大小。
旋转动画
RotationTransition:可以将 Widget 平滑地旋转。
透明渐变动画
FadeTransition:可以将 Widget 平滑地改变透明度。
AnimatedOpacity:可以平滑地调整 Widget 的透明度。

flutter自己的代码打开错乱
把.idea删掉、对应错误的文件本地打开,然后删掉,或者用flutter SDK重新替换

FlutterEngineGroup

FlutterEngineGroup 加快首次渲染的速度、还能降低内存占用

FlutterEngineGroup 是 Flutter 框架提供的一个类,用于管理多个 Flutter 引擎的组合。它提供了引擎的创建和销毁、引擎之间的通信、引擎的生命周期管理、资源共享和多引擎的并发执行等功能。通过 FlutterEngineGroup,可以灵活地管理和控制多个 Flutter 页面的运行和交互。

共享资源:FlutterEngineGroup 允许多个 Flutter 引擎共享一些资源,如字体、图像等。通过资源的共享,可以避免多次加载相同的资源,从而减少内存占用。

引擎的生命周期管理:通过 FlutterEngineGroup,可以灵活地管理引擎的生命周期,包括启动引擎、暂停和恢复引擎等。合理管理引擎的生命周期可以在不需要时释放资源,从而减少内存占用。

dialog 高度自适应

unknown_filename.6

Flexible 可以让textview换行

flutter可以分架构打包
flutter build apk --obfuscate --split-debug-info debuginfo --target-platform android-arm,android-arm64,android-x64 --split-per-abi

键盘弹出overflowed:放这个
Scaffold(  resizeToAvoidBottomInset: false,
这样在键盘弹出时将不会resize

Expanded 仅应在 Row,Column 或者 Flex 使用,检查代码.必须是直接的子类

  • 使用 Flutter Web 目前不适合Web ,对于具有大量密集文本的静态网页,传统的 Web 开发方法支持更快的加载时间和更容易维护。 webdev

Flutter Inspector 不显示解决

https://stackoverflow.com/questions/64725383/flutter-inspector-stuck-on-installing-dev-tools/65542661#65542661

LayoutBuilder

一个 text 的右边和另一个 text 的左边对齐, 另一个 text 宽度还不固定,这两个 widget 不在同一行,是上下两行

使用LayoutBuilder控件来获取第一个Text控件的宽度,并使用这个宽度来设置第二个Text控件的位置

Column(
  children: [
    Row(
      children: [
        Text('Left Text'),
      ],
    ),
    LayoutBuilder(
      builder: (context, constraints) {
        final leftTextWidth =
            (TextPainter(text: TextSpan(text: 'Left Text'), maxLines: 1, textDirection: TextDirection.ltr)..layout()).width;
        return Row(
          children: [
            SizedBox(width: leftTextWidth),
            Text('Right Text'),
          ],
        );
      },
    ),
  ],
),

约束

flutter 布局规则
首先,上层 widget 向下层 widget 传递约束条件
然后,下层 widget 向上层 widget 传递大小信息
最后,上层 widget 决定下层 widget 的位置。

ConstrainedBox

ConstrainedBox: 对子组件添加额外的约束。例如,如果你想让子组件的最小高度是80像素
UnconstrainedBox: 不会对子组件产生任何限制,它允许其子组件按照其本身大小绘制, 一般用来去掉父约束

在 Flutter 中,Container 的大小通常由其父组件和子组件共同决定。如果 Container 没有父组件,或者它的父组件没有提供足够的约束,那么 Container 会尽可能地大。这就是为什么你看到的 Container 占据了整个屏幕。

如果你想让 Container 的大小为特定的值,你需要确保它的父组件提供了足够的约束。例如,你可以将 Container 放在一个 Center 组件中,这样 Container 就会被约束在屏幕中心,而不是占据整个屏幕。

Align

Column控件外层包裹一层Align控件,是为了让 Column 控件的高度仅包裹其子控件的高度,而不是填充整个屏幕。Align 控件可以将其子控件对齐到指定位置,并根据子控件的大小来调整自身的大小。当您将 Align 控件的 alignment 属性设置为Alignment. topCenter时,它会将其子控件垂直居中对齐到顶部,并根据子控件的高度来调整自身的高度。度。度。度。。
如果您希望让 Column 控件填充整个屏幕,那么您可以不使用 Align 控件,直接将 Column 控件作为 Container 控件的子控件即可。

unknown_filename.7

Draggable文章

http://events.jianshu.io/p/4b4be9eef65c

https://blog.csdn.net/du591310450/article/details/89845157

https://blog.csdn.net/weixin_52262025/article/details/123618314,用的这个

角度转弧度 π/180×角度
弧度变角度 180/π×弧度
1度=π/180≈0.01745弧度,1弧度=180/π≈57.3度。

计算重叠区域面积

https://leetcode.cn/problems/rectangle-area/solution/223-ju-xing-mian-ji-3xing-dai-ma-by-acw_weian/

UI

  • CarDialog 、TaxiSuperRuleDialog示例
  • SingleChildScrollView 可以滚动,如果SingleChildScrollView嵌套SingleChildScrollView,第二SingleChildScrollView需要加个Expanded
  • 有问题的时候可以试试Expanded
  • Expanded 平分加三个Expanded
  • Scaffold(  resizeToAvoidBottomInset: true,) 可以把布局顶上去,不会被输入法遮盖
  • Text.rich(TextSpan 一个textviwe不同颜色大小
    RichText(text: TextSpan(
                    children: [
                       TextSpan(
                         text:"*",
                         style: TextStyle(color: JCColor.colorAuxRedColor, fontSize: 15)
                       ),
                      TextSpan(
                          text:"费用归属",
                          style: TextStyle(color: JCColor.colorText222Color, fontSize: 15)
                      )
                    ]
                )),
    
  • alignment: Alignment.centerLeft, 左对齐
  • row 水平居中 mainAxisAlignment:MainAxisAlignment.spaceBetween

    enum MainAxisAlignment {
     //将子控件放在主轴的开始位置
      start,  
       //将子控件放在主轴的结束位置
      end,
      //将子控件放在主轴的中间位置
      center,
      //将主轴空白位置进行均分,排列子元素,手尾没有空隙
      spaceBetween,
      //将主轴空白区域均分,使中间各个子控件间距相等,首尾子控件间距为中间子控件间距的一半
      spaceAround,
      //将主轴空白区域均分,使各个子控件间距相等
      spaceEvenly,
    }
  • Row mainAxisSize: MainAxisSize.min,//wrap_content ,不加的话默认为match_parent(MainAxisSize.max)
  • Column mainAxisAlignment: MainAxisAlignment.center,

unknown_filename

listview嵌套listview

    child: ListView.separated(
                          shrinkWrap: true,
                          physics: NeverScrollableScrollPhysics(),  //list嵌套listview
                          itemCount: logic.architectureList?.length ?? 0,
                          itemBuilder: (context, index) =>
                              _buildItem(logic.architectureList?[index]),
                          separatorBuilder: (context, index) => Divider(height: .0),
                        ));
    

ListView.separated 有分割线


     Visibility(
       visible: true,
       //是否保持占位
       maintainState: false,
       child: Text("显示"),
     ),
    

弹窗

      showModalBottomSheet(
                            shape: const RoundedRectangleBorder(
                                borderRadius: BorderRadius.only(
                                    topLeft: Radius.circular(16),
                                    topRight: Radius.circular(16))),
                            context: context,
                            builder: (BuildContext context) {
                              return AirTicketRuleDialog();
                            });
  • Spacer其实就是包装了一个 Expanded 的 SizedBox. 我们可以通过它灵活控制 Row/Column。 Spacer(flex: 2), // 弹性系数为2
  • 返回键
    WillPopScope(
                  child: this,
                  onWillPop: () async {
                    return Future.value(false);
                  });
  • 这种布局
    unknown_filename.1

       Row(children: [
                const SizedBox(width: 32),
                Expanded(
                  child: Text(
                    '退改行李规定',
                    textAlign: TextAlign.center,
                ),
                InkWell(    ]),
    
  • MediaQuery.removePadding 可以移除组件的边距,有些组件自带有边距,

动画

在使用Flutter动画的时候,我们通常使用这几个组件.
AnimationController,控制动画的抽象类
Animation,给定值,转换为动画
Tween, 执行范围
AnimatedBuilder, 处理动画的Widget
Transform控件可以将动画执行中的变量值处理反馈在子控件上.

https://github.com/dlgchg/animations_flutter

刷新

  • flutter 同一个页面在重新打开,啥也不做。。需要关闭、
  • eventbus
  • then back
  • 在onresume里刷新
  • find原来的logic,调用他的方法

Android二次进入同一Flutter页面,Flutter没有刷新
Flutter页面使用StatefulWidget组件,并重写didUpdateWidget()。

技巧

expenand 必须和colum或row一起用,否则debug能运行,release报错。
flutter run --release 这样运行,正式版也可以看日志

dio抓包

        dio = Dio(options);
        (dio?.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
            (HttpClient client) {
          client.findProxy = (uri) {
            return 'PROXY 172.16.60.122:8888';
          };
        };
    

普通路由 :直接跳转页面
命名路由:给路由起名字Navigator.of(context).pushNamed("/search");
unknown_filename.5

通知栏高度

final dynamic padding = MediaQuery.of(context).padding;
padding: EdgeInsets.only(top: padding.top),

cancelTap
传接口时不要当成方法,要不然直接调用

日志过滤

防止tab每次都刷新
AutomaticKeepAliveClientMixin

修改minSdkVersion

由于 Flutter 3.13 及更高版本的更改而更新的响应

在此版本中,此文件_flutter-directory/packages/flutter_tools/gradle/flutter.gradle的内容已移至此新位置flutter-directory/packages/flutter_tools/gradle/src/main/groovy/flutter.groovy_。和默认的minSdkVersion = 19. 但为了安全地使用最新的软件包和 Android 设备,最好将其设置为minSdkVersion = 20.

posted @ 2022-03-02 11:25  梦和远方  阅读(236)  评论(0编辑  收藏  举报