阻止UIWebView垂直“反弹”?


225

有谁知道如何阻止UIWebView垂直反弹?我的意思是,当用户触摸其iPhone屏幕时,将其手指向下拖动,并且Webview在我加载的网页上方显示空白点吗?

我研究了以下可能的解决方案,但没有一个对我有用:

http://www.iphonedevsdk.com/forum/iphone-sdk-development/996-turn-off-scrolling-bounces-uiwebview.html

http://forums.macrumors.com/showthread.php?t=619534

如何阻止UIScrollView水平反弹?


1
希望您考虑了禁用该功能的可用性含义。在那里是有原因的。那就是说,我也很好奇,你会怎么做。
Michael Haren

我将其嵌入到我的应用程序中的方式,似乎与我拥有的其他视图元素一起出现,并且只有当反弹发生时才出现,这是唯一的一次。
布莱德·帕克斯

Answers:


424
for (id subview in webView.subviews)
  if ([[subview class] isSubclassOfClass: [UIScrollView class]])
    ((UIScrollView *)subview).bounces = NO;

...似乎工作正常。

它也会被App Store接受。

更新:在iOS 5.x +中,有一种更简单的方法- UIWebView具有scrollView属性,因此您的代码如下所示:

webView.scrollView.bounces = NO;

同样适用WKWebView


有用。不需要子类,并且如果Apple曾经更改过UIWebView层次结构,它就不会崩溃。
leolobato

2
此修复程序似乎仅在我的OS 4.1 Simulator中起作用,而在我的OS 3.1.3 iPhone中不起作用。有人知道此修补程序是否仅适用于特定的OS版本吗?
Dan J

@MirukRusin-您如何基于三行代码来保证将接受该应用程序?:P
Moshe

@Mirek-你错过了我的观点。您怎么知道应用程序中没有其他东西会拒绝它?
Moshe

6
这对我来说很好。为了方便起见,我在其中添加了一个类别,UIWebView以便可以[webView setBounces:NO]在任何需要的地方打电话。
zekel 2011年

46

我当时正在研究一个项目,该项目可以很容易地在iPhone上将Web应用程序创建为完整的可安装应用程序,称为QuickConnect,并且找到了一个可行的解决方案,如果您根本不希望屏幕可滚动的话。我没有

在以上提到的project / blog帖子中,他们提到了您可以添加的javascript函数来关闭反弹功能,这实际上可以归结为:

    document.ontouchmove = function(event){
        event.preventDefault();
    }

如果您想了解有关他们如何实现的更多信息,只需下载QuickConnect并进行检查即可。...但基本上,它所做的只是在页面加载时调用javascript ...我试图将其放在文档的开头,而且似乎工作正常。


此答案是停止UIWebView中内容的垂直滚动的正确方法。
2010年

3
您可能已经给出了完整的答案,首先,我不想下载另一个应用程序的完整搜索源代码,而我什至找不到它。您的答案依赖于与您回答时相同的另一个网站。
乔纳森。

有时似乎需要这个答案和上面被接受的答案。就我而言,我发现如果尚未加载Web视图,则在将上面的JS实际加载到系统中之前,会一直存在反弹。因此,答案似乎是有时需要同时满足以上要求和接受的答案。
Kalle 2010年

3
正如Jessedc所说,这将停止垂直滚动,而不仅仅是反弹。这意味着如果您有div左右需要滚动,它将不会滚动。
记忆式的2012年

18

我要做的就是:

UIView *firstView = [webView.subviews firstObject];

if ([firstView isKindOfClass:[UIScrollView class]]) {

    UIScrollView *scroll = (UIScrollView*)firstView;
   [scroll setScrollEnabled:NO];  //to stop scrolling completely
   [scroll setBounces:NO]; //to stop bouncing 

}

对我来说很好用...此外,如果您在iphone应用程序中使用该问题,则此问题的答案是Apple会拒绝的答案。


3
这是最好和最简单的方法。这应该是公认的答案!+1
PostCodeism 2010年

3
不要那样做-我的应用因使用第一行而被拒绝。为我浪费了很多时间。我使用了[[webView.subviews lastObject] setScrollEnabled:NO]; 苹果说这是私有API,因此拒绝了它。即将重新提交,但使用了“ userInteractionEnabled:NO”,因为我在应用程序中不需要任何活动链接。
Veeru

UIWebView继承自UIView。UIView具有属性子视图。这里有什么私人的?您可以在developer.apple.com上找到所有这些
Valerii Pavlov

3
我在appstore上有4个类似的应用程序正在使用它。您的应用显然因其他原因被拒绝。这不是私有API。
Zigglzworth 2011年

4
这确实不是一个好主意。您所依赖的事实UIScrollView是,UIWebView这可能是目前的第一个子视图,但是在将来对iOS或特定配置进行的更新(即使是次要的更新)中,也很容易更改。您应该真正进行一次for迭代subviews才能真正找到它UIScrollView(实际上并不需要那么多的工作,至少可以保证可以得到a UIScrollView并且不会使您的程序崩溃……
Jonathan Ellis

17

在iOS 5 SDK中,您可以直接访问与Web视图关联的滚动视图,而无需遍历其子视图。

因此,要在滚动视图中禁用“弹跳”,可以使用:

myWebView.scrollView.bounces = NO;

请参见UIWebView类参考

(但是,如果您需要支持5.0之前的SDK版本,则应遵循Mirek Rusin的建议。)



9

警告。我在应用程序中使用了setAllowsRubberBanding:,而Apple拒绝了它,指出不允许使用非公共API函数(引用:3.3.1)



3

布拉德的方法对我有用。如果使用它,则可能需要使其更加安全。

id scrollView = [yourWebView.subviews objectAtIndex:0];
if([scrollView responsesToSelector:@selector(setAllowsRubberBanding :)])
{
    [scrollView performSelector:@selector(setAllowsRubberBanding :) withObject:NO];
}

如果苹果改变了一些东西,那么反弹将重新出现-但至少您的应用程序不会崩溃。


3

仅在iOS5上,如果您计划让用户缩放Web视图的内容(即双击),则跳出设置是不够的。您还需要将alwaysBounceHorizo​​ntal和alwaysBounceVertical属性设置为NO,否则当它们缩小(另一个双击...)默认值时,它将再次反弹。


2

我遍历了UIWebView的子视图的集合,并将它们的背景设置为[UIColor blackColor],与网页背景的颜色相同。该视图仍会反弹,但不会显示难看的深灰色背景。


1
实际上,这是一个非常糟糕的情况,因为如果Apple曾经更改过UIWebView的内部结构,则这种破解可能会中断。
bpapa 2010年

2

在我看来,UIWebView具有UIScrollView。您可以为此使用已记录的API,但是会为两个方向(而不是单独)设置跳动。这在API文档中。UIScrollView具有bounce属性,因此类似这样的工作(不知道是否有多个滚动视图):

NSArray *subviews = myWebView.subviews;
NSObject *obj = nil;
int i = 0;
for (; i < subviews.count ; i++)
{
    obj = [subviews objectAtIndex:i];

    if([[obj class] isSubclassOfClass:[UIScrollView class]] == YES)
    {
        ((UIScrollView*)obj).bounces = NO;
    }
}

2

我很生气地发现UIWebView不是滚动视图,所以我做了一个自定义子类来获取Web视图的滚动视图。此suclass包含滚动视图,因此您可以自定义Web视图的行为。该课程的重点是:

@class CustomWebView : UIWebview
...

- (id) initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
// WebViews are subclass of NSObject and not UIScrollView and therefore don't allow customization.
// However, a UIWebView is a UIScrollViewDelegate, so it must CONTAIN a ScrollView somewhere.
// To use a web view like a scroll view, let's traverse the view hierarchy to find the scroll view inside the web view.
for (UIView* v in self.subviews){
    if ([v isKindOfClass:[UIScrollView class]]){
        _scrollView = (UIScrollView*)v; 
        break;
    }
}
return self;

}

然后,当您创建自定义Web视图时,可以通过以下方式禁用跳动:

customWebView.scrollView.bounces = NO; //(or customWebView.scrollView.alwaysBounceVertically = NO)

这是一种使Web视图具有可自定义滚动行为的绝佳通用方法。只有几件事需要注意:

  • 与任何视图一样,您还需要重写-(id)initWithCoder:如果在Interface Builder中使用它
  • 最初创建Web视图时,其内容大小始终与视图框架的大小相同。滚动Web后,内容大小表示视图内实际Web内容的大小。为了解决这个问题,我做了一些棘手的事情-调用-setContentOffset:CGPointMake(0,1)animated:YES强制进行不明显的更改,该更改将设置Web视图的适当内容大小。

2

在寻找答案时遇到了这个问题,我最终只是通过弄乱自己找到了自己的答案。我做了

[[webview scrollView] setBounces:NO];

而且有效。


2

这对我有用,也很漂亮(我在webView中使用phonegap)

[[webView.webView scrollView] setScrollEnabled:NO];

要么

[[webView scrollView] setScrollEnabled:NO];

1

我尝试了一种稍微不同的方法来防止UIWebView对象滚动和弹跳:添加手势识别器以覆盖其他手势。

似乎,UIWebView或其滚动子视图使用其自己的平移手势识别器来检测用户的滚动。但是根据Apple的文档,有一种合法的方法可以将一个手势识别器替换为另一个。UIGestureRecognizerDelegate协议具有一个方法roleRecognizer:shouldRecognizeWithGestureRecognizer: -可以控制任何碰撞手势识别器的行为。

所以,我所做的是

在视图控制器的viewDidLoad方法中:

// Install a pan gesture recognizer                                                                                        // We ignore all the touches except the first and try to prevent other pan gestures                                                     
// by registering this object as the recognizer's delegate                                                                                        
UIPanGestureRecognizer *recognizer;                                                                                                               
recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanFrom:)];                                                   
recognizer.delegate = self;                                                                                                                       
recognizer.maximumNumberOfTouches = 1;                                                                                                            
[self.view addGestureRecognizer:recognizer];                                                                                                          
self.panGestureFixer = recognizer;                                                                                                                  
[recognizer release]; 

然后,手势替代方法:

// Control gestures precedence                                                                                                                            
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer                                                                                        
        shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer                                                  
{                                                                                                                                                         
        // Prevent all panning gestures (which do nothing but scroll webViews, something we want to disable in                                          
        // the most painless way)                                                                                                                         
        if ([otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])                                                                        
        {
            // Just disable every other pan gesture recognizer right away                                                                             
            otherGestureRecognizer.enabled = FALSE;
        }                                                                                                                                                  
        return NO;                                                                                                                                        
}              

当然,在实际的应用程序中,这种委托方法会使我更加复杂-我们可以有选择地禁用其他识别器,分析otherGestureRecognizer.view并根据其视图进行决策。

最后,为了完整起见,我们注册为平移处理程序的方法:

- (void)handlePanFrom:(UIPanGestureRecognizer *)recognizer 
{ 
    // do nothing as of yet
}

如果我们只想取消Web视图的滚动和弹跳,则可以为空;也可以包含我们自己的代码,以实现我们真正想要的平移运动和动画。

到目前为止,我只是在尝试所有这些东西,它似乎或多或少地发挥了我的作用。我还没有尝试将任何应用程序提交到iStore。但是我相信到目前为止我还没有使用过任何未记载的东西。如果有人发现它,请通知我。





0

的子视图之一UIWebView应该是UIScrollView。将其scrollEnabled属性设置为NO,Web视图将完全禁用滚动。

注意:从技术上讲,这是使用私有API的,因此您的应用可能会在以后的OS版本中被拒绝或崩溃。使用@tryrespondsToSelector


我尝试了一下,尝试时出现了错误...奇怪的是,我可以访问并设置scrollView.bounces(无效果),但是当我尝试设置scrollEnabled时,则出错了……
Brad Parks

我相信该子视图称为UIScroller,而不是UIScrollView。UIScroller是一个未记录且不受支持的类,与UIScrollView有很多共同点,但是您不能依赖于所有工作方式相同且在将来的OS版本中不会更改的东西。
Marco

我是在运行iOS 3.2的iPad(不是iPhone)应用程序上执行此操作的,并且能够从UIWebView中获取UIScrollView。我成功地自定义了此视图,以改变其弹跳行为而不仅仅是改变它,因此我可以在iPad上证明这一点。我的应用程序未通过应用程序商店访问,但我认为此处未记录的API不会出现问题。此解决方案的巧妙之处在于,您只是遍历UIView层次结构并使用UIScrollView-两者都是完美的。
罗尔夫·亨德里克斯

0

查看的bounces属性UIScrollView。苹果文档:

如果该属性的值为YES(默认值),则滚动视图在遇到内容边界时会反弹。视觉上弹起表示滚动已到达内容的边缘。如果值为NO,则滚动将立即在内容边界停止而不反弹。

确保您使用的是正确的UIScrollView。我不确定的层次结构如何UIWebView,但是滚动视图可能是的父级,而不是子级UIWebView


0

要禁用UIWebView滚动,可以使用以下代码行:

[ObjWebview setUserInteractionEnabled:FALSE];

在此示例中,ObjWebview类型为UIWebView


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.