【问题标题】:How to disable horizontal scrolling of UIScrollView?如何禁用 UIScrollView 的水平滚动?
【发布时间】:2010-11-06 22:55:42
【问题描述】:

我有一个UIView,比如 iPhone 的 Springboard。我使用UIScrollViewUIButtons 创建了它。我想在所述滚动视图上禁用水平滚动。我只想要垂直滚动。我该如何做到这一点?

【问题讨论】:

  • 你应该改变你的标题:你在问题中要求水平,在标题中要求垂直。人们稍后会在搜索引擎上找到您的问题,所以 2 年后仍然很重要 :)
  • @RahulVyas 上面的人有一点。更改标题将减少通过搜索引擎到达这里的初学者的任何困惑(例如我;))。
  • 已代表发帖者编辑标题。 (虽然它目前正在等待同行评审,然后才能看到编辑。)

标签: ios objective-c uiscrollview


【解决方案1】:

@Gulfam Khan 的回答是正确的,我正在添加图像以帮助该概念获得更多可见性。

当我们将 contentView 设置为与 Scroll view 等宽时,如果乘数比 1:1 稍大一点,我们就会得到水平滚动。

这是它产生的结果:

如果你不想水平滚动,你很可能没有超过超级视图宽度的水平内容。

因此,如果您确保 contentView 的宽度不超过滚动视图的宽度,这将自动解决问题,因为 UIKit 识别到没有水平内容可以滚动到。像这样:

现在你应该只看到垂直:

【讨论】:

  • 值得检查您的约束。我不确定为什么 multiplier 会以十进制数字结尾,但这为我解决了问题。
  • 我认为当您在拖动时将宽度设置为相等时,我们认为我们将其设置为完全相等,但我们实际上将其设置为几乎完全相等,然后我们得到 1.00003 作为乘数.这是拖累乘数的不完美之处。
【解决方案2】:

在 iOS 11 中引入的是 UIScrollView 上的新属性

var contentLayoutGuide: UILayoutGuide

文档声明您:

当您想要创建与滚动视图的内容区域相关的自动布局约束时,请使用此布局指南。

除了您可能添加的任何其他自动布局约束外,您还需要将UIScrollViewcontentLayoutGuidewidthAnchor 约束为与“框架”相同的大小。你可以使用frameLayoutGuide(也在iOS 11中引入)或者任何外部宽度(比如你的superView的)

示例:

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

文档: https://developer.apple.com/documentation/uikit/uiscrollview/2865870-contentlayoutguide

【讨论】:

    【解决方案3】:

    通过覆盖子类中的contentOffset 属性来禁用水平滚动。

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

    【讨论】:

      【解决方案4】:

      在我的情况下,您可以使用 Swift 4.2:

      禁用垂直滚动:

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

      禁用水平滚动:

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

      【讨论】:

        【解决方案5】:

        在我的情况下,contentView 的宽度大于 UIScrollView 的宽度,这就是不需要的水平滚动的原因。我通过将 contentView 的宽度设置为 UIScrollView 的宽度来解决它。

        希望对某人有所帮助

        【讨论】:

        • @Nostradamus 乐于提供帮助
        • 这应该是选择的答案。其他一切都是分心。当没有可滚动的水平内容时,不应发生水平滚动。
        【解决方案6】:

        使用这一行。

        self.automaticallyAdjustsScrollViewInsets = NO;

        【讨论】:

          【解决方案7】:

          试试这个:

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

          【讨论】:

            【解决方案8】:

            我为此苦苦挣扎了一段时间,尝试了此主题和其他主题中的各种建议,但均未成功。

            但是,在另一个线程中(不确定在哪里),有人建议对 UIScrollView 使用负约束对他有用。

            所以我尝试了各种约束组合,但结果不一致。最终对我有用的是向滚动视图添加 -32 的前导和尾随约束,并添加一个宽度为 320(并居中)的(不可见)文本视图。

            【讨论】:

              【解决方案9】:

              Swift 解决方案

              创建两个出口,一个用于您的视图,一个用于您的滚动视图:

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

              然后在你的 viewDidLayoutSubviews 中你可以添加如下代码:

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

              我们所做的是收集视图的高度和宽度,并设置滚动视图的内容大小以匹配它。这将阻止您的滚动视图水平滚动。


              更多想法:

              CGSizeMake 使用 CGFloats 获取宽度和高度。您可能需要使用 UIScrollViews 现有高度作为第二个参数。看起来像这样:

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

              【讨论】:

              • 如果不知道高度或宽度怎么办(通用设备)? @danbeaulieu
              • @lukesIvi "myView.frame.width" 正在从 "myView" IBOutlet 动态拉取宽度。
              【解决方案10】:

              我在 viewDidLoad 中设置了 tableview contentInset(如下所示),这是导致水平滚动的原因

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

              检查是否有任何因不同原因设置的tableview contentInset并禁用它

              【讨论】:

                【解决方案11】:

                您可以选择视图,然后在Attributes Inspector 下取消选中User Interaction Enabled

                【讨论】:

                  【解决方案12】:

                  更新:(在@EranMarom 指出他的评论之后)

                  您可以在ScrollViewDelegate 方法中停止水平滚动或垂直滚动​​。 方法如下,

                  停止水平滚动:

                  如果要横向滚动,则需要增加contentOffset.x。防止停止滚动视图在水平方向滚动。

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

                  停止垂直滚动:

                  如果要垂直滚动,则需要增加contentOffset.y。防止在垂直方向停止滚动视图滚动。

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

                  以上代码阻止scrollview contentOffsetxy 发生变化,并导致scrollViewDidScroll: 方法中的滚动停止。

                  【讨论】:

                  • 我正在考虑投反对票,因为这个答案并不能解释你刚刚给出的代码就是它自己,就是这样。这样的回答不太好。好的答案可以解释自己,而有经验的开发人员可能会理解这个新开发人员可能不明白这里发生了什么。还没有被否决,因为它有机会改进。
                  • 这有点像 hack,但是当所有其他方法都失败时,它仍然有效。所以 +1,但仅作为最后的手段使用。
                  • 我也使用这种委托方法,但我用单行替换正文,例如:scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y); 以禁用水平滚动。我发现它更具可读性,更小,并且没有必要对零进行测试,因为几乎没有不经常运行的代码(即每秒最多几十次)的开销。
                  • 因为您在“didscroll”之后更改了 contentOffset,而不是像在“willscroll”之前那样,这是一个锤子解决方案,但我自己没有投反对票,因为 18 票赞成,答案是 75 ,所以不值得投反对票
                  • 更简单,在scrollViewDidScroll()委托函数中使用scrollView.contentOffset.y = 0.0停止垂直滚动和scrollView.contentOffset.x = 0.0停止水平滚动。但是,我相信确保scrollView.contentSize 等于scrollView.frame.size 是更好(正确)的解决方案。请参阅@danbeaulieu 答案。
                  【解决方案13】:

                  您必须设置UIScrollViewcontentSize 属性。例如,如果您的UIScrollView 是 320 像素宽(屏幕宽度),那么您可以这样做:

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

                  UIScrollView 将只能垂直滚动,因为它已经可以水平显示所有内容。

                  【讨论】:

                  • 嗨。这个解决方案真的很好用!感谢那。我尝试将静态宽度设置为 0。对我来说这也适用。不知道以后会不会有什么副作用。但如果不知道尺寸(即 iPhone 和 iPad 的通用代码),这很好用!
                  • 我认为最好做 CGSizeMake(0, myScrollableHeight),所以即使没有显示所有子视图,水平滚动也会被禁用。
                  • NB 在使用分页时将其中一个维度设置为 0 将导致 VoiceOver 将页码宣布为“第 1 页,共 1 页”,而不管值是否正确
                  • 我们可以这样传递,而不是像硬编码那样传递 320 宽度,而是传递: CGSize scrollableSize = CGSizeMake(self.scrollview.frame.size.width, myScrollableHeight); [myScrollView setContentSize:scrollableSize];
                  【解决方案14】:

                  一旦我用只有 1 个单元格的 UITableView 替换 UIScrollView,它就可以正常工作了。

                  【讨论】:

                  • 抱歉,这不能回答问题。
                  【解决方案15】:

                  从iOS7开始使用

                  self.automaticallyAdjustsScrollViewInsets = NO;
                  

                  //并为您创建包含 3 页的页面滚动条

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

                  【讨论】:

                  • 我认为这不会禁用滚动视图的滚动行为。是吗??
                  • self.collectionView.pagingEnabled = YES; 帮助我解决了平滑滚动(而不是拖动)的问题。问题出在方法scrollViewWillEndDragging: - targetContentOffset 与 scrollView.contentOffset 相同,页面检测逻辑无法正常工作。
                  猜你喜欢
                  • 1970-01-01
                  • 2013-01-31
                  • 2015-11-18
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-10-21
                  • 2015-12-07
                  • 1970-01-01
                  • 2011-01-24
                  相关资源
                  最近更新 更多