在Swift 3中以编程方式使用ScrollView

时间:2017-07-05 16:48:34

标签: ios swift swift3 uiscrollview autolayout

我已经搜索了其他问题,似乎仍然在使用swift 3中的autolayout以编程方式创建我的scrollView时遇到了一些麻烦。我能够让我的scrollview显示如下图所示,但是当我滚动到底部时其他标签未显示,“滚动顶部”标签不会消失。

ScrollView

希望有人可以帮助我们查看下面的代码!

import UIKit

class ViewController: UIViewController {

let labelOne: UILabel = {
    let label = UILabel()
    label.text = "Scroll Top"
    label.backgroundColor = .red
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

let labelTwo: UILabel = {
    let label = UILabel()
    label.text = "Scroll Bottom"
    label.backgroundColor = .green
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()


override func viewDidLoad() {
    super.viewDidLoad()

    let screensize: CGRect = UIScreen.main.bounds
    let screenWidth = screensize.width
    let screenHeight = screensize.height
    var scrollView: UIScrollView!
    scrollView = UIScrollView(frame: CGRect(x: 0, y: 120, width: screenWidth, height: screenHeight))
    scrollView.contentSize = CGSize(width: screenWidth, height: 2000)
    scrollView.addSubview(labelOne)
    scrollView.addSubview(labelTwo)


    view.addSubview(labelOne)
    view.addSubview(labelTwo)
    view.addSubview(scrollView)

    // Visual Format Constraints
    view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": labelOne]))
    view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-100-[v0]", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": labelOne]))

    // Using iOS 9 Constraints in order to place the label past the iPhone 7 view
    view.addConstraint(NSLayoutConstraint(item: labelTwo, attribute: .top, relatedBy: .equal, toItem: labelOne, attribute: .bottom, multiplier: 1, constant: screenHeight + 200))
    view.addConstraint(NSLayoutConstraint(item: labelTwo, attribute: .right, relatedBy: .equal, toItem: labelOne, attribute: .right, multiplier: 1, constant: 0))
    view.addConstraint(NSLayoutConstraint(item: labelTwo, attribute: .left, relatedBy: .equal, toItem: labelOne, attribute: .left, multiplier: 1, constant: 0)     

    }

}

6 个答案:

答案 0 :(得分:30)

使用约束来定义滚动内容大小很容易 - 因此您不必进行任何手动计算。

请记住:

  1. 滚动视图的内容元素必须具有左/上/宽度/高度值。对于标签等对象,它们具有固有的大小,因此您只需定义左侧和右侧。顶部。
  2. 滚动视图的内容元素 定义可滚动区域的边界 - <link> - 但它们会所以底部&amp;正确的约束。
  3. 结合这两个概念,您会发现需要一个“连续链”,其中至少有一个元素定义了顶部/左侧/底部/右侧范围。
  4. 这是一个简单的例子,它将直接在Playground页面中运行:

    contentSize

答案 1 :(得分:5)

两件事。

<强> 1。添加标签以滚动视图,而不是视图

您希望标签以滚动视图滚动,然后您不应将其添加到视图中。运行代码时,您可以滚动,但固定标签固定在您的视图中,而不是滚动视图

<强> 2。确保正确添加了约束

在故事板上尝试一下约束的组合对于视图是否足够。标签至少需要4个约束。

底线

以下是您的代码的修改版本。对于约束我添加了填充,填充顶部,宽度和高度,它的工作原理。我的代码是

let labelOne: UILabel = {
    let label = UILabel()
    label.text = "Scroll Top"
    label.backgroundColor = .red
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

let labelTwo: UILabel = {
    let label = UILabel()
    label.text = "Scroll Bottom"
    label.backgroundColor = .green
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()


override func viewDidLoad() {
    super.viewDidLoad()

    let screensize: CGRect = UIScreen.main.bounds
    let screenWidth = screensize.width
    let screenHeight = screensize.height
    var scrollView: UIScrollView!
    scrollView = UIScrollView(frame: CGRect(x: 0, y: 120, width: screenWidth, height: screenHeight))

    scrollView.addSubview(labelTwo)

    NSLayoutConstraint(item: labelTwo, attribute: .leading, relatedBy: .equal, toItem: scrollView, attribute: .leadingMargin, multiplier: 1, constant: 10).isActive = true
    NSLayoutConstraint(item: labelTwo, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200).isActive = true
    NSLayoutConstraint(item: labelTwo, attribute: .top, relatedBy: .equal, toItem: scrollView, attribute: .topMargin, multiplier: 1, constant: 10).isActive = true
    NSLayoutConstraint(item: labelTwo, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 30).isActive = true

    scrollView.contentSize = CGSize(width: screenWidth, height: 2000)
    view.addSubview(scrollView)

}

滚动视图看起来像这样

enter image description here

答案 2 :(得分:0)

将滚动视图图像设置为壁纸:

@IBOutlet var scroll_view_img: UIScrollView!

var itemPhotoList = NSMutableArray()

var button = NSMutableArray()    

@IBOutlet var imageview_big: UIImageView!

override func viewDidLoad() {

    super.viewDidLoad()
    itemPhotoList = ["grief-and-loss copy.jpg","aaa.jpg","image_4.jpeg"]        

    // button = ["btn1","btn2"]

    let width:CGFloat = 100
    let height:CGFloat = 100
    var xposition:CGFloat = 10
    var scroll_contont:CGFloat = 0

    for i in 0 ..< itemPhotoList.count
    {
        var button_img = UIButton()
        button_img = UIButton(frame: CGRect(x: xposition, y: 50, width: width, height: height))
        let img = UIImage(named:itemPhotoList[i] as! String)
        button_img.setImage(img, for: .normal)
        scroll_view_img.addSubview(button_img)
        button_img.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
        button_img.tag = i
        view.addSubview(scroll_view_img)
        xposition += width+10
        scroll_contont += width
        scroll_view_img.contentSize = CGSize(width: scroll_contont, height: height)
    }
}

func buttonAction(sender: UIButton!)
{
    switch sender.tag {
    case 0:
        imageview_big.image = UIImage(named: "grief-and-loss copy.jpg")
    case 1:
        imageview_big.image = UIImage(named: "aaa.jpg")
    case 2:
        imageview_big.image = UIImage(named: "image_4.jpeg")
    default:
        break
    }
}

答案 3 :(得分:0)

我的分数还不够高,无法发表评论,但是我想添加一个很小的细节,使我在这个滚动视图任务中停留了几个小时。

这些答案不适用于导航栏中的大标题。确保视图控制器的viewDidLoad()方法中具有以下代码。

self.navigationController?.navigationBar.prefersLargeTitles = false

答案 4 :(得分:0)

将此控制器复制并粘贴到您的项目中

class BaseScrollViewController: UIViewController {

lazy var contentViewSize = CGSize(width: self.view.frame.width, height: self.view.frame.height + 100)
lazy var scrollView: UIScrollView = {
    let view = UIScrollView(frame: .zero)
    view.backgroundColor = .white
    view.frame = self.view.bounds
    view.contentSize = contentViewSize
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()
lazy var containerView: UIView = {
    let v = UIView()
    v.backgroundColor = .white
    v.frame.size = contentViewSize
    return v
}()

override func viewDidLoad() {
    view.backgroundColor = .white
    view.addSubview(scrollView)
    scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

    scrollView.addSubview(containerView)
    setupContainer(containerView)
    super.viewDidLoad()
    
}

public func setupContainer(_ container: UIView) {
    
}

}

上述代码的用法:

class ClientViewController: BaseScrollViewController {
override func viewDidLoad() {
    super.viewDidLoad()
    // do your stuff here
}

override func setupContainer(_ container: UIView) {
    // add views here
}

}

答案 5 :(得分:0)

对我来说,这项工作就像魅力

class WithDrawConfirmationViewController: UIViewController, WithDrawConfirmationViewProtocol {

    var presenter: WithDrawConfirmationPresenterProtocol?
    private let viewbackgroundColor = UIColor(hexString: "#F5F5F8")
    // MARK:- View properties
    lazy var scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        //view.backgroundColor = .red
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        return scrollView
    }()
    
    lazy var contentView: UIView = {
        let view = UIView()
        //view.backgroundColor = .green
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
    
    lazy var headerView: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
    
    private lazy var titleLabel:UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.textColor = UIColor.themeBlack
        label.text = "Withdraw Confirmation"//"Loading.."
        label.textAlignment = .center
        label.font = UIFont(name: "AvenirNext-DemiBold", size: 20)
        label.numberOfLines = 0
        label.lineBreakMode = .byWordWrapping
        return label
    }()
    
    
    private lazy var descriptionLabel:UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.textColor = UIColor.themeGray
        label.text = "Please confirm your fixed deposit details before withdrawing your deposit"// "Loading.."
        label.textAlignment = .center
        label.font = UIFont(name: "AvenirNext-Medium", size: 14)
        label.numberOfLines = 0
        label.lineBreakMode = .byWordWrapping
        label.setContentHuggingPriority(1000, for: .vertical)
        return label
    }()
    
    private lazy var instructionLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.textColor = UIColor.themeGray
        label.text = "Complete fixed deposit will be withdrawn and the money will be debited to your account within 1-2 working days."//"Loading.."
        label.textAlignment = .left
        label.font = UIFont(name: "AvenirNext-Medium", size: 14)
        label.numberOfLines = 0
        label.lineBreakMode = .byWordWrapping
        return label
    }()
    
    private lazy var warningLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.textColor = UIColor.themeBlue
        label.text = "Axis bank will levy a penalty of 1% - 2% for premature withdrawal"//"Loading.."
        label.textAlignment = .left
        label.font = UIFont(name: "AvenirNext-DemiBold", size: 13)
        label.numberOfLines = 0
        label.lineBreakMode = .byWordWrapping
        return label
    }()
    
    private lazy var warningView: UIView = {
        let view = UIView()
        view.cornerradius = 5
        view.backgroundColor = UIColor(hexFromString: "#E8F4FD")
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
    private lazy var fdInformationDetailView: FDPurchaseDetailView = {
        let view = FDPurchaseDetailView(isPoweredByViewVisible: false)
        //view.backgroundColor = .red
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
    
    private lazy var footerCTAView: FooterButtonViewView = {
        let view = FooterButtonViewView()
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
    
    // MARK:- Life cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        contentView.backgroundColor = viewbackgroundColor
        scrollView.backgroundColor = viewbackgroundColor
        setUpUI()
        presenter?.viewDidLoadTriggered()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    }
    
    private func setUpUI() {
        view.addSubview(scrollView)
        scrollView.addSubview(contentView)
        view.backgroundColor = viewbackgroundColor
        addFooter()
        setUpHeaderView()
        setUpFDDetailView()
        setUpInformationAndWarningView()
        //scrollView.backgroundColor = .lightGray
        scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: footerCTAView.topAnchor).isActive = true
        scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 100, right: 0)
        
        contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
        contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
        contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
        contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
        contentView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
        //contentView.bottomAnchor.constraint(equalTo: footerCTAView.topAnchor).isActive = true
    }
    
    private func setUpHeaderView() {
        contentView.addSubview(headerView)
        headerView.addSubviews([titleLabel, descriptionLabel])
        
        headerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
        headerView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20).isActive = true
        headerView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4).isActive = true
       
        titleLabel.leadingAnchor.constraint(equalTo: headerView.leadingAnchor, constant: 8).isActive = true
        titleLabel.trailingAnchor.constraint(equalTo: headerView.trailingAnchor).isActive = true
        titleLabel.topAnchor.constraint(equalTo: headerView.topAnchor, constant: 8).isActive = true
        
        descriptionLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant:  20).isActive = true
        descriptionLabel.leadingAnchor.constraint(equalTo: headerView.leadingAnchor, constant: 8).isActive = true
        descriptionLabel.trailingAnchor.constraint(equalTo: headerView.trailingAnchor).isActive = true
        descriptionLabel.bottomAnchor.constraint(equalTo: headerView.bottomAnchor, constant: -20).isActive = true
    }
    
    
    private func setUpFDDetailView() {
        contentView.addSubview(fdInformationDetailView)
        fdInformationDetailView.topAnchor.constraint(equalTo: headerView.bottomAnchor).isActive = true
        fdInformationDetailView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
        fdInformationDetailView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20).isActive = true
       
    }
    
    private func setUpInformationAndWarningView() {
        contentView.addSubview(instructionLabel)
        
        instructionLabel.topAnchor.constraint(equalTo: fdInformationDetailView.bottomAnchor, constant: 20).isActive = true
        instructionLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
        instructionLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20).isActive = true
        
        warningView.addSubview(warningLabel)
        warningLabel.topAnchor.constraint(equalTo: warningView.topAnchor, constant: 8).isActive = true
        warningLabel.leadingAnchor.constraint(equalTo: warningView.leadingAnchor, constant: 20).isActive = true
        warningLabel.trailingAnchor.constraint(equalTo: warningView.trailingAnchor, constant: -20).isActive = true
        warningLabel.bottomAnchor.constraint(equalTo: warningView.bottomAnchor, constant: -8).isActive = true
        
        contentView.addSubview(warningView)
        
        warningView.topAnchor.constraint(equalTo: instructionLabel.bottomAnchor, constant: 8).isActive = true
        warningView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
        warningView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20).isActive = true
       //warningView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
        warningView.bottomAnchor.constraint(greaterThanOrEqualTo: contentView.bottomAnchor, constant: -20).isActive = true
        
    }
    
    private func addFooter() {
        view.addSubview(footerCTAView)
        footerCTAView.delegate = self
        footerCTAView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        footerCTAView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        footerCTAView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
    }
}