从XIB加载视图作为scrollview的子视图 [英] Load view from XIB as a subview of a scrollview

查看:48
本文介绍了从XIB加载视图作为scrollview的子视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我还是SO和Swift的新手,所以请耐心等待,随时跳过此问题:-)

I'm still a SO and Swift newbie, so please, be patient and feel free to skip this question :-)

XIBawakeFromNib主体中,我想加载一些视图作为UIScrollView的子视图(基本上,XIB包含滚动视图,标签和按钮).

In the body of a XIB's awakeFromNib, I want to load some views as subviews of a UIScrollView (basically, the XIB contains a scrollview, a label and a button).

例如,如果循环加载我即时创建的视图,则滚动视图将完美工作.

The scrollview perfectly works if in a loop I load views I create on the fly, eg.

 let customView = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 150))
 customView.frame = CGRect(x: i*300 , y: 0, width: 300, height: 150)
 customView.translatesAutoresizingMaskIntoConstraints = false
 scrollView.addSubview(customView)

但是我有一个不同的目标.

But I have a different goal.

在另一个XIB中,我有一个图像视图和一个带有一些标签的堆栈视图.此XIB在情节提要中连接到扩展UIView的类SingleEvent.

In another XIB I have an image view and a stackview with some labels. This XIB is connected in the storyboard to a class SingleEvent that extends UIView.

我要执行以下操作:

  1. XIB用作一种蓝图",并在我的滚动视图中多次加载同一视图;
  2. 将任何数据传递给任何实例;
  1. use the XIB as a sort of "blueprint" and load the same view multiple times in my scrollview;
  2. pass to any instance some data;

这可能吗?

我试图以这种方式加载XIB的内容:

I tried to load the content of the XIB this way:

 let customView = Bundle.main.loadNibNamed("SingleEvent", owner: self, options: nil)?.first as? SingleEvent

以这种方式:

let customView = SingleEvent()

第一个使应用程序崩溃,而第二个没有问题,但我看不到任何效果(它不会加载任何东西).

The first one makes the app crash, while the second causes no issue, but I can't see any effect (it doesn't load anything).

我最新的SingleEvent的内容如下:

 import UIKit

    class SingleEvent: UIView {

        @IBOutlet weak var label:UILabel!
        @IBOutlet weak var imageView:UIImageView!

        override init(frame: CGRect) {
            super.init(frame: frame)

            loadViewFromNib()
        }

        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)

            loadViewFromNib()
        }

        func loadViewFromNib() -> UIView {
            let myView = Bundle.main.loadNibNamed("SingleEvent", owner: self, options: nil)?.first as! UIView
            return myView
        }
    }

在此先感谢您的帮助:-)

Thanks in advance, any help is appreciated :-)

推荐答案

有很多方法可以从xib加载自定义视图(类).您可能会发现此方法容易一些.

There are a number of approaches to loading custom views (classes) from xibs. You may find this method a bit easier.

首先,像这样创建您的xib:

First, create your xib like this:

请注意,File's Owner的类别是默认名称(NSObject).

Note that the Class of File's Owner is the default (NSObject).

相反,将自定义类分配给xib中的"root"视图:

Instead, assign your custom class to the "root" view in your xib:

现在,我们的整个自定义视图类如下:

Now, our entire custom view class looks like this:

class SingleEvent: UIView {

    @IBOutlet var topLabel: UILabel!
    @IBOutlet var middleLabel: UILabel!
    @IBOutlet var bottomLabel: UILabel!

    @IBOutlet var imageView: UIImageView!

}

而且,我们没有创建UIView扩展名,而是将loadNibNamed(...)放到了自定义类中:

And, instead of putting loadNibNamed(...) inside our custom class, we create a UIView extension:

extension UIView {
    class func fromNib<T: UIView>() -> T {
        return Bundle.main.loadNibNamed(String(describing: T.self), owner: nil, options: nil)![0] as! T
    }
}

要加载和使用我们的自定义类,我们可以这样做:

To load and use our custom class, we can do this:

class FromXIBViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // create an instance of SingleEvent from its xib/nib
        let v = UIView.fromNib() as SingleEvent

        // we're going to use auto-layout & constraints
        v.translatesAutoresizingMaskIntoConstraints = false

        // set the text of the labels
        v.topLabel?.text    = "Top Label"
        v.middleLabel?.text = "Middle Label"
        v.bottomLabel?.text = "Bottom Label"

        // set the image
        v.imageView.image = UIImage(named: "myImage")

        // add the SingleEvent view
        view.addSubview(v)

        // constrain it 200 x 200, centered X & Y
        NSLayoutConstraint.activate([
            v.widthAnchor.constraint(equalToConstant: 200.0),
            v.heightAnchor.constraint(equalToConstant: 200.0),
            v.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            v.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            ])

    }

}

结果:

还有...这是加载10个SingleEvent视图实例并将其添加到垂直滚动视图的示例:

And... here is an example of loading 10 instances of SingleEvent view and adding them to a vertical scroll view:

class FromXIBViewController: UIViewController {

    var theScrollView: UIScrollView = {
        let v = UIScrollView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = .cyan
        return v
    }()

    var theStackView: UIStackView = {
        let v = UIStackView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.axis = .vertical
        v.alignment = .fill
        v.distribution = .fill
        v.spacing = 20.0
        return v
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        // add the scroll view to the view
        view.addSubview(theScrollView)

        // constrain it 40-pts on each side
        NSLayoutConstraint.activate([
            theScrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40.0),
            theScrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -40.0),
            theScrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 40.0),
            theScrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -40.0),
            ])

        // add a stack view to the scroll view
        theScrollView.addSubview(theStackView)

        // constrain it 20-pts on each side
        NSLayoutConstraint.activate([
            theStackView.topAnchor.constraint(equalTo: theScrollView.topAnchor, constant: 20.0),
            theStackView.bottomAnchor.constraint(equalTo: theScrollView.bottomAnchor, constant: -20.0),
            theStackView.leadingAnchor.constraint(equalTo: theScrollView.leadingAnchor, constant: 20.0),
            theStackView.trailingAnchor.constraint(equalTo: theScrollView.trailingAnchor, constant: -20.0),

            // stackView width = scrollView width -40 (20-pts padding on left & right
            theStackView.widthAnchor.constraint(equalTo: theScrollView.widthAnchor, constant: -40.0),
            ])


        for i in 0..<10 {

            // create an instance of SingleEvent from its xib/nib
            let v = UIView.fromNib() as SingleEvent

            // we're going to use auto-layout & constraints
            v.translatesAutoresizingMaskIntoConstraints = false

            // set the text of the labels
            v.topLabel?.text    = "Top Label: \(i)"
            v.middleLabel?.text = "Middle Label: \(i)"
            v.bottomLabel?.text = "Bottom Label: \(i)"

            // set the image (assuming we have images named myImage0 thru myImage9
            v.imageView.image = UIImage(named: "myImage\(i)")

            theStackView.addArrangedSubview(v)

        }

    }

}

结果:

这篇关于从XIB加载视图作为scrollview的子视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆