feat(录音): RecordingOverlay 录音浮层(波形/上滑取消/太短,触摸穿透)
新增 entry/src/main/ets/components/RecordingOverlay.ets: - @Prop state: 'recording'|'cancel'|'tooShort' 三态展示 - recording 状态:7根波形柱 setInterval(120ms) 随机高度跳动动画 - cancel 状态:红底(#C0392B) + '✕' - tooShort 状态:暗底 + '!' - hitTestBehavior(HitTestMode.None) 触摸穿透到下方 Web,由容器 Web.onTouch 感知手势 - aboutToAppear/aboutToDisappear 正确管理 timer 生命周期 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
0a9ba6c8be
commit
481afc803d
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 录音浮层(设计 §10,纯展示,仿微信"按住说话")。状态由容器手势驱动,自身不处理触摸
|
||||
* (HitTestMode.None 让触摸穿透到下方 Web,由 Web.onTouch 观察手势)。
|
||||
* - recording:跳动波形 + "手指上滑,取消发送"
|
||||
* - cancel:红底 + "✕" + "松开手指,取消发送"
|
||||
* - tooShort:黑底 + "!" + "说话时间太短"
|
||||
*/
|
||||
@Component
|
||||
export struct RecordingOverlay {
|
||||
/** 'recording' | 'cancel' | 'tooShort' */
|
||||
@Prop state: string;
|
||||
@State private bars: number[] = [0.4, 0.7, 0.5, 0.9, 0.6, 0.8, 0.45];
|
||||
private timer: number = -1;
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.timer = setInterval(() => {
|
||||
this.bars = this.bars.map(() => 0.25 + 0.75 * Math.random());
|
||||
}, 120);
|
||||
}
|
||||
|
||||
aboutToDisappear(): void {
|
||||
if (this.timer >= 0) {
|
||||
clearInterval(this.timer);
|
||||
this.timer = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private hintText(): string {
|
||||
if (this.state === 'cancel') {
|
||||
return '松开手指,取消发送';
|
||||
}
|
||||
if (this.state === 'tooShort') {
|
||||
return '说话时间太短';
|
||||
}
|
||||
return '手指上滑,取消发送';
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Column({ space: 14 }) {
|
||||
if (this.state === 'recording') {
|
||||
Row({ space: 4 }) {
|
||||
ForEach(this.bars, (h: number, i: number) => {
|
||||
Column()
|
||||
.width(5)
|
||||
.height(48 * h)
|
||||
.borderRadius(3)
|
||||
.backgroundColor('#FFFFFF')
|
||||
}, (h: number, i: number) => i.toString())
|
||||
}
|
||||
.height(52)
|
||||
.alignItems(VerticalAlign.Center)
|
||||
} else {
|
||||
Text(this.state === 'cancel' ? '✕' : '!')
|
||||
.fontSize(42)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.fontColor('#FFFFFF')
|
||||
}
|
||||
Text(this.hintText())
|
||||
.fontSize(14)
|
||||
.fontColor('#FFFFFF')
|
||||
}
|
||||
.width(168)
|
||||
.height(168)
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.borderRadius(18)
|
||||
.backgroundColor(this.state === 'cancel' ? '#C0392B' : 'rgba(0, 0, 0, 0.78)')
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.hitTestBehavior(HitTestMode.None)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user