【开发环境】
开发工具: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布局上。
【完整代码】
javascript
@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%')
}
}