TL; DR - >创建扩展UIScrollView的类,实例化该类,然后使用NSLayoutConstraints为我的UI添加它作为现有UIView的子视图的必要步骤是什么?
我需要在现有的UIViewController子视图中添加UIScrollView(不是self.view - self.view的子级)。我也没有使用IB,因为我想了解我的代码。我设法布置了每个UI组件,我可以看到我的视图层次结构已在调试器中正确组装。
不幸的是,我的UIScrollView不会滚动,因为某些原因我的子视图都没有直观显示(请注意,我的滚动视图的直接子节点也是滚动视图,因此我的问题可能是我对UIScrollView类的理解)。 / p>
上图显示了我的UI的一般结构,浅灰色区域是我的UIScrollView。我有一个扩展UIScrollView和UIScrollDelegate的类(如果需要后一个父类,则不是100%)。该课程看起来像这样
import UIKit
class PlayWorkout: UIScrollView, UIScrollViewDelegate{
var workoutInstructionTiles : [WorkoutInstruction] = [WorkoutInstruction]();
var heightsTotal : Int = 0; //This variable will keep track of the running total for each of the workout tile subviews to help with positioning
init(workoutSubviews : [WorkoutInstruction]){
super.init(frame : CGRect.zero);
workoutInstructionTiles = workoutSubviews;
appendTiles();
self.translatesAutoresizingMaskIntoConstraints = false;
}
func appendTiles(){
print("appending tiles \(workoutInstructionTiles.count)");
for(var i = 0; i < workoutInstructionTiles.count; i++){
let setCount = workoutInstructionTiles[i].getNumSets();
workoutInstructionTiles[i].layer.cornerRadius = 5;
workoutInstructionTiles[i].backgroundColor = UIColor.whiteColor();
workoutInstructionTiles[i].translatesAutoresizingMaskIntoConstraints = false;
changeContentSize(workoutInstructionTiles[i]);
self.addSubview(workoutInstructionTiles[i]);
//Formula for position relative to top of the ScrollView will be 10 (margin) + 20 (label space) + setCount * 20 (content) + heightsTotal
let verticalConstraint = NSLayoutConstraint(item: workoutInstructionTiles[i], attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: CGFloat(30 + heightsTotal));
let leftConstraint = NSLayoutConstraint(item: workoutInstructionTiles[i], attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 10);
let rightConstraint = NSLayoutConstraint(item: workoutInstructionTiles[i], attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 10);
let heightConstraint = NSLayoutConstraint(item: workoutInstructionTiles[i], attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: CGFloat(setCount * 20 + 20));
self.addConstraints([verticalConstraint, leftConstraint, rightConstraint, heightConstraint]);
heightsTotal += setCount * 20;
}
}
func setViewConstraints(superView : UIView) -> Void{
let verticalConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: superView, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant:30);
let horizontalConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: superView, attribute: NSLayoutAttribute.CenterXWithinMargins, multiplier: 1.0, constant: 0);
let heightConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: superView, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: -60);
let widthConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: superView, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0);
superView.addConstraints([verticalConstraint, horizontalConstraint, heightConstraint, widthConstraint]);
}
func changeContentSize(aView : UIView){
var contentRect : CGRect = CGRect.zero;
for view in aView.subviews {
contentRect = CGRectUnion(contentRect, view.frame);
}
self.contentSize = contentRect.size;
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
然后,当单击一个按钮开始锻炼时,我会实现该类。从我迄今为止能够确定的内容来看,我需要为UIScrollView调用/设置的唯一方法是
scrollView.contentSize = CGSize(width: aWidth, height: aHeight)
scrollView.translateAutoResizingMaskIntoConstraints = false
所以,这是我的类实例化 - 这是在UIViewController内的UIGestureRecognizer事件处理程序内部,它也扩展了UIScrollViewDelegate:
workoutConfig = PlayWorkout(workoutSubviews : workoutInstructions);
workoutConfig.delegate = self;
workoutConfig.changeContentSize(workoutConfig);
workoutConfig.translatesAutoresizingMaskIntoConstraints = false;
self.contentView.addSubview(workoutConfig);
workoutConfig.setViewConstraints(self.contentView);
我还使用了一个名为changeContentSize()的方法,该方法改编自发布到SO的Objective-C方法,如下所示:
func changeContentSize(aView : UIView){
var contentRect : CGRect = CGRect.zero;
for view in aView.subviews {
contentRect = CGRectUnion(contentRect, view.frame);
}
self.contentSize = contentRect.size;
}
我知道很多阅读,但我想要彻底。我感谢任何帮助。谢谢!
答案 0 :(得分:0)
好的,所以经过3天疯狂的研究,并且为了实现这一目标而走下各种无意义的道路,我终于得到了它,而且实际上并不那么难(苹果的记录非常糟糕)。我将尝试分享我发现的内容 - 这个链接最终帮助我理解了如何做到这一点,所以我觉得有必要给予应有的信用:
http://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/#comment-541731
好的,这是使用自动布局创建可滚动视图的一步一步。
1 - UIScrollView只能有1个子视图,通常应该是UIView 保存所有可滚动内容。确保创建一个UIView,添加要滚动到该UIView的任何内容,然后将该UIView添加为UIScrollView的子视图
2 - 使用您想要的任何约束将滚动视图固定到其超级视图,只需确保设置顶部,前导,尾部和底部。这是我的代码的样子(在我的例子中,self是一个扩展UIScrollView的类):
func setViewConstraints(superView : UIView) -> Void{
let verticalConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: superView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant:60);
let leftConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: superView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0);
let rightConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: superView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0);
let bottomConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Bottom, relatedBy: .Equal, toItem: superView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0);
superView.addConstraints([verticalConstraint, leftConstraint, bottomConstraint,rightConstraint]);
}
3 - 将UIView在步骤1中提到的子项固定到确保设置的滚动视图 - &gt;顶部,前导,尾随和底部。除非UIView设计为小于滚动视图的尺寸,否则通常应该完全固定。完成此步骤以确保设备知道放置UIView的位置。我的代码看起来像这样(再次,self指的是扩展UIScrollView的类)
let pinTop = NSLayoutConstraint(item: subScrollView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant:0);
let pinBottom = NSLayoutConstraint(item: subScrollView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0);
let pinLeft = NSLayoutConstraint(item: subScrollView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0);
let pinRight = NSLayoutConstraint(item: subScrollView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0);
self.addConstraints([pinTop, pinBottom, pinLeft, pinRight]);
4 - 为了使滚动视图能够理解视图的内容大小,您必须根据滚动视图的概念设置高度和视野的宽度,或者进行滚动视图的计算。不要担心相对于滚动视图superview设置UIView的其他维度,只需要高度和宽度来使cocoa api推断内容大小。我的代码看起来像这样(在这种情况下,self.viewController.contentView引用了滚动视图的超级视图):
let widthConstraint = NSLayoutConstraint(item: subScrollView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: self.viewController.contentView, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0);
let heightConstraint = NSLayoutConstraint(item: subScrollView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: CGFloat(heightsTotal + (self.workoutInstructionTiles.count * 10)));
self.viewController.contentView.addConstraints([heightConstraint, widthConstraint]);
如果正确遵循了这些步骤,则结果应该是可滚动的视图。现在我得到这个,如果我可以帮助任何人使用他们的代码,只需发表评论。