flutter 开发踩坑集

本文围绕Flutter开发展开,涵盖TextField文字居中、界面适配错乱、键盘处理、流合并、版本升级报错等多个常见问题,并针对每个问题给出了相应的解决方案,如设置decoration属性解决文字居中问题,调整代码位置解决界面适配问题等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、 TextField设置高度后,文字无法居中

解决方案:

TextField(
        style: TextStyle(
        ),
        decoration: InputDecoration(
          prefixIcon: ImageUtils.getImage("search")/*Icon(Icons.search)*/,
          hintText: widget.hint,
          fillColor: Color(0xfff1f1f2),
          contentPadding: EdgeInsets.all(0),//设置输入内容垂直居中
          border: OutlineInputBorder(
            borderSide: BorderSide.none,
//              borderRadius: BorderRadius.circular(20)
          ),
        ),
      )
  1. 设置decoration属性,在InputDecoration中设置contentPadding: EdgeInsets.all(0),
  2. 在InputDecoration中设置border属性,不能直接设置InputBorder.none,否则还是不能居中。

二、项目使用window.physicalSize和设定尺寸作比来做适配,奇怪的某些界面偶现的错乱问题

解决方案:(我的是由于项目中使用了隐藏导航栏await SystemChrome.setEnabledSystemUIOverlays([]);的原因,可能还有其他的因素会影响到window.physicalSize的获取计算问题),

void main() async {
  return SentryUtil.wrap(() async {
    WidgetsFlutterBinding.ensureInitialized();
    await SystemChrome.setPreferredOrientations(
        [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
    if (Platform.isIOS) {
      await ScreenRotationiOS.changeScreenOrientation(
          DeviceOrientationMask.Landscape);
    }
    Devices.init(width: 1080, height: 810);
    runApp(MyApp(
      appRoutes: routes,
      home: HomeScreen(),
    ));
    //这个需要放置在runApp后,不影响项目内部的window.physicalSize的获取
    await SystemChrome.setEnabledSystemUIOverlays([]);
  }, dsn: kDebugMode ? null : sentryDsn);
}

 //这个需要放置在runApp后,不影响项目内部的window.physicalSize的获取
    await SystemChrome.setEnabledSystemUIOverlays([]);

三、点击空白触发取消键盘

FocusScope.of(context).requestFocus(FocusNode());

四、软键盘把界面底部顶起,不让界面底部自动升起

Scaffold(
        resizeToAvoidBottomPadding: false,
        )

五、合并多个流做为一个stream

//yaml引入依赖 async 
//使用StreamGroup.merge()
StreamBuilder(
            stream: StreamGroup.merge(_streams),
            builder:....,)

六、flutter在用??的时候要小心,

 下面这两个结果返回是不一样的哦,只有dataValue是null或者0的时候返回结果才是一样的!!

(dataValue ?? 0 / 60)
//和
((dataValue ?? 0) / 60)

七、base64转为图片保存本地或者转为unit8list

class FileUtil {
 
  static Future<String> createFileFromString(String base64Str) async {
    Uint8List bytes = base64.decode(base64Str);
    String dir = (await getApplicationDocumentsDirectory()).path;
    File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + ".png");
    await file.writeAsBytes(bytes);
    return file.path;
  }
 
}

八、flutter之前的版本是2.2.3,升级到下一版本2.5.0之后出现之前的textfield基本组件使用报错异常问题:以及对应的修改调整如下:

 九、clipper参数定义裁剪规则说明

十、多级for循环,里面的beak打破的是最小的for循环么?还是所有的for循环。

十一、Flutter路由里面用routename相同的两个,不相邻。进入和退出第二个相同routename的页面路由记录和页面显示如何?

 home ->MultiPageOne->MultiPageTwo(1)->MultiPageThree->MultiPageTwo(2)->MultiPageFour

1.返回到MultiPageTwo(2)可以pop,可以poputil通过之前的路由跳转的route.settings.name == MultiPageTwo.routeName。

Navigator.popUntil(context, (route) {
            return route.settings.name == MultiPageTwo.routeName;
          }),

2.返回到MultiPageTwo(1),还需要通过前面的settings.arguments参数加上做限制。

Navigator.popUntil(context, (route) {
            
            return route.settings.name == MultiPageTwo.routeName &&
                route.settings.arguments == MultiPageOne.routeName;
          })

十二、Border是在container的外层还是在内层,还是一半内层一般外层。

Container(
                width: 60,
                height: 60,
                color: Colors.red,
                clipBehavior: Clip.none,
                alignment: Alignment.center,
                child: Container(
                  width: 56,
                  height: 56,
                  clipBehavior: Clip.none,
                  decoration: BoxDecoration(
                    border: Border.all(
                        width: 10, color: Colors.orange.withOpacity(0.5)),
                    color: Colors.cyan.withOpacity(0.5),
                  ),
                ),
              )

看结果是在container的内层

十三、 flutter执行帧动画,使用Image.asset(),来加载(尤其是资源多或者大的图片),动画卡顿。

可使用Image(),通过ImageProvider来将资源提前加入的方式操作,可解。

 AnimatedBuilder(
                  animation: controller.xingxAnimation,
                  builder: (context, child) {
                    var index = controller.xingxAnimation.value.round();
                    return Image(
//controller.girlImagesProviders是帧动画的所有图片的ImageProvider的数组,
                      image: controller.girlImagesProviders[index],
                      width: 306.ratio,
                      height: 396.ratio,
//gaplessPlayback默认false,设置为true,可避免切换加载间的闪动(加载中的显示模式)
                      gaplessPlayback: true,
                    );
                  },
                ),

十四、column中第一行有一个tab选择器,结果在iOS设备上面无法点击。下面的其他元素可以点击,查看图层没有遮挡,手势也正确使用。

经查看,发现是最外层页面根布局为Scaffold,其中加载的列表根布局也是Scaffold,导致了这个问题的出现。(解决方法:删除子元素的scaffold使用)

保证Scaffold仅在最外层,避免嵌套。

根本原因scaffold内部根据平台时iOS和macos有一个手势丢弃处理:

所以解决方案可以有三种:

1.在父组件外面套一层SafeArea(这样顶部会有边距,不是我想要的)

2.子组件不使用Scaffold(但同时也会失去floatbutton属性)

3.子组件Scaffold外层套一个MediaQuery.removePadding,把顶部空间移除掉

MediaQuery.removePadding(
  context: context,
  removeTop: true,
  child: Scaffold(
    backgroundColor: Colors.white,
    floatingActionButton: _floatingBtn(),
    body: _initSubviews(),
  ),
)

十五、

### 关于 'cache-loader' 模块未找到的解决方案 当遇到 `Syntax Error: Error: Cannot find module 'cache-loader'` 错误时,通常是因为某些依赖项未能正确安装或存在版本兼容性问题。以下是针对该问题的具体分析和解决方法: #### 1. 删除现有依赖并重新安装 由于部分依赖可能未完全下载或配置失败,建议清理当前环境中的依赖文件,并重新执行安装操作。 - **删除旧依赖** 进入项目根目录,运行以下命令以移除现有的 `node_modules` 文件夹以及锁定文件: ```bash rm -rf node_modules package-lock.json ``` - **重新安装依赖** 使用以下命令重新拉取所有必要的模块: ```bash npm install ``` 此过程会依据 `package.json` 配置自动解析所需依赖关系[^3]。 #### 2. 处理高版本 Node.js 和 NPM 的兼容性问题 如果使用的 Node.js 或 NPM 版本较高,则可能会触发上游依赖冲突的情况。此时可以通过指定参数来忽略此类警告并强制完成安装流程。 - 执行带选项的安装指令: ```bash npm install --legacy-peer-deps ``` 上述命令能够有效规避因新策略引入而导致的部分历史遗留库无法匹配的问题[^4]。 #### 3. 明确目标加载器及其关联插件的状态 确认是否遗漏了其他间接影响到构建链路的关键组件(例如 `sass-loader`, `style-loader`)。对于特定场景下的样式表预处理工具缺失情况也需要同步关注[^1]。 通过上述措施基本可以消除由缓存机制引发的相关异常状况;当然,在实际开发过程中还应定期更新全局管理软件至最新稳定版次从而减少不必要的麻烦发生几率。 ```javascript // 示例代码片段展示如何验证已修复后的服务端渲染功能是否恢复正常工作状态。 const express = require('express'); const path = require('path'); let app = express(); app.use(express.static(path.join(__dirname, './dist'))); app.listen(8080,function(){ console.log("Server is running on port 8080..."); }); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值