Como desabilitar a rolagem horizontal de UIScrollView?


92

Eu tenho um UIViewiPhone como Springboard. Eu o criei usando um UIScrollViewe UIButtons. Desejo desativar a rolagem horizontal na referida visualização de rolagem. Eu quero apenas rolagem vertical. Como faço isso?


5
Você deve mudar seu título: você pede horizontal na pergunta e vertical no título. As pessoas encontram suas perguntas mais tarde nos mecanismos de pesquisa, então isso ainda importa 2 anos depois :)
Julien

@RahulVyas O homem acima tem razão. Mudar o título diminuirá qualquer confusão para iniciantes que chegam aqui através de um mecanismo de busca (como eu;)).
SpacyRicochet

Ter editado o título em nome do autor da postagem. (Embora esteja atualmente aguardando revisão por pares antes de a edição ficar visível.)
Duncan Babbage

Respostas:


125

Você deve definir a contentSizepropriedade do UIScrollView. Por exemplo, se você UIScrollViewtiver 320 pixels de largura (a largura da tela), você pode fazer o seguinte:

CGSize scrollableSize = CGSizeMake(320, myScrollableHeight);
[myScrollView setContentSize:scrollableSize];

O UIScrollViewirá então rolar apenas verticalmente, porque já pode exibir tudo horizontalmente.


6
Oi. Esta solução funciona muito bem! Obrigado por isso. Tentei definir a largura estática para 0. Para mim, isso também funciona. Não sei se pode haver alguns efeitos colaterais mais tarde. Mas se você não souber o tamanho (ou seja, código universal para iPhone e iPad), isso funciona muito bem!
JackPearse

5
Acho melhor fazer CGSizeMake (0, myScrollableHeight), então a rolagem horizontal desabilitada mesmo que nem todas as subvisualizações sejam mostradas.
LightNight

NB: Definir uma das dimensões como 0 ao usar paging fará com que o VoiceOver anuncie o número da página como "página 1 de 1", independentemente do valor correto
Josef

1
Em vez de passar a largura como 320 codificado, podemos passar como: CGSize scrollableSize = CGSizeMake (self.scrollview.frame.size.width, myScrollableHeight); [myScrollView setContentSize: scrollableSize];
Mohit kumar

90

ATUALIZADO: (após @EranMarom apontar em seu comentário)

Você pode interromper a rolagem horizontal ou vertical no ScrollViewDelegateMétodo. Aqui é como,

Para a rolagem horizontal:

Se você deseja rolar horizontalmente, você precisa aumentar o contentOffset.x. Impedindo que pare o scrollview scroll na direção horizontal.

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    sender.contentOffset.x = 0.0
}

Para a rolagem vertical:

Se você deseja rolar verticalmente, é necessário aumentar o contentOffset.y. Impedindo que pare a rolagem scrollview na direção vertical.

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    sender.contentOffset.y = 0.0
}

O código acima impede as mudanças em xe yde a scrollview contentOffsete leva a interromper a rolagem no scrollViewDidScroll:método.


1
Estou pensando em fazer downvoting porque essa resposta não explica se você acabou de fornecer o código e é isso. Responder assim não é muito bom. Boas respostas se explicam, embora os desenvolvedores experientes possam entender isso, os desenvolvedores mais novos podem não entender o que está acontecendo aqui. Ainda não votado como uma chance de melhorar.
Popeye

13
É uma espécie de hack, mas funcionou quando tudo o mais falhou. Portanto, +1, mas use apenas como último recurso.
i_am_jorf de

5
Eu também uso esse método delegado, mas substituo o corpo por um de uma linha, por exemplo: scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y);para desativar a rolagem horizontal. Acho que é mais legível, é menor e não faz sentido fazer o teste para zero porque não há virtualmente nenhuma sobrecarga com código que é executado com pouca frequência (ou seja, algumas dezenas de vezes por segundo no máximo).
Echelon

porque você está mudando o contentOffset depois de "didscroll", não como antes de 'willscroll', e esta é uma solução de martelo, mas eu mesmo não votei negativamente, porque 18 votos positivos e a resposta é 75, então não vale a pena votar negativo
LolaRun

2
Ainda mais fácil, use scrollView.contentOffset.y = 0.0para parar a rolagem vertical e scrollView.contentOffset.x = 0.0para parar a rolagem horizontal, na scrollViewDidScroll()função de delegado. No entanto, acredito que certificar-se de que scrollView.contentSizeigual a scrollView.frame.sizeé a melhor solução (correta). Veja a resposta de @danbeaulieu.
emem

11

desde iOS7 uso

self.automaticallyAdjustsScrollViewInsets = NO;

// e criar seu rolador de página com 3 páginas

    self.pageView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    [self.pageView setContentSize:CGSizeMake(self.view.frame.size.width*3, self.view.frame.size.height)];
    [self.pageView setShowsVerticalScrollIndicator:NO];
    [self.pageView setPagingEnabled:YES];
    [self.view addSubview:self.pageView];

Não acho que isso desabilite o comportamento de rolagem de um scrollview. É isso??
Dinesh Raja

self.collectionView.pagingEnabled = YES;me ajudou a resolver o problema com a rolagem suave (não arrastar). O problema estava no método scrollViewWillEndDragging:- targetContentOffset era o mesmo que scrollView.contentOffset e a lógica de detecção de página não funciona corretamente.
sig

11

Solução rápida

Crie duas saídas, uma para sua visualização e outra para sua visualização de rolagem:

@IBOutlet weak var myView: UIView!
@IBOutlet weak var scrollView: UIScrollView!

Em seguida, em viewDidLayoutSubviews, você pode adicionar o seguinte código:

let scrollSize = CGSize(width: myView.frame.size.width, 
                        height: myView.frame.size.height)
scrollView.contentSize = scrollSize

O que fizemos foi coletar a altura e largura da visualização e definir o tamanho do conteúdo scrollViews para corresponder a ele. Isso impedirá que a sua visualização de rolagem role horizontalmente.


Mais pensamentos:

CGSizeMake obtém largura e altura usando CGFloats. Você pode precisar usar sua altura existente de UIScrollViews para o segundo parâmetro. Que ficaria assim:

let scrollSize = CGSize(width: myView.frame.size.width, 
                        height: scrollView.contentSize.height)

E se você não souber a altura ou a largura (dispositivo universal)? @danbeaulieu
Lukesivi

@lukesIvi "myView.frame.width" está puxando dinamicamente a largura do IBOutlet "myView".
Dan Beaulieu

4

No meu caso, com o Swift 4.2 você pode usar:

Desativar rolagem vertical:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.y = 0.0
}

Desativar rolagem horizontal:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.x = 0.0
}

3

Você pode selecionar a visualização e, em seguida, Attributes Inspectordesmarcar User Interaction Enabled.


3

No meu caso, a largura de contentView era maior do que a largura de UIScrollView e esse era o motivo da rolagem horizontal indesejada. Eu resolvi isso definindo a largura de contentView igual à largura de UIScrollView.

Espero que ajude alguém


@Nostradamus feliz em ajudar
Gulfam Khan

0

Eu tinha o tableview contentInset definido em viewDidLoad (como abaixo) que o que causava a rolagem horizontal

self.tableView.contentInset = UIEdgeInsetsMake(0, 30, 0, 0);

Verifique se há algum tableview contentInset definido por diferentes motivos e desative-o


0

Lutei com isso por algum tempo, tentando sem sucesso as várias sugestões neste e em outros tópicos.

No entanto, em outro segmento (não tenho certeza de onde), alguém sugeriu que usar uma restrição negativa no UIScrollView funcionou para ele.

Então, tentei várias combinações de restrições com resultados inconsistentes. O que funcionou para mim foi adicionar restrições iniciais e finais de -32 à visualização de rolagem e adicionar uma visualização de texto (invisível) com largura de 320 (e centralizada).


0

Experimente isto:

CGSize scrollSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, scrollHeight);
[scrollView setContentSize: scrollSize];

0

Desative a rolagem horizontal substituindo a contentOffsetpropriedade na subclasse.

override var contentOffset: CGPoint {
  get {
    return super.contentOffset
  }
  set {
    super.contentOffset = CGPoint(x: 0, y: newValue.y)
  }
}

0

Introduzido no iOS 11 é uma nova propriedade em UIScrollView

var contentLayoutGuide: UILayoutGuide

A documentação afirma que você:

Use este guia de layout quando quiser criar restrições de layout automático relacionadas à área de conteúdo de uma visualização de rolagem.

Juntamente com quaisquer outras restrições autoLayout que você pode ser a adição de que você vai querer restringir a widthAnchordos UIScrollView'scontentLayoutGuide para ser o mesmo tamanho que o 'frame'. Você pode usar o frameLayoutGuide(também introduzido no iOS 11) ou qualquer largura externa (como o seusuperView ).

exemplo:

NSLayoutConstraint.activate([
  scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: self.widthAnchor)
])

Documentação: https://developer.apple.com/documentation/uikit/uiscrollview/2865870-contentlayoutguide


-1

Uma vez que fiz isso substituindo o UIScrollView por um UITableView com apenas 1 célula, funcionou bem.


1
Desculpe, isso não responde à pergunta.
David

-1

Use esta única linha.

self.automaticallyAdjustsScrollViewInsets = NO;

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.