ios Swift UIScrollView - 仅垂直滚动的正确实现
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27326924/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Swift UIScrollView - Correct Implementation for Only Vertical Scrolling
提问by fabdarice
In advance, I apologize as I would say that I'm a beginner with iOS programming.
事先,我很抱歉,因为我会说我是 iOS 编程的初学者。
I want to use UIScrollView
because the content to display exceed the height of the screen.
Therefore, I would like only a vertical scroll and not a horizontal scrolling.
我想使用UIScrollView
是因为要显示的内容超过了屏幕的高度。因此,我只想要垂直滚动而不是水平滚动。
I'm using the Storyboard to draw the views with AutoLayout
.
我正在使用 Storyboard 绘制带有AutoLayout
.
Here's are the screenshot of my UIViewController
with the UIScrollView
:
这里是我的截图UIViewController
与UIScrollView
:
Then I change the Label to a big text like that
然后我将标签更改为这样的大文本
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()
My problem is that if I don't set manually a width for my contentView (inside the UIScrollView
), the scrolling is horizontal, not vertical. (Look Screenshot below):
我的问题是,如果我不为我的 contentView 手动设置宽度(在 内UIScrollView
),滚动是水平的,而不是垂直的。(看下面的截图):
I've tried to set contentSize as I've seen in many google post but without success :
我尝试设置 contentSize ,就像我在许多谷歌帖子中看到的那样,但没有成功:
self.scrollView.contentSize = CGSizeMake(400.0, 600.0)
If I set a width manually for my contentview (i.e : 320pts
), the scrolling will be vertical (GOOD) but then depending on the iphone size, it won't cover the whole width of the screen as shown in the following screenshot :
如果我为 contentview ( i.e : 320pts
)手动设置宽度,滚动将是垂直的 (GOOD),但随后根据 iphone 大小,它不会覆盖屏幕的整个宽度,如下面的屏幕截图所示:
The question is : what is the correct implementation to use UIScrollView
to have a contentView
that respect the autolayout constraint (full screen : 0top - 0bottom - 0left - 0right
) and the scrolling to be only vertical.
现在的问题是:什么是正确的实施,利用UIScrollView
有一个contentView
尊重的自动布局约束(full screen : 0top - 0bottom - 0left - 0right
),并滚动到只有垂直。
Thanks a lot for your help!
非常感谢你的帮助!
回答by NadtheVlad
Mike Woelmer shows how to do this correctly with Interface Builder on the Atomic Object blog.
Mike Woelmer 在 Atomic Object 博客上展示了如何使用 Interface Builder 正确执行此操作。
http://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/
http://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/
I also have my own code only (no storyboard implementation) on github.
我在 github 上也只有自己的代码(没有故事板实现)。
https://github.com/nadthevlad/AutolayotScrollview
https://github.com/nadthevlad/AutolayotScrollview
You don't want to set the height or width of your content or views. Instead you want to use Autolayouts pins and constraints to set how the scrollview behaves.
您不想设置内容或视图的高度或宽度。相反,您希望使用 Autolayouts 引脚和约束来设置滚动视图的行为方式。
Create your UIScrollView *scrollView.
You want to create one UIView *contentView which you will put the rest of your view elements into.
[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];
Pin the 4 edges of scrollView to the 4 edges of self.view
Pin the top and bottom edges of contentView to the top and bottom of scrollView.
This is the tricky part. To set the horizontal sizing, you want the leading (right) and trailing(left) edges of the contentView to be pinned to the leading and trailing edges self.view instead of scrollView. Even though contenView is a sub view of scrollView its horizontal constraints are going to reach outside of the scrollView and connect to self.view.
Pin any other view elements to contentView as you normally would.
创建您的 UIScrollView *scrollView。
您想创建一个 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];
将 scrollView 的 4 条边固定到 self.view 的 4 条边上
将 contentView 的顶部和底部边缘固定到 scrollView 的顶部和底部。
这是棘手的部分。要设置水平尺寸,您需要将 contentView 的前缘(右)和后缘(左)固定到前缘和后缘 self.view 而不是 scrollView。尽管 contenView 是 scrollView 的子视图,但它的水平约束将到达 scrollView 之外并连接到 self.view。
像往常一样将任何其他视图元素固定到 contentView。
回答by gavdotnet
The trick to permitting a UIScrollView to scroll in only one direction is to make the content size of the UIScrollView for the restricted dimension the same as the size of the UIScrollView's frame in the same dimension. So in this case, scrollview.contentSize.width
should equal scrollview.frame.size.width
.
允许 UIScrollView 仅向一个方向滚动的技巧是使受限维度的 UIScrollView 的内容大小与相同维度的 UIScrollView 框架的大小相同。所以在这种情况下,scrollview.contentSize.width
应该等于scrollview.frame.size.width
.
With that in mind, try the following:
考虑到这一点,请尝试以下操作:
Ensure you have constraints set up in the same way as described in this answer
Add the following code to your view controller:
override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews(); self.scrollView.contentSize.height = 3000; // Or whatever you want it to be. }
确保您以与此答案中所述相同的方式设置约束
将以下代码添加到您的视图控制器:
override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews(); self.scrollView.contentSize.height = 3000; // Or whatever you want it to be. }
Personally, I'm really not a fan of Auto Layout. If you are interested in trying this without Auto Layout - ie. just with code instead of constraints - you could turn off Auto Layout for the view controller's view and change your viewWillLayoutSubviews
method to look like this:
就个人而言,我真的不是自动布局的粉丝。如果您有兴趣在没有自动布局的情况下尝试此操作 - 即。只需使用代码而不是约束 - 您可以关闭视图控制器视图的自动布局并将您的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.
}
回答by IsPha
This how I always do it for scrolling vertically from storyboard with constraints :
这是我总是从带有约束的故事板垂直滚动的方式:
1-drag a viewcontroller
1-拖动一个视图控制器
2-drag a scrollview in the controller's main view with constraints L=0 , T =0 , T =0 and B = 0 to its superview (controller's main view).
2-将控制器主视图中的滚动视图与约束 L=0 、 T =0 、 T =0 和 B = 0 拖动到其超级视图(控制器的主视图)。
3-drag a UIVIew into the scroll view to work as its content view with constraints L-0,T=0,T=0,B=0 to its superview(the scrollview)
3-将 UIVIew 拖入滚动视图以用作其内容视图,约束 L-0,T=0,T=0,B=0 到其超级视图(滚动视图)
- well here its time for setting Content size of scroll view , which controls scrolling both Horizontally and vertically as follows.
- 现在是设置滚动视图的内容大小的时候了,它控制水平和垂直滚动,如下所示。
4-for stoping horizontal scrolling , make content view equal width to scrollview with constraint.
4-为了停止水平滚动,使内容视图与带有约束的滚动视图等宽。
5-make height of content view equal hight of controller's view , This is temporarytill we fill it with scrollable content.
5-使内容视图的高度等于控制器视图的高度,这是暂时的,直到我们用可滚动的内容填充它。
6-add controls in the content view till finish .
6-在内容视图中添加控件直到完成。
7-and the most important delete the constraint you made in point 5 of the hight of content view and instead of it make constraint from the control on bottom of content view to have bottom alignment to it . This helps in making content view hight starts from first control on top and down till last control (it is all depends on this step).
7-最重要的是删除您在内容视图高度的第 5 点所做的约束,而不是从内容视图底部的控件中进行约束以使其底部对齐。这有助于使内容视图高度从顶部和底部的第一个控件开始,直到最后一个控件(这完全取决于此步骤)。
8-just run and results should be as expected , otherwise please let me know .
8-刚刚运行,结果应该如预期的那样,否则请告诉我。
Hope this helps!
希望这可以帮助!
回答by Vette
You can define ScrollView normally and constrain the properties of ScrollView normally
可以正常定义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
But the trick is in how you define your Label (or other view) that may be wider than the screen. Instead of using
但诀窍在于如何定义可能比屏幕更宽的标签(或其他视图)。而不是使用
myLabel.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: -10.0).isActive = true
You should use
你应该使用
myLabel.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -10.0).isActive = true
This second line will stop that view from causing horizontal scrolling. Do that with all your subviews and you won't scroll horizontally. (It will still scroll vertically as planned.)
第二行将阻止该视图导致水平滚动。对所有子视图执行此操作,您将不会水平滚动。(它仍会按计划垂直滚动。)
Also, don't forget to set the bottom constraint on your last subview to make sure your UIScrollview scrolls vertically.
另外,不要忘记在最后一个子视图上设置底部约束,以确保 UIScrollview 垂直滚动。
labelX.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -10.0).isActive = true
回答by Richard Topchii
I use this implementation for only horizontal/vertical scrollviews, although it is in Objective-C, I will try to explain the logic if something is unclear to you.
我只将这个实现用于水平/垂直滚动视图,尽管它是在 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;
Now the width of the contentSize property of the scrollview is being attached to the actual width of the device's screen, so the scrollview will be scrolling only in vertical direction.
现在滚动视图的 contentSize 属性的宽度被附加到设备屏幕的实际宽度,因此滚动视图将仅在垂直方向滚动。
回答by jazzgil
Thanks to @NadtheVlad, I finally saw the light. Some further fiddling taught me that contentView just needs to be pinned to scrollView's Top, Bottom and Width. No need to reference self.view.
感谢@NadtheVlad,我终于看到了曙光。一些进一步的摆弄让我知道 contentView 只需要固定到 scrollView 的 Top、Bottom 和 Width。无需引用 self.view。
With EasyPeasy, this is simply:
使用EasyPeasy,这很简单:
scrollView <- Edges()
contentView <- [Top(), Bottom(), Width().like(scrollView)]