Flutter技术问题:如何实现组件间响应式曲线路径避免缩放重叠
Flutter 故事时间线曲线路径适配问题
问题概述
我需要在Flutter项目中实现组件间的故事时间线曲线路径,目前已成功绘制曲线路径,但页面缩放(尺寸变化)时,路径会移位并与组件重叠。
效果说明
- 目标效果:曲线路径始终精准连接对应组件,页面缩放/尺寸变化时保持相对位置,不会出现错位或重叠
- 当前效果:曲线路径已绘制完成,但页面缩放时会偏离预设位置,与相邻组件重叠
- 缩放问题:调整页面尺寸后,路径的位置和比例无法适配新的页面布局,导致与组件错位
已尝试方案
- 使用Figma导出的图片做定位,同样出现缩放移位问题
- 更倾向于代码实现曲线路径,方便后续修改维护
当前实现代码
import 'dart:math'; import 'package:flutter/material.dart'; import 'package:sales_pitch/views/1.dart'; import 'package:sales_pitch/views/2.dart'; import 'package:sales_pitch/views/4.dart'; import 'package:sales_pitch/views/5.dart'; import 'package:sales_pitch/views/6.dart'; import 'package:sales_pitch/views/landing.dart'; import 'package:sales_pitch/widgets/curved_painter.dart'; import '../constants/assets.dart'; import '3.dart'; class HomeView extends StatefulWidget { const HomeView({super.key}); @override State<HomeView> createState() => _HomeViewState(); } class _HomeViewState extends State<HomeView> { @override Widget build(BuildContext context) { var size = MediaQuery.of(context).size; List<Widget> sections = [ const LandingView(), const FirstView(), const SecondView(), const ThirdView(), const FourthView(), const FifthView(), const SixthView(), const SizedBox(height: 250), ]; //* 曾尝试用定位图片,但同样会移位打乱布局 List<Widget> lines = [ Positioned( top: size.height * 0.95, left: 0, right: 0, child: Align( alignment: Alignment.bottomCenter, child: SizedBox( width: size.width * 0.18, child: Image.asset( AppAssets.getAppPath(1), fit: BoxFit.fitWidth, ), ), ), ), Positioned( top: size.height * 1.42, left: size.width * 0.2, child: Align( alignment: Alignment.centerLeft, child: SizedBox( width: size.width * 0.3, child: Image.asset( AppAssets.getAppPath(2), fit: BoxFit.fitWidth, ), ), ), ), Positioned( top: size.height * 1.58, right: size.width * 0.2, child: Align( alignment: Alignment.centerRight, child: SizedBox( width: size.width * 0.35, child: Image.asset( AppAssets.getAppPath(3), fit: BoxFit.fitWidth, ), ), ), ), Positioned( top: size.height * 1.75, left: size.width * 0.15, right: size.width * 0.1, child: Align( alignment: Alignment.bottomCenter, child: SizedBox( height: size.height * 0.2, child: Image.asset( AppAssets.getAppPath(4), fit: BoxFit.fitHeight, ), ), ), ), Positioned( top: size.height * 2.5, left: 0, right: 0, child: Align( alignment: Alignment.bottomCenter, child: SizedBox( height: size.height * 0.26, child: Image.asset( AppAssets.getAppPath(5), fit: BoxFit.fitHeight, ), ), ), ), Positioned( top: size.height * 3.2, left: size.width * 0.4, child: Align( alignment: Alignment.topCenter, child: SizedBox( height: size.height * 0.3, child: Image.asset( AppAssets.getAppPath(6), fit: BoxFit.fitHeight, ), ), ), ), Positioned( top: size.height * 4, right: size.width * 0.1, child: Align( alignment: Alignment.centerRight, child: SizedBox( height: size.height * 0.45, child: Image.asset( AppAssets.getAppPath(7), fit: BoxFit.fitHeight, ), ), ), ), Positioned( top: size.height * 5.4, left: 0, right: 0, child: Align( alignment: Alignment.bottomCenter, child: SizedBox( height: size.height * 0.2, child: Image.asset( AppAssets.getAppPath(8), fit: BoxFit.fitHeight, ), ), ), ), ]; return Scaffold( body: SingleChildScrollView( child: Stack( clipBehavior: Clip.none, children: [ SizedBox(height: size.height * (sections.length / 2)), //...lines, //TODO: 将新路径整理到列表中优化代码 //* 第一条路径 Positioned( top: size.height * 0.95, left: size.width * 0.35, height: size.height * 0.23, width: size.width * 0.15, child: CustomPaint( painter: CurvePainter(), willChange: true, child: Container(), ), ), //* 第二条路径 Positioned( top: size.height * 1.35, left: size.width * 0.15, height: size.height * 0.12, width: size.width * 0.35, child: Transform( transform: Matrix4.rotationY(pi), alignment: Alignment.center, child: CustomPaint( painter: CurvePainter(), willChange: true, child: Container(), ), ), ), Column( mainAxisAlignment: MainAxisAlignment.start, children: sections), ], ), ), ); } }
内容的提问来源于stack exchange,提问作者Luca Rughani Jeevanjee
相关产品推荐
相关产品推荐

