iphone - que - webview tutorial ios




Parar UIWebView de "saltando" verticalmente? (15)

Alguém sabe como parar um UIWebView de saltar verticalmente? Quero dizer, quando um usuário toca na tela do seu iPhone, arrasta o dedo para baixo, e a webview mostra um ponto em branco acima da página da web que eu carreguei?

Eu olhei as seguintes soluções possíveis, mas nenhuma delas funcionou para mim:

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

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

Como faço para parar um UIScrollView de saltar horizontalmente?




Bem, tudo que fiz para conseguir isso é:

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 

}

Funciona bem para mim ... Além disso, a resposta marcada para esta pergunta é aquela que a Apple irá rejeitar se você usá-lo em seu aplicativo para iPhone.


Eu estava olhando para um projeto que facilita a criação de aplicativos da web como aplicativos instaláveis ​​completos no iPhone chamado QuickConnect , e encontrei uma solução que funciona, se você não quiser que sua tela seja rolável, o que no meu caso Eu não fiz.

No projeto / blog mencionado acima, eles mencionam uma função de javascript que você pode adicionar para desativar o salto, que essencialmente se resume a isto:

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

Se você quiser ver mais sobre como eles implementam, basta baixar o QuickConnect e dar uma olhada ... Mas basicamente tudo o que ele faz é chamar isso de javascript no carregamento da página ... Eu tentei apenas colocá-lo na cabeça do meu documento, e parece funcionar bem.


Eu tentei uma abordagem ligeiramente diferente para evitar que os objetos UIWebView rolassem e saltassem: adicionando um reconhecedor de gestos para substituir outros gestos.

Ao que parece, o UIWebView ou sua subview de scroller usa seu próprio reconhecedor de gesto de pan para detectar a rolagem do usuário. Mas, de acordo com a documentação da Apple, existe uma maneira legítima de substituir um reconhecedor de gestos por outro. O protocolo UIGestureRecognizerDelegate possui um método gestureRecognizer: shouldRecognizeSimultaneouslyWithGestureRecognizer: - que permite controlar o comportamento de qualquer reconhecedor de gestos em colisão.

Então, o que eu fiz foi

no método viewDidLoad do view controller:

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

então, o método de substituição de gestos:

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

É claro que esse método delegado pode me tornar mais complexo em um aplicativo real - podemos desabilitar outros reconhecedores seletivamente, analisando otherGestureRecognizer.view e tomando decisões com base em qual visão ele é.

E, finalmente, por uma questão de completude, o método que registramos como um manipulador de pan:

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

pode estar vazio se tudo o que queremos é cancelar a rolagem e a exibição de exibições da Web ou pode conter nosso próprio código para implementar o tipo de movimentos e animações panorâmicas que realmente desejamos ...

Até agora estou apenas experimentando todas essas coisas, e parece estar funcionando mais ou menos como eu quero. Ainda não tentei enviar aplicativos para o iStore. Mas eu acredito que não usei nada indocumentado até agora ... Se alguém encontrar o contrário, por favor me informe.


Fiquei irritado ao descobrir que UIWebView não é uma exibição de rolagem, então criei uma subclasse personalizada para acessar a exibição de rolagem da visualização da Web. Essa suclasse contém uma visualização de rolagem para que você possa personalizar o comportamento da sua visualização da web. As punchlines desta aula são:

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

}

Em seguida, quando você criar uma visualização da Web personalizada, poderá desativar a rejeição com:

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

Essa é uma ótima maneira geral de criar uma exibição da Web com um comportamento de rolagem personalizável. Há apenas algumas coisas a observar:

  • como com qualquer visão, você também precisará sobrescrever - (id) initWithCoder: se você usá-lo no Interface Builder
  • Quando você cria inicialmente uma visualização da Web, seu tamanho de conteúdo é sempre igual ao tamanho do quadro da exibição. Depois de percorrer a web, o tamanho do conteúdo representa o tamanho do conteúdo real da web dentro da exibição. Para contornar isso, fiz algo hacky - chamando -setContentOffset: CGPointMake (0,1) animado: YES para forçar uma alteração imperceptível que definirá o tamanho apropriado do conteúdo da visualização da web.

No Swift para desativar rejeições

webViewObj.scrollView.bounces = false

No iOS 5 SDK, você pode acessar a visualização de rolagem associada a uma visualização da Web diretamente, em vez de percorrer suas subvisualizações.

Então, para desativar o 'salto' na tela de rolagem, você pode usar:

myWebView.scrollView.bounces = NO;

Veja a Referência da Classe UIWebView .

(No entanto, se você precisar dar suporte a versões do SDK antes de 5.0, deverá seguir o conselho de Mirek Rusin .)


O método de Brad funcionou para mim. Se você usá-lo, você pode querer torná-lo um pouco mais seguro.

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

Se a apple mudar alguma coisa, a devolução voltará, mas pelo menos seu aplicativo não irá falhar.


Olhe para a propriedade bounces do UIScrollView . Quoth os docs da Apple:

Se o valor da propriedade for YES (o padrão), a exibição de rolagem será refletida quando encontrar um limite do conteúdo. Saltar visualmente indica que a rolagem atingiu uma borda do conteúdo. Se o valor for NO , a rolagem pára imediatamente no limite de conteúdo sem saltar.

Certifique-se de usar o UIScrollView correto. Não tenho certeza de como é a hierarquia de um UIWebView , mas a exibição de rolagem pode ser um pai, não um filho, do UIWebView .


Parece-me que o UIWebView tem um UIScrollView. Você pode usar APIs documentadas para isso, mas a rejeição é definida para ambas as direções, não individualmente. Isso está nos documentos da API. O UIScrollView tem uma propriedade de rejeição, então algo assim funciona (não sei se há mais de um 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;
    }
}

Swift 3

webView.scrollView.bounces = false

Veio em busca de uma resposta e acabei por sorte em uma resposta minha por mexer. eu fiz

[[webview scrollView] setBounces:NO];

e funcionou.


webView.scrollView.scrollEnabled = NÃO; webView.scrollView.bounces = NÃO;


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

... parece funcionar bem.

Também será aceito na App Store.

Atualização : no iOS 5.x + há uma maneira mais fácil - o UIWebView possui a propriedade scrollView , assim seu código pode ficar assim:

webView.scrollView.bounces = NO;

O mesmo vale para o WKWebView .