当前位置: 首页 > news >正文

FlutterOpenHarmony卡片组件设计与实现

前言

卡片是移动应用中展示信息的常用组件,它将相关内容组织在一个视觉容器中,通过阴影、圆角等效果与背景区分开来。在笔记应用中,卡片常用于展示笔记列表项、笔记详情、统计信息等内容。一个设计良好的卡片组件应该具有清晰的视觉层次、合理的信息布局和良好的交互反馈。本文将详细介绍如何在Flutter和OpenHarmony平台上设计和实现卡片组件。

Flutter Card组件基础

Flutter提供了Card组件作为卡片的基础实现。

Card(elevation:2,shape:RoundedRectangleBorder(borderRadius:BorderRadius.circular(12),),child:Padding(padding:EdgeInsets.all(16),child:Column(crossAxisAlignment:CrossAxisAlignment.start,children:[Text('笔记标题',style:TextStyle(fontSize:18,fontWeight:FontWeight.bold)),SizedBox(height:8),Text('笔记内容摘要...',style:TextStyle(color:Colors.grey)),SizedBox(height:12),Text('2024-01-01',style:TextStyle(fontSize:12,color:Colors.grey)),],),),)

Card组件提供了Material风格的卡片外观。elevation属性设置阴影高度,数值越大阴影越明显。shape属性自定义卡片形状,RoundedRectangleBorder设置圆角。Card本身不提供内边距,需要在child中使用Padding添加。Column垂直排列标题、内容和日期,crossAxisAlignment设置左对齐。这种基础卡片结构适用于大多数笔记展示场景。

Card(clipBehavior:Clip.antiAlias,child:Column(children:[Image.network('https://example.com/cover.jpg',height:150,width:double.infinity,fit:BoxFit.cover,),Padding(padding:EdgeInsets.all(16),child:Column(crossAxisAlignment:CrossAxisAlignment.start,children:[Text('带封面的笔记'),SizedBox(height:8),Text('笔记描述内容...'),],),),],),)

带封面图片的卡片需要设置clipBehavior为Clip.antiAlias,确保图片被圆角裁剪。Image组件放在Column的第一个位置,width设置为double.infinity使图片填满卡片宽度。fit设置为BoxFit.cover保持图片比例并填满区域。这种带封面的卡片设计可以让笔记列表更加丰富多彩。

自定义笔记卡片

根据笔记应用的需求自定义卡片组件。

classNoteCardextendsStatelessWidget{finalNote note;finalVoidCallback?onTap;finalVoidCallback?onLongPress;constNoteCard({requiredthis.note,this.onTap,this.onLongPress,});@overrideWidgetbuild(BuildContext context){returnCard(margin:EdgeInsets.symmetric(horizontal:16,vertical:8),child:InkWell(onTap:onTap,onLongPress:onLongPress,borderRadius:BorderRadius.circular(12),child:Padding(padding:EdgeInsets.all(16),child:Column(crossAxisAlignment:CrossAxisAlignment.start,children:[_buildHeader(),SizedBox(height:8),_buildContent(),SizedBox(height:12),_buildFooter(),],),),),);}}

自定义NoteCard组件接收Note数据和回调函数作为参数。InkWell包裹内容提供点击水波纹效果,borderRadius需要与Card的圆角一致。将卡片内容拆分为_buildHeader、_buildContent、_buildFooter三个方法,使代码结构更清晰。这种组件化的设计使得卡片可以在多处复用,修改样式也更加方便。

Widget_buildHeader(){returnRow(children:[Expanded(child:Text(note.title,style:TextStyle(fontSize:16,fontWeight:FontWeight.w600),maxLines:1,overflow:TextOverflow.ellipsis,),),if(note.isPinned)Icon(Icons.push_pin,size:16,color:Colors.orange),],);}Widget_buildContent(){returnText(note.content,style:TextStyle(fontSize:14,color:Colors.grey.shade700),maxLines:3,overflow:TextOverflow.ellipsis,);}Widget_buildFooter(){returnRow(children:[if(note.tags.isNotEmpty)...[Icon(Icons.label,size:14,color:Colors.grey),SizedBox(width:4),Text(note.tags.first,style:TextStyle(fontSize:12,color:Colors.grey)),Spacer(),],Text(_formatDate(note.updatedAt),style:TextStyle(fontSize:12,color:Colors.grey),),],);}

头部显示标题和置顶图标,Expanded确保标题占据剩余空间,maxLines和overflow处理长标题的截断。内容区域限制显示3行,超出部分显示省略号。底部显示标签和更新时间,Spacer将时间推到右侧。这种布局清晰地展示了笔记的关键信息,用户可以快速浏览和识别。

OpenHarmony卡片实现

OpenHarmony通过组合基础组件实现卡片效果。

@Component struct NoteCard{@Prop note:NoteItemonTap:()=>void=()=>{}onLongPress:()=>void=()=>{}build(){Column(){this.HeaderBuilder()this.ContentBuilder()this.FooterBuilder()}.width('100%').padding(16).backgroundColor('#FFFFFF').borderRadius(12).shadow({radius:8,color:'rgba(0, 0, 0, 0.1)',offsetX:0,offsetY:2}).onClick(()=>{this.onTap()}).gesture(LongPressGesture().onAction(()=>{this.onLongPress()}))}}

OpenHarmony没有内置的Card组件,需要通过设置背景色、圆角和阴影来实现卡片效果。shadow属性配置阴影,radius是模糊半径,color是阴影颜色,offsetX和offsetY是偏移量。onClick处理点击事件,LongPressGesture处理长按事件。@Prop装饰器接收父组件传递的数据。

@BuilderHeaderBuilder(){Row(){Text(this.note.title).fontSize(16).fontWeight(FontWeight.Medium).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis}).layoutWeight(1)if(this.note.isPinned){Image($r('app.media.pin_icon')).width(16).height(16).fillColor('#FF9800')}}.width('100%')}@BuilderContentBuilder(){Text(this.note.content).fontSize(14).fontColor('#666666').maxLines(3).textOverflow({overflow:TextOverflow.Ellipsis}).width('100%').margin({top:8})}@BuilderFooterBuilder(){Row(){if(this.note.tags.length>0){Image($r('app.media.tag_icon')).width(14).height(14).fillColor('#999999')Text(this.note.tags[0]).fontSize(12).fontColor('#999999').margin({left:4})}Blank()Text(this.formatDate(this.note.updatedAt)).fontSize(12).fontColor('#999999')}.width('100%').margin({top:12})}

使用@Builder装饰器将卡片内容拆分为多个构建函数。layoutWeight(1)使标题占据剩余空间,类似于Flutter的Expanded。maxLines和textOverflow处理文本截断。Blank组件填充中间空白,将日期推到右侧。fillColor设置图标的填充颜色。这种模块化的构建方式使代码结构清晰,易于维护。

卡片交互效果

卡片的交互反馈可以提升用户体验。

classAnimatedNoteCardextendsStatefulWidget{finalNote note;@override_AnimatedNoteCardStatecreateState()=>_AnimatedNoteCardState();}class_AnimatedNoteCardStateextendsState<AnimatedNoteCard>{bool _isPressed=false;@overrideWidgetbuild(BuildContext context){returnGestureDetector(onTapDown:(_)=>setState(()=>_isPressed=true),onTapUp:(_)=>setState(()=>_isPressed=false),onTapCancel:()=>setState(()=>_isPressed=false),child:AnimatedContainer(duration:Duration(milliseconds:150),transform:Matrix4.identity()..scale(_isPressed?0.98:1.0),child:Card(elevation:_isPressed?1:2,child:NoteCardContent(note:widget.note),),),);}}

按下卡片时添加缩放和阴影变化的动画效果。GestureDetector的onTapDown、onTapUp、onTapCancel分别处理按下、抬起和取消事件。AnimatedContainer自动对transform和elevation变化添加动画。scale(0.98)使卡片略微缩小,配合阴影降低,营造按下的视觉效果。这种微妙的交互反馈让应用感觉更加精致。

卡片列表布局

卡片在列表中的布局方式影响整体视觉效果。

GridView.builder(padding:EdgeInsets.all(16),gridDelegate:SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2,crossAxisSpacing:12,mainAxisSpacing:12,childAspectRatio:0.85,),itemCount:notes.length,itemBuilder:(context,index){returnNoteCard(note:notes[index]);},)

GridView可以将卡片以网格形式排列,适合展示较多内容。crossAxisCount设置每行显示的卡片数量,crossAxisSpacing和mainAxisSpacing设置间距,childAspectRatio设置卡片的宽高比。网格布局可以在有限空间内展示更多笔记,适合笔记概览场景。

总结

卡片组件是笔记应用中展示信息的核心组件。Flutter和OpenHarmony都可以通过组合基础组件实现丰富的卡片效果。开发者需要关注卡片的视觉层次、信息布局、交互反馈等细节,为用户提供清晰美观的笔记展示体验。通过组件化的设计,卡片可以在应用中灵活复用。

http://www.cnnetsun.cn/news/175725.html

相关文章:

  • Excalidraw实现KANO模型:需求优先级排序
  • 基于Java+大数据+SSMB站数据分析可视化系统(源码+LW+调试文档+讲解等)/B站数据可视化/B站数据分析/B站分析系统/数据可视化系统/数据分析系统/B站数据平台/B站可视化工具
  • 基于Python+大数据+SSMCBA球员数据可视化分析系统(源码+LW+调试文档+讲解等)/CBA球员数据展示系统/CBA球员数据统计系统/CBA球员数据分析平台/篮球数据可视化分析系统
  • Excalidraw导出PDF注意事项:格式保持完整
  • 【C++】优选算法必修篇之双指针实战:移动零 复写零
  • 【C++】继承深度解析:继承方式和菱形虚拟继承的详解
  • Excalidraw背景设置:更换画布颜色或图片
  • Excalidraw深度测评:为什么它成技术团队首选白板工具?
  • 笨人小白的温故知新——排序(3)
  • 基于python的RSA加密算法软件的研究设计(源码+文档)
  • Excalidraw界面原型设计:产品经理快速出稿方案
  • Excalidraw价值流图:精益生产流程优化
  • 嵌入式多线程从“能跑“到“稳定“的关键一步!
  • 【空间辨识】一致模态指标与模态参与因子的随机子空间辨识研究(Matlab代码实现)
  • 基于Java+SSM+SSM线上管理系统(源码+LW+调试文档+讲解等)/线上管理平台/在线管理系统/线上管理软件/网络管理系统/线上办公系统
  • 分层模糊系统:梯度下降与递推最小二乘法联合辨识研究(Matlab代码实现)
  • 人机差异的核心
  • Excalidraw暗黑模式设置:夜间使用的护眼方案
  • 精品UI知识付费系统源码 响应式视频教程知识付费软件下载网站模板
  • CentOS 7 x86系统安装EMQX 【kaki备忘录】
  • 文献综述:近年“知识工程(Knowledge Engineering)与知识库/知识图谱建设(KB/KG)”研究脉络与展望
  • Excalidraw监控指标采集:Prometheus+Grafana集成
  • 【自动驾驶基础】LDM(Latent Diffusion Model) 要点总结
  • 【FreeRTOS实战】互斥锁专题:从理论到STM32应用题
  • STM32学习——AD单通道AD多通道
  • 基于Spring Boot的农产品销售系统的设计与实现毕设源码
  • 基于Spring Boot的流浪动物救助平台的设计与实现毕业设计
  • 备份恢复-Cordovaopenharmony本地安全方案
  • 创建目标模块 Cordova 与 OpenHarmony 混合开发实战
  • 解决MQ消息丢失问题的5种方案