Files
keyboard/keyBoard/Class/AiTalk/V/KBVoiceInputBar.m
2026-01-26 18:17:02 +08:00

203 lines
5.6 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// KBVoiceInputBar.m
// keyBoard
//
// Created by Kiro on 2026/1/26.
//
#import "KBVoiceInputBar.h"
#import "KBAiRecordButton.h"
#import <Masonry/Masonry.h>
@interface KBVoiceInputBar () <KBAiRecordButtonDelegate>
/// 毛玻璃背景容器
@property (nonatomic, strong) UIView *backgroundView;
/// 毛玻璃效果
@property (nonatomic, strong) UIVisualEffectView *blurEffectView;
/// 状态标签
@property (nonatomic, strong) UILabel *statusLabel;
/// 录音按钮
@property (nonatomic, strong) KBAiRecordButton *recordButton;
/// 是否正在录音
@property (nonatomic, assign) BOOL isRecording;
@end
@implementation KBVoiceInputBar
#pragma mark - Lifecycle
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setupUI];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder {
if (self = [super initWithCoder:coder]) {
[self setupUI];
}
return self;
}
#pragma mark - 1控件初始化
- (void)setupUI {
self.backgroundColor = [UIColor clearColor];
self.enabled = YES;
self.isRecording = NO;
// 毛玻璃背景容器
[self addSubview:self.backgroundView];
[self.backgroundView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
// 毛玻璃效果
[self.backgroundView addSubview:self.blurEffectView];
[self.blurEffectView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.backgroundView);
}];
// 为 blurEffectView 创建透明度渐变 mask
CAGradientLayer *maskLayer = [CAGradientLayer layer];
maskLayer.startPoint = CGPointMake(0.5, 1); // 底部
maskLayer.endPoint = CGPointMake(0.5, 0); // 顶部
maskLayer.colors = @[
(__bridge id)[UIColor whiteColor].CGColor, // 底部:完全不透明
(__bridge id)[UIColor whiteColor].CGColor, // 中间:完全不透明
(__bridge id)[UIColor clearColor].CGColor // 顶部:完全透明
];
maskLayer.locations = @[@(0.0), @(0.5), @(1.0)];
self.blurEffectView.layer.mask = maskLayer;
// 状态标签
[self addSubview:self.statusLabel];
[self.statusLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self).offset(16);
make.left.equalTo(self).offset(20);
make.right.equalTo(self).offset(-20);
make.height.mas_equalTo(20);
}];
// 录音按钮
[self addSubview:self.recordButton];
[self.recordButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.statusLabel.mas_bottom).offset(12);
make.left.equalTo(self).offset(20);
make.right.equalTo(self).offset(-20);
make.height.mas_equalTo(50);
make.bottom.lessThanOrEqualTo(self).offset(-16);
}];
}
- (void)layoutSubviews {
[super layoutSubviews];
// 更新 mask 的 frame
if (self.blurEffectView.layer.mask) {
self.blurEffectView.layer.mask.frame = self.blurEffectView.bounds;
}
}
#pragma mark - Setter
- (void)setStatusText:(NSString *)statusText {
_statusText = [statusText copy];
self.statusLabel.text = statusText;
}
- (void)setEnabled:(BOOL)enabled {
_enabled = enabled;
self.recordButton.userInteractionEnabled = enabled;
self.recordButton.alpha = enabled ? 1.0 : 0.5;
}
- (void)setRecording:(BOOL)recording {
_isRecording = recording;
self.recordButton.state = recording ? KBAiRecordButtonStateRecording : KBAiRecordButtonStateNormal;
}
#pragma mark - Public Methods
- (void)updateVolumeRMS:(float)rms {
[self.recordButton updateVolumeRMS:rms];
}
#pragma mark - KBAiRecordButtonDelegate
- (void)recordButtonDidBeginPress:(KBAiRecordButton *)button {
if (!self.enabled) {
return;
}
self.isRecording = YES;
if ([self.delegate respondsToSelector:@selector(voiceInputBarDidBeginRecording:)]) {
[self.delegate voiceInputBarDidBeginRecording:self];
}
}
- (void)recordButtonDidEndPress:(KBAiRecordButton *)button {
self.isRecording = NO;
if ([self.delegate respondsToSelector:@selector(voiceInputBarDidEndRecording:)]) {
[self.delegate voiceInputBarDidEndRecording:self];
}
}
- (void)recordButtonDidCancelPress:(KBAiRecordButton *)button {
self.isRecording = NO;
if ([self.delegate respondsToSelector:@selector(voiceInputBarDidCancelRecording:)]) {
[self.delegate voiceInputBarDidCancelRecording:self];
}
}
#pragma mark - Lazy Load
- (UIView *)backgroundView {
if (!_backgroundView) {
_backgroundView = [[UIView alloc] init];
_backgroundView.clipsToBounds = YES;
}
return _backgroundView;
}
- (UIVisualEffectView *)blurEffectView {
if (!_blurEffectView) {
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
_blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
}
return _blurEffectView;
}
- (UILabel *)statusLabel {
if (!_statusLabel) {
_statusLabel = [[UILabel alloc] init];
_statusLabel.text = @"按住按钮开始对话";
_statusLabel.font = [UIFont systemFontOfSize:14];
_statusLabel.textColor = [UIColor secondaryLabelColor];
_statusLabel.textAlignment = NSTextAlignmentCenter;
}
return _statusLabel;
}
- (KBAiRecordButton *)recordButton {
if (!_recordButton) {
_recordButton = [[KBAiRecordButton alloc] init];
_recordButton.delegate = self;
_recordButton.normalTitle = @"按住说话";
_recordButton.recordingTitle = @"松开结束";
}
return _recordButton;
}
@end