新增手势优化和触摸区域缓存管理模块,提升了 Banner 交互性能和用户体验。新增 GestureOptimizer 和 TouchAreaCacheManager,分别负责手势识别优化和触摸区域信息缓存。更新 RoomAnimationView 和 BravoGiftBannerView,集成新模块以优化手势处理逻辑,确保更流畅的用户交互。同时,重构相关方法以支持新的逻辑流程,提升代码可维护性和可读性。
This commit is contained in:
@@ -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) {
|
||||
|
Reference in New Issue
Block a user