UIViewController 停止在 UIWebView 上接收触摸事件
Posted
技术标签:
【中文标题】UIViewController 停止在 UIWebView 上接收触摸事件【英文标题】:UIViewController stops receiving touch events on UIWebView 【发布时间】:2012-08-13 06:53:52 【问题描述】:我正在开发杂志查看器,由于 html5 交互式内容,我必须将 UIWebView 用于页面。首先,我在 UIScrollView 中尝试了 uiwebviews,但滚动视图在滑动页面上太慢了。 所以现在我正在尝试编写自己的类似滚动视图的代码。我有一个 MainView.xib、一个视图控制器 (Viewer) 和扩展 UIWindow 类 (TouchCapturingWindow),我从这里获取:http://wyldco.com/blog/2010/11/how-to-capture-touches-over-a-uiwebview/
当我尝试快速滑动页面时,没有问题,但是当我触摸并通过不拉手指慢慢滑动时,“查看器”视图控制器停止接收触摸事件,因此页面停止移动。我正在记录 TouchCapturingWindow,它仍在发送事件。我搜索了许多信息和教程,但我无法使其工作。如何让它连续接收触摸事件?
我上传了一个简单的 Xcode 项目,其中仅包含我项目的这一部分。你可以在这里下载:http://testdergi.mysys.com/touchEvents.zip 运行项目时,应先点击“下载页面”按钮下载页面(180Kb),然后点击“打开查看器”按钮。
你也可以看看下面的代码:
TouchCapturingWindow.h:
@interface TouchCapturingWindow : UIWindow
NSMutableArray *views;
@private
UIView *touchView;
- (void)addViewForTouchPriority:(UIView*)view;
- (void)removeViewForTouchPriority:(UIView*)view;
@end
TouchCapturingWindow.m:
@implementation TouchCapturingWindow
- (void)dealloc
- (void)addViewForTouchPriority:(UIView*)view
if ( !views ) views = [[NSMutableArray alloc] init];
[views addObject:view];
- (void)removeViewForTouchPriority:(UIView*)view
if ( !views ) return;
[views removeObject:view];
- (void)sendEvent:(UIEvent *)event
//get a touch
UITouch *touch = [[event allTouches] anyObject];
//check which phase the touch is at, and process it
if (touch.phase == UITouchPhaseBegan)
for ( UIView *view in views )
//if ( CGRectContainsPoint([view frame], [touch locationInView:[view superview]]) )
NSLog(@"TouchCapturingWindow --> TouchPhaseBegan");
touchView = view;
[touchView touchesBegan:[event allTouches] withEvent:event];
break;
else if (touch.phase == UITouchPhaseMoved)
NSLog(@"TouchCapturingWindow --> TouchPhaseMoved");
if ( touchView )
[touchView touchesMoved:[event allTouches] withEvent:event];
else
NSLog(@"touch view is nil");
else if (touch.phase == UITouchPhaseCancelled)
NSLog(@"TouchCapturingWindow --> TouchPhaseCancelled");
if ( touchView )
[touchView touchesCancelled:[event allTouches] withEvent:event];
touchView = nil;
else if (touch.phase == UITouchPhaseEnded)
NSLog(@"TouchCapturingWindow --> TouchPhaseEnded");
if ( touchView )
[touchView touchesEnded:[event allTouches] withEvent:event];
touchView = nil;
//we need to send the message to the super for the
//text overlay to work (holding touch to show copy/paste)
[super sendEvent:event];
@end
Viewer.h:
@interface Viewer : UIViewController
int currentPage;
int totalPages;
IBOutlet UIView *pagesView;
int lastTchX;
int difference;
BOOL hasMoved;
int touchBeganSeritX;
- (IBAction)backBtnClicked:(id)sender;
- (void)loadImages;
- (void)animationDidStop;
- (void)loadSinglePage:(int)pageNo;
@property (nonatomic, retain) IBOutlet UIView *pagesView;
@end
Viewer.m:
@interface Viewer ()
@end
@implementation Viewer
@synthesize pagesView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
// Custom initialization
return self;
- (void)viewDidLoad
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
- (IBAction)backBtnClicked:(id)sender
[self.navigationController popViewControllerAnimated:YES];
- (void)loadImages
for(UIView *subView in pagesView.subviews)
[subView removeFromSuperview];
currentPage = 1;
totalPages = 12;
for(int count = 1; count <= 12; count++)
[self loadSinglePage:count];
- (void)loadSinglePage:(int)pageNo
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory , NSUserDomainMask, YES);
NSString *cachesDir = [paths objectAtIndex:0];
NSString *pagesDir = [NSString stringWithFormat:@"%@/pages", cachesDir];
int pageX = (pageNo - 1) * 768;
UIWebView *aPageWebView = [[UIWebView alloc] init];
[aPageWebView setFrame:CGRectMake(pageX, 0, 768, 1024)];
aPageWebView.backgroundColor = [UIColor clearColor];
aPageWebView.opaque = YES;
[aPageWebView setClearsContextBeforeDrawing:YES];
aPageWebView.clipsToBounds = NO;
[aPageWebView setScalesPageToFit:YES];
NSString *hamData = [NSString stringWithFormat:@"<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"user-scalable=yes, width=1024, height=1365, maximum-scale=1.0\"><style type=\"text/css\">body margin:0; padding:0;</style></head><body bgcolor=\"#508CCF\"><div id=\"touchable\" style=\"top:0px; left:0px; width:1024px; height:1365px; background-image:url(%@.jpg)\"></div></body></html>", [[NSNumber numberWithInt:pageNo] stringValue]];
[aPageWebView loadHTMLString:hamData baseURL:[NSURL fileURLWithPath:pagesDir isDirectory:YES]];
aPageWebView.scrollView.bounces = NO;
[aPageWebView.scrollView setMaximumZoomScale:1.3333f];
[aPageWebView.scrollView setMinimumZoomScale:1.0f];
aPageWebView.scrollView.zoomScale = 1.0f;
[aPageWebView setMultipleTouchEnabled:YES];
[pagesView addSubview:aPageWebView];
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
NSLog(@"touchesBegan");
UITouch *myTouch = [[event allTouches] anyObject];
int curTchX = [myTouch locationInView:self.view].x;
lastTchX = curTchX;
hasMoved = NO;
touchBeganSeritX = pagesView.frame.origin.x;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
NSLog(@"Viewer : .....moved");
hasMoved = YES;
UITouch *myTouch = [[event allTouches] anyObject];
int curTchX = [myTouch locationInView:self.view].x;
difference = curTchX - lastTchX;
int newX = (pagesView.frame.origin.x + difference);
if(newX <= 0)
[pagesView setFrame:CGRectMake((pagesView.frame.origin.x + difference), 0, pagesView.frame.size.width, 1024)];
lastTchX = curTchX;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
NSLog(@"touchesEnded");
if(hasMoved == YES)
hasMoved = NO;
int curSeritX = pagesView.frame.origin.x;
curSeritX = curSeritX / (-1);
int newX = 0;
if(difference < 0) //Sağa geçilecek
if((currentPage + 1) <= totalPages)
currentPage++;
else //Sola geçilecek
if((currentPage - 1) >= 1)
currentPage--;
newX = (currentPage - 1)*768*(-1);
[UIView animateWithDuration:0.2f
delay:0.0f
options:UIViewAnimationOptionCurveEaseOut
animations:^
// Do your animations here.
[pagesView setFrame:CGRectMake(newX, 0, pagesView.frame.size.width, pagesView.frame.size.height)];
completion:^(BOOL finished)
if (finished)
// Do your method here after your animation.
];
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
NSLog(@"touchesCancelled");
- (void)viewDidUnload
[super viewDidUnload];
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
return YES;
@end
【问题讨论】:
【参考方案1】:我正在回答我自己的问题。经过一番努力,我找到了一些东西。我更改了“(void)sendEvent:(UIEvent *)event”方法,如下面的代码。我看到使用“[super sendEvent:event];” UITouchPhaseMoved 阶段后有问题。
- (void)sendEvent:(UIEvent *)event
//we need to send the message to the super for the
//text overlay to work (holding touch to show copy/paste)
//[super sendEvent:event];
//get a touch
UITouch *touch = [[event allTouches] anyObject];
//check which phase the touch is at, and process it
if (touch.phase == UITouchPhaseBegan)
for ( UIView *view in views )
//if ( CGRectContainsPoint([view frame], [touch locationInView:[view superview]]) )
NSLog(@"TouchCapturingWindow --> TouchPhaseBegan");
touchView = view;
[touchView touchesBegan:[event allTouches] withEvent:event];
break;
[super sendEvent:event];
else if (touch.phase == UITouchPhaseMoved)
NSLog(@"TouchCapturingWindow --> TouchPhaseMoved");
if ( touchView )
[touchView touchesMoved:[event allTouches] withEvent:event];
int curTchX = [touch locationInView:self].x;
NSLog(@"curTchX : %d", curTchX);
else
NSLog(@"touch view is nil");
else if (touch.phase == UITouchPhaseCancelled)
NSLog(@"TouchCapturingWindow --> TouchPhaseCancelled");
if ( touchView )
[touchView touchesCancelled:[event allTouches] withEvent:event];
touchView = nil;
[super sendEvent:event];
else if (touch.phase == UITouchPhaseEnded)
NSLog(@"TouchCapturingWindow --> TouchPhaseEnded");
if ( touchView )
[touchView touchesEnded:[event allTouches] withEvent:event];
touchView = nil;
[super sendEvent:event];
//we need to send the message to the super for the
//text overlay to work (holding touch to show copy/paste)
但新的问题是;如果我在网页中添加视频,并尝试使用滑块转发视频,页面正在移动。我必须找到一种方法来检测用户是否点击了视频。
【讨论】:
以上是关于UIViewController 停止在 UIWebView 上接收触摸事件的主要内容,如果未能解决你的问题,请参考以下文章
如何停止将 UIViewController 推到自身之上?
对于UINavigationController和UIViewController,在swift 4中禁用屏幕方向