【发布时间】:2020-06-30 14:03:14
【问题描述】:
- 所以我有一个 UIPageViewController。它包含 5 个 UIHostingViewControllers (Swift UI)
- 我将托管视图控制器添加为 child,然后按照推荐的方法设置视图
- 一切正常,我能够在控制器之间滑动
- 现在我需要显示突出显示的圆圈,以便用户在滚动时了解他们正在查看的页面。这就是问题发生的地方
- 我将这些圆圈作为 子视图 添加到 UIPageViewController 的视图上。一切正常,但仅页面视图控制器的第一个控制器就有一个视图错误。视图的框架未填充页面视图的边界
- 这就是我得到的。正如您在下图中看到的,除了第一个控制器之外,所有其他控制器都能够适应视图。仅当我尝试将这些指示器圆圈添加为 self.view 或 UIPageViewController.view 的子视图时,才会发生此行为
代码如下:
class TutorialController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate{
var controllers = [UIViewController]()
var circleStackView: UIStackView = {
let sv = UIStackView()
sv.axis = .horizontal
sv.spacing = 16
return sv
}()
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
dataSource = self
setupViewControllers()
}
fileprivate func setupViewControllers(){
let tutorialPage1 = UIHostingController(rootView: TutorialPage1())
let sampleViewController1 = UIViewController()
sampleViewController1.addChild(tutorialPage1)
tutorialPage1.view.translatesAutoresizingMaskIntoConstraints = false
sampleViewController1.view.addSubview(tutorialPage1.view)
tutorialPage1.didMove(toParent: sampleViewController1)
tutorialPage1.view.frame = sampleViewController1.view.bounds
controllers.append(sampleViewController1)
let tutorialPage2 = UIHostingController(rootView: TutorialPage2())
let sampleViewController2 = UIViewController()
sampleViewController2.addChild(tutorialPage2)
tutorialPage2.view.translatesAutoresizingMaskIntoConstraints = false
sampleViewController2.view.addSubview(tutorialPage2.view)
tutorialPage2.didMove(toParent: sampleViewController2)
tutorialPage2.view.frame = sampleViewController2.view.bounds
controllers.append(sampleViewController2)
setViewControllers([controllers.first!], direction: .forward, animated: false)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
controllers.forEach { (_) in
let circleView = UIView()
circleView.anchor(top: nil, leading: nil, bottom: nil, trailing: nil, size: .init(width: 24, height: 24))
circleView.layer.cornerRadius = 12
circleView.clipsToBounds = true
circleView.backgroundColor = UIColor.white.withAlphaComponent(0.8)
self.circleStackView.addArrangedSubview(circleView)
self.circleStackView.bringSubviewToFront(view)
}
view.addSubview(circleStackView)
circleStackView.anchor(top: nil, leading: nil, bottom: view.safeAreaLayoutGuide.bottomAnchor, trailing: nil, padding: .init(top: 0, left: 0, bottom: 16, right: 0))
circleStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let index = controllers.firstIndex(where: {$0 == viewController}) ?? 0
if index == 0{
return nil
}
return controllers[index - 1]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let index = controllers.firstIndex(where: {$0 == viewController}) ?? 0
if index == controllers.count - 1{
return nil
}
return controllers[index + 1]
}
}
【问题讨论】:
-
TutorialPage1和TutorialPage2的代码可以分享吗?
-
@IFTTT 这是一个基本的 VStack,带有一个 Rectangle() 和一个 Spacer()。就像我说的,只要我不向页面视图控制器添加任何子视图,视图就会准确呈现。当我将这些圆圈添加为子视图时,仅第一个视图控制器就会像图像中一样移位
-
这个问题似乎是特定于使用 UIStackView 和 SwiftUI。我尝试用 uilabel 替换 stackview,但问题没有出现。
-
@IFTTT 哦,这很奇怪。这是一个已知的问题?如果是这样,您可以将其发布为答案,我会将其标记为正确答案。我认为一个好的解决方法是将页面视图控制器放入另一个带有底部填充的视图控制器中,并在那里添加一个堆栈视图。然后可能使用委托来检测页面滑动并更改这些圆圈的 alpha 值。