通过触摸到UIWebView的一部分

时间:2012-04-05 08:58:31

标签: objective-c ios uiwebview

我有一个UIWebView。使用这样的东西:

http://blog.evandavey.com/2009/02/how-to-make-uiwebview-transparent.html

..我让UIWebView变得透明。我现在需要能够将webview上的触摸传递到下面的视图,但仅限于Web视图的矩形部分。

所以,想象一下webview是一个正方形,它在中心有一个方形区域,必须通过触摸到下面的视图。

有办法做到这一点吗?

5 个答案:

答案 0 :(得分:3)

这是hitTest操纵的一种更具体的形式。

首先,创建UIView的子类。我打电话给我ViewWithHole

在其标题中,为UIView定义一个属性,该属性将成为穿过外部视图的洞。将其设为IBOutlet

@property (retain) IBOutlet UIView *holeView;

然后覆盖hitTest。如果该点返回洞内的命中,则返回该值。否则返回它通常会发生的事情。

- (UIView*) hitTest:(CGPoint)point withEvent:(UIEvent *)event;
{
    CGPoint pointInHole = [self convertPoint:point toView:self.holeView];
    UIView *viewInHole = [self.holeView hitTest:pointInHole withEvent:event];

    if (viewInHole)
        return viewInHole;
    else
        return [super hitTest:point withEvent:event];
}

在Interface Builder中,或以编程方式放置ViewWithHole。按顺序在其中加UIViewUIWebView。制作UIView holeView的{​​{1}}。

Interface Builder configuring ViewWithHole

ViewWithHole本身可以是交互式的,或者您可以在其中放置任意数量的交互式视图。在这里,我在其中放置了一些标准视图以确保它们正常工作。洞内的任何点击都会发送到它及其子视图,而不是顶部的holeView。 <{1}}以外的任何点击都会像往常一样由UIWebView收到。

您可以在洞前显示任意数量和类型的视图;重要的是holeView已正确连接。

答案 1 :(得分:1)

我的第一个想法是这样的:

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch * touch = (UITouch *)[touches anyObject];
CGPoint location = [touch locationInView:self];

//min_x,max_x,min_y,max_y are the min and max coord of your rect below

if (CGRectContainsPoint(CGRectMake(min_x,min_y,max_x,max_y),location))
{
     //send the touches to the view below
}

}

如果下面的视图是静止的,但是你没有提供任何关于下面视图的信息(如果有按钮,或者如果它移动......就像那样)那么这应该有效...所以......是的......那个

答案 2 :(得分:1)

您可以创建UIWebView的子类并覆盖其hitTest:withEvent:pointInside:withEvent:以忽略'洞' - 但Apple say you shouldn't subclass UIWebView

或者,您可以创建一个UIView子类并将UIWebView作为子视图放在其中,然后使其hitTest:withEvent:方法返回UIWebView下的视图。

这是hitTest子类的通用UIView方法,它优先考虑任何非UIWebView的交互式子视图,即使它们位于UIWebView下面。它没有任何特定的“漏洞”检测,但hitTest也是您想要这样做的地方。如果在忽略UIWebView之前point在洞中,那就试试吧。

// - (UIView*) hitTest:(CGPoint)point withEvent:(UIEvent *)event;
// This overrides the usual hitTest method to give priority to objects that are not in a chosen class.
// For this example, that class has been hard-coded to UIWebView.
// This allows the webview to be displayed over other interactive components.
// For the UIWebView case, it would be nice to look at its layout and only return views beneath it in locations where it is transparent, but that information is not obtainable.
- (UIView*) hitTest:(CGPoint)point withEvent:(UIEvent *)event;
{
    UIView *viewFound = nil;
    Class lowPriorityClass = [UIWebView class];
    NSMutableArray *lowPriorityViews = [NSMutableArray array];

    // Search the subviews from front to back.
    NSEnumerator *viewEnumerator = [[self subviews] reverseObjectEnumerator];
    UIView *subview;
    while ((subview = [viewEnumerator nextObject]) && (!viewFound))
    {
        // Save low-priority cases for later.
        if ([subview isKindOfClass:lowPriorityClass])
            [lowPriorityViews addObject:subview];
        else
        {
            CGPoint pointInSubview = [self convertPoint:point toView:subview];
            if ([subview pointInside:pointInSubview withEvent:event])
            {
                // Subviews may themselves have subviews to return.
                viewFound = [subview hitTest:pointInSubview withEvent:event];
                // However, if not, return the subview itself.
                if (!viewFound)
                    viewFound = subview;
            }
        }
    }

    if (!viewFound)
    {
        // At this point, no other interactive views were found, so search the low-priority cases previously stored to see if they apply.
        // Since the lowPriorityViews are already in front to back order, enumerate forward.
        viewEnumerator = [lowPriorityViews objectEnumerator];
        while ((subview = [viewEnumerator nextObject]) && (!viewFound))
        {
            CGPoint pointInSubview = [self convertPoint:point toView:subview];
            if ([subview pointInside:pointInSubview withEvent:event])
            {
                // Subviews may themselves have subviews to return.
                viewFound = [subview hitTest:pointInSubview withEvent:event];
                // However, if not, return the subview itself.
                if (!viewFound)
                    viewFound = subview;
            }
        }
    }

    // All cases dealt with, return whatever was found.  This will be nil if no views were under the point.
    return viewFound;
}

答案 3 :(得分:1)

我认为您的问题有一个非常简单的解决方案......您没有指定它,但我推断您不希望用户与webview HTML进行交互。如果是这样,只需在webview上禁用UserInteractionEnabled,触摸即可通过。

然后,如您所述,您需要位于中心的活动视图。

我希望它有所帮助,如果你需要任何澄清,只需评论它。

答案 4 :(得分:1)

我有另一个想法:获取全局点击。当有人点击iPhone时,它会向全局sendEvent发送消息。所以你听它并完成你想要的任务。

为此,您需要继承UIApplication。首先,在main.c中使用此函数

    int retVal = UIApplicationMain(argc, argv, @"myUIApplicationClass" ,nil);

然后实现这个类:

@implementation BBAplicationDebug

- (void)sendEvent:(UIEvent *)event
{
    [super sendEvent:event];
    NSSet *touches = [event allTouches];
    UITouch *touch = touches.anyObject;
    [[NSNotificationCenter defaultCenter] postNotificationName:@"userClick" object:touch];
}

@end

现在你听这个NSNotification并做所有的检查:是在正确的框架中,有正确的UIView等等......