Files
keyboard/keyBoard/Class/Guard/V/KBKeyboardMaskView.m
2025-11-27 20:05:39 +08:00

152 lines
5.2 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.

//
// KBKeyboardMaskView.m
// keyBoard
//
// Created by Mac on 2025/11/27.
//
#import "KBKeyboardMaskView.h"
@interface KBKeyboardMaskView ()
@property (nonatomic, strong) UIButton *backButton;
@property (nonatomic, strong) FLAnimatedImageView *gifView;
@property (nonatomic, strong) UIImageView *tipLabel; // 顶部提示图
@property (nonatomic, assign) CGFloat keyboardHeight;
@end
@implementation KBKeyboardMaskView
static const CGFloat KGifViewH = (209);
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (!self) return nil;
self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
self.userInteractionEnabled = YES;
// 返回按钮
_backButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *backImg = [UIImage imageNamed:@"close_white2_icon"];
[_backButton setImage:backImg forState:UIControlStateNormal];
[self addSubview:_backButton];
[_backButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self).offset(9);
make.top.equalTo(self.mas_safeAreaLayoutGuideTop).offset(4);
make.width.height.mas_equalTo(40);
}];
// GIF 区域
_gifView = [FLAnimatedImageView new];
_gifView.contentMode = UIViewContentModeScaleAspectFit;
_gifView.clipsToBounds = YES;
_gifView.layer.cornerRadius = 30;
// _gifView.clipsToBounds = true;
_gifView.layer.masksToBounds = true;
[self addSubview:_gifView];
[_gifView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self);
make.width.mas_equalTo(KBFit(316));
make.height.mas_equalTo(KBFit(KGifViewH));
// 竖直方向不在这里约束,由 layoutSubviews 手动布局
}];
// 顶部提示图
_tipLabel = [UIImageView new];
_tipLabel.image = [UIImage imageNamed:@"mask_top_title"];
_tipLabel.contentMode = UIViewContentModeScaleAspectFit;
[self addSubview:_tipLabel];
// 整个蒙层点击:激活输入框
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapMask:)];
[self addGestureRecognizer:tap];
// 加载 GIF 资源(占位名,可按需更换为实际文件名)
NSString *gifPath = [[NSBundle mainBundle] pathForResource:@"kb_guide_keyboard" ofType:@"gif"];
if (gifPath.length > 0) {
NSData *data = [NSData dataWithContentsOfFile:gifPath];
if (data.length > 0) {
FLAnimatedImage *img = [FLAnimatedImage animatedImageWithGIFData:data];
_gifView.animatedImage = img;
}
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
// 根据键盘高度,保证 GIF 不被遮挡:
// - 无键盘:居中显示;
// - 有键盘:底部距离键盘上方 20pt若空间不足则向上顶到顶部预留的 safe 区域。
CGFloat viewH = CGRectGetHeight(self.bounds);
CGFloat gifH = KBFit(KGifViewH);
CGFloat topMargin = 80.0; // 预留给返回按钮和标题等
CGFloat bottomMargin = 20.0;
CGFloat y = 0;
if (self.keyboardHeight <= 0) {
// 无键盘:垂直居中
y = (viewH - gifH) * 0.5;
if (y < topMargin) y = topMargin;
} else {
CGFloat maxBottom = viewH - self.keyboardHeight - bottomMargin;
y = maxBottom - gifH;
if (y < topMargin) y = topMargin;
}
CGRect gifFrame = self.gifView.frame;
gifFrame.origin.y = y;
self.gifView.frame = gifFrame;
// 布局顶部提示图:底部距离 gifView 顶部 20pt居中显示
CGFloat labelMaxWidth = CGRectGetWidth(self.bounds) - 40.0; // 左右各留 20
if (labelMaxWidth < 0) { labelMaxWidth = 0; }
UIImage *tipImage = self.tipLabel.image;
if (!tipImage) { return; }
CGFloat imgW = tipImage.size.width;
CGFloat imgH = tipImage.size.height;
if (imgW <= 0 || imgH <= 0) { return; }
CGFloat scale = 1.0;
if (imgW > labelMaxWidth && labelMaxWidth > 0) {
scale = labelMaxWidth / imgW;
}
CGFloat labelW = imgW * scale;
CGFloat labelH = imgH * scale;
CGFloat labelX = (CGRectGetWidth(self.bounds) - labelW) * 0.5;
CGFloat labelBottom = CGRectGetMinY(self.gifView.frame) - 20.0;
CGFloat labelY = labelBottom - labelH;
self.tipLabel.frame = CGRectMake(labelX, labelY, labelW, labelH);
}
- (void)onTapMask:(UITapGestureRecognizer *)gr {
CGPoint p = [gr locationInView:self];
// 如果点在返回按钮区域内,则不走 tapHandler交由按钮自己的事件处理
if (CGRectContainsPoint(self.backButton.frame, p)) {
return;
}
if (self.tapHandler) {
self.tapHandler();
}
}
- (void)updateForKeyboardHeight:(CGFloat)kbHeight
duration:(NSTimeInterval)duration
curve:(UIViewAnimationOptions)curve {
self.keyboardHeight = MAX(kbHeight, 0);
// 触发布局刷新,以便在 layoutSubviews 里根据最新键盘高度重算 gifView 的 Y 值
[self setNeedsLayout];
[UIView animateWithDuration:duration
delay:0
options:curve
animations:^{
[self layoutIfNeeded];
}
completion:nil];
}
@end