换肤完成

This commit is contained in:
启星
2025-08-18 15:23:07 +08:00
parent 4b577a31f0
commit 72d156aa41
59 changed files with 585 additions and 420 deletions

View File

@@ -0,0 +1,30 @@
//
// QXSkyPraizeView.h
// QXLive
//
// Created by 启星 on 2025/8/16.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface QXSkyPraizeView : UIView
-(void)showInView:(UIView *)view;
@end
@interface QXSkyPraizeSubView :UIView
@property (nonatomic,strong)UIView *bgView;
@property (nonatomic,strong)UIImageView *bgImageView;
@property (nonatomic,strong)UIImageView *giftImageView;
@property (nonatomic,strong)UILabel *titleLabel;
@property (nonatomic,strong)UIButton *giftCoin;
@property (nonatomic,assign)BOOL isSelected;
- (void)startPulseAnimationWithLayer;
// 停止动画
- (void)stopPulseAnimationWithLayer;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,459 @@
//
// QXSkyPraizeView.m
// QXLive
//
// Created by on 2025/8/16.
//
#import "QXSkyPraizeView.h"
/// 12
static NSInteger giftMaxCount = 12;
/// 2
static NSInteger minRoundCount = 2;
/// 4
static NSInteger toSlowCount = 4;
@interface QXSkyPraizeView()<UIGestureRecognizerDelegate>
///
@property (nonatomic,assign)NSInteger targetIndex;
@property (nonatomic,strong)NSMutableArray* targetArrayIndex;
@property (nonatomic,strong)NSMutableArray* finishTargetArrayIndex;
///
@property (nonatomic,assign)NSInteger currentIndex;
///
@property (nonatomic,assign)NSInteger roundCount;
///
@property (nonatomic,assign)double delayTime;
/// 22 33 44 100
@property (nonatomic,assign)NSInteger startType;
@property (nonatomic,strong)QXSkyPraizeSubView *currentGiftView;
@property (nonatomic,strong)UIView *bgView;
@property (nonatomic,strong)NSMutableArray *allViewsArray;
@property (nonatomic,strong)dispatch_source_t fastTimer;
@property (nonatomic,strong)dispatch_source_t slowTimer;
@end
@implementation QXSkyPraizeView
- (instancetype)init
{
self = [super init];
if (self) {
self.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
[self initSubviews];
}
return self;
}
-(void)initSubviews{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hide)];
tap.delegate = self;
[self addGestureRecognizer:tap];
self.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.3];
self.bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, ScaleWidth(520)+kSafeAreaBottom)];
self.bgView.backgroundColor = UIColor.whiteColor;
[self.bgView addRoundedCornersWithRadius:16 byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight)];
[self addSubview:self.bgView];
CGFloat topMargin = 60;
CGFloat margin = 16;
CGFloat space = 10;
CGFloat itemWidth = (SCREEN_WIDTH - margin*2 - space*3) / 4;
CGFloat itemHeight = itemWidth/7*8;;
for (int i = 0; i < giftMaxCount; i++) {
QXSkyPraizeSubView *giftView;
if (i < 4) {
/// 4
giftView = [[QXSkyPraizeSubView alloc] initWithFrame:CGRectMake(margin+(itemWidth+space)*i, topMargin, itemWidth, itemHeight)];
giftView.titleLabel.text = [NSString stringWithFormat:@"%d",i];
[self.allViewsArray replaceObjectAtIndex:i withObject:giftView];
}else if (i > 3 && i < 6){
///
if (i == 4) {
giftView = [[QXSkyPraizeSubView alloc] initWithFrame:CGRectMake(margin, topMargin+itemHeight+space, itemWidth, itemHeight)];
giftView.titleLabel.text = [NSString stringWithFormat:@"%d",11];
[self.allViewsArray replaceObjectAtIndex:11 withObject:giftView];
}else{
giftView = [[QXSkyPraizeSubView alloc] initWithFrame:CGRectMake(margin+(itemWidth+space)*3, topMargin+itemHeight+space, itemWidth, itemHeight)];
[self.allViewsArray replaceObjectAtIndex:4 withObject:giftView];
giftView.titleLabel.text = [NSString stringWithFormat:@"%d",4];
}
}else if (i > 5 && i < 8){
///
if (i == 6) {
giftView = [[QXSkyPraizeSubView alloc] initWithFrame:CGRectMake(margin, topMargin+(itemHeight+space)*2, itemWidth, itemHeight)];
[self.allViewsArray replaceObjectAtIndex:10 withObject:giftView];
giftView.titleLabel.text = [NSString stringWithFormat:@"%d",10];
}else{
giftView = [[QXSkyPraizeSubView alloc] initWithFrame:CGRectMake(margin+(itemWidth+space)*3, topMargin+(itemHeight+space)*2, itemWidth, itemHeight)];
[self.allViewsArray replaceObjectAtIndex:5 withObject:giftView];
giftView.titleLabel.text = [NSString stringWithFormat:@"%d",5];
}
}else{
giftView = [[QXSkyPraizeSubView alloc] initWithFrame:CGRectMake(margin+(itemWidth+space)*(i%4), topMargin+(itemHeight+space)*3, itemWidth, itemHeight)];
[self.allViewsArray replaceObjectAtIndex:11-(i-6) withObject:giftView];
giftView.titleLabel.text = [NSString stringWithFormat:@"%d",11-(i-6)];
}
[self.bgView addSubview:giftView];
}
[self resetViews];
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(16, 20, 100, 40)];
[btn setTitle:@"抽1次" forState:(UIControlStateNormal)];
[btn setTitleColor:UIColor.blueColor forState:(UIControlStateNormal)];
btn.tag = 22;
[btn addTarget:self action:@selector(startAction:) forControlEvents:(UIControlEventTouchUpInside)];
[self.bgView addSubview:btn];
UIButton *tenBtn = [[UIButton alloc] initWithFrame:CGRectMake(116, 20, 100, 40)];
[tenBtn setTitle:@"抽10次" forState:(UIControlStateNormal)];
tenBtn.tag = 33;
[tenBtn setTitleColor:UIColor.blueColor forState:(UIControlStateNormal)];
[tenBtn addTarget:self action:@selector(startAction:) forControlEvents:(UIControlEventTouchUpInside)];
[self.bgView addSubview:tenBtn];
UIButton *hundredBtn = [[UIButton alloc] initWithFrame:CGRectMake(216, 20, 100, 40)];
[hundredBtn setTitle:@"抽100次" forState:(UIControlStateNormal)];
hundredBtn.tag = 44;
[hundredBtn setTitleColor:UIColor.blueColor forState:(UIControlStateNormal)];
[hundredBtn addTarget:self action:@selector(startAction:) forControlEvents:(UIControlEventTouchUpInside)];
[self.bgView addSubview:hundredBtn];
}
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
return touch.view == self;
}
-(void)startAction:(UIButton*)sender{
self.startType = sender.tag;
///
[self resetViews];
[self getTargetGift];
[self startFastAnimate];
}
-(void)resetViews{
self.targetIndex = -1;
self.currentIndex = -1;
self.roundCount = 0;
self.delayTime = 0.3;
[self.targetArrayIndex removeAllObjects];
[self.finishTargetArrayIndex removeAllObjects];
if (self.currentGiftView != nil) {
self.currentGiftView.isSelected = NO;
[self.currentGiftView stopPulseAnimationWithLayer];
}
for (QXSkyPraizeSubView *giftView in self.allViewsArray) {
giftView.isSelected = NO;
[giftView stopPulseAnimationWithLayer];
}
}
-(void)startFastAnimate{
self.currentGiftView = self.allViewsArray.firstObject;
self.currentGiftView.isSelected = YES;
[self stopFastAnimate];
if (_fastTimer == nil) {
_fastTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
}
// dispatch_source_set_timer(_fastTimer,
// dispatch_time(DISPATCH_TIME_NOW, 0),
// NSEC_PER_SEC * 0.06, // 0.1
// NSEC_PER_SEC * 0.01); // 0.01
dispatch_source_set_timer(_fastTimer,
dispatch_time(DISPATCH_TIME_NOW, 0.06 * NSEC_PER_SEC),
DISPATCH_TIME_FOREVER, // 使
0.01 * NSEC_PER_SEC);
__weak typeof(self) weakSelf = self;
dispatch_source_set_event_handler(_fastTimer, ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) return;
// UI线
dispatch_async(dispatch_get_main_queue(), ^{
strongSelf.roundCount++;
if ((strongSelf.roundCount / giftMaxCount == minRoundCount) && strongSelf.startType != 22) {
BOOL has = NO;
for (NSNumber *index in self.finishTargetArrayIndex) {
if (index.integerValue == self.currentIndex) {
has = YES;
break;
}
}
self.currentGiftView.isSelected = NO;
if (has) {
QXSkyPraizeSubView *giftView = strongSelf.allViewsArray[strongSelf.currentIndex];
giftView.isSelected = YES;
}else{
QXSkyPraizeSubView *giftView = strongSelf.allViewsArray[strongSelf.currentIndex];
giftView.isSelected = NO;
}
}else{
///
strongSelf.currentGiftView.isSelected = NO;
}
///
strongSelf.currentIndex = strongSelf.roundCount%giftMaxCount;
/// view
QXSkyPraizeSubView *giftView = strongSelf.allViewsArray[strongSelf.currentIndex];
giftView.isSelected = YES;
/// view
strongSelf.currentGiftView = giftView;
if (strongSelf.roundCount / giftMaxCount == minRoundCount) {
/// 2
if (strongSelf.startType == 22) {
NSInteger index = strongSelf.targetIndex;
// 0 - > 11
// 1 - > 12
// 2->13
// 3->14
// 4->15
// 0-4
if (index < 5) {
index = (giftMaxCount-1) + index;
}
if ((strongSelf.currentIndex + toSlowCount) == index) {
//4
QXLOG(@"当前下标为%ld---目标为%ld",strongSelf.currentIndex,strongSelf.targetIndex);
[self stopFastAnimate];
[self startSlowAnimate];
}else{
dispatch_source_set_timer(strongSelf.fastTimer,
dispatch_time(DISPATCH_TIME_NOW, 0.06 * NSEC_PER_SEC),
DISPATCH_TIME_FOREVER,
0.01 * NSEC_PER_SEC);
}
}else{
// for (QXSkyPraizeSubView *giftView in strongSelf.allViewsArray) {
// giftView.isSelected = NO;
// }
BOOL has = NO;
for (NSNumber *index in strongSelf.targetArrayIndex) {
if (strongSelf.currentIndex == index.integerValue) {
QXSkyPraizeSubView *giftView = strongSelf.allViewsArray[index.integerValue];
giftView.isSelected = YES;
[giftView startPulseAnimationWithLayer];
// [strongSelf pauseGCDTimer];
[strongSelf.targetArrayIndex removeObject:index];
[strongSelf.finishTargetArrayIndex addObject:index];
has = YES;
break;
}
}
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// [strongSelf resumeGCDTimer];
// });
if (has) {
dispatch_source_set_timer(strongSelf.fastTimer,
dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC),
DISPATCH_TIME_FOREVER,
0.01 * NSEC_PER_SEC);
}else{
dispatch_source_set_timer(strongSelf.fastTimer,
dispatch_time(DISPATCH_TIME_NOW, 0.06 * NSEC_PER_SEC),
DISPATCH_TIME_FOREVER,
0.01 * NSEC_PER_SEC);
}
if (strongSelf.targetArrayIndex.count == 0) {
[strongSelf stopFastAnimate];
}
}
}else{
dispatch_source_set_timer(strongSelf.fastTimer,
dispatch_time(DISPATCH_TIME_NOW, 0.06 * NSEC_PER_SEC),
DISPATCH_TIME_FOREVER,
0.01 * NSEC_PER_SEC);
}
});
});
dispatch_resume(_fastTimer);
}
-(void)startSlowAnimate{
if (_slowTimer == nil) {
_slowTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
}
// 0.1
dispatch_source_set_timer(_slowTimer,
dispatch_time(DISPATCH_TIME_NOW, self.delayTime * NSEC_PER_SEC),
DISPATCH_TIME_FOREVER, // 使
0.01 * NSEC_PER_SEC);
__weak typeof(self) weakSelf = self;
dispatch_source_set_event_handler(_slowTimer, ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) return;
// UI线
dispatch_async(dispatch_get_main_queue(), ^{
///
strongSelf.currentGiftView.isSelected = NO;
strongSelf.roundCount++;
///
strongSelf.currentIndex = strongSelf.roundCount%giftMaxCount;
/// view
QXSkyPraizeSubView *giftView = strongSelf.allViewsArray[strongSelf.currentIndex];
giftView.isSelected = YES;
/// view
strongSelf.currentGiftView = giftView;
if (strongSelf.currentIndex == strongSelf.targetIndex) {
//4
QXLOG(@"礼物结束====当前下标为%ld---目标为%ld",strongSelf.currentIndex,strongSelf.targetIndex);
[strongSelf stopSlowAnimate];
[strongSelf.currentGiftView startPulseAnimationWithLayer];
}
});
strongSelf.delayTime = strongSelf.delayTime+0.1;
dispatch_source_set_timer(strongSelf.slowTimer,
dispatch_time(DISPATCH_TIME_NOW, strongSelf.delayTime * NSEC_PER_SEC),
DISPATCH_TIME_FOREVER,
0.01 * NSEC_PER_SEC);
});
dispatch_resume(_slowTimer);
}
-(void)stopFastAnimate{
if (_fastTimer != nil) {
dispatch_source_cancel(_fastTimer);
_fastTimer = nil;
}
}
- (void)pauseGCDTimer {
if (_fastTimer) {
dispatch_suspend(_fastTimer);
NSLog(@"GCD定时器已暂停");
}
}
- (void)resumeGCDTimer {
if (_fastTimer) {
dispatch_resume(_fastTimer);
NSLog(@"GCD定时器已恢复");
}
}
-(void)stopSlowAnimate{
if (_slowTimer != nil) {
dispatch_source_cancel(_slowTimer);
_slowTimer = nil;
}
}
-(void)getTargetGift{
self.targetArrayIndex = [NSMutableArray arrayWithArray:@[@3,@5,@8,@10]];
if (self.startType == 22) {
self.targetIndex = arc4random() % 12;
}else{
// NSNumber *number = self.targetArrayIndex.firstObject;
// self.targetIndex = number.integerValue;
}
}
-(void)getTenTargetGift{
}
-(NSMutableArray *)allViewsArray{
if (!_allViewsArray) {
_allViewsArray = [NSMutableArray arrayWithArray:@[@"",@"",@"",@"",@"",@"",@"",@"",@"",@"",@"",@""]];
}
return _allViewsArray;
}
-(NSMutableArray *)finishTargetArrayIndex{
if (!_finishTargetArrayIndex) {
_finishTargetArrayIndex = [NSMutableArray array];
}
return _finishTargetArrayIndex;
}
-(void)showInView:(UIView *)view{
self.bgView.y = SCREEN_HEIGHT;
[view addSubview:self];
[UIView animateWithDuration:0.3 animations:^{
self.bgView.y = SCREEN_HEIGHT-ScaleWidth(520)-kSafeAreaBottom;
}];
}
-(void)hide{
[self stopFastAnimate];
[self stopSlowAnimate];
[UIView animateWithDuration:0.3 animations:^{
self.bgView.y = SCREEN_HEIGHT;
} completion:^(BOOL finished) {
[self removeFromSuperview];
}];
}
@end
@implementation QXSkyPraizeSubView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor cyanColor];
[self initSubviews];
}
return self;
}
-(void)initSubviews{
self.titleLabel = [[UILabel alloc] init];
self.titleLabel.font = [UIFont boldSystemFontOfSize:22];
self.titleLabel.textColor = UIColor.blackColor;
self.titleLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:self.titleLabel];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
}
-(void)setIsSelected:(BOOL)isSelected{
_isSelected = isSelected;
self.backgroundColor = isSelected?[UIColor blueColor]:[UIColor cyanColor];
}
- (void)startPulseAnimationWithLayer {
CABasicAnimation *pulseAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
pulseAnimation.duration = 0.5;
pulseAnimation.fromValue = @0.9;
pulseAnimation.toValue = @1.1;
pulseAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
pulseAnimation.autoreverses = YES;
pulseAnimation.repeatCount = HUGE_VALF; //
[self.layer addAnimation:pulseAnimation forKey:@"pulse"];
}
//
- (void)stopPulseAnimationWithLayer {
[self.layer removeAnimationForKey:@"pulse"];
}
@end