大家好,我是 V 哥。
最近看到在 HarmonyOS NEXT開發(fā)中,實(shí)現(xiàn)拖動(dòng)卡片背景模糊的案例效果,在拖動(dòng)時(shí)背景圖片模糊,松開后恢復(fù)正常。感覺很酷,寫一個(gè)案例玩一下。

需求分析
首先,咱們來一起分析一下這個(gè)效果要怎么實(shí)現(xiàn)。
分析需求:卡片可拖動(dòng),拖動(dòng)時(shí)背景模糊,松開后恢復(fù)。這需要處理拖拽事件和動(dòng)態(tài)調(diào)整背景的模糊效果。咱們需要確定如何監(jiān)聽拖拽動(dòng)作,以及如何動(dòng)態(tài)改變背景的樣式。
ArkUI中的組件,比如Stack布局可以用來放置背景和卡片??ㄆ赡苄枰褂每赏蟿?dòng)的組件,比如PanGesture或者拖拽事件相關(guān)的組件。在HarmonyOS中,手勢(shì)處理通常是通過Gesture組件來實(shí)現(xiàn)的,比如PanGesture用于拖動(dòng)手勢(shì)。
接下來,背景圖片的模糊效果。在ArkUI中,有類似于前端的backdrop-filter樣式,或者需要使用某種圖像處理模塊。
然后,狀態(tài)管理的問題。當(dāng)卡片被拖動(dòng)時(shí),需要觸發(fā)背景模糊,松開后恢復(fù)。這需要維護(hù)一個(gè)狀態(tài)變量,比如isDragging,當(dāng)拖拽開始的時(shí)候設(shè)置為true,拖拽結(jié)束或松開的時(shí)候設(shè)置為false。這個(gè)狀態(tài)變量控制背景的模糊效果是否應(yīng)用。
接下來,拖拽的實(shí)現(xiàn)。使用PanGesture手勢(shì),監(jiān)聽onActionStart、onActionUpdate、onActionEnd事件。在onActionStart時(shí)設(shè)置isDragging為true,onActionEnd或onActionCancel時(shí)設(shè)置為false。同時(shí),根據(jù)手勢(shì)的偏移量更新卡片的位置,可能需要使用絕對(duì)定位,比如設(shè)置卡片的position為絕對(duì)定位,然后通過left和top屬性來調(diào)整位置,或者使用translate屬性進(jìn)行平移。
關(guān)于卡片的定位,需要將卡片放在一個(gè)容器中,比如Stack布局,這樣卡片可以自由移動(dòng)。然后通過手勢(shì)事件中的偏移量來更新卡片的位置。需要注意處理手勢(shì)事件的offsetX和offsetY,或者在onActionUpdate中獲取手指移動(dòng)的差值,然后累加到卡片的位置上。
然后,背景的動(dòng)態(tài)模糊。假設(shè)背景是一個(gè)Image組件,當(dāng)isDragging為true時(shí),應(yīng)用blur效果。例如,在ArkUI中,Image組件可能有effect屬性,可以設(shè)置為ImageEffect.blur(radius),根據(jù)isDragging的狀態(tài)調(diào)整radius的值?;蛘呖赡苄枰褂脳l件渲染,根據(jù)狀態(tài)改變樣式類。
咱們需要?jiǎng)?chuàng)建一個(gè)狀態(tài)變量,比如blurRadius,初始為0,拖動(dòng)時(shí)設(shè)置為5,這樣背景圖片的模糊效果就會(huì)動(dòng)態(tài)變化。同時(shí),動(dòng)畫效果可能需要使用動(dòng)畫API,比如animateTo,讓模糊過渡更平滑。
另外,需要注意性能問題,頻繁的模糊效果可能會(huì)影響性能,需要確認(rèn)HarmonyOS中是否優(yōu)化了這類效果,或者是否有更好的實(shí)現(xiàn)方式,比如使用離屏渲染或者緩存模糊后的圖片,不過這可能比較復(fù)雜,作為基礎(chǔ)功能可能直接動(dòng)態(tài)調(diào)整即可。
現(xiàn)在,整合這些思路,代碼的大致結(jié)構(gòu)可能是這樣的:
? 外層使用Stack布局,包含背景Image和可拖動(dòng)的卡片。
? 卡片組件包裹在Gesture組件中,監(jiān)聽PanGesture事件。
? 當(dāng)拖拽開始時(shí),設(shè)置isDragging為true,更新背景的模糊效果。
? 拖拽過程中,根據(jù)手勢(shì)的偏移量更新卡片的位置。
? 拖拽結(jié)束時(shí),恢復(fù)背景的模糊效果。
案例實(shí)現(xiàn)
V 哥來總結(jié)一下實(shí)現(xiàn)步驟:
- 創(chuàng)建頁面組件,使用Stack布局包含背景和卡片。
- 背景圖片應(yīng)用模糊效果,根據(jù)isDragging狀態(tài)變化。
- 卡片使用Gesture組件處理PanGesture手勢(shì)。
- 拖動(dòng)手勢(shì)事件中更新卡片的位置,并控制isDragging狀態(tài)。
- 狀態(tài)變化觸發(fā)背景模糊的樣式更新。
- 可能需要添加過渡動(dòng)畫使模糊效果更平滑。
在HarmonyOS NEXT中,可以通過以下步驟實(shí)現(xiàn)可拖動(dòng)卡片并控制背景模糊效果:
@Entry
@Component
struct DragCardExample {
@State cardPosition: { x: number, y: number } = { x: 0, y: 0 };
@State isDragging: boolean = false;
private initialPosition: { x: number, y: number } = { x: 0, y: 0 };
build() {
Stack() {
// 背景圖片
Image($r('app.media.background'))
.width('100%')
.height('100%')
.objectFit(ImageFit.Cover)
.blur(this.isDragging ? 10 : 0) // 根據(jù)拖動(dòng)狀態(tài)調(diào)整模糊度
.animation({ duration: 300, curve: Curve.EaseInOut })
// 可拖動(dòng)卡片
Gesture(
GesturePriority.Low,
PanGesture({
onActionStart: () => {
this.isDragging = true;
this.initialPosition = { ...this.cardPosition };
},
onActionUpdate: (event: GestureEvent) => {
this.cardPosition = {
x: this.initialPosition.x + event.offsetX,
y: this.initialPosition.y + event.offsetY
};
},
onActionEnd: () => {
this.isDragging = false;
// 這里可以添加自動(dòng)回中或其他結(jié)束邏輯
},
onActionCancel: () => {
this.isDragging = false;
}
})
) {
Column() {
Text('拖拽我')
.fontSize(20)
.fontColor(Color.Black)
}
.width(200)
.height(150)
.padding(20)
.backgroundColor(Color.White)
.borderRadius(16)
.shadow({ radius: 8, color: '#30000000', offsetX: 2, offsetY: 4 })
}
.position({ x: this.cardPosition.x, y: this.cardPosition.y })
.animation({ duration: 100, curve: Curve.Linear })
}
.width('100%')
.height('100%')
}
}
實(shí)現(xiàn)原理說明:
狀態(tài)管理:
?@State cardPosition:記錄卡片的當(dāng)前位置
?@State isDragging:控制拖動(dòng)狀態(tài)
?initialPosition:記錄拖動(dòng)前的初始位置手勢(shì)處理:
? 使用PanGesture實(shí)現(xiàn)拖動(dòng)手勢(shì)識(shí)別
?onActionStart:記錄初始位置并設(shè)置拖動(dòng)狀態(tài)
?onActionUpdate:實(shí)時(shí)更新卡片位置
?onActionEnd/Cancel:重置拖動(dòng)狀態(tài)背景模糊控制:
? 使用blur()API根據(jù)isDragging狀態(tài)動(dòng)態(tài)調(diào)整模糊度
? 添加animation實(shí)現(xiàn)平滑的過渡效果卡片樣式:
? 使用position實(shí)現(xiàn)絕對(duì)定位
? 添加陰影和圓角提升視覺效果
? 為位置變化添加微小的動(dòng)畫提升拖動(dòng)手感
擴(kuò)展建議:
- 邊界控制: 添加位置限制防止卡片拖出屏幕
// 在onActionUpdate中添加限制邏輯
const maxX = 屏幕寬度 - 卡片寬度;
const maxY = 屏幕高度 - 卡片高度;
x = Math.min(Math.max(x, 0), maxX);
y = Math.min(Math.max(y, 0), maxY);
- 磁性吸附效果: 在onActionEnd中添加自動(dòng)居中邏輯
animateTo({ duration: 200 }, () => {
this.cardPosition = { x: 0, y: 0 };
});
-
性能優(yōu)化: 對(duì)于復(fù)雜背景,建議:
? 使用緩存后的模糊圖片
? 控制模糊半徑不超過15px
? 在模糊層添加backdropBlur()代替全圖模糊
最后
這個(gè)實(shí)現(xiàn)方案完整展示了如何在HarmonyOS NEXT中結(jié)合手勢(shì)識(shí)別、狀態(tài)管理和視覺效果API,實(shí)現(xiàn)具有交互視覺反饋的可拖動(dòng)卡片效果。關(guān)注威哥愛編程,鴻蒙開發(fā)一定行。
想要學(xué)習(xí)鴻蒙開發(fā),一定繞不開學(xué)習(xí) ArkTS 語言,V 哥寫了三本鴻蒙開發(fā)之路的書,第一本《鴻蒙 HarmonyOS NEXT開發(fā)之路 卷1 ArkTS 篇》已上市,歡迎鴻蒙開發(fā)愛好者讀一讀,可以幫助你快速系統(tǒng)的拿下 ArkTS,每二本鴻蒙應(yīng)用開發(fā)篇和項(xiàng)目實(shí)踐篇也即將上市,清華大學(xué)出版社正在緊張校稿中。
