新增手势优化和触摸区域缓存管理模块,提升了 Banner 交互性能和用户体验。新增 GestureOptimizer 和 TouchAreaCacheManager,分别负责手势识别优化和触摸区域信息缓存。更新 RoomAnimationView 和 BravoGiftBannerView,集成新模块以优化手势处理逻辑,确保更流畅的用户交互。同时,重构相关方法以支持新的逻辑流程,提升代码可维护性和可读性。

This commit is contained in:
edwinQQQ
2025-08-20 16:37:48 +08:00
parent be52c53b2f
commit e0466700b5
21 changed files with 20628 additions and 49 deletions

View File

@@ -34,6 +34,8 @@
#import "GiftComboManager.h"
#import "GiftAnimationManager.h"
#import "BannerScheduler.h"
#import "TouchAreaCacheManager.h"
#import "GestureOptimizer.h"
#import "MSRoomGameWebVC.h"
#import "XPRoomViewController.h"
@@ -184,20 +186,50 @@ BannerSchedulerDelegate
- (void)dealloc
{
}
- (void)removeItSelf {
NSLog(@"<22><> RoomAnimationView: 开始销毁");
// 广
[[NIMSDK sharedSDK].broadcastManager removeDelegate:self];
//
[NSObject cancelPreviousPerformRequestsWithTarget:self];
// POP
[self pop_removeAllAnimations];
//
if (_giftEffectTimer && !dispatch_source_testcancel(_giftEffectTimer)) {
dispatch_source_cancel(_giftEffectTimer);
_giftEffectTimer = nil;
}
//
if (_giftEffectsQueue) {
self.giftEffectsQueue = NULL;
}
// 🔧 BannerScheduler
if (self.bannerScheduler) {
NSLog(@"<22><> 清理 BannerScheduler");
[self.bannerScheduler clearQueue];
[self.bannerScheduler pause];
self.bannerScheduler = nil;
}
//
[self cleanupGestureRecognizers];
//
[self cleanupCacheManagers];
//
[self removeNotificationObservers];
NSLog(@"<22><> RoomAnimationView: 销毁完成");
}
-(void)resumeTimer{
@@ -2169,6 +2201,11 @@ BannerSchedulerDelegate
[self insertSubview:self.bannerLeftTapGestureContainer aboveSubview:self.bannerContainer];
[self insertSubview:self.bannerRightTapGestureContainer aboveSubview:self.bannerContainer];
// tag
self.bannerSwipeGestureContainer.tag = 1001; //
self.bannerLeftTapGestureContainer.tag = 1002; //
self.bannerRightTapGestureContainer.tag = 1003; //
[self.bannerSwipeGestureContainer mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(self.bannerContainer);
make.top.bottom.mas_equalTo(self.bannerContainer);
@@ -2218,10 +2255,32 @@ BannerSchedulerDelegate
[self.bannerSwipeGestureContainer addGestureRecognizer:centerTap];
[self.bannerLeftTapGestureContainer addGestureRecognizer:leftTap];
[self.bannerRightTapGestureContainer addGestureRecognizer:rightTap];
NSLog(@"🎯 手势识别器设置完成 - 中央容器: %@, 左侧容器: %@, 右侧容器: %@",
NSStringFromClass([self.bannerSwipeGestureContainer class]),
NSStringFromClass([self.bannerLeftTapGestureContainer class]),
NSStringFromClass([self.bannerRightTapGestureContainer class]));
}
- (void)handleSwipe {
[[NSNotificationCenter defaultCenter] postNotificationName:@"SwipeOutBanner" object:nil];
// banner swipe
// bannerContainer banner
UIView *currentVisibleBanner = nil;
for (UIView *subview in self.bannerContainer.subviews) {
if (!subview.hidden && subview.alpha > 0.01) {
currentVisibleBanner = subview;
break;
}
}
if (currentVisibleBanner) {
NSLog(@"🎯 检测到 swipe 手势,当前有可见 banner: %@,发送 SwipeOutBanner 通知", NSStringFromClass([currentVisibleBanner class]));
// banner banner swipe
[[NSNotificationCenter defaultCenter] postNotificationName:@"SwipeOutBanner"
object:currentVisibleBanner];
} else {
NSLog(@"🎯 检测到 swipe 手势,但当前没有可见 banner忽略此手势");
}
}
- (void)handleBannerTap:(UITapGestureRecognizer *)tapGesture {
@@ -2249,7 +2308,17 @@ BannerSchedulerDelegate
}
- (BOOL)isPointInBannerInteractiveArea:(CGPoint)point {
// banner
// 使
TouchAreaCacheManager *cacheManager = [TouchAreaCacheManager sharedManager];
// 使
if ([cacheManager isPointInInteractiveArea:point]) {
NSLog(@"🎯 isPointInBannerInteractiveArea: 缓存命中 - 点 %@ 在可交互区域内", NSStringFromCGPoint(point));
return YES;
}
// 使
NSLog(@"🎯 isPointInBannerInteractiveArea: 缓存未命中,使用传统方法检查");
for (UIView *subview in self.bannerContainer.subviews) {
if (subview.hidden || subview.alpha <= 0.01) {
continue;
@@ -2263,11 +2332,21 @@ BannerSchedulerDelegate
CGPoint subviewPoint = [subview convertPoint:point fromView:self.bannerContainer];
UIView *hitView = [subview hitTest:subviewPoint withEvent:nil];
if (hitView && hitView.userInteractionEnabled) {
//
CGRect bannerBounds = subview.bounds;
CGRect interactiveBounds = [self calculateInteractiveBoundsForView:subview];
[cacheManager updateBannerBounds:bannerBounds
interactiveBounds:interactiveBounds
forBanner:subview];
NSLog(@"🎯 isPointInBannerInteractiveArea: 传统方法命中,已更新缓存");
return YES;
}
}
}
}
NSLog(@"🎯 isPointInBannerInteractiveArea: 点 %@ 不在可交互区域内", NSStringFromCGPoint(point));
return NO;
}
@@ -2282,27 +2361,18 @@ BannerSchedulerDelegate
CGPoint touchPoint = [touch locationInView:self.bannerContainer];
CGFloat containerWidth = self.bannerContainer.bounds.size.width;
//
CGFloat leftBoundary = containerWidth / 6.0; // 1/6
CGFloat rightBoundary = containerWidth * 5.0 / 6.0; // 5/6
// 使
GestureOptimizer *optimizer = [GestureOptimizer sharedOptimizer];
BOOL shouldReceive = [optimizer shouldGestureRecognizer:gestureRecognizer
receiveTouchAtPoint:touchPoint
containerWidth:containerWidth];
if ([gestureRecognizer isKindOfClass:[UISwipeGestureRecognizer class]]) {
// Swipe 2/3
return touchPoint.x >= leftBoundary && touchPoint.x <= rightBoundary;
} else if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
// Tap 1/6
// return touchPoint.x < leftBoundary || touchPoint.x > rightBoundary;
//
if (gestureRecognizer.view == self.bannerSwipeGestureContainer) {
// tap
return touchPoint.x >= leftBoundary && touchPoint.x <= rightBoundary;
} else {
// tap
return touchPoint.x < leftBoundary || touchPoint.x > rightBoundary;
}
//
if (shouldReceive) {
[optimizer debugGestureAreaForPoint:touchPoint containerWidth:containerWidth];
}
return YES;
return shouldReceive;
}
#pragma mark - Animations
@@ -3486,6 +3556,23 @@ BannerSchedulerDelegate
NSLog(@" - bannerContainer.subviews.count: %ld", (long)self.bannerContainer.subviews.count);
}
- (CGRect)calculateInteractiveBoundsForView:(UIView *)view {
//
// Banner
CGRect bounds = view.bounds;
// Banner
//
if ([view isKindOfClass:[PIUniversalBannerView class]]) {
//
// 使
return bounds;
}
// 使
return bounds;
}
- (void)testBannerScheduler {
NSLog(@"🧪 开始测试 BannerScheduler");
@@ -3499,6 +3586,101 @@ BannerSchedulerDelegate
NSLog(@"🧪 测试完成");
}
- (void)debugTouchAreaCache {
NSLog(@"🎯 触摸区域缓存调试信息:");
TouchAreaCacheManager *cacheManager = [TouchAreaCacheManager sharedManager];
[cacheManager debugPrintCache];
}
- (void)debugGestureOptimizer {
NSLog(@"🎯 手势优化器调试信息:");
GestureOptimizer *optimizer = [GestureOptimizer sharedOptimizer];
//
CGFloat containerWidth = self.bannerContainer.bounds.size.width;
CGPoint leftPoint = CGPointMake(containerWidth * 0.1, 40); //
CGPoint centerPoint = CGPointMake(containerWidth * 0.5, 40); //
CGPoint rightPoint = CGPointMake(containerWidth * 0.9, 40); //
NSLog(@"🎯 测试左侧区域点:");
[optimizer debugGestureAreaForPoint:leftPoint containerWidth:containerWidth];
NSLog(@"🎯 测试中央区域点:");
[optimizer debugGestureAreaForPoint:centerPoint containerWidth:containerWidth];
NSLog(@"🎯 测试右侧区域点:");
[optimizer debugGestureAreaForPoint:rightPoint containerWidth:containerWidth];
}
#pragma mark - Cleanup Methods
- (void)cleanupGestureRecognizers {
NSLog(@"🔄 清理手势识别器");
//
if (self.bannerSwipeGestureContainer) {
for (UIGestureRecognizer *gesture in self.bannerSwipeGestureContainer.gestureRecognizers.copy) {
[self.bannerSwipeGestureContainer removeGestureRecognizer:gesture];
}
}
//
if (self.bannerLeftTapGestureContainer) {
for (UIGestureRecognizer *gesture in self.bannerLeftTapGestureContainer.gestureRecognizers.copy) {
[self.bannerLeftTapGestureContainer removeGestureRecognizer:gesture];
}
}
//
if (self.bannerRightTapGestureContainer) {
for (UIGestureRecognizer *gesture in self.bannerRightTapGestureContainer.gestureRecognizers.copy) {
[self.bannerRightTapGestureContainer removeGestureRecognizer:gesture];
}
}
NSLog(@"🔄 手势识别器清理完成");
}
- (void)cleanupCacheManagers {
NSLog(@"🔄 清理缓存管理器");
// BannerScheduler
[self cleanupBannerScheduler];
//
TouchAreaCacheManager *touchCacheManager = [TouchAreaCacheManager sharedManager];
[touchCacheManager clearCache];
//
GestureOptimizer *gestureOptimizer = [GestureOptimizer sharedOptimizer];
[gestureOptimizer clearCache];
NSLog(@"🔄 缓存管理器清理完成");
}
- (void)cleanupBannerScheduler {
if (self.bannerScheduler) {
NSLog(@"<22><> 清理 BannerScheduler");
[self.bannerScheduler clearQueue];
[self.bannerScheduler pause];
self.bannerScheduler = nil;
}
}
- (void)removeNotificationObservers {
NSLog(@"🔄 移除通知监听");
//
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"SwipeOutBanner" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"TapBanner" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"BannerTapToFunctionContainer" object:nil];
//
[[NSNotificationCenter defaultCenter] removeObserver:self];
NSLog(@"🔄 通知监听移除完成");
}
#pragma mark - BannerSchedulerDelegate
- (void)bannerScheduler:(BannerScheduler *)scheduler shouldPlayBanner:(id)banner {
@@ -3536,6 +3718,10 @@ BannerSchedulerDelegate
for (UIView *subview in self.bannerContainer.subviews) {
[viewsToRemove addObject:subview];
NSLog(@"🔄 标记移除banner: %@", NSStringFromClass([subview class]));
// Banner
TouchAreaCacheManager *cacheManager = [TouchAreaCacheManager sharedManager];
[cacheManager removeBannerFromCache:subview];
}
for (UIView *view in viewsToRemove) {