如何禁用水平滚动,并且使用UIScrollView单击页面时页面会发生变化?

时间:2018-08-01 09:52:59

标签: objective-c swift uiscrollview uisegmentedcontrol uistackview

我有一个UIScrollView和一个pagingEnabled。在UIStackView的子视图中添加了5个UIScrollView,并且还有一个UISegmentedControl。我想显示当前选定的片段,也想禁用水平滚动,但是视图将能够垂直滚动。

举个例子:

  • 让所选页面索引= 0
  • 用户无法水平滚动或拖动以导航到下一页。
  • 用户可以垂直滚动
  • 现在用户在UISegmentedControl中选择的页面索引= 1
  • 第二页将可见
  • 现在用户无法滚动或拖动到0和2索引

如何使用UIScrollView

实现此功能

尝试过的逻辑

- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];

CGFloat xOff = self.scrollView.frame.size.width * self.currentPage;
[self.scrollView setContentSize:CGSizeMake(xOff, self.scrollView.contentSize.height)];
//[self.scrollView setContentOffset:CGPointMake(xOff, 0) animated:true];

}

但在更改页面后使用此UIScrollView当我再次滚动时,转到0页。

3 个答案:

答案 0 :(得分:8)

您可以在启用分页的情况下使用UICollectionView,而在内部可以启用垂直滚动的UIScrollView。使用以下代码,禁用UICollectionView滚动并在单击时更改索引收集单元格:

接受 修改后的新答案:

将此添加到viewDidLayoutSubviews

SWIFT

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    let indexPath = IndexPath(item: 12, section: 0)
    self.collectionView.scrollToItem(at: indexPath, at: [ .centeredHorizontally], animated: true)
}

通常情况下是.centerVertically

Objective-C

-(void)viewDidLayoutSubviews {
   [super viewDidLayoutSubviews];
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:12 inSection:0];
   [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}

答案 1 :(得分:4)

我正在根据自己的问题使用此解决方案

psql方法中

segmentDidChange()

现在为选定的索引准备stackView

[self.scrollView.subviews makeObjectsPerformSelector: @selector(removeFromSuperview)];
self.scrollView.showsVerticalScrollIndicator = false;
self.scrollView.showsHorizontalScrollIndicator = false;

self.arrSubViews = [NSMutableArray array];

// Loading view's from xib's
// Now
UIView *containerView = [[UIView alloc]initWithFrame:self.scrollView.frame];
    containerView.translatesAutoresizingMaskIntoConstraints = false;

[self prepareStackViewforPage:index withContainerView:containerView];

在applyConstraintsToParent:andSubView:方法中

- (void)prepareStackViewforPage:(NSInteger)index withContainerView:(UIView *)containerView {

  [self.scrollView addSubview:containerView];

  [self applyConstraintsToParent:self.scrollView andSubView:containerView];


  UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:self.arrSubViews];
  [stackView setFrame:self.scrollView.frame];
  stackView.translatesAutoresizingMaskIntoConstraints = false;
  stackView.axis = UILayoutConstraintAxisVertical;
  stackView.spacing = 0;
  stackView.distribution = UIStackViewDistributionFill;
  stackView.alignment = UIStackViewAlignmentFill;
  [containerView addSubview:stackView];

  [self applyConstraintsToParent:containerView andSubView:stackView];

  [self.view updateConstraintsIfNeeded];
  [self.view layoutIfNeeded];
  [self.view layoutSubviews];
}

现在一切正常,但是现在我遇到了以下问题

  • 通过xib高度添加的视图不会动态更改

我在UIStackView: Loading views from xib and updating height constraint of subView did not reflect any changes? 上对此问题提出了疑问

但是这种逻辑在情节提要中正常吗?

Storyboard Demo

答案 2 :(得分:2)

在回答问题后,将isScrollEnabled的{​​{1}}属性设置为UIScrollView,如下所示:

  

对于Objective-C

false
  

快速

[self.scrollView setScrollEnabled:NO];

如Apple文档所述关于此属性:

  

一个布尔值,它确定是否启用滚动。

     

如果此属性的值为true,则启用滚动,如果为false,则禁用滚动。默认值为true。   禁用滚动时,滚动视图不接受触摸事件;否则,滚动视图将停止。它将它们转发到响应者链。

因此您的self.scrollView.isScrollEnabled = false 将不接受触摸,但您的scrollView的内容将被接受。

并且这不允许您以编程方式滚动scrollView(这正在更改scrollView的{​​{1}}属性)。因此,当contentOffset的所选句段发生更改时,您应该根据页面大小为scrollView计算新的内容偏移并进行设置,我建议您使用{{1}的UISegmentedControl方法}以实现滚动。

希望有帮助。