如何禁用水平滚动并且页面将在使用 UIScrollView 的分页中单击时更改?
How can I disable horizontal scrolling and page will change on click in paging using UIScrollView?
我有一个 UIScrollView
和 pagingEnabled
。添加了 5 UIStackView
到 UIScrollView
的子视图,还有一个 UISegmentedControl
。我想显示当前选择的片段,也想禁用水平滚动,但视图可以垂直滚动。
举个例子:
- 让选中的页面索引=0
- 用户无法滚动或水平拖动以导航到下一页。
- 用户可以垂直滚动
- 现在
UISegmentedControl
中用户选择的页面索引 = 1
- 第 2 页将可见
- 现在用户无法滚动或拖动到 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 页。
我正在使用我自己的问题的解决方案
在segmentDidChange()
方法中
[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];
正在为所选索引准备 stackView
- (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];
}
在applyConstraintsToParent:andSubView中:方法
- (void)applyConstraintsToParent:(UIView *)parentView andSubView:(UIView *)subView {
//constraints
NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
[parentView addConstraint:leading];
NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0];
[parentView addConstraint:trailing];
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
[parentView addConstraint:top];
NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-8];
[parentView addConstraint:bottom];
NSLayoutConstraint *equalWidth = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0];
[parentView addConstraint:equalWidth];
leading.active = true;
trailing.active = true;
top.active = true;
bottom.active = true;
equalWidth.active = true;
}
现在一切正常,但现在我遇到了以下问题
- 通过 xib 添加的视图高度不会动态变化
我已经在 UIStackView 上提出了这个问题:从 xib 加载视图并更新子视图的高度约束没有反映任何变化?
但是这个逻辑在情节提要中工作得很好吗?
根据您的问题,将 UIScrollView
的 isScrollEnabled
属性 设置为 false
的答案如下:
For Objective-C
[self.scrollView setScrollEnabled:NO];
For swift
self.scrollView.isScrollEnabled = false
正如 Apple 文档所说 属性:
A Boolean value that determines whether scrolling is enabled.
If the value of this property is true , scrolling is enabled, and if it is false , scrolling is disabled. The default is true.
When scrolling is disabled, the scroll view does not accept touch events; it forwards them up the responder chain.
因此您的 scrollView
不会接受触摸,但您的 scrollView
的内容会。
这不会禁止您以编程方式滚动 scrollView
(这会改变 scrollView
的 contentOffset
属性)。因此,当您 UISegmentedControl
的选定部分发生更改时,您应该根据页面大小为 scrollView
计算新的内容偏移量并进行设置,我建议您使用 [=13= 的 setContentOffset(_:animated:)
方法]实现滚动
希望对您有所帮助。
您可以在启用分页的情况下使用 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];
}
我有一个 UIScrollView
和 pagingEnabled
。添加了 5 UIStackView
到 UIScrollView
的子视图,还有一个 UISegmentedControl
。我想显示当前选择的片段,也想禁用水平滚动,但视图可以垂直滚动。
举个例子:
- 让选中的页面索引=0
- 用户无法滚动或水平拖动以导航到下一页。
- 用户可以垂直滚动
- 现在
UISegmentedControl
中用户选择的页面索引 = 1
- 第 2 页将可见
- 现在用户无法滚动或拖动到 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 页。
我正在使用我自己的问题的解决方案
在segmentDidChange()
方法中
[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];
正在为所选索引准备 stackView
- (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];
}
在applyConstraintsToParent:andSubView中:方法
- (void)applyConstraintsToParent:(UIView *)parentView andSubView:(UIView *)subView {
//constraints
NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
[parentView addConstraint:leading];
NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0];
[parentView addConstraint:trailing];
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
[parentView addConstraint:top];
NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-8];
[parentView addConstraint:bottom];
NSLayoutConstraint *equalWidth = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0];
[parentView addConstraint:equalWidth];
leading.active = true;
trailing.active = true;
top.active = true;
bottom.active = true;
equalWidth.active = true;
}
现在一切正常,但现在我遇到了以下问题
- 通过 xib 添加的视图高度不会动态变化
我已经在 UIStackView 上提出了这个问题:从 xib 加载视图并更新子视图的高度约束没有反映任何变化?
但是这个逻辑在情节提要中工作得很好吗?
根据您的问题,将 UIScrollView
的 isScrollEnabled
属性 设置为 false
的答案如下:
For Objective-C
[self.scrollView setScrollEnabled:NO];
For swift
self.scrollView.isScrollEnabled = false
正如 Apple 文档所说 属性:
A Boolean value that determines whether scrolling is enabled.
If the value of this property is true , scrolling is enabled, and if it is false , scrolling is disabled. The default is true. When scrolling is disabled, the scroll view does not accept touch events; it forwards them up the responder chain.
因此您的 scrollView
不会接受触摸,但您的 scrollView
的内容会。
这不会禁止您以编程方式滚动 scrollView
(这会改变 scrollView
的 contentOffset
属性)。因此,当您 UISegmentedControl
的选定部分发生更改时,您应该根据页面大小为 scrollView
计算新的内容偏移量并进行设置,我建议您使用 [=13= 的 setContentOffset(_:animated:)
方法]实现滚动
希望对您有所帮助。
您可以在启用分页的情况下使用 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];
}