UIWebView daran hindern, vertikal zu "springen"?


225

Weiß jemand, wie man verhindert, dass ein UIWebView vertikal springt? Ich meine, wenn ein Benutzer seinen iPhone-Bildschirm berührt, seinen Finger nach unten zieht und die Webansicht eine leere Stelle über der von mir geladenen Webseite anzeigt?

Ich habe mir die folgenden möglichen Lösungen angesehen, aber keine davon hat für mich funktioniert:

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

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

Wie kann ich verhindern, dass eine UIScrollView horizontal abprallt?


1
Ich hoffe, Sie haben die Auswirkungen der Deaktivierung dieser Funktion auf die Benutzerfreundlichkeit berücksichtigt. Es ist aus einem Grund da. Trotzdem bin ich auch neugierig, wie du das machen würdest.
Michael Haren

So wie ich es in meine App eingebettet habe, erscheint es scheinbar nahtlos mit einigen anderen Ansichtselementen, die ich habe, und das einzige Mal, dass es nicht so erscheint, ist, wenn der Sprung stattfindet ... Auf jeden Fall ein guter Punkt!
Brad Parks

Antworten:


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

... scheint gut zu funktionieren.

Es wird auch in den App Store aufgenommen.

Update : In iOS 5.x + gibt es einen einfacheren Weg - UIWebViewhat eine scrollViewEigenschaft, sodass Ihr Code folgendermaßen aussehen kann:

webView.scrollView.bounces = NO;

Gleiches gilt für WKWebView.


Es klappt. Keine Unterklassen erforderlich. Sollte Apple jemals die UIWebView-Hierarchie ändern, sollte sie nicht abstürzen.
Leolobato

2
Dieser Fix scheint nur in meinem OS 4.1 Simulator zu funktionieren, nicht auf meinem OS 3.1.3 iPhone. Weiß jemand, ob dieses Update nur unter bestimmten Betriebssystemversionen funktioniert?
Dan J

@MirukRusin - Wie können Sie garantieren, dass diese App basierend auf drei Codezeilen akzeptiert wird? : P
Moshe

@Mirek - Du hast meinen Standpunkt verfehlt. Woher weißt du, dass nichts anderes in der App abgelehnt wird?
Moshe

6
Das hat bei mir gut funktioniert. Der Einfachheit halber habe ich eine Kategorie hinzugefügt, UIWebViewdamit ich [webView setBounces:NO]überall anrufen kann, wo ich möchte.
Zekel

46

Ich habe mir ein Projekt angesehen, das es einfach macht, Webanwendungen als vollwertige installierbare Anwendungen auf dem iPhone namens QuickConnect zu erstellen , und eine Lösung gefunden, die funktioniert, wenn Sie nicht möchten, dass Ihr Bildschirm überhaupt scrollbar ist, was in meinem Fall der Fall ist Ich habe nicht.

In dem oben erwähnten Projekt- / Blog-Beitrag wird eine Javascript-Funktion erwähnt, die Sie hinzufügen können, um das Bouncing auszuschalten, was im Wesentlichen auf Folgendes hinausläuft:

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

Wenn Sie mehr darüber erfahren möchten, wie sie es implementieren, laden Sie einfach QuickConnect herunter und probieren Sie es aus. Aber im Grunde ist es nur das Aufrufen von Javascript beim Laden der Seite ... Ich habe versucht, es einfach in den Kopf meines Dokuments zu setzen. und es scheint gut zu funktionieren.


Diese Antwort ist der richtige Weg, um das vertikale Scrollen des Inhalts in einer UIWebView zu stoppen.
Jessedc

3
Sie hätten die ganze Antwort geben können. Erstens möchte ich nicht den gesamten Quellcode einer anderen App herunterladen, und ich kann ihn nicht einmal finden. Ihre Antwort hängt davon ab, dass eine andere Website mit Ihrer Antwort übereinstimmt.
Jonathan.

Diese Antwort und die oben akzeptierte Antwort scheinen manchmal erforderlich zu sein. In meinem Fall stellte ich fest, dass, wenn die Webansicht noch nicht geladen war, die Bounciness vorhanden sein würde, bis der obige JS tatsächlich in das System geladen wurde. Die Antwort scheint also zu sein, dass dies und die oben akzeptierte Antwort manchmal beide erforderlich sind.
Kalle

3
Wie Jessedc sagte, wird dies das vertikale Scrollen stoppen und nicht nur das Hüpfen. Das heißt, wenn Sie div oder so haben, das einen Bildlauf erfordert, wird nicht gescrollt.
memical

18

Nun, alles, was ich getan habe, um dies zu erreichen, ist:

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 

}

Funktioniert gut für mich ... Außerdem ist die angekreuzte Antwort auf diese Frage eine, die Apple ablehnt, wenn Sie sie in Ihrer iPhone-App verwenden.


3
Dies ist der beste und einfachste Weg. Dies sollte die akzeptierte Antwort sein! +1
PostCodeism

3
Tun Sie das nicht - meine App wurde abgelehnt, weil sie die erste Zeile verwendet hat. Ich habe so viel Zeit für mich verschwendet. Ich habe [[webView.subviews lastObject] setScrollEnabled: NO] verwendet. und Apple sagte, es sei eine private API und lehnte sie daher ab. Ich werde es jetzt erneut einreichen, habe aber "userInteractionEnabled: NO" verwendet, da ich keine aktiven Links in der App benötige.
Veeru

UIWebView erbt von UIView. UIView verfügt über Unteransichten von Eigenschaften. Was ist hier privat? All dies finden Sie auf developer.apple.com
Valerii Pavlov

3
Ich habe so etwas wie 4 Apps im Appstore, die dies verwenden. Ihre App wurde aus einem anderen Grund eindeutig abgelehnt. Dies ist keine private API.
Zigglzworth

4
Das ist wirklich keine gute Idee. Sie verlassen sich auf die Tatsache, dass dies die UIScrollViewerste Unteransicht ist, die derzeit UIWebViewmöglicherweise der Fall ist. Dies kann sich jedoch in zukünftigen (sogar geringfügigen) Updates für iOS oder bestimmte Konfigurationen leicht ändern. Sie sollten wirklich eine forIteration durchführen, um subviewsdas tatsächlich zu finden UIScrollView(es ist wirklich nicht so viel Arbeit und zumindest werden Sie garantiert ein bekommen UIScrollViewund Ihr Programm nicht zum Absturz bringen ...
Jonathan Ellis

17

Im iOS 5 SDK können Sie direkt auf die einer Webansicht zugeordnete Bildlaufansicht zugreifen, anstatt die Unteransichten zu durchlaufen.

Um das "Bouncing" in der Bildlaufansicht zu deaktivieren, können Sie Folgendes verwenden:

myWebView.scrollView.bounces = NO;

Siehe die UIWebView-Klassenreferenz .

(Wenn Sie jedoch Versionen des SDK vor 5.0 unterstützen müssen, sollten Sie den Ratschlägen von Mirek Rusin folgen .)



9

Warnung. Ich habe setAllowsRubberBanding: in meiner App verwendet, und Apple lehnte dies ab und erklärte, dass nicht öffentliche API-Funktionen nicht zulässig sind (Zitat: 3.3.1).



3

Brads Methode hat bei mir funktioniert. Wenn Sie es verwenden, möchten Sie es vielleicht etwas sicherer machen.

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

Wenn Apple etwas ändert, kommt der Sprung zurück - aber zumindest stürzt Ihre App nicht ab.


3

Unter iOS5 reicht die Bounce-Einstellung nicht aus, wenn Sie vorhaben, die Benutzer den Inhalt der Webansicht zoomen zu lassen (z. B. doppeltes Tippen). Sie müssen auch die Eigenschaften alwaysBounceHorizontal und alwaysBounceVertical auf NO setzen, da sie sonst beim Herauszoomen (ein weiteres doppeltes Tippen ...) auf die Standardeinstellungen wieder zurückspringen.


2

Ich habe die Sammlung der UIWebView-Unteransichten durchsucht und deren Hintergrund auf [UIColor blackColor] gesetzt, dieselbe Farbe wie der Hintergrund der Webseite. Die Ansicht wird weiterhin angezeigt, zeigt jedoch nicht den hässlichen dunkelgrauen Hintergrund.


1
Eigentlich ist es ziemlich schlimm, denn wenn Apple jemals die Interna von UIWebView ändert, könnte dieser Hack brechen.
Papa

2

Es sieht für mich so aus, als hätte die UIWebView eine UIScrollView. Sie können hierfür dokumentierte APIs verwenden, aber das Bouncing wird für beide Richtungen und nicht einzeln festgelegt. Dies ist in den API-Dokumenten. UIScrollView verfügt über eine Bounce-Eigenschaft, sodass so etwas funktioniert (ich weiß nicht, ob es mehr als eine Bildlaufansicht gibt):

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

Ich war verärgert, als ich herausfand, dass UIWebView keine Bildlaufansicht ist, und habe daher eine benutzerdefinierte Unterklasse erstellt, um die Bildlaufansicht der Webansicht aufzurufen. Diese Klasse enthält eine Bildlaufansicht, mit der Sie das Verhalten Ihrer Webansicht anpassen können. Die Pointen dieser Klasse sind:

@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;

}}

Wenn Sie dann eine benutzerdefinierte Webansicht erstellen, können Sie das Bouncen deaktivieren mit:

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

Dies ist eine großartige allgemeine Möglichkeit, eine Webansicht mit anpassbarem Bildlaufverhalten zu erstellen. Es gibt nur ein paar Dinge, auf die Sie achten müssen:

  • Wie bei jeder Ansicht müssen Sie auch - (id) initWithCoder: überschreiben, wenn Sie es in Interface Builder verwenden
  • Wenn Sie zum ersten Mal eine Webansicht erstellen, entspricht deren Inhaltsgröße immer der Größe des Rahmens der Ansicht. Nachdem Sie durch das Web gescrollt haben, entspricht die Inhaltsgröße der Größe des tatsächlichen Webinhalts in der Ansicht. Um dies zu umgehen, habe ich etwas Hackiges getan - Aufruf von -setContentOffset: CGPointMake (0,1) animiert: YES, um eine nicht wahrnehmbare Änderung zu erzwingen, die die richtige Inhaltsgröße der Webansicht festlegt.

2

Kam über diese Suche nach einer Antwort und ich hatte schließlich nur Glück mit einer eigenen Antwort, indem ich herumgespielt habe. Ich tat

[[webview scrollView] setBounces:NO];

und es hat funktioniert.


2

Das hat bei mir funktioniert und auch wunderbar (ich verwende Phonegap mit webView)

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

oder

[[webView scrollView] setScrollEnabled:NO];

1

Ich habe einen etwas anderen Ansatz versucht, um zu verhindern, dass UIWebView- Objekte scrollen und springen können: Hinzufügen eines Gestenerkenners, um andere Gesten zu überschreiben.

Es scheint, dass UIWebView oder seine Scroller-Unteransicht einen eigenen Pan-Gesten-Erkenner verwendet, um das Scrollen von Benutzern zu erkennen. Laut Apples Dokumentation gibt es jedoch eine legitime Möglichkeit, einen Gestenerkenner mit einem anderen zu überschreiben. Das UIGestureRecognizerDelegate- Protokoll verfügt über eine Methode gestureRecognizer: shouldRecognizeSimultaneousWithGestureRecognizer: - Mit dieser Methode kann das Verhalten kollidierender Gestenerkenner gesteuert werden.

Also, was ich getan habe war

in der viewDidLoad-Methode des View Controllers:

// 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]; 

dann die Gestenüberschreibungsmethode:

// 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;                                                                                                                                        
}              

Natürlich kann diese Delegatmethode in einer realen Anwendung komplexer sein - wir können andere Erkenner selektiv deaktivieren, otherGestureRecognizer.view analysieren und Entscheidungen basierend auf der Ansicht treffen.

Und schließlich der Vollständigkeit halber die Methode, die wir als Pan-Handler registriert haben:

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

Es kann leer sein, wenn wir nur das Scrollen und Bouncen von Webansichten abbrechen möchten, oder es kann unseren eigenen Code enthalten, um die Art von Schwenkbewegungen und Animationen zu implementieren, die wir wirklich wollen ...

Bisher experimentiere ich nur mit all dem Zeug und es scheint mehr oder weniger so zu funktionieren, wie ich es will. Ich habe jedoch noch nicht versucht, Apps an iStore zu senden. Aber ich glaube, ich habe bisher nichts undokumentiertes verwendet ... Wenn jemand etwas anderes findet, informieren Sie mich bitte.





0

Eine der Unteransichten von UIWebViewsollte a sein UIScrollView. Wenn Sie die scrollEnabledEigenschaft auf NOfestlegen, wird das Scrollen in der Webansicht vollständig deaktiviert.

Hinweis: Hierbei wird technisch eine private API verwendet. Daher kann Ihre App in zukünftigen Betriebssystemversionen abgelehnt werden oder abstürzen. Verwenden Sie @tryundrespondsToSelector


Ich habe es ausprobiert und es ist fehlerhaft, wenn ich es ausprobiere ... Seltsamerweise kann ich auf scrollView.bounces zugreifen und es einstellen (ohne Wirkung), aber wenn ich versuche, scrollEnabled einzustellen, ist es fehlerhaft ...
Brad Parks

Ich glaube, die Unteransicht heißt UIScroller, nicht UIScrollView. UIScroller ist eine undokumentierte und nicht unterstützte Klasse, die viele Gemeinsamkeiten mit UIScrollView aufweist. Sie können sich jedoch nicht darauf verlassen, dass alles auf die gleiche Weise funktioniert und sich in zukünftigen Betriebssystemversionen nicht ändert.
Marco

Ich habe dies auf einer iPad-App (nicht iPhone) mit iOS 3.2 getan und konnte eine UIScrollView aus meiner UIWebView herausholen. Ich habe diese Ansicht erfolgreich angepasst, um mehr als nur das Sprungverhalten zu ändern, damit ich dies auf dem iPad bestätigen kann. Meine App hat den App Store nicht durchlaufen, aber ich glaube nicht, dass es hier ein Problem mit undokumentierten APIs geben wird. Der clevere Teil dieser Lösung ist, dass Sie nur eine UIView-Hierarchie durchlaufen und eine UIScrollView verwenden - beide sind perfekt koscher.
Rolf Hendriks

0

Schauen Sie in das bouncesEigentum von UIScrollView. Quoth die Apple-Dokumente:

Wenn der Wert der Eigenschaft YES(Standardeinstellung) ist, wird die Bildlaufansicht angezeigt, wenn sie auf eine Grenze des Inhalts stößt. Visuelles Bouncen zeigt an, dass das Scrollen einen Rand des Inhalts erreicht hat. Wenn der Wert "Wert" ist NO, stoppt das Scrollen sofort an der Inhaltsgrenze, ohne zu springen.

Stellen Sie sicher, dass Sie das richtige verwenden UIScrollView. Ich bin nicht sicher, wie die Hierarchie für a aussieht UIWebView, aber die Bildlaufansicht könnte ein Elternteil und kein Kind der sein UIWebView.


0

Um das UIWebViewScrollen zu deaktivieren, können Sie die folgende Codezeile verwenden:

[ObjWebview setUserInteractionEnabled:FALSE];

In diesem Beispiel ObjWebviewist vom Typ UIWebView.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.