Skip to content

Commit dfda356

Browse files
authored
fix(overlay): avoid edit toolbar covering keys (#45)
1 parent 8babf16 commit dfda356

1 file changed

Lines changed: 98 additions & 3 deletions

File tree

entry/src/main/ets/components/CustomKeyOverlay.ets

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ export struct CustomKeyOverlay {
136136
@State private snapEnabled: boolean = false;
137137
/** 吸附阈值 (vp) */
138138
private static readonly SNAP_THRESHOLD_VP = 8;
139+
/** 编辑工具栏避让按键时保留的缓冲距离 (vp) */
140+
private static readonly EDIT_TOOLBAR_AVOID_MARGIN_VP = 12;
139141
/** 对齐辅助线位置 (vp),-1 表示隐藏 */
140142
@State private alignGuideX: number = -1;
141143
@State private alignGuideY: number = -1;
@@ -145,6 +147,9 @@ export struct CustomKeyOverlay {
145147
@State private groupDragKeyId: string = ''; // 正在被直接拖拽的键 ID
146148
@State private groupDragX: number = 0;
147149
@State private groupDragY: number = 0;
150+
/** 正在拖拽的按键,用于让编辑工具栏避让当前操作区域 */
151+
@State private activeDragKeyId: string = '';
152+
@State private activeDragY: number = 0;
148153

149154
/** 二维码分享面板 */
150155
@State private showSharePanel: boolean = false;
@@ -204,6 +209,90 @@ export struct CustomKeyOverlay {
204209
return this.keys.slice().sort((a: CustomKeyDef, b: CustomKeyDef) => a.layer - b.layer);
205210
}
206211

212+
private isEditToolbarVisible(): boolean {
213+
return this.editMode &&
214+
!this.showAddPanel &&
215+
!this.showPropertyPanel &&
216+
!this.showSharePanel &&
217+
!this.showThemePanel &&
218+
!this.showProfilePanel &&
219+
!this.showAiPanel;
220+
}
221+
222+
private getToolbarTargetKeyId(): string {
223+
return this.activeDragKeyId !== '' ? this.activeDragKeyId : this.selectedKeyId;
224+
}
225+
226+
private getToolbarTargetGroupId(): string {
227+
const keyId = this.getToolbarTargetKeyId();
228+
if (keyId === '') return '';
229+
const key = this.keys.find((item: CustomKeyDef): boolean => item.id === keyId);
230+
return key?.groupId ?? '';
231+
}
232+
233+
private isToolbarTargetKey(key: CustomKeyDef): boolean {
234+
const keyId = this.getToolbarTargetKeyId();
235+
if (keyId === '') return false;
236+
if (key.id === keyId) return true;
237+
const groupId = this.getToolbarTargetGroupId();
238+
return groupId !== '' && key.groupId === groupId;
239+
}
240+
241+
private getToolbarKeyVisualDy(key: CustomKeyDef): number {
242+
if (this.activeDragKeyId === '') return 0;
243+
if (key.id === this.activeDragKeyId) return this.activeDragY;
244+
const groupId = this.getToolbarTargetGroupId();
245+
if (groupId !== '' && key.groupId === groupId) {
246+
return this.activeDragY;
247+
}
248+
return 0;
249+
}
250+
251+
private getToolbarDockOverlapScore(dockTop: boolean, targetOnly: boolean): number {
252+
if (this.screenHeightVp <= 0) return 0;
253+
const margin = CustomKeyOverlay.EDIT_TOOLBAR_AVOID_MARGIN_VP;
254+
const bandTop = dockTop ? 0 : Math.max(0, this.screenHeightVp - EDIT_TOOLBAR_HEIGHT - margin);
255+
const bandBottom = dockTop ? Math.min(this.screenHeightVp, EDIT_TOOLBAR_HEIGHT + margin) : this.screenHeightVp;
256+
let score = 0;
257+
258+
for (const key of this.keys) {
259+
if (targetOnly && !this.isToolbarTargetKey(key)) continue;
260+
const dy = this.getToolbarKeyVisualDy(key);
261+
const keyTop = key.yPercent * this.screenHeightVp - key.height / 2 + dy;
262+
const keyBottom = key.yPercent * this.screenHeightVp + key.height / 2 + dy;
263+
const overlapTop = Math.max(keyTop, bandTop);
264+
const overlapBottom = Math.min(keyBottom, bandBottom);
265+
if (overlapBottom > overlapTop) {
266+
score += overlapBottom - overlapTop;
267+
}
268+
}
269+
270+
return score;
271+
}
272+
273+
private shouldDockToolbarToTop(): boolean {
274+
if (this.screenHeightVp <= 0) return false;
275+
276+
const bottomTargetScore = this.getToolbarDockOverlapScore(false, true);
277+
const topTargetScore = this.getToolbarDockOverlapScore(true, true);
278+
if (bottomTargetScore !== topTargetScore) {
279+
return topTargetScore < bottomTargetScore;
280+
}
281+
282+
const bottomScore = this.getToolbarDockOverlapScore(false, false);
283+
const topScore = this.getToolbarDockOverlapScore(true, false);
284+
if (bottomScore !== topScore) {
285+
return topScore < bottomScore;
286+
}
287+
288+
return false;
289+
}
290+
291+
private getEditToolbarY(): number {
292+
if (this.shouldDockToolbarToTop()) return 0;
293+
return Math.max(0, this.screenHeightVp - EDIT_TOOLBAR_HEIGHT);
294+
}
295+
207296
/** 屏幕变化监听回调引用,用于注销 */
208297
private displayChangeCallback: ((displayId: number) => void) | null = null;
209298

@@ -262,7 +351,7 @@ export struct CustomKeyOverlay {
262351
}
263352

264353
build() {
265-
Column() {
354+
Stack() {
266355
// 主区域
267356
Stack() {
268357
// 对齐辅助线(拖拽吸附时显示)
@@ -398,6 +487,8 @@ export struct CustomKeyOverlay {
398487
this.onKeyAction(action, isDown);
399488
},
400489
onGroupDragMove: (keyId: string, deltaX: number, deltaY: number): void => {
490+
this.activeDragKeyId = deltaX === 0 && deltaY === 0 ? '' : keyId;
491+
this.activeDragY = deltaY;
401492
// 更新组拖拽视觉偏移
402493
const dragKey = this.keys.find(k => k.id === keyId);
403494
if (dragKey && dragKey.groupId) {
@@ -417,6 +508,8 @@ export struct CustomKeyOverlay {
417508
this.groupDragKeyId = '';
418509
this.groupDragX = 0;
419510
this.groupDragY = 0;
511+
this.activeDragKeyId = '';
512+
this.activeDragY = 0;
420513
this.alignGuideX = -1;
421514
this.alignGuideY = -1;
422515
this.handleDragEnd(keyId, deltaX, deltaY);
@@ -564,14 +657,14 @@ export struct CustomKeyOverlay {
564657
}
565658
}
566659
.width('100%')
567-
.layoutWeight(1)
660+
.height('100%')
568661
.alignContent(Alignment.BottomStart)
569662
.hitTestBehavior(HitTestMode.Transparent)
570663
// hitTestReady: 微小 opacity 变化触发父层重渲染,刷新命中测试树
571664
.opacity(this.hidingForCapture ? 0 : (this.hitTestReady > 0 ? 1 : 0.99))
572665

573666
// 编辑模式工具栏(面板打开时隐藏,避免遮挡面板)
574-
if (this.editMode && !this.showAddPanel && !this.showPropertyPanel && !this.showSharePanel && !this.showThemePanel && !this.showProfilePanel && !this.showAiPanel) {
667+
if (this.isEditToolbarVisible()) {
575668
Row({ space: 12 }) {
576669
Row({ space: 4 }) {
577670
SymbolGlyph($r('sys.symbol.plus_circle'))
@@ -728,6 +821,8 @@ export struct CustomKeyOverlay {
728821
.backgroundColor('#CC1A1A2E')
729822
.backdropBlur(30)
730823
.border({ width: { top: 1 }, color: '#20FFFFFF' })
824+
.position({ x: 0, y: this.getEditToolbarY() })
825+
.hitTestBehavior(HitTestMode.Transparent)
731826
}
732827
}
733828
.width('100%')

0 commit comments

Comments
 (0)