Commit b946c1cd by suolong

1

parent e422cb9b
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
/**
限时表演(主播端)取消表演二次确认弹窗视图
设计目标:
- 独立于 Helper 的 UI 视图类,仅负责界面与交互展示
- 提供 30s(或外部传入)自动取消倒计时,倒计时结束自动触发“确定”
- 外部通过 block 获取“继续表演”和“确定”两种操作结果
- 使用 Masonry 进行约束布局,样式复用项目统一的配色和字体工具
*/
@interface FUSLiveShowTimeCancelConfirmPopView : UIView
/** 用户点击“继续表演”后的回调(不取消当前回合) */
@property (nonatomic, copy, nullable) void (^continueHandler)(void);
/** 用户点击“确定”或倒计时归零后的回调(取消当前回合) */
@property (nonatomic, copy, nullable) void (^confirmHandler)(void);
/**
在指定父视图上展示弹窗并启动倒计时
@param onView 承载弹窗的父视图(通常为手动弹层容器或顶层 VC.view)
@param seconds 初始倒计时秒数(<=0 则不展示倒计时文案与自动取消逻辑)
@return 已添加到父视图上的弹窗实例
*/
+ (instancetype)fus_showOnView:(UIView *)onView countdownSeconds:(NSInteger)seconds;
/**
主动关闭弹窗
说明:会停止内部倒计时并移除自身
*/
- (void)fus_dismiss;
/**
获取当前剩余倒计时秒数
用途:在弹窗被关闭或二次出现时,用于外部延续倒计时状态
@return 当前剩余秒数(最小为 0)
*/
- (NSInteger)fus_currentRemainingSeconds;
@end
NS_ASSUME_NONNULL_END
#import "FUSLiveShowTimeCancelConfirmPopView.h"
#import <Masonry/Masonry.h>
#import <FUSFoundation/FUSFoundation-Swift.h>
@interface FUSLiveShowTimeCancelConfirmPopView ()
@property (nonatomic, strong) UIButton *bgButton;
@property (nonatomic, strong) UIView *contentView;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *countdownLabel;
@property (nonatomic, strong) UIButton *continueButton;
@property (nonatomic, strong) UIButton *confirmButton;
@property (nonatomic, assign) NSInteger remainingSeconds;
@property (nonatomic, strong, nullable) dispatch_source_t countdownTimer;
@property (nonatomic, assign) BOOL hasConfirmed;
@end
@implementation FUSLiveShowTimeCancelConfirmPopView
+ (instancetype)fus_showOnView:(UIView *)onView countdownSeconds:(NSInteger)seconds {
if (!onView) {
return [[self alloc] initWithFrame:CGRectZero];
}
FUSLiveShowTimeCancelConfirmPopView *view = [[FUSLiveShowTimeCancelConfirmPopView alloc] initWithFrame:CGRectZero];
[onView addSubview:view];
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(onView);
}];
view.alpha = 0;
[UIView animateWithDuration:0.2 animations:^{
view.alpha = 1;
}];
if (seconds > 0) {
[view fus_startCountdownWithSeconds:seconds];
} else {
view.countdownLabel.text = @"";
}
return view;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (!self) {
return nil;
}
self.backgroundColor = UIColor.clearColor;
_remainingSeconds = 0;
_hasConfirmed = NO;
[self fus_setupViews];
[self fus_setupConstraints];
return self;
}
- (void)dealloc {
[self fus_stopCountdownTimer];
}
- (void)fus_setupViews {
self.bgButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.bgButton.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
[self addSubview:self.bgButton];
self.contentView = [[UIView alloc] initWithFrame:CGRectZero];
self.contentView.backgroundColor = UIColor.whiteColor;
self.contentView.layer.cornerRadius = 12;
self.contentView.layer.masksToBounds = YES;
[self addSubview:self.contentView];
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.titleLabel.text = [NSString fus_localString:@"确定取消表演?"];
self.titleLabel.textColor = [UIColor colorWithHex:@"#111111"];
self.titleLabel.font = [UIFont fus_themeBoldFont:16];
self.titleLabel.textAlignment = NSTextAlignmentCenter;
[self.contentView addSubview:self.titleLabel];
self.countdownLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.countdownLabel.text = @"";
self.countdownLabel.textColor = [UIColor colorWithHex:@"#9AA0A6"];
self.countdownLabel.font = [UIFont fus_themeFont:12];
self.countdownLabel.textAlignment = NSTextAlignmentCenter;
[self.contentView addSubview:self.countdownLabel];
CGFloat buttonH = 40;
self.continueButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.continueButton.backgroundColor = UIColor.whiteColor;
self.continueButton.layer.cornerRadius = buttonH / 2.0;
self.continueButton.layer.masksToBounds = YES;
self.continueButton.layer.borderWidth = 1;
self.continueButton.layer.borderColor = [UIColor colorWithHex:@"#E6E8EB"].CGColor;
[self.continueButton setTitle:[NSString fus_localString:@"继续表演"] forState:UIControlStateNormal];
[self.continueButton setTitleColor:[UIColor colorWithHex:@"#1F1F1F"] forState:UIControlStateNormal];
self.continueButton.titleLabel.font = [UIFont fus_themeBoldFont:15];
[self.continueButton addTarget:self action:@selector(fus_onTapContinue) forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:self.continueButton];
self.confirmButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.confirmButton.backgroundColor = [UIColor colorWithHex:@"#52DDE2"];
self.confirmButton.layer.cornerRadius = buttonH / 2.0;
self.confirmButton.layer.masksToBounds = YES;
[self.confirmButton setTitle:[NSString fus_localString:@"确定"] forState:UIControlStateNormal];
[self.confirmButton setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
self.confirmButton.titleLabel.font = [UIFont fus_themeBoldFont:15];
[self.confirmButton addTarget:self action:@selector(fus_onTapConfirm) forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:self.confirmButton];
}
- (void)fus_setupConstraints {
[self.bgButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self);
make.width.equalTo(@295).priorityHigh();
make.left.greaterThanOrEqualTo(self).offset(40);
make.right.lessThanOrEqualTo(self).offset(-40);
}];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.contentView).offset(24);
make.left.equalTo(self.contentView).offset(20);
make.right.equalTo(self.contentView).offset(-20);
}];
[self.countdownLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.titleLabel.mas_bottom).offset(10);
make.left.equalTo(self.contentView).offset(20);
make.right.equalTo(self.contentView).offset(-20);
}];
CGFloat buttonH = 40;
[self.continueButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.countdownLabel.mas_bottom).offset(20);
make.left.equalTo(self.contentView).offset(20);
make.height.equalTo(@(buttonH));
make.bottom.equalTo(self.contentView).offset(-20);
}];
[self.confirmButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.equalTo(self.continueButton);
make.left.equalTo(self.continueButton.mas_right).offset(12);
make.right.equalTo(self.contentView).offset(-20);
make.width.equalTo(self.continueButton);
}];
}
- (void)fus_startCountdownWithSeconds:(NSInteger)seconds {
self.remainingSeconds = MAX(0, seconds);
[self fus_refreshCountdownText];
[self fus_stopCountdownTimer];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
self.countdownTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(self.countdownTimer, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC), NSEC_PER_SEC, 0);
__weak typeof(self) weakSelf = self;
dispatch_source_set_event_handler(self.countdownTimer, ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
if (strongSelf.remainingSeconds <= 0) {
dispatch_source_cancel(strongSelf.countdownTimer);
strongSelf.countdownTimer = nil;
dispatch_async(dispatch_get_main_queue(), ^{
[strongSelf fus_triggerConfirmIfNeeded];
});
return;
}
strongSelf.remainingSeconds -= 1;
dispatch_async(dispatch_get_main_queue(), ^{
[strongSelf fus_refreshCountdownText];
});
});
dispatch_resume(self.countdownTimer);
}
- (void)fus_stopCountdownTimer {
if (self.countdownTimer) {
dispatch_source_cancel(self.countdownTimer);
self.countdownTimer = nil;
}
}
- (void)fus_refreshCountdownText {
NSInteger seconds = MAX(0, self.remainingSeconds);
self.countdownLabel.text = [NSString stringWithFormat:@"%zdS%@", (NSInteger)seconds, [NSString fus_localString:@"后自动取消"]];
}
- (void)fus_onTapContinue {
if (self.hasConfirmed) {
return;
}
[self fus_stopCountdownTimer];
if (self.continueHandler) {
self.continueHandler();
}
}
- (void)fus_onTapConfirm {
[self fus_triggerConfirmIfNeeded];
}
- (void)fus_triggerConfirmIfNeeded {
if (self.hasConfirmed) {
return;
}
self.hasConfirmed = YES;
[self fus_stopCountdownTimer];
self.continueButton.enabled = NO;
self.confirmButton.enabled = NO;
if (self.confirmHandler) {
self.confirmHandler();
}
}
- (void)fus_dismiss {
[self fus_stopCountdownTimer];
[UIView animateWithDuration:0.2 animations:^{
self.alpha = 0;
} completion:^(BOOL finished) {
[self removeFromSuperview];
}];
}
- (NSInteger)fus_currentRemainingSeconds {
return MAX(0, self.remainingSeconds);
}
@end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment