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