拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Flutter OHOS 渲染引擎与UI相关问题

渲染引擎切换指导PlatformView 同层渲染方案适配切换指导flutter inappwebview 设置高度后网页内容被拉伸问题分析目前 OS 原生 web 画布限制范围是在 2400 以下超过 2400 的高度原生 web 无法加载解决方案将 px 类型的参数转换为 dp 类型class_MyHomePageStateextendsStateMyHomePage{ double _height 10.0; void _changeHeight(double newHeight) { setState(() { double devicePixelRatio MediaQuery.of(context).devicePixelRatio; _height newHeight / devicePixelRatio; }); }overrideWidgetbuild(BuildContextcontext) { ...Tab组件TabBar/TabBarView使用注意事项手势冲突TabBarTabBarView是 Flutter 中常用的选项卡切换组件。TabBarView内部使用PageView实现页面切换当它与其它水平滚动手势或系统返回手势处于同一手势竞技场GestureArena时由于手势方向相同竞技场难以区分胜出者容易产生手势冲突。以下列举几个常见场景及规避方案。1. TabBarView 内嵌横向滚动组件WebView/PageView/ListView/CarouselView问题现象将WebView、PageView、横向ListView或CarouselView等横向滚动组件直接放在TabBarView的子页面中时内层组件无法正常横向滑动手势被外层TabBarView抢占或两者滑动相互干扰。问题分析TabBarView与内层横向滚动组件都会向手势竞技场GestureArena注册HorizontalDragGestureRecognizer由于两者手势方向相同竞技场无法仅凭方向区分胜出者导致外层TabBarView总是赢得手势内层组件收不到拖拽事件。这是 Flutter 框架本身的已知问题参见flutter/flutter#84238。解决方案当内层组件自身不需要横向切换 Tab 时给TabBarView设置NeverScrollableScrollPhysics()让手势交由内层组件处理仅通过点击TabBar切换TabBarView( physics: const NeverScrollableScrollPhysics(), controller: _tabController, children: [//WebView/ PageView /横向 ListView 等 ], )若希望外层与内层都能滑动可使用PageView的PageScrollPhysics配合内层ScrollController判断是否到达边界再决定将手势让给外层也可借助Listener/RawGestureDetector自定义手势识别器按边界条件分发手势。2. TabBarView 滑动切换与系统侧滑返回手势冲突问题现象在TabBarView中左右滑动切换页面时从屏幕边缘起滑会触发系统的侧滑返回手势导致页面被意外返回或在TabBarView区域内滑动时角度稍有倾斜就被系统判定为返回手势。问题分析TabBarView的横向拖拽手势与系统侧滑返回手势方向一致均为横向当手指起滑点靠近屏幕边缘时系统返回手势优先级较高会与TabBarView的滑动切换产生竞争。例如在 Flutter Web 端表现为水平滑动角度不“完美水平”即触发浏览器返回参见flutter/flutter#152588。解决方案优先使用点击TabBar切换页面避免依赖TabBarView的边缘横向滑动如确需滑动切换可给TabBarView设置NeverScrollableScrollPhysics()关闭横向滑动仅保留点击切换。若需同时保留滑动切换可在页面非边缘区域引导用户操作或在TabBarView外层通过Listener监听起滑点position.dx对靠近边缘的横向手势做拦截处理。3. TabBarView 与 PageView 嵌套问题现象TabBarView嵌套在PageView中或PageView嵌套在TabBarView中时两层横向翻页手势相互争抢难以流畅地分别翻动外层和内层。问题分析TabBarView本质是受限的PageView两层PageView同为横向手势竞技场无法稳定区分导致手势在两层之间抖动或只响应其中一层。解决方案通常只保留一层横向翻页外层用TabBarView时内层PageView设置NeverScrollableScrollPhysics()反之亦然。若必须双层都滑动可使用自定义ScrollPhysics或监听内层ScrollController的边界在内层到达边界时将手势让给外层类似实现可参考社区中nested_page_view等方案。小结上述手势冲突多源于横向手势方向相同导致竞技场无法区分。建议优先采用点击TabBar切换 内层组件单独处理横向滚动的组合必要时通过physics或自定义手势识别器明确手势归属以获得稳定的手势体验。Flutter 项目如何适配折叠屏手机和折叠屏折叠态应用需要适配竖屏布局。仅部分特殊场景例如横屏游戏、长视频需要适配横屏布局。当设备尺寸比例接近1:1时建议横竖屏使用相同或相近的布局当设备尺寸比例差异大时横竖屏可以使用不同的布局从而提供更好的使用体验。对于挖孔区的适配需要考虑核心内容或重要交互不要被挖孔区遮挡。如果被遮挡则应进行局部内容等避让可滚动内容无需专门避让挖孔区。要避免因为避让挖孔导致左右侧留白不一致。在多端设备上长视频、直播、会议、通话等场景下支持画中画功能。卡片广告在宽屏设备上建议使用延伸布局和形变进行响应式适配。针对折叠屏悬停态即用户可以将产品半折后立在桌面上中间弯折区域难以操作且显示内容会变形因此建议页面内容进行折痕区避让适配。建议上半屏内容由中线向上避让16vp3毫米、下半屏内容由中线向下避让40vp7毫米。这些是折叠屏设计的主要方案概述。可参考多设备响应式设计折叠屏UX体验判断折叠状态一多开发通过 windowSizeChange 来监听高度折叠屏悬停态FolderStack设置启动页后加载 Flutter 页面出现闪动问题现象开发者在设置启动页后加载 Flutter 页面时出现闪动效果希望避免这种情况。问题分析闪屏页背景图片采用异步加载应用启动时图片尚未就绪导致启动页到 Flutter 页面切换时出现闪动。解决方案在ohos/entry/src/main/ets/pages/Index.ets文件的componentBuilder中为每个Image组件添加.syncLoad(true)使图片同步加载避免闪动。EntryComponentstruct Index {// ...BuildercomponentBuilder() {// 启动页中的每个 Image 均添加 syncLoad(true)Image($r(app.media.start_icon)).syncLoad(true).width(100%).height(100%) }// ...}注意.syncLoad(true)会在 UI 主线程同步解码图片阻塞渲染直至解码完成。适用于启动页等少量、小尺寸图片场景。若启动图较大或图片数量较多可能导致启动明显卡顿甚至 ANR。此时建议优先压缩图片资源或将图片放在rawfile目录并提前预加载也可考虑使用PixelMap预解码后再展示。确保引用的图片资源确实存在且路径正确syncLoad(true)同步加载时若资源不存在将直接导致应用崩溃不会像异步加载那样仅显示空白。可参考Image 组件 syncLoad 属性说明鸿蒙端使用 flutter_svg 渲染 SVG 时出现锯齿问题现象鸿蒙端使用 Impeller 渲染 SVG 时图形的圆弧或斜线边缘可能出现锯齿使用flutter_svg的colorFilter属性修改 SVG 颜色时该现象可能更加明显。问题分析鸿蒙端当前全局开启 2x MSAA多重采样抗锯齿所有使用 MSAA 的渲染内容都会采用 2 倍采样。相较于 4x MSAA2x MSAA 的采样数更少因此部分 SVG 的圆弧或斜线边缘可能不够平滑。若全局开启 4x MSAA会增加 GPU 的采样和渲染负载在部分机型上可能导致性能下降、画面卡顿、功耗升高或设备发热因此鸿蒙端采用 2x MSAA以平衡显示效果、性能和功耗。解决方案推荐使用RenderingStrategy.raster以目标显示尺寸的 2 倍宽高栅格化 SVG再通过外层组件将图片缩放到目标尺寸。例如WidgetbuildSvg(StringassetName,doublesize){returnSizedBox( width: size, height: size, child:FittedBox( fit: BoxFit.contain, child: SvgPicture.asset( assetName, width: size *2, height: size *2, renderingStrategy: RenderingStrategy.raster, ), ), ); }该方案可以增加边缘像素的取色层级减小平均取色偏差从而减弱锯齿。由于会生成分辨率更高的栅格图可能增加内存占用和栅格化开销建议仅对存在明显锯齿的 SVG 使用并结合实际机型验证性能。也可以根据业务场景采用以下方案切换使用 Skia。在 SVG 文件中预先设置颜色避免通过flutter_svg的colorFilter属性修改颜色。SVG 描边相关说明可参考SVG Stroke 属性。物理键盘 Numlock、Capslock、ScrollLock 暂不支持当前版本暂不支持。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门