在上一节中,我们学习了如何使用按钮更改iPhone的屏幕。让我们进一步推动!我们将实现一个CollectionView,我们将能够切换到您想要的壁纸。该的CollectionView将是滚动的水平。
要学习本教程,您需要Xcode 10。您可以下载Final Xcode项目,以帮助您与自己的进度进行比较。
在主故事板中,让我们构建我们的集合视图。首先,把视图控制器从对象库旁边我们的视图控制器。将其背景颜色更改为Clear,因为我们希望Collection View位于当前View Controller之上。在第二个视图控制器和约束内插入一个UIView:0左,0右和0底(全部相对于superview)。取消选中“ 约束”到边距并将高度设置为380。
MultipleScreens01
让我们在收集视图的角落。在Identity Inspector中,单击小+并添加此属性。
MultipleScreens02
让我们将这两个View Controller连接在一起。在第一个图标的顶部,Control +从第一个图标(黄色圆圈)拖动到第二个图标的视图。它将创建一个segue并选择Present Modally。命名segue:HomeToDialog。然后,将演示文稿更改为当前上下文。对于placeScreenButtonTapped,删除代码并调用segue。
performSegue(withIdentifier: "HomeToDialog", sender: nil)
现在,让我们贴上标签!从对象库中拖放标签并将其约束到Container中的水平居中并将顶部设置为30。在Attributes Inspector中,将字体设置为Semibold,将其Color更改为深灰色,将文本更改为CHOOSE A SCREEN。
从对象库中拖放Collection View并将其放在UIView中。(不要与Collection View Controller混淆)。约束Collection View:
约束 | 值 |
---|---|
左 | 0点 |
右 | 0点 |
上 | 30点 |
高 | 250点 |
MultipleScreens03
由于我们创建了一个新的View Controller,我们需要将它与一个新类相关联。通过按住Command + N创建一个新的Cocoa Touch文件,将Subclass更改为UIViewController,将名称更改为DialogViewController。然后,打开主故事板并启用助理编辑器。单击第二个View Controller的顶部,转到Identity Inspector并将其Class更改为DialogViewController。该助理编辑会自动更改为新的类文件。删除已注释的代码块。
MultipleScreens04
首先,让我们为CollectionView创建一个IBOutlet,Control +从Collection View ****拖动到swift文件,然后拖到****viewDidLoad上。将其命名为:screensCollectionView。然后,在viewDidLoad中,调用IBOutlet并将其委托给self。这样,我们的ViewController将能够使用我们的Collection View。另外,将数据源设置为self。
screensCollectionView.delegate = self
screensCollectionView.dataSource = self
要分离我们的代码,在最后创建一个新的扩展,它将是DialogViewController的扩展类型:UICollectionViewDataSource和UICollectionViewDelegate。
extension DialogViewController: UICollectionViewDataSource, UICollectionViewDelegate {
}
设置委托时,尝试运行代码,它会建议您丢失哪种方法。使用Command + R运行代码,然后修复2个错误。它将为您提供运行CollectionView所需的两种方法。
在第一个函数内部,我们只需返回3。
return 3
在cells函数内,为cell声明一个常量,然后调用CollectionView,它的cell和路径。然后,将cell返回。
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "screenCell", for: indexPath)
return cell
转到主故事板,选择集合视图的cell,在Identity Inspector中,您将看到Cell名称的文本持有者,将其命名为:screenCell。现在,选择尺寸检查器,我们将给我们的cell大小:( 宽度:140高度:250)。设置cell的Min Spacing和左侧的Section Insets为20。它会在每个cell之间留出一些空间。改变cell的颜色白,因为集合视图也是白色的。
MultipleScreens05
然后,从对象库中,将Button拖放到cell内。将按钮限制为(顶部:0点,左:0点,右:0点,高:220点)。取消选中边距。选择按钮并选择iPhoneX1作为图像。你会觉得它很有弹性,所以将内容模式改为Aspect Fit。我们在图像下面插入一个标签。文本是iPhone X并将底部约束为0并将容器中的水平中心约束。在“ 属性”检查器中,将“滚动方向”更改为“ 水平”并取消选中“ 显示”指示器。到目前为止,如果您运行该应用程序,您将看到3个类似的cell,并且它是可滚动的。问题是它现在做的不多。
MultipleScreens06
让我们声明一组具有不同屏幕的手机,这样我们就可以将数据注入我们的Collection View。转到DialogViewController,为屏幕声明一个常量并枚举它们:iPhoneX1,iPhoneX2和iPhoneX3。
let screens = ["iPhoneX1", "iPhoneX2", "iPhoneX3"]
我们需要将这个数组放入我们的cell中,但是,我们的问题是这些数据都没有连接到cell。让我们为Cell Class创建一个新文件。单击Command + N并为子类选择UICollectionViewCell,其名称为:DialogCollectionViewCell。然后,转到主故事板并选择cell,将其类更改为DialogCollectionViewCell。启用Assistant Editor并选择DialogCollectionViewCell。现在,我们可以创建IBOutlet。按住Ctrl并拖动按钮并将其命名为:screenImageButton。对标签重复相同的步骤并将其命名为:screenLabel。
MultipleScreens07
转到DialogViewController,在cell声明的末尾,将cell指定为我们刚刚创建的新类。
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "screenCell", for: indexPath) as! DialogCollectionViewCell
小区现在已连接到DialogCollectionViewCell用正确的IBOulet。让我们调用cellscreenImageButton并通过调用其索引路径来注入数据数组。
cell.screenImageButton.setImage(UIImage(named: screens[indexPath.row]), for: .normal)
如果您运行该应用程序,您将看到cell图像不同!
让我们应用相同的技术来更改screenLabel。首先,为标签声明第二个数组,然后调用screenLabel并注入新数据。
let titles = ["Wallpaper", "Home", "Chapters"]
cell.screenLabel.text = titles[indexPath.row]
如果您运行该应用程序,您将看到cell标签不同!
当我们点击按钮时,我们想要关闭Collection View。转到主故事板,启用Assistant Editor,从按钮创建IBAction。将其命名为:screenImageButtonTapped。我们遇到的问题是按钮位于cell中,但操作发生在DialogCollectionView中。我们必须设立委托。委托将允许我们向View Controller发送消息。在最后,声明一个协议并命名它:DialogCollectionViewCellDelegate。然后,为按钮声明一个动作。
protocol DialogCollectionViewCellDelegate {
func screenImageButtonTapped()
}
为了能够调用该委托,我们也需要声明它。
var delegate: DialogCollectionViewCellDelegate?
然后,在screenImageButtonTapped内部,调用其委托。
delegate?.screenImageButtonTapped()
现在返回DialogViewController,创建一个新扩展并调用委托。然后,尝试运行代码,它会自动为您提供缺少的方法。
extension DialogViewController: DialogCollectionViewCellDelegate {
func screenImageButtonTapped() {
}
}
每当你创建一个委托时,你需要将它附加到segue或我们这里,cell本身。在返回cell的上方,将委托设置为self。这样,您将cell附加到DialogViewController。
cell.delegate = self
现在,在screenImageButtonTapped中调用dismiss ,它应该删除CollectionView。
dismiss(animation: true, completion: nil)
在手机上运行该应用,点击任何手机,它应该会关闭您的CollectionView。
我们需要设置另一个协议,以便能够通过segue 将委托发送给View Controller。在DialogViewController中,在最后声明一个协议并命名它:DialogViewControllerDelegate并声明函数:screenImageButtonTapped。
protocol DialogViewControllerDelegate {
func screenImageButtonTapped()
}
然后,声明它。
var delegate: DialogViewControllerDelegate?
在screenImageButtonTapped中调用委托。
delegate?.screenImageButtonTapped()
现在我们已经设置了委托,转到View Controller,最后为DialogViewControllerDelegate创建一个新的扩展。运行该应用程序以修复缺少的方法。
extension ViewController: DialogViewControllerDelegate {
func screenImageButtonTapped() {
}
}
我们需要一个segue来执行这两者之间的连接。使用segue的名称声明一个if语句。这样,您确定在调用此segue时,我们将执行操作。将委托设置为self。我们需要使用委托来指定我们正在调用,否则,View Controller不知道。
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "HomeToDialog" {
let toVC = segue.destination as! DialogViewController
toVC.delegate = self
}
}
我们需要发送索引的信息才能检索信息。在 Cell 文件中,为索引声明一个变量并使其为0.然后,在screenImageButtonTapped的值内,调用索引及其类型Int。因此,它上面的代理将具有相同的值,它将返回一个索引。转至DialogViewController,放型的指数诠释的价值里面screenImageButton。在返回cell之上,将cell的索引更改为索引路径行。
cell.index = indexPath.row
当我们点击按钮时,它将在函数中返回UIImage类型的图像。为ARScreen的图像声明一个新数组。在委托中,返回:
delegate?.screenImageButtonTapped(image: UIImage(named: images[index])!)
在ViewController中,在函数内部,更改3D模型的材质。在括号内,声明图像是UIImage。
iPhoneXNode.geometry?.firstMaterial?.diffuse.contents = image
祝贺完成本课程!这部分是一个非常漫长而艰难的部分。我们学到了很多关于如何实现Collection View的知识。我们还学会了如何委派。这是ARKit 2扩展的结束,我们已经走了很长的路!我希望你喜欢这门课程!