This commit is contained in:
2026-02-02 19:07:00 +08:00
parent 0416a64235
commit 993ec623af
3 changed files with 85 additions and 3 deletions

View File

@@ -25,6 +25,9 @@ NS_ASSUME_NONNULL_BEGIN
/// 波形条间距
@property(nonatomic, assign) CGFloat barSpacing;
/// 自定义柱状高度基准0~1长度需 >= barCount未设置则使用默认算法
@property(nonatomic, strong, nullable) NSArray<NSNumber *> *barHeightPattern;
/// 更新音量值
/// @param rms 音量 RMS 值 (0.0 - 1.0)
- (void)updateWithRMS:(float)rms;

View File

@@ -74,6 +74,11 @@
CGFloat x = startX + i * (self.barWidth + self.barSpacing);
CGFloat height = minHeight;
if (self.barHeightPattern.count > i) {
CGFloat base = [self.barHeightPattern[i] floatValue];
base = MIN(MAX(base, 0.15), 0.9);
height = MAX(minHeight, maxHeight * base);
}
CGFloat y = (maxHeight - height) / 2;
barLayer.frame = CGRectMake(x, y, self.barWidth, height);
@@ -141,9 +146,15 @@
CGFloat phase = (CGFloat)i / self.barLayers.count * M_PI * 2;
CGFloat wave = sin(time * 3 + phase) * 0.3 + 0.7; // 0.4 - 1.0
//
CGFloat heightFactor = rms * wave;
CGFloat height = minHeight + range * heightFactor;
CGFloat baseFactor = 0.2;
if (self.barHeightPattern.count > i) {
baseFactor = [self.barHeightPattern[i] floatValue];
baseFactor = MIN(MAX(baseFactor, 0.15), 0.9);
}
// + RMS
CGFloat dynamicFactor = rms * (0.35 + 0.15 * wave); // 0.35~0.5
CGFloat heightFactor = MIN(1.0, baseFactor + dynamicFactor * (1.0 - baseFactor));
CGFloat height = maxHeight * heightFactor;
height = MAX(minHeight, MIN(maxHeight, height));
//

View File

@@ -7,6 +7,7 @@
#import "KBVoiceInputBar.h"
#import "KBAiRecordButton.h"
#import "KBAiWaveformView.h"
#import <Masonry/Masonry.h>
@interface KBVoiceInputBar () <KBAiRecordButtonDelegate>
@@ -34,6 +35,8 @@
///
@property (nonatomic, strong) UIView *recordingView;
@property (nonatomic, strong) UIImageView *recordingCenterIconView;
@property (nonatomic, strong) KBAiWaveformView *leftWaveformView;
@property (nonatomic, strong) KBAiWaveformView *rightWaveformView;
///
@property (nonatomic, strong) UIView *cancelView;
@@ -146,6 +149,21 @@
make.width.height.mas_equalTo(36);
}];
[self.recordingView addSubview:self.leftWaveformView];
[self.recordingView addSubview:self.rightWaveformView];
[self.leftWaveformView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.recordingCenterIconView);
make.right.equalTo(self.recordingCenterIconView.mas_left).offset(-16);
make.width.mas_equalTo(84);
make.height.mas_equalTo(34);
}];
[self.rightWaveformView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.recordingCenterIconView);
make.left.equalTo(self.recordingCenterIconView.mas_right).offset(16);
make.width.mas_equalTo(84);
make.height.mas_equalTo(34);
}];
//
[self.inputContainer addSubview:self.cancelView];
[self.cancelView mas_makeConstraints:^(MASConstraintMaker *make) {
@@ -224,6 +242,11 @@
if (!self.toggleIconButton.hidden) {
[self.inputContainer bringSubviewToFront:self.toggleIconButton];
}
if (inputState == KBVoiceInputBarStateRecording) {
[self startRecordingWaveAnimationIfNeeded];
} else {
[self stopRecordingWaveAnimation];
}
[self updateCenterTextIfNeeded];
}
@@ -231,6 +254,11 @@
- (void)updateVolumeRMS:(float)rms {
[self.recordButton updateVolumeRMS:rms];
if (self.inputState == KBVoiceInputBarStateRecording) {
CGFloat safeRMS = MAX(rms, 0.6f);
[self.leftWaveformView updateWithRMS:safeRMS];
[self.rightWaveformView updateWithRMS:safeRMS];
}
}
#pragma mark - KBAiRecordButtonDelegate
@@ -370,6 +398,30 @@
return _recordingCenterIconView;
}
- (KBAiWaveformView *)leftWaveformView {
if (!_leftWaveformView) {
_leftWaveformView = [[KBAiWaveformView alloc] init];
_leftWaveformView.waveColor = [UIColor whiteColor];
_leftWaveformView.barCount = 7;
_leftWaveformView.barWidth = 3;
_leftWaveformView.barSpacing = 6;
_leftWaveformView.barHeightPattern = @[@0.35, @0.85, @0.5, @0.35, @0.9, @0.55, @0.35];
}
return _leftWaveformView;
}
- (KBAiWaveformView *)rightWaveformView {
if (!_rightWaveformView) {
_rightWaveformView = [[KBAiWaveformView alloc] init];
_rightWaveformView.waveColor = [UIColor whiteColor];
_rightWaveformView.barCount = 7;
_rightWaveformView.barWidth = 3;
_rightWaveformView.barSpacing = 6;
_rightWaveformView.barHeightPattern = @[@0.35, @0.85, @0.5, @0.35, @0.9, @0.55, @0.35];
}
return _rightWaveformView;
}
- (UIView *)cancelView {
if (!_cancelView) {
_cancelView = [[UIView alloc] init];
@@ -478,4 +530,20 @@
}
}
#pragma mark - Recording Wave
- (void)startRecordingWaveAnimationIfNeeded {
[self.leftWaveformView startIdleAnimation];
[self.rightWaveformView startIdleAnimation];
[self.leftWaveformView updateWithRMS:0.7f];
[self.rightWaveformView updateWithRMS:0.7f];
}
- (void)stopRecordingWaveAnimation {
[self.leftWaveformView stopAnimation];
[self.rightWaveformView stopAnimation];
[self.leftWaveformView reset];
[self.rightWaveformView reset];
}
@end