gpt4 book ai didi

ios - 以编程方式创建 UIScrollView 作为另一个 UIView 的 subview 的必要步骤是什么?

转载 作者:行者123 更新时间:2023-11-28 08:49:53 25 4
gpt4 key购买 nike

TL;DR -> 创建一个扩展 UIScrollView 的类,实例化该类,然后使用 NSLayoutConstraints 将其添加为现有 UIView 的 subview 需要哪些必要步骤?

我处于需要将 UIScrollView 添加到现有 UIViewController 的 subview (不是 self.view - self.view 的 subview )的情况。我也不使用 IB,因为我想了解我的代码。我已经设法布置了每个 UI 组件,并且可以看到我的 View 层次结构已在调试器中正确组装。

不幸的是,我的 UIScrollView 不会滚动,并且由于某种原因,我的 subview 都没有在视觉上显示(请注意,我的 ScrollView 的直接 subview 也是 ScrollView ,所以我的问题可能是我对 UIScrollView 类的理解)。

enter image description here

上图显示了我的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;
}

我知道这需要大量阅读,但我想做到透彻。我感谢任何帮助。谢谢!

最佳答案

好吧,经过 3 天的疯狂研究并走上各种荒谬的道路来实现这一目标,我终于明白了,而且实际上并不难(苹果公司的记录非常糟糕)。我将尝试分享我的发现 - 这个链接最终帮助我理解了如何做到这一点,所以我觉得有义务在到期时给予信任:

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

好的,这是使用自动布局创建可 ScrollView 的逐步步骤。

1 - 一个 UIScrollView 只能有 1 个 subview ,通常应该是一个 UIView 保存所有可滚动的内容。确保创建一个 UIView,将任何你想要滚动的内容添加到该 UIView,然后将该 UIView 添加为你的 UIScrollView 的 subview

2 - 将 ScrollView 固定到它的父 View ,无论你想要什么约束,只要确保你设置了顶部、前导、尾随和底部。这是我的代码的样子(在我的例子中,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 - 将步骤 1 中提到的子 UIView 固定到 ScrollView ,确保设置 -> 顶部、前导、尾随和底部。这通常应该被精确固定,除非 UIView 被设计为小于 ScrollView 的尺寸。完成此步骤是为了确保设备知道放置 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 - 为了让 ScrollView 了解 View 的内容大小,您必须根据 ScrollView 监督或不涉及 ScrollView 的计算来设置 UIVIEW 的高度和宽度。不要担心设置 UIView 相对于 ScrollView superview 的其他尺寸,cocoa api 推断内容大小只需要高度和宽度。我的代码看起来像这样(在这种情况下,self.viewController.contentView 指的是 ScrollView 的 super View ):

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

如果每个步骤都正确执行,您的结果应该是一个可滚动的 View 。现在我明白了,如果我可以帮助任何人处理他们的代码,请发表评论。

关于ios - 以编程方式创建 UIScrollView 作为另一个 UIView 的 subview 的必要步骤是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34504676/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com