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方法在画布上生成基本图形。敬请期待

相关新闻

C++高精度阶乘实现:从数组模拟到压位优化与FFT进阶

C++高精度阶乘实现:从数组模拟到压位优化与FFT进阶

1. 项目概述:从“为什么没有”到“如何实现”在C的日常开发中,我们经常会遇到需要计算阶乘的场景,比如组合数学、概率统计,或者一些算法题。很多初学者会下意识地在标准库中寻找一个像std::factorial这样的函数,结果当…

2026/7/13 2:00:14阅读更多 →
用PowerPoint+Paint打造可呼吸的数字黑板

用PowerPoint+Paint打造可呼吸的数字黑板

1. 项目概述:为什么物理课不能只靠PPT“念稿”?我带过七届大学物理实验课,也在线上教过三年理论课,最常被学生私信问的一句话是:“老师,您讲的推导过程能不能慢一点?我刚想记下中间步骤&#xf…

2026/7/13 1:55:14阅读更多 →
CTF 音频隐写实战:Audacity 与 MP3Stego 1.1.17 工具链的 5 步排查流程

CTF 音频隐写实战:Audacity 与 MP3Stego 1.1.17 工具链的 5 步排查流程

CTF 音频隐写实战:Audacity 与 MP3Stego 工具链的 5 步排查流程在CTF竞赛中,音频隐写题目往往让参赛者感到棘手。与图片隐写不同,音频文件包含更多维度的信息载体——时域波形、频域频谱、编码参数等都可能成为隐藏数据的媒介。本文将介绍一套…

2026/7/13 1:55:14阅读更多 →
为什么药品冷藏箱不能只看最低温度?——基于PMG MP8 6L压缩机药品冷藏箱的一次完整工程测试解析

为什么药品冷藏箱不能只看最低温度?——基于PMG MP8 6L压缩机药品冷藏箱的一次完整工程测试解析

从降温速度、温度波动到锂电池续航,看一台药品冷藏箱真正应该关注哪些指标关键词:药品冷藏箱、医用小冰箱、医用小冰箱2-8℃、药品便携冷藏盒、GLP-1冷藏杯、胰岛素冷藏盒、司美格鲁肽冷藏、替尔泊肽冷藏、疫苗运输、医疗冷链、车载冰箱、压缩机冷藏箱、…

2026/7/13 3:20:22阅读更多 →
产后私密清爽护理泡沫使用注意

产后私密清爽护理泡沫使用注意

女性产后尤其是哺乳期阶段,私密部位分泌物较多,局部容易闷热潮湿,做好日常清洁护理是产后身体护理的重要部分。产后私密清爽护理泡沫因为使用方便、摩擦感低受到不少新手妈妈关注,使用时需要结合产后特殊的身体状态,遵…

2026/7/13 3:20:22阅读更多 →
已解决:注册谷歌gmail邮箱出现扫码验证的5个有效办法

已解决:注册谷歌gmail邮箱出现扫码验证的5个有效办法

遇到这类注册验证问题确实让人有些头疼,不过不用担心!✨ 出现扫码或严格的手机号验证提示,通常是因为当前的网络环境或设备状态触发了系统的安全风控机制。 您可以尝试以下几个实用且成功率较高的方法来解决这个问题: &#x1f…

2026/7/13 3:20:22阅读更多 →
AI 回复比用户提问还早?一个空字符串引发的“时间倒流“

AI 回复比用户提问还早?一个空字符串引发的“时间倒流“

我今天在查 AI 聊天记录时,看到一条很离谱的数据:assistant message 的 created_at 竟然比触发它的 user message 还早。AI 难道会时间倒流?当然不是。最后查下来,根因居然是一个空字符串:id ""。项目背景:…

2026/7/13 3:20:22阅读更多 →
框架表示法 vs 产生式规则:5 个维度对比结构化与因果式知识建模

框架表示法 vs 产生式规则:5 个维度对比结构化与因果式知识建模

框架表示法与产生式规则:5个维度解析结构化与因果式知识建模的抉择在构建专家系统或业务规则引擎时,知识表示方法的选择往往决定了系统的表达能力、推理效率和维护成本。框架表示法与产生式规则作为两种经典的知识建模范式,分别代表了结构化思…

2026/7/13 3:20:22阅读更多 →
YOLO26目标检测实战:从环境配置到自定义模型训练完整指南

YOLO26目标检测实战:从环境配置到自定义模型训练完整指南

如果你正在学习计算机视觉,特别是目标检测方向,那么YOLO(You Only Look Once)这个名字你一定不会陌生。但面对网络上零散的教程、复杂的配置过程和不断更新的版本,很多初学者往往在环境安装这一步就放弃了,…

2026/7/13 3:15:22阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时,第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/12 0:02:11阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/13 0:50:34阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/12 0:02:11阅读更多 →
卡梅德生物技术快报|蛋白质分离纯化:肠激酶可溶性原核表达 + 两步层析全参数|标准化蛋白质分离纯化 SOP

卡梅德生物技术快报|蛋白质分离纯化:肠激酶可溶性原核表达 + 两步层析全参数|标准化蛋白质分离纯化 SOP

研究痛点提出(提出问题)重组肠激酶是融合标签切除核心工具酶,当前原核表达体系存在三大标准化难题,直接阻碍可复现的蛋白质分离纯化流程搭建:Trx、GST、单 SUMO 标签融合产物绝大多数为包涵体,沉淀占比超 9…

2026/7/13 0:04:58阅读更多 →
语音转文字工具AsrTools:让音频整理变得简单高效

语音转文字工具AsrTools:让音频整理变得简单高效

语音转文字工具AsrTools:让音频整理变得简单高效 【免费下载链接】AsrTools ✨ AsrTools: Smart Voice-to-Text Tool | Efficient Batch Processing | User-Friendly Interface | No GPU Required | Supports SRT/TXT Output | Turn your audio into accurate text …

2026/7/13 0:04:58阅读更多 →
Palworld存档编辑完全掌握:从零开始实现游戏数据可视化修改

Palworld存档编辑完全掌握:从零开始实现游戏数据可视化修改

Palworld存档编辑完全掌握:从零开始实现游戏数据可视化修改 【免费下载链接】palworld-save-tools Tools for converting Palworld .sav files to JSON and back 项目地址: https://gitcode.com/gh_mirrors/pa/palworld-save-tools 你是否曾经想要调整Palwor…

2026/7/13 0:04:58阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/11 16:20:28阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/11 23:15:38阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/12 21:43:43阅读更多 →