HarmonyOS APP实战-画图APP - 第2篇:核心框架搭建

📅 2026/7/13 1:59:54
HarmonyOS APP实战-画图APP - 第2篇:核心框架搭建
HarmonyOS APP实战-画图APP - 第2篇主页面布局与基础交互1. 开篇在上一篇《准备开发环境与创建项目》中我们完成了HarmonyOS开发环境的搭建使用DevEco Studio创建了画图APP项目工程并成功运行了默认的Hello World页面。在EntryAbility中配置了全屏显示项目基础结构已准备就绪。本文将聚焦于画图APP的核心界面搭建。我们将设计一个三栏式布局顶部工具栏绘制模式切换、撤销重做按钮、中间画布区域承载所有绘制内容、底部颜色选择栏基础颜色选择。同时我们将集成Canvas组件并为其绑定基础触摸事件为后续章节的形状绘制、手绘功能打下坚实基础。完成本篇后你将看到一个完整的画图APP界面框架具备响应式布局能力可以在不同屏幕尺寸上自适应显示。2. 核心实现2.1 基础配置与数据模型设计在开始界面布局之前我们需要设计APP的数据模型。创建一个model文件夹定义绘制模式和颜色相关的枚举与接口。// model/DrawingData.ets// 绘制模式枚举后续将扩展矩形、圆形、自由画笔等exportenumDrawMode{RECTANGLErectangle,// 矩形CIRCLEcircle,// 圆形FREEDRAWfreedraw,// 自由画笔NONEnone// 无模式初始状态}// 画笔属性接口管理当前画笔的颜色、粗细、透明度exportinterfaceBrushProperty{color:string;// 画笔颜色格式#RRGGBBlineWidth:number;// 画笔粗细像素值opacity:number;// 透明度0-1}关键点说明DrawMode枚举定义了三种绘制模式后续将在工具栏中通过图标按钮切换BrushProperty接口封装了画笔的核心属性后续颜色选择器和粗细滑块将修改这些属性使用export关键字导出便于其他模块引用2.2 核心逻辑主页面布局组件Index.ets是整个APP的入口页面负责组装ToolBar、Canvas和ColorPicker三个核心区域。我们需要实现响应式布局确保在竖屏和横屏下都能正常显示。// pages/Index.etsimport{DrawMode,BrushProperty}from../model/DrawingDataimport{ToolBar}from./ToolBarimport{ColorPicker}from./ColorPickerEntryComponentstruct Index{// 当前绘制模式默认无模式StatecurrentMode:DrawModeDrawMode.NONE// 画笔属性初始颜色黑色粗细5px透明度1不透明Statebrush:BrushProperty{color:#000000,lineWidth:5,opacity:1}// Canvas画布的尺寸通过onAreaChange动态获取StatecanvasWidth:number0StatecanvasHeight:number0build(){// 使用Column垂直布局从上到下排列工具栏、画布、颜色选择器Column(){// 顶部工具栏提供绘制模式切换、撤销重做ToolBar({currentMode:this.currentMode,brush:this.brush,onModeChange:(mode:DrawMode){this.currentModemode}})// 中间画布区域使用Stack包裹Canvas以便后续添加触摸事件Stack(){// Canvas组件后续绘制操作都在此进行Canvas(this.canvasContext).width(100%).height(100%).backgroundColor(#FFFFFF)// 获取Canvas的渲染上下文用于绘制操作.onReady((){console.info(Canvas 已就绪)})// 触摸事件开始触摸时记录位置用于后续绘制.onTouch((event:TouchEvent){if(event.typeTouchType.Down){// 获取触摸点在Canvas内的坐标constxevent.touches[0].xconstyevent.touches[0].yconsole.info(触摸点坐标: (${x},${y}))// 后续章节将在此触发绘制逻辑}})}.layoutWeight(1)// 自动填充剩余空间.width(100%)// 底部颜色选择栏提供基础颜色选择和透明度调节ColorPicker({brush:this.brush,onColorChange:(color:string){this.brush{...this.brush,color:color}}})}.width(100%).height(100%).backgroundColor(#F5F5F5)// 监听容器尺寸变化动态更新Canvas尺寸.onAreaChange((oldValue:Area,newValue:Area){this.canvasWidthnewValue.widthasnumberthis.canvasHeightnewValue.heightasnumberconsole.info(容器尺寸:${this.canvasWidth}x${this.canvasHeight})})}// Canvas渲染上下文用于后续绘制privatecanvasContext:CanvasRenderingContext2DnewCanvasRenderingContext2D()}关键点说明State装饰的变量用于声明式响应UI更新brush对象的变化会自动触发颜色选择器和后续绘制组件的刷新layoutWeight(1)让Canvas区域填充工具栏和颜色选择器之外的剩余空间CanvasRenderingContext2D是HarmonyOS提供的2D渲染上下文所有绘制操作都通过它完成。文档中提到的ohos.graphics.drawing模块提供了更底层的绘制能力我们将在后续篇章中结合使用onAreaChange回调用于监听容器尺寸变化确保Canvas能够自适应屏幕旋转和窗口调整2.3 完整模块工具栏组件工具栏组件包含绘制模式切换按钮矩形、圆形、自由画笔和功能按钮撤销、重做、清空。按钮采用图标式设计选中状态高亮显示。// pages/ToolBar.etsimport{DrawMode,BrushProperty}from../model/DrawingDataComponentexportstruct ToolBar{// 当前绘制模式privatecurrentMode:DrawMode// 画笔属性privatebrush:BrushProperty// 模式切换回调privateonModeChange:(mode:DrawMode)voidbuild(){// 使用Row水平布局均匀分布所有工具按钮Row(){// 矩形模式按钮Button(){Text(□).fontSize(24).fontColor(this.currentModeDrawMode.RECTANGLE?#FF6600:#333333)}.width(40).height(40).backgroundColor(this.currentModeDrawMode.RECTANGLE?#E0E0E0:#FFFFFF).borderRadius(8).onClick((){this.onModeChange(DrawMode.RECTANGLE)})// 圆形模式按钮Button(){Text(○).fontSize(24).fontColor(this.currentModeDrawMode.CIRCLE?#FF6600:#333333)}.width(40).height(40).backgroundColor(this.currentModeDrawMode.CIRCLE?#E0E0E0:#FFFFFF).borderRadius(8).onClick((){this.onModeChange(DrawMode.CIRCLE)})// 自由画笔模式按钮Button(){Text(✎).fontSize(24).fontColor(this.currentModeDrawMode.FREEDRAW?#FF6600:#333333)}.width(40).height(40).backgroundColor(this.currentModeDrawMode.FREEDRAW?#E0E0E0:#FFFFFF).borderRadius(8).onClick((){this.onModeChange(DrawMode.FREEDRAW)})// 分隔线Divider().vertical(true).height(30).color(#CCCCCC).margin({left:10,right:10})// 撤销按钮Button(){Text(↩).fontSize(24).fontColor(#333333)}.width(40).height(40).backgroundColor(#FFFFFF).borderRadius(8).onClick((){// 撤销功能将在第11篇实现console.info(撤销操作)})// 重做按钮Button(){Text(↪).fontSize(24).fontColor(#333333)}.width(40).height(40).backgroundColor(#FFFFFF).borderRadius(8).onClick((){// 重做功能将在第11篇实现console.info(重做操作)})// 清空按钮Button(){Text().fontSize(24).fontColor(#333333)}.width(40).height(40).backgroundColor(#FFFFFF).borderRadius(8).onClick((){// 清空画布功能console.info(清空画布)})}.width(100%).padding({left:16,right:16,top:8,bottom:8}).backgroundColor(#FFFFFF).justifyContent(FlexAlign.SpaceAround)// 添加阴影效果.shadow({radius:4,color:#1A000000,offsetX:0,offsetY:2})}}关键点说明按钮选中状态通过currentMode判断矩形模式选中时文字颜色变为橙色(#FF6600)背景变为浅灰色提供清晰的视觉反馈Divider组件作为分隔线将绘制模式按钮与功能按钮分开提升界面层次感shadow属性为工具栏添加了底部阴影使其与画布区域产生视觉分离撤销、重做、清空按钮目前仅打印日志具体逻辑将在后续章节实现2.4 完整模块颜色选择器组件颜色选择器提供8种常用颜色和透明度滑块用户点击颜色按钮即可切换画笔颜色。后续可扩展为自定义色盘。// pages/ColorPicker.etsimport{BrushProperty}from../model/DrawingDataComponentexportstruct ColorPicker{// 画笔属性privatebrush:BrushProperty// 颜色变更回调privateonColorChange:(color:string)void// 颜色列表8种常用颜色privatecolors:string[][#000000,#FF0000,#00FF00,#0000FF,#FFFF00,#FF00FF,#00FFFF,#808080]build(){// 使用Column垂直布局上方是颜色按钮行下方是透明度控制Column(){// 颜色按钮行Row(){ForEach(this.colors,(color:string){Button(){// 颜色按钮显示当前颜色}.width(30).height(30).backgroundColor(color).borderRadius(15)// 圆形按钮.border({width:this.brush.colorcolor?3:1,color:this.brush.colorcolor?#FF6600:#CCCCCC}).onClick((){this.onColorChange(color)})},(color:string)color)}.width(100%).justifyContent(FlexAlign.SpaceAround).padding({top:8,bottom:8})// 透明度控制行使用Slider滑块调节透明度Row(){Text(透明度).fontSize(14).fontColor(#666666).margin({right:8})Slider({value:this.brush.opacity*100,// Slider的值范围0-100min:0,max:100,step:1}).width(70%)// 滑块值变化时更新画笔透明度.onChange((value:number){this.brush.opacityvalue/100// 触发UI刷新this.brush{...this.brush}})}.width(100%).padding({left:16,right:16,bottom:8})}.width(100%).padding({left:16,right:16,top:8,bottom:8}).backgroundColor(#F0F0F0)}}关键点说明颜色按钮通过backgroundColor直接显示对应颜色使用borderRadius(15)将其变为圆形选中状态的判断当前画笔颜色与按钮颜色一致时边框变为橙色并加粗提供清晰的选中指示Slider组件用于透明度调节其value范围是0-100我们需要将其转换为0-1的透明度值存储在brush.opacity中注意修改brush对象的属性后需要重新赋值this.brush { ...this.brush }才能触发UI重绘因为State装饰器只监听引用变化不监听属性变化3. 运行验证启动DevEco Studio选择模拟器或真机运行项目。我们将看到以下预期效果页面布局顶部显示工具栏包含6个按钮矩形、圆形、自由画笔、撤销、重做、清空中间为白色画布区域占据大部分屏幕底部显示8个颜色按钮和透明度滑块模式切换点击工具栏中的矩形、圆形或自由画笔按钮对应的图标会变为橙色高亮背景变为灰色表示当前选中状态颜色选择点击底部颜色按钮画笔颜色会立即切换选中按钮显示橙色边框。拖动透明度滑块可以看到滑块值相应变化触摸响应在画布上触摸时控制台会打印触摸点的坐标信息表明触摸事件已正确绑定实际运行效果如下图所示如果遇到布局错乱可以检查模拟器的屏幕尺寸设置建议使用Phone1080x1920模板。你也可以在项目config.json中配置orientation: portrait暂时锁定竖屏。4. 小结与预告本篇成功搭建了画图APP的主界面框架完成了以下核心工作设计了DrawMode枚举和BrushProperty接口作为数据模型实现了Index.ets主页面采用三栏式布局工具栏 画布 颜色选择器开发了ToolBar.ets组件支持绘制模式切换和功能按钮占位开发了ColorPicker.ets组件提供颜色选择和透明度调节集成了Canvas组件并绑定了基础触摸事件画布尺寸可自适应至此画图APP的基础交互框架已经完成所有UI元素都处于响应式状态为后续绘制功能的实现做好了准备。下一篇「实现基本形状绘制」将聚焦于CanvasRenderingContext2D的绘制API实现矩形、正方形和圆形的绘制逻辑。我们将在触摸事件中获取起点和终点坐标利用drawRect和drawCircle方法在画布上生成基本图形。敬请期待