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

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{RECTANGLE='rectangle',// 矩形CIRCLE='circle',// 圆形FREEDRAW='freedraw',// 自由画笔NONE='none'// 无模式(初始状态)}// 画笔属性接口:管理当前画笔的颜色、粗细、透明度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/DrawingData'import{ToolBar}from'./ToolBar'import{ColorPicker}from'./ColorPicker'@Entry@Componentstruct Index{// 当前绘制模式,默认无模式@StatecurrentMode:DrawMode=DrawMode.NONE// 画笔属性,初始颜色黑色,粗细5px,透明度1(不透明)@Statebrush:BrushProperty={color:'#000000',lineWidth:5,opacity:1}// Canvas画布的尺寸,通过onAreaChange动态获取@StatecanvasWidth:number=0@StatecanvasHeight:number=0build(){// 使用Column垂直布局,从上到下排列工具栏、画布、颜色选择器Column(){// 顶部工具栏:提供绘制模式切换、撤销重做ToolBar({currentMode:this.currentMode,brush:this.brush,onModeChange:(mode:DrawMode)=>{this.currentMode=mode}})// 中间画布区域:使用Stack包裹Canvas,以便后续添加触摸事件Stack(){// Canvas组件,后续绘制操作都在此进行Canvas(this.canvasContext).width('100%').height('100%').backgroundColor('#FFFFFF')// 获取Canvas的渲染上下文,用于绘制操作.onReady(()=>{console.info('Canvas 已就绪')})// 触摸事件:开始触摸时记录位置,用于后续绘制.onTouch((event:TouchEvent)=>{if(event.type===TouchType.Down){// 获取触摸点在Canvas内的坐标constx=event.touches[0].xconsty=event.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.canvasWidth=newValue.widthasnumberthis.canvasHeight=newValue.heightasnumberconsole.info(`容器尺寸:${this.canvasWidth}x${this.canvasHeight}`)})}// Canvas渲染上下文,用于后续绘制privatecanvasContext:CanvasRenderingContext2D=newCanvasRenderingContext2D()}

关键点说明

  • @State装饰的变量用于声明式响应UI更新,brush对象的变化会自动触发颜色选择器和后续绘制组件的刷新
  • layoutWeight(1)让Canvas区域填充工具栏和颜色选择器之外的剩余空间
  • CanvasRenderingContext2D是HarmonyOS提供的2D渲染上下文,所有绘制操作都通过它完成。文档中提到的@ohos.graphics.drawing模块提供了更底层的绘制能力,我们将在后续篇章中结合使用
  • onAreaChange回调用于监听容器尺寸变化,确保Canvas能够自适应屏幕旋转和窗口调整

2.3 完整模块:工具栏组件

工具栏组件包含绘制模式切换按钮(矩形、圆形、自由画笔)和功能按钮(撤销、重做、清空)。按钮采用图标式设计,选中状态高亮显示。

// pages/ToolBar.etsimport{DrawMode,BrushProperty}from'../model/DrawingData'@Componentexportstruct ToolBar{// 当前绘制模式privatecurrentMode:DrawMode// 画笔属性privatebrush:BrushProperty// 模式切换回调privateonModeChange:(mode:DrawMode)=>voidbuild(){// 使用Row水平布局,均匀分布所有工具按钮Row(){// 矩形模式按钮Button(){Text('□').fontSize(24).fontColor(this.currentMode===DrawMode.RECTANGLE?'#FF6600':'#333333')}.width(40).height(40).backgroundColor(this.currentMode===DrawMode.RECTANGLE?'#E0E0E0':'#FFFFFF').borderRadius(8).onClick(()=>{this.onModeChange(DrawMode.RECTANGLE)})// 圆形模式按钮Button(){Text('○').fontSize(24).fontColor(this.currentMode===DrawMode.CIRCLE?'#FF6600':'#333333')}.width(40).height(40).backgroundColor(this.currentMode===DrawMode.CIRCLE?'#E0E0E0':'#FFFFFF').borderRadius(8).onClick(()=>{this.onModeChange(DrawMode.CIRCLE)})// 自由画笔模式按钮Button(){Text('✎').fontSize(24).fontColor(this.currentMode===DrawMode.FREEDRAW?'#FF6600':'#333333')}.width(40).height(40).backgroundColor(this.currentMode===DrawMode.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/DrawingData'@Componentexportstruct 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.color===color?3:1,color:this.brush.color===color?'#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.opacity=value/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,选择模拟器或真机运行项目。我们将看到以下预期效果:

  1. 页面布局:顶部显示工具栏,包含6个按钮(矩形、圆形、自由画笔、撤销、重做、清空);中间为白色画布区域,占据大部分屏幕;底部显示8个颜色按钮和透明度滑块

  2. 模式切换:点击工具栏中的矩形、圆形或自由画笔按钮,对应的图标会变为橙色高亮,背景变为灰色,表示当前选中状态

  3. 颜色选择:点击底部颜色按钮,画笔颜色会立即切换,选中按钮显示橙色边框。拖动透明度滑块,可以看到滑块值相应变化

  4. 触摸响应:在画布上触摸时,控制台会打印触摸点的坐标信息,表明触摸事件已正确绑定

实际运行效果如下图所示:

如果遇到布局错乱,可以检查模拟器的屏幕尺寸设置,建议使用Phone(1080x1920)模板。你也可以在项目config.json中配置"orientation": "portrait"暂时锁定竖屏。

4. 小结与预告

本篇成功搭建了画图APP的主界面框架,完成了以下核心工作:

  • 设计了DrawMode枚举和BrushProperty接口作为数据模型
  • 实现了Index.ets主页面,采用三栏式布局(工具栏 + 画布 + 颜色选择器)
  • 开发了ToolBar.ets组件,支持绘制模式切换和功能按钮占位
  • 开发了ColorPicker.ets组件,提供颜色选择和透明度调节
  • 集成了Canvas组件并绑定了基础触摸事件,画布尺寸可自适应

至此,画图APP的基础交互框架已经完成,所有UI元素都处于响应式状态,为后续绘制功能的实现做好了准备。

下一篇「实现基本形状绘制」将聚焦于CanvasRenderingContext2D的绘制API,实现矩形、正方形和圆形的绘制逻辑。我们将在触摸事件中获取起点和终点坐标,利用drawRectdrawCircle方法在画布上生成基本图形。敬请期待!

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

相关文章:

  • 从零开始:大气层整合包系统如何让Switch破解变得简单又安全
  • 2026 论文AI率助手横向对比:公认好用的,科研党救急指南
  • 星网宇达:公司与近期市场关注的长征十号乙运载火箭海上回收技术突破不存在业务关联
  • 题型归纳与重要模版
  • 工业负载控制:TPD2017FN与PIC18F57K42的智能驱动方案
  • C++14数字分隔符:提升代码可读性的零开销语法糖
  • ROS 2 Galactic 在 Ubuntu 22.04 环境下的 3 种安装方式与避坑实测
  • Linux 挖矿病毒应急响应:从 top 异常到 chattr 恢复的 5 步排查手册
  • SAP SD POD 配置与 VLPOD 操作:3步完成交货证明与开票数量同步
  • 龙魂蚁群引擎 v2.0 · 深度学习与融合报告
  • Canal 1.1.5 数据同步性能调优:解析并行度与MQ参数配置实测
  • 终极macOS窗口管理指南:用Loop告别桌面混乱的完整教程
  • [论文学习]LLM-based AI Agent 安全威胁与防御系统性综述
  • 如何用 DeepSeek 搭建自己的 RAG 知识库问答系统?
  • 30分钟快速搭建wvp-GB28181-pro:国标视频监控平台容器化部署终极指南
  • 面向演艺合作的头条号清单记录表设计
  • 高压与低压系统互联的光耦隔离技术解析
  • 编译原理实战:从正则表达式到DFA转换的5步算法与Python实现
  • ADP5350与PIC32MX460F512L构建智能电源管理系统
  • Oracle SQL Developer 23.1.1 安装配置:Windows/Linux/Mac 三平台 5 步避坑指南
  • Windows 11专业工作站版重装指南:三种方法详解与实操步骤
  • 暑假外出旅游没时间清日常?手机远控电脑用排队时间搞定!
  • 【无标题】HarmonyOS ArkTS实战:使用 ColumnSplit 与 RowSplit 构建企业级自适应布局(API 23+)
  • Steam成就管理器终极指南:三步掌握游戏成就自由
  • 营业执照识别 API 最小可运行示例:从请求到解析返回字段
  • 高精度ADC与PIC微控制器的工业测量系统设计
  • 如何彻底卸载FanControl?5步完全清理Windows风扇控制软件
  • 【OpenSpec】openspec\config.yaml 项目中config.yaml是如何使用的
  • 免费解锁WeMod专业版:Wand-Enhancer终极方案完全指南
  • 【OpenSpec】/opsx:archive 的作用是什么解析