【问题标题】:Swift UIScrollView - Correct Implementation for Only Vertical ScrollingSwift UIScrollView - 仅垂直滚动的正确实现
【发布时间】:2015-02-04 06:35:20
【问题描述】:

在此先向您道歉,因为我是 iOS 编程的初学者。

我想使用UIScrollView,因为要显示的内容超出了屏幕的高度。 因此,我只想要垂直滚动而不是水平滚动。

我正在使用情节提要通过AutoLayout 绘制视图。

这是我的UIViewControllerUIScrollView 的屏幕截图:

然后我把Label改成这样的大文字

override func viewDidLoad() {
    super.viewDidLoad()

    self.label1Label.text = "Seize jours après la chute du président Blaise Compaoré, le Burkina Faso a un nouveau chef d'EtatA l'issue d'ultimes tractions, civils et militaires se sont accordés, lundi 17 novembre, sur le nom du diplomate Michel KafandoSeize jours après la chute du président Blaise Compaoré, le Burkina Faso a un nouveau chef d'EtatA l'issue d'ultimes tractions, civils et militaires se sont accordés, lundi 17 novembre, sur le nom du diplomate Michel Kafando"
    self.label1Label.numberOfLines = 0
    self.label1Label.sizeToFit()

我的问题是,如果我不为我的 contentView 手动设置宽度(在 UIScrollView 内),滚动是水平的,而不是垂直的。 (看下面的截图):

我尝试设置 contentSize,就像我在许多谷歌帖子中看到的那样,但没有成功:

self.scrollView.contentSize = CGSizeMake(400.0, 600.0)

如果我为我的 contentview (i.e : 320pts) 手动设置宽度,滚动将是垂直的 (GOOD) 但根据 iphone 大小,它不会覆盖屏幕的整个宽度,如下所示截图:

问题是:使用UIScrollView 来拥有一个尊重自动布局约束(full screen : 0top - 0bottom - 0left - 0right)的contentView 和仅垂直滚动的正确实现是什么。

非常感谢您的帮助!

【问题讨论】:

    标签: ios swift uiview uiscrollview autolayout


    【解决方案1】:

    我迟到了..如果你给标签的宽度约束等于视图那么你可以实现同样的事情

     aboutCaption.widthAnchor.constraint(equalTo: self.view.widthAnchor , multiplier: 0.9).isActive = true
    

    这是我的示例代码

    class AboutVC: UIViewController{
    
    let scrollView = UIScrollView()
    
    lazy var aboutLbl : UILabel = {
        let lbl = UILabel()
        lbl.text = "About"
        lbl.font = .boldSystemFont(ofSize: 19)
        return lbl
    }()
    
    lazy var aboutCaption : UILabel = {
        let lbl = UILabel()
        lbl.text = "Hi. My name is Uzumaki Naruto. I am a professional MMA Coach with 15+ years of experience. I specialize in ninjutsu, shadow clones and various other techniques. I am in the TOP50 coaches in the Sports category. Been with GIGIMOT for 5 years already. Not a single bad review. "
        lbl.numberOfLines = 0
        lbl.font  = UIFont(name: "Helvetica Neue Thin", size: 16)!
        lbl.textColor = .systemGray2
        return lbl
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureUI()
        //        tableView.dataSource = self
        //        tableView.delegate = self
    }
    
    func configureUI() {
        self.view.backgroundColor = UIColor.white
        
        //Add and setup scroll view
        self.view.addSubview(self.scrollView)
        scrollView.backgroundColor = .white
        self.scrollView.translatesAutoresizingMaskIntoConstraints = false;
        self.scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0).isActive = true;
        self.scrollView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true;
        self.scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0).isActive = true;
        self.scrollView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true;
        
        scrollView.addSubview(aboutLbl)
        
        aboutLbl.anchor(top: scrollView.topAnchor, left: scrollView.leftAnchor , paddingTop: 10 , paddingLeft: 10)
        
        
        scrollView.addSubview(aboutCaption)
        aboutCaption.anchor(top: aboutLbl.bottomAnchor, left: scrollView.leftAnchor, bottom: scrollView.bottomAnchor , right: scrollView.rightAnchor, paddingTop: 10, paddingLeft: 10, paddingBottom: 10, paddingRight: 0)
        aboutCaption.widthAnchor.constraint(equalTo: self.view.widthAnchor , multiplier: 0.9).isActive = true
        
    }}
    

    【讨论】:

      【解决方案2】:

      可以正常定义ScrollView,正常约束ScrollView的属性

              let scrollView = UIScrollView()
          scrollView.translatesAutoresizingMaskIntoConstraints = false
          scrollView.backgroundColor = .white
          self.view.addSubview(scrollView)
      
          scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0.0).isActive = true
          scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0.0).isActive = true
          scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0.0).isActive = true
          scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0.0).isActive = true
      

      但诀窍在于如何定义可能比屏幕更宽的标签(或其他视图)。 而不是使用

      myLabel.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: -10.0).isActive = true
      

      你应该使用

      myLabel.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -10.0).isActive = true
      

      第二行将阻止该视图导致水平滚动。对所有子视图执行此操作,您将不会水平滚动。 (它仍会按计划垂直滚动。)

      另外,不要忘记在最后一个子视图上设置底部约束,以确保 UIScrollview 垂直滚动。

      labelX.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -10.0).isActive = true
      

      【讨论】:

        【解决方案3】:

        这是我总是这样做的,从带有约束的情节提要中垂直滚动:

        1-拖动视图控制器

        在控制器的主视图中将带有约束 L=0 、 T =0 、 T =0 和 B = 0 的滚动视图拖动到其父视图(控制器的主视图)。

        3-将 UIVIew 拖入滚动视图以作为其内容视图,并对其父视图(滚动视图)具有约束 L-0、T=0、T=0、B=0

        • 现在是时候设置滚动视图的内容大小了,它控制水平和垂直滚动,如下所示。

        4-用于停止水平滚动,使内容视图与带约束的滚动视图等宽。

        5-使内容视图的高度等于控制器视图的高度,这是临时的 直到我们用可滚动的内容填充它

        6-在内容视图中添加控件直到完成。

        7-最重要的是删除您在内容视图高度的第 5 点所做的约束,而不是从内容视图底部的控件中进行约束以使其底部对齐。这有助于使内容视图从顶部的第一个控件开始,直到最后一个控件(这完全取决于此步骤)。

        8-运行,结果应该和预期一样,否则请告诉我。

        希望这会有所帮助!

        【讨论】:

        • 非常感谢它完美运行!开发时可以直接跳过第5步(滚动和控件不起作用但可以构建应用)
        【解决方案4】:

        感谢@NadtheVlad,我终于看到了曙光。一些进一步的摆弄告诉我 contentView 只需要固定到 scrollView 的顶部、底部和宽度。无需引用self.view。

        使用EasyPeasy,这很简单:

        scrollView <- Edges()
        contentView <- [Top(), Bottom(), Width().like(scrollView)]
        

        【讨论】:

          【解决方案5】:

          Mike Woelmer 在 Atomic Object 博客上展示了如何使用 Interface Builder 正确执行此操作。

          http://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/

          我在 github 上也只有自己的代码(没有情节提要实现)。

          https://github.com/nadthevlad/AutolayotScrollview

          您不想设置内容或视图的高度或宽度。 相反,您想使用 Autolayouts 引脚和约束来设置滚动视图的行为方式。

          1. 创建您的 UIScrollView *scrollView。

          2. 您想创建一个 UIView *contentView,您将把其余的视图元素放入其中。

            [self.view addSubview:scrollView];
            [scrollView addSubview:contentView];
            [contentView addSubview:_label1];
            [contentView addSubview:_label2];
            [contentView addSubview:_label3];
            [contentView addSubview:_label4];
            [contentView addSubview:_label5];
            [contentView addSubview:_label6];
            
          3. 将scrollView的4条边固定到self.view的4条边

          4. 将 contentView 的顶部和底部边缘固定到 scrollView 的顶部和底部。

          5. 这是棘手的部分。要设置水平尺寸,您希望将 contentView 的前缘(右)和后缘(左)固定到 self.view 而不是 scrollView 的前缘和后缘。即使 contenView 是 scrollView 的子视图,它的水平约束也会到达 scrollView 之外并连接到 self.view。

          6. 像往常一样将任何其他视图元素固定到 contentView。

          【讨论】:

          • 您不必将所有视图元素都包含在一个视图中。那没有必要。关键是要确保约束可以指定可滚动内容的维度。来自 Apple 技术说明:“对滚动视图的子视图的约束必须导致要填充的大小,然后将其解释为滚动视图的内容大小。” 技术说明链接:developer.apple.com/library/ios/technotes/tn2154/_index.html
          • 第 5 步中的水平尺寸调整可以通过将 ContentView 宽度设置为等于 ScrollView 宽度来解决。可以在 IB 中完成
          • 我能够通过在第 4 步中将 contentView 的 4 个边缘设置为 scrollView 并在第 5 步中将 contentView 的宽度设置为self.view的宽度来解决它
          • 完全按照步骤进行操作,结果一针见血。还要记得为内容视图添加一个固定的高度,并将该高度设置为大于设备的高度以测试滚动。
          • 对我来说,除了这个列表之外,我还必须将内容视图设置为具有 y 值(即垂直居中),并且还必须将后沿固定到滚动视图。没有固定后缘,它抱怨滚动不明确。
          【解决方案6】:

          允许 UIScrollView 仅向一个方向滚动的技巧是使受限维度的 UIScrollView 的内容大小与同一维度的 UIScrollView 框架的大小相同。所以在这种情况下,scrollview.contentSize.width 应该等于 scrollview.frame.size.width

          考虑到这一点,请尝试以下操作:

          1. 确保按照this answer中所述的相同方式设置约束

          2. 将以下代码添加到您的视图控制器:

            override func viewWillLayoutSubviews()
            {
                super.viewWillLayoutSubviews();
                self.scrollView.contentSize.height = 3000; // Or whatever you want it to be.
            }
            

          就个人而言,我真的不喜欢自动布局。如果您有兴趣在没有自动布局的情况下尝试这个 - 即。只需使用代码而不是约束 - 您可以关闭视图控制器视图的自动布局并将您的 viewWillLayoutSubviews 方法更改为如下所示:

          override func viewWillLayoutSubviews()
          {
              super.viewWillLayoutSubviews();
          
              self.scrollView.frame = self.view.bounds; // Instead of using auto layout
              self.scrollView.contentSize.height = 3000; // Or whatever you want it to be.
          }
          

          【讨论】:

          • 感谢我在尝试解决此问题后为我解决了问题!
          • 诀窍是计算viewWillLayoutSubviews 上的大小!
          【解决方案7】:

          我只将这个实现用于水平/垂直滚动视图,虽然它是在 Objective-C 中,但如果你有不清楚的地方,我会尝试解释逻辑。

          //Getting iDevice's screen width
          CGRect screenRect = [[UIScreen mainScreen] bounds];
          CGFloat screenWidth = screenRect.size.width;
          
          //Setting the right content size - only height is being calculated depenging on content.
          CGSize contentSize = CGSizeMake(screenWidth, HEIGHT_OF_YOUR_CONTENT);
          self.scrollView.contentSize = contentSize;
          

          现在滚动视图的 contentSize 属性的宽度被附加到设备屏幕的实际宽度上,所以滚动视图只会在垂直方向滚动。

          【讨论】:

          • 不幸的是,我已经尝试过您的解决方案,但 contentSize 似乎不会影响 UIScrollView。你会明白为什么吗?
          • 据我所知,这是一个教程代码,你能把项目上传到这里吗?
          猜你喜欢
          • 2014-11-02
          • 1970-01-01
          • 2016-04-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-07-22
          • 1970-01-01
          相关资源
          最近更新 更多