Flutter Clean架构项目中富文本个人资料的多端响应式实现咨询
在Clean架构Flutter项目中实现跨端适配的富文本个人资料
一、Clean架构下的职责拆分
在Clean架构里,适配与渲染逻辑完全放在UI层,域层只负责处理个人资料的业务规则(比如数据校验、格式转换),数据层负责从接口/本地获取原始资料数据。这样能保证适配逻辑不侵入核心业务,也方便后续修改适配规则。
二、适配方案优化(基于你已用的LayoutBuilder)
你用LayoutBuilder获取约束是正确方向,这里可以结合MediaQuery和封装响应式工具类,让样式调整更高效:
1. 封装响应式工具类
创建ResponsiveUtils类统一处理尺寸判断与样式计算,避免在UI组件里写大量重复条件:
class ResponsiveUtils { static bool isMobile(BuildContext context) { return MediaQuery.of(context).size.width < 768; } static bool isWeb(BuildContext context) { return MediaQuery.of(context).size.width >= 1200; } static double getTextSize(BuildContext context, double mobileSize, double webSize) { return isMobile(context) ? mobileSize : webSize; } static EdgeInsets getPadding(BuildContext context, EdgeInsets mobilePadding, EdgeInsets webPadding) { return isMobile(context) ? mobilePadding : webPadding; } }
2. 结合LayoutBuilder动态调整富文本样式
LayoutBuilder能获取父组件约束,适合不确定父组件尺寸时的适配场景(比如侧边栏内的个人资料):
class ProfileRichText extends StatelessWidget { final ProfileData profileData; // 从域层传递的已处理数据 const ProfileRichText({super.key, required this.profileData}); @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { final isMobile = constraints.maxWidth < 768; final baseStyle = TextStyle( fontSize: isMobile ? 16 : 20, fontWeight: FontWeight.w500, color: Colors.black87, ); final highlightStyle = TextStyle( fontSize: isMobile ? 18 : 22, fontWeight: FontWeight.bold, color: Colors.blueAccent, ); return RichText( text: TextSpan( children: [ TextSpan(text: "姓名:", style: baseStyle), TextSpan(text: "${profileData.name}\n", style: highlightStyle), TextSpan(text: "职位:", style: baseStyle), TextSpan(text: "${profileData.position}\n", style: highlightStyle), TextSpan(text: "简介:", style: baseStyle), TextSpan(text: profileData.bio, style: baseStyle.copyWith(height: 1.5)), ], ), textAlign: TextAlign.left, ); }, ); } }
三、富文本进阶处理(支持Markdown格式)
如果个人资料需要支持Markdown(加粗、链接、换行等),可以用flutter_markdown包,同时动态调整渲染样式:
class MarkdownProfile extends StatelessWidget { final String markdownContent; const MarkdownProfile({super.key, required this.markdownContent}); @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { final isMobile = constraints.maxWidth < 768; return MarkdownBody( data: markdownContent, styleSheet: MarkdownStyleSheet( p: TextStyle(fontSize: isMobile ? 16 : 18, height: 1.5), strong: TextStyle(fontSize: isMobile ? 17 : 19, fontWeight: FontWeight.bold), link: TextStyle(fontSize: isMobile ? 16 : 18, color: Colors.blueAccent), ), ); }, ); } }
四、Clean架构下的数据流转
- 数据层:从API获取原始个人资料数据(如JSON),返回给域层。
- 域层:将原始数据转换为
ProfileData实体类,处理格式转换(比如把Markdown字符串整理为可渲染格式),不涉及任何适配逻辑。 - UI层:通过Presenter/ViewModel从域层获取
ProfileData,再用适配组件渲染富文本。
五、额外优化点
- 搭配
OrientationBuilder处理横竖屏切换适配,比如移动端横屏时自动切换为Web端样式。 - Web端可添加
MouseRegion实现hover交互效果,移动端自动隐藏该逻辑:
Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { final isWeb = constraints.maxWidth >= 1200; return isWeb ? MouseRegion( onHover: (_) {}, // 这里添加hover时的样式变化逻辑 child: RichText(...), ) : RichText(...); }, ); }
内容的提问来源于stack exchange,提问作者bv.dev.br
相关产品推荐
相关产品推荐

