web-dev-qa-db-fra.com

Empêcher UIWebView de "rebondir" verticalement?

Est-ce que quelqu'un sait comment empêcher un UIWebView de rebondir verticalement? Je veux dire quand un utilisateur touche son écran d'iphone, fait glisser son doigt vers le bas et que la vue Web affiche un point vide au-dessus de la page Web que j'ai chargée?

J'ai examiné les solutions possibles suivantes, mais aucune d'entre elles n'a fonctionné pour moi:

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

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

Comment puis-je empêcher un UIScrollView de rebondir horizontalement?

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

... semble fonctionner correctement.

Il sera également accepté sur l'App Store.

Mise à jour: dans iOS 5.x +, il existe un moyen plus simple - UIWebView possède la propriété scrollView, afin que votre code puisse ressembler à ceci:

webView.scrollView.bounces = NO;

Il en va de même pour WKWebView.

420
Mirek Rusin

Je cherchais un projet qui facilite la création d'applications Web en tant qu'applications installables à part entière sur l'iPhone, appelé QuickConnect , et j'ai trouvé une solution qui fonctionne si vous ne voulez pas que votre écran soit déroulant. du tout, ce que je n'ai pas fait dans mon cas.

Dans le projet/blog mentionné ci-dessus, ils mentionnent une fonction javascript que vous pouvez ajouter pour désactiver le rebondissement, ce qui revient essentiellement à ceci:

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

Si vous voulez en savoir plus sur leur implémentation, il suffit de télécharger QuickConnect et de le vérifier .... Mais en gros, tout ce qu'il appelle, c'est appeler javascript au chargement de la page ... J'ai simplement essayé de le mettre dans la tête de mon document, et cela semble bien fonctionner.

46
Brad Parks

Eh bien tout ce que j'ai fait pour accomplir ceci est:

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 

}

Cela fonctionne bien pour moi ... De plus, la réponse cochée pour cette question est une réponse que Apple rejettera si vous l'utilisez dans votre application iPhone.

18
Zigglzworth

Dans le SDK iOS 5, vous pouvez accéder directement à la vue de défilement associée à une vue Web au lieu de parcourir les sous-vues.

Donc, pour désactiver le "rebond" dans la vue de défilement, vous pouvez utiliser:

myWebView.scrollView.bounces = NO;

Voir le Référence de la classe UIWebView .

(Toutefois, si vous devez prendre en charge les versions du SDK antérieures à la version 5.0, vous devez suivre le conseil de Mirek Rusin .)

17
jstr

Swift 3

webView.scrollView.bounces = false
11
Ego Slayer

Attention. J'ai utilisé setAllowsRubberBanding: dans mon application et Apple l'a rejetée, déclarant que les fonctions d'API non publiques ne sont pas autorisées (cite: 3.3.1)

9
Raf

Dans Swift pour désactiver les rebonds

webViewObj.scrollView.bounces = false
4
Jugal K Balara

Sur iOS5 uniquement si vous prévoyez de laisser les utilisateurs zoomer sur le contenu de la visualisation Web (par exemple, appuyer deux fois), le paramètre de rebond ne suffit pas. Vous devez également définir les propriétés alwaysBounceHorizontal et alwaysBounceVertical sur NO, sinon, lorsqu'elles effectuent un zoom arrière (une autre double frappe ...), les valeurs par défaut sont renvoyées.

La méthode de Brad a fonctionné pour moi. Si vous l'utilisez, vous voudrez peut-être le rendre un peu plus sûr.

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

Si Apple change quelque chose, le rebond reviendra, mais au moins votre application ne se plantera pas.

3
Gavin Maclean

J'ai parcouru la collection de sous-vues d'UIWebView et ai défini leurs arrière-plans sur [UIColor blackColor], la même couleur que l'arrière-plan de la page Web. La vue continuera à rebondir mais elle ne montrera pas cet horrible fond gris foncé.

2
pedro

J'étais ennuyé d'apprendre que UIWebView n'est pas une vue par défilement. J'ai donc créé une sous-classe personnalisée pour accéder à la vue par défilement de la vue Web. Cette sous-classe contient une vue de défilement afin que vous puissiez personnaliser le comportement de votre vue Web. Les lignes de frappe de cette classe sont:

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

}

Ensuite, lorsque vous créez un affichage Web personnalisé, vous pouvez désactiver le renvoi avec:

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

C'est un excellent moyen de créer une vue Web avec un comportement de défilement personnalisable. Il y a juste quelques points à surveiller:

  • comme pour toute vue, vous devez également remplacer - (id) initWithCoder: si vous l'utilisez dans Interface Builder
  • lorsque vous créez une vue Web pour la première fois, sa taille de contenu est toujours identique à la taille du cadre de la vue. Après avoir fait défiler le Web, la taille du contenu représente la taille du contenu Web réel dans la vue. Pour résoudre ce problème, j'ai fait quelque chose de mal: appeler -setContentOffset: CGPointMake (0,1) animé: OUI pour imposer un changement imperceptible qui définira la taille de contenu appropriée de la vue Web.
2
Rolf Hendriks

Je suis tombé sur cette recherche d’une réponse et j’ai finalement eu de la chance d’avoir une réponse personnelle en décochant. J'ai fait

[[webview scrollView] setBounces:NO];

et cela a fonctionné.

2
Luke

Cela a fonctionné pour moi, et aussi très bien (j'utilise phonegap avec webView)

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

ou

[[webView scrollView] setScrollEnabled:NO];
2
Jason G

Il me semble que UIWebView a un UIScrollView. Vous pouvez utiliser des API documentées à cet effet, mais le rebond est défini dans les deux sens, pas individuellement. C'est dans la documentation de l'API. UIScrollView a une propriété bounce, donc quelque chose comme ça marche (je ne sais pas s'il y a plus d'un scrollview):

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
spymaster

Voici deux nouvelles solutions potentielles. Apparemment, vous pouvez utiliser jqtouch ou pastrykit pour désactiver le défilement. Cependant, je ne les ai pas au travail. Vous pourriez être plus compétent.

désactivation du défilement vertical

creuser dans pâtisserie

1
cannyboy

positionnement fixe sur safari mobile

Ce lien m'a beaucoup aidé ..... C'est facile .. Il y a une démo ..

1
S.P.

(Exemple de Xcode 5 iOS 7 SDK) Voici un exemple d’application universelle utilisant la fonction scrollview setBounces. Il s’agit d’un projet/exemple open source situé ici: Lien vers SimpleWebView (exemple de code source et de projet)

1
Matthew Ferguson

J'ai essayé une approche légèrement différente pour empêcher les objets IWebView de défiler et de rebondir: ajouter un outil de reconnaissance des gestes pour remplacer les autres gestes.

Il semble que IWebView ou sa sous-vue Scroller utilise son propre outil de reconnaissance des gestes de panoramique pour détecter le défilement de l'utilisateur. Selon la documentation d'Apple, il existe un moyen légitime de remplacer un identificateur de geste par un autre. Le protocole IGestureRecognizerDelegate a une méthode gestureRecognizer: shouldRecognizeSimultaneousWithGestureRecognizer: - qui permet de contrôler le comportement des dispositifs de reconnaissance de mouvements en collision.

Alors, ce que j'ai fait était

dans la méthode viewDidLoad du contrôleur de vue:

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

ensuite, la méthode de substitution de geste:

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

Bien sûr, cette méthode de délégation peut être plus complexe dans une application réelle - nous pouvons désactiver d'autres identificateurs de reconnaissance de manière sélective, en analysant otherGestureRecognizer.view et en prenant une décision en fonction de la vue.

Et, enfin, par souci d’exhaustivité, la méthode que nous avons enregistrée en tant que gestionnaire de panoramique:

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

il peut être vide si tout ce que nous voulons, c'est annuler le défilement et le rebondissement des vues Web, ou contenir notre propre code pour implémenter le type de mouvements et d'animations que nous souhaitons réellement ...

Jusqu'à présent, je ne fais qu'expérimenter avec tout cela, et il semble fonctionner plus ou moins comme je le veux. Je n'ai toutefois pas encore essayé de soumettre d'applications sur iStore. Mais je pense ne pas avoir utilisé de documents sans papiers jusqu'à présent ... Si quelqu'un trouve le contraire, merci de m'en informer.

1
PP-RD

Pour désactiver le défilement UIWebView, vous pouvez utiliser la ligne de code suivante:

[ObjWebview setUserInteractionEnabled:FALSE];

Dans cet exemple, ObjWebview est de type UIWebView.

0
Sandip Patel - SM

Examinez la propriété bounces de UIScrollView. La Apple docs:

Si la valeur de la propriété est YES (valeur par défaut), la vue de défilement rebondit lorsqu'elle rencontre une limite du contenu. Le rebond visuel indique que le défilement a atteint un bord du contenu. Si la valeur est NO, le défilement s'arrête immédiatement à la limite du contenu sans rebondir.

Assurez-vous que vous utilisez le bon UIScrollView. Je ne suis pas sûr de ce à quoi ressemble la hiérarchie pour un UIWebView, mais la vue de défilement pourrait être un parent, pas un enfant, du UIWebView.

0
Alex

Une des sous-vues de UIWebView devrait être un UIScrollView. Définissez sa propriété scrollEnabled sur NO et le défilement de la vue Web sera entièrement désactivé.

Remarque: il s'agit techniquement d'une API privée et votre application pourrait donc être rejetée ou se bloquer dans les versions futures du système d'exploitation. Utilisez @try et respondsToSelector

0
rpetrich

webView.scrollView.scrollEnabled = NO; webView.scrollView.bounces = NO;

0
Kumaresan P