鸿蒙应用示例:仿钉钉日历新建日程

【开发环境】
开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.814
工程API版本:12
【组件初始化】
Page02结构体定义了几个状态变量:offsetX, offsetY, positionX, positionY,这些变量用于跟踪用户操作引起的UI位置变化。containerHeight和originalHeight则用来控制UI容器的高度,同时containerHeightChanged方法确保容器的高度不会低于设定的最小值。
【用户界面构建】
build()方法是创建UI的核心逻辑。它首先创建了一个Column布局,用于垂直排列子元素。内部的RelativeContainer则允许更精细的位置控制,通过绝对或相对位置来放置子元素。
【动态UI元素】
在RelativeContainer中,我们添加了一个带有文字的矩形和两个圆点。这两个圆点不仅作为视觉元素,还绑定了拖动手势(PanGesture),这使得用户可以通过拖动操作改变容器的高度,从而模拟日程项的增加或减少过程。
【手势处理】
我们使用了两种不同的拖动手势:一种用于调整容器的高度,另一种则用于整体移动容器的位置。这些手势操作更新了相应的状态变量,并最终反映在UI布局上。
【完整代码】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | @Entry @Component struct Page02 { @State offsetX: number = 0; @State offsetY: number = 0; @State positionX: number = 0; @State positionY: number = 0; @State @Watch( 'containerHeightChanged' ) containerHeight: number = 50; @State originalHeight: number = 50; containerHeightChanged() { if ( this .containerHeight < 50) { this .containerHeight = 50 } } build() { Column() { RelativeContainer() { Rect() .fill( "#2fd164" ) .borderColor( "#39bd66" ) .borderWidth(1) .borderRadius(5) .clip( true ) .width( "100%" ) .height( "100%" ) Text( "再次点击新建日程" ) .fontColor(Color.White) .margin({ top: 30, left: 130 }) .fontSize(15) .alignRules({ center: { anchor: "__container__" , align: VerticalAlign.Top }, middle: { anchor: "__container__" , align: HorizontalAlign.Start } }) Stack() { Circle({ height: 5, width: 5 }) .fill(Color.White) .stroke(Color.White) .strokeWidth(2) } .hitTestBehavior(HitTestMode.Block) .padding(20) .margin({ left: 60 }) .alignRules({ center: { anchor: "__container__" , align: VerticalAlign.Top }, middle: { anchor: "__container__" , align: HorizontalAlign.Start } }) .gesture(PanGesture({ fingers: 1, direction: PanDirection.Vertical, distance: 1 }).onActionUpdate((event: GestureEvent) => { if (event) { this .offsetY = this .positionY + event.offsetY; this .containerHeight = this .originalHeight - event.offsetY; } }).onActionEnd(() => { this .positionX = this .offsetX; this .positionY = this .offsetY; this .originalHeight = this .containerHeight; }) ) Stack() { Circle({ height: 5, width: 5 }) .fill(Color.White) .stroke(Color.White) .strokeWidth(2) } .hitTestBehavior(HitTestMode.Block) .padding(20) .margin({ right: 60 }) .alignRules({ center: { anchor: "__container__" , align: VerticalAlign.Bottom }, middle: { anchor: "__container__" , align: HorizontalAlign.End } }) .gesture(PanGesture({ fingers: 1, direction: PanDirection.Vertical, distance: 2 }).onActionUpdate((event: GestureEvent) => { this .containerHeight = this .originalHeight + event.offsetY; }).onActionEnd(() => { this .originalHeight = this .containerHeight; }) ) } .height( this .containerHeight) .width( "80%" ) .translate({ x: this .offsetX, y: this .offsetY }) .gesture(PanGesture({ fingers: 1, direction: PanDirection.Vertical, distance: 1 }).onActionUpdate((event: GestureEvent) => { if (event) { this .offsetX = this .positionX + event.offsetX; this .offsetY = this .positionY + event.offsetY; } }).onActionEnd(() => { this .positionX = this .offsetX; this .positionY = this .offsetY; }) ) } .height( '100%' ) .width( '100%' ) } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了