Swift UIScrollView - 仅针对垂直滚动的正确实现

时间:2014-12-06 00:37:21

标签: ios swift uiview uiscrollview autolayout

事先,我道歉,因为我会说我是iOS编程的初学者。

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

我正在使用故事板以AutoLayout绘制视图。

以下是UIViewController UIScrollView的屏幕截图:

enter image description here enter image description here

然后我将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内),则滚动是水平的,而不是垂直的。 (看下面的截图):

enter image description here

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

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

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

enter image description here

问题是:使用UIScrollView使contentView尊重自动布局约束(full screen : 0top - 0bottom - 0left - 0right)并且滚动只是垂直的正确实现是什么。

非常感谢你的帮助!

7 个答案:

答案 0 :(得分:38)

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

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

我在github上也只有自己的代码(没有故事板实现)。

https://github.com/nadthevlad/AutolayotScrollview

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

  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个边缘
  5. 将contentView的顶部和底部边缘固定在scrollView的顶部和底部。

  6. 这是棘手的部分。要设置水平大小调整,您希望将contentView的前(右)和后(左)边固定到前端和后端self.view而不是scrollView。尽管contenView是scrollView的子视图,但它的水平约束将到达scrollView之外并连接到self.view。

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

答案 1 :(得分:22)

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

考虑到这一点,请尝试以下方法:

  1. 确保您设置的约束方式与this answer

  2. 中描述的方式相同
  3. 将以下代码添加到视图控制器:

    override func viewWillLayoutSubviews()
    {
        super.viewWillLayoutSubviews();
        self.scrollView.contentSize.height = 3000; // Or whatever you want it to be.
    }
    
  4. 就个人而言,我真的不喜欢Auto Layout。如果你有兴趣尝试没有自动布局 - 即。只需使用代码而不是约束 - 您可以关闭视图控制器视图的自动布局,并将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.
    }
    

答案 2 :(得分:4)

这是我总是这样做,以便从有关约束的故事板垂直滚动:

1拖动视图控制器

在控制器的主视图中拖动滚动视图,其约束L = 0,T = 0,T = 0和B = 0到其超视图(控制器的主视图)。

将UIVIew拖动到滚动视图中作为其内容视图,其约束L-0,T = 0,T = 0,B = 0到其superview(滚动视图)

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

4 - 用于停止水平滚动,使内容视图的宽度等于具有约束的scrollview。

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

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

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

8 - 刚刚运行,结果应该符合预期,否则请告诉我。

希望这有帮助!

答案 3 :(得分:0)

我只将这个实现用于水平/垂直滚动视图,虽然它在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;

现在,scrollview的contentSize属性的宽度将附加到设备屏幕的实际宽度,因此scrollview将仅在垂直方向上滚动。

答案 4 :(得分:0)

感谢@NadtheVlad,我终于看到了光明。一些进一步的小提示告诉我,contentView只需要固定到scrollView的顶部,底部和宽度。无需参考self.view。

使用EasyPeasy,这只是:

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

答案 5 :(得分:0)

您可以正常定义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

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

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

您应该使用

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

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

答案 6 :(得分:0)

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

 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
    
}}