Files
keyboard/keyBoard/Class/Guard/V/KBKeyboardMaskView.m

229 lines
8.2 KiB
Mathematica
Raw Normal View History

2025-11-27 15:34:33 +08:00
//
// KBKeyboardMaskView.m
// keyBoard
//
// Created by Mac on 2025/11/27.
//
#import "KBKeyboardMaskView.h"
2025-11-28 16:06:34 +08:00
#import <AVFoundation/AVFoundation.h>
2025-11-27 15:34:33 +08:00
@interface KBKeyboardMaskView ()
@property (nonatomic, strong) UIButton *backButton;
2025-11-28 16:06:34 +08:00
@property (nonatomic, strong) UIView *videoContainerView; // GIF
@property (nonatomic, strong) AVPlayer *kb_maskPlayer; //
@property (nonatomic, strong) AVPlayerLayer *kb_maskPlayerLayer;
@property (nonatomic, strong) UIImageView *tipLabel; //
2025-11-27 15:34:33 +08:00
@property (nonatomic, assign) CGFloat keyboardHeight;
@end
@implementation KBKeyboardMaskView
2025-11-27 20:05:39 +08:00
static const CGFloat KGifViewH = (209);
2025-11-27 15:34:33 +08:00
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (!self) return nil;
2025-11-27 19:20:20 +08:00
self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
2025-11-27 15:34:33 +08:00
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);
2025-11-27 20:05:39 +08:00
2025-11-27 15:34:33 +08:00
make.width.height.mas_equalTo(40);
}];
2025-11-28 16:06:34 +08:00
// GIF
_videoContainerView = [UIView new];
_videoContainerView.backgroundColor = [UIColor clearColor];
_videoContainerView.clipsToBounds = YES;
_videoContainerView.layer.cornerRadius = 30.0;
_videoContainerView.layer.masksToBounds = YES;
[self addSubview:_videoContainerView];
2025-11-27 15:34:33 +08:00
2025-11-28 16:06:34 +08:00
[_videoContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
2025-11-27 15:34:33 +08:00
make.centerX.equalTo(self);
2025-11-27 19:20:20 +08:00
make.width.mas_equalTo(KBFit(316));
2025-11-27 20:05:39 +08:00
make.height.mas_equalTo(KBFit(KGifViewH));
2025-11-27 15:34:33 +08:00
// layoutSubviews
}];
2025-11-27 20:05:39 +08:00
//
_tipLabel = [UIImageView new];
_tipLabel.image = [UIImage imageNamed:@"mask_top_title"];
_tipLabel.contentMode = UIViewContentModeScaleAspectFit;
[self addSubview:_tipLabel];
2025-11-27 15:34:33 +08:00
//
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapMask:)];
[self addGestureRecognizer:tap];
2025-11-28 16:06:34 +08:00
// App
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(kb_maskAppDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(kb_maskAppDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
//
[self kb_setupGuideVideoPlayerIfNeeded];
2025-11-27 15:34:33 +08:00
return self;
}
2025-11-28 16:06:34 +08:00
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
2025-11-27 15:34:33 +08:00
- (void)layoutSubviews {
[super layoutSubviews];
2025-11-28 16:06:34 +08:00
//
2025-11-27 15:34:33 +08:00
// -
// - 20pt safe
CGFloat viewH = CGRectGetHeight(self.bounds);
2025-11-27 20:05:39 +08:00
CGFloat gifH = KBFit(KGifViewH);
2025-11-27 15:34:33 +08:00
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;
}
2025-11-28 16:06:34 +08:00
CGRect gifFrame = self.videoContainerView.frame;
2025-11-27 20:05:39 +08:00
gifFrame.origin.y = y;
2025-11-28 16:06:34 +08:00
self.videoContainerView.frame = gifFrame;
2025-11-27 20:05:39 +08:00
2025-11-28 16:06:34 +08:00
// 20pt
2025-11-27 20:05:39 +08:00
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;
2025-11-28 16:06:34 +08:00
CGFloat labelBottom = CGRectGetMinY(self.videoContainerView.frame) - 20.0;
2025-11-27 20:05:39 +08:00
CGFloat labelY = labelBottom - labelH;
self.tipLabel.frame = CGRectMake(labelX, labelY, labelW, labelH);
2025-11-28 16:06:34 +08:00
// 使
if (self.kb_maskPlayerLayer) {
self.kb_maskPlayerLayer.frame = self.videoContainerView.bounds;
}
}
- (void)setHidden:(BOOL)hidden {
[super setHidden:hidden];
if (hidden) {
[self.kb_maskPlayer pause];
} else {
[self.kb_maskPlayer play];
}
2025-11-27 15:34:33 +08:00
}
- (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);
2025-11-28 16:06:34 +08:00
// 便 layoutSubviews Y
2025-11-27 15:34:33 +08:00
[self setNeedsLayout];
[UIView animateWithDuration:duration
delay:0
options:curve
animations:^{
[self layoutIfNeeded];
}
completion:nil];
}
2025-11-28 16:06:34 +08:00
#pragma mark - App Lifecycle
- (void)kb_maskAppDidBecomeActive:(NSNotification *)note {
//
if (self.window && !self.hidden) {
if (!self.kb_maskPlayer) {
[self kb_setupGuideVideoPlayerIfNeeded];
} else {
[self.kb_maskPlayer play];
}
}
}
- (void)kb_maskAppDidEnterBackground:(NSNotification *)note {
[self.kb_maskPlayer pause];
}
#pragma mark - Video
- (void)kb_setupGuideVideoPlayerIfNeeded {
if (self.kb_maskPlayer) { return; }
NSURL *videoURL = [[NSBundle mainBundle] URLForResource:@"permiss_video_2" withExtension:@"mp4"];
if (!videoURL) { return; }
AVPlayerItem *item = [AVPlayerItem playerItemWithURL:videoURL];
self.kb_maskPlayer = [AVPlayer playerWithPlayerItem:item];
self.kb_maskPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
self.kb_maskPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.kb_maskPlayer];
self.kb_maskPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
self.kb_maskPlayerLayer.cornerRadius = 30.0;
self.kb_maskPlayerLayer.masksToBounds = YES;
[self.videoContainerView.layer addSublayer:self.kb_maskPlayerLayer];
//
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(kb_maskPlayerDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:item];
[self.kb_maskPlayer play];
}
- (void)kb_maskPlayerDidReachEnd:(NSNotification *)note {
AVPlayerItem *item = (AVPlayerItem *)note.object;
if (!item) return;
__weak typeof(self) weakSelf = self;
[item seekToTime:kCMTimeZero completionHandler:^(BOOL finished) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf.kb_maskPlayer play];
}];
}
2025-11-27 15:34:33 +08:00
@end