我有一个
UIPageViewController
使用transitionStyle.pageCurl
。我注意到在翻页的时候,翻页的正面在翻页的背面出现了波谷。即使有坚实的背景,即使 isOpaque
对于 viewcontroller 的翻页视图也是如此。
Apple 的 documentation for
isDoubleSided
状态:
如果页面背面没有内容(值为false),则翻页时,页面正面的内容会部分透到背面
有什么办法可以改变这种行为,让页面的背面只显示纯色背景(而不是上面可能出现的任何其他内容)?
首先想到的是......使用双面页面视图控制器,并在每个“真实”页面之后插入一个“空白”页面。
快速示例...
我将使用一个“基本”视图控制器来容纳两个子页面视图控制器——一个单面,另一个双面。我们将在该“基本”控制器中创建页面数组,将空白(深灰色)页面插入第二个页面的数组中:
Base controller - 将持有一个页面视图控制器的两个实例作为孩子:
class BaseViewController: UIViewController {
var singleSidedPVC: SamplePageViewController!
var doubleSidedPVC: SamplePageViewController!
override func viewDidLoad() {
super.viewDidLoad()
// views to hold the page view controllers
let ssContainer = UIView()
ssContainer.backgroundColor = .gray
let dsContainer = UIView()
dsContainer.backgroundColor = .gray
[ssContainer, dsContainer].forEach { v in
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
}
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
ssContainer.topAnchor.constraint(equalTo: g.topAnchor, constant: 60.0),
ssContainer.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
ssContainer.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
ssContainer.heightAnchor.constraint(equalTo: ssContainer.widthAnchor, multiplier: 0.75),
dsContainer.topAnchor.constraint(equalTo: ssContainer.bottomAnchor, constant: 60.0),
dsContainer.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
dsContainer.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
dsContainer.heightAnchor.constraint(equalTo: dsContainer.widthAnchor, multiplier: 0.75),
])
// single-sided - back of page shows through
singleSidedPVC = SamplePageViewController(transitionStyle: .pageCurl, navigationOrientation: .horizontal)
singleSidedPVC.isDoubleSided = false
addChild(singleSidedPVC)
singleSidedPVC.view.translatesAutoresizingMaskIntoConstraints = false
ssContainer.addSubview(singleSidedPVC.view)
NSLayoutConstraint.activate([
singleSidedPVC.view.topAnchor.constraint(equalTo: ssContainer.topAnchor),
singleSidedPVC.view.leadingAnchor.constraint(equalTo: ssContainer.leadingAnchor),
singleSidedPVC.view.trailingAnchor.constraint(equalTo: ssContainer.trailingAnchor),
singleSidedPVC.view.bottomAnchor.constraint(equalTo: ssContainer.bottomAnchor),
])
singleSidedPVC.didMove(toParent: self)
// double-sided - we'll insert a blank page between every page
doubleSidedPVC = SamplePageViewController(transitionStyle: .pageCurl, navigationOrientation: .horizontal)
doubleSidedPVC.isDoubleSided = true
addChild(doubleSidedPVC)
doubleSidedPVC.view.translatesAutoresizingMaskIntoConstraints = false
dsContainer.addSubview(doubleSidedPVC.view)
NSLayoutConstraint.activate([
doubleSidedPVC.view.topAnchor.constraint(equalTo: dsContainer.topAnchor),
doubleSidedPVC.view.leadingAnchor.constraint(equalTo: dsContainer.leadingAnchor),
doubleSidedPVC.view.trailingAnchor.constraint(equalTo: dsContainer.trailingAnchor),
doubleSidedPVC.view.bottomAnchor.constraint(equalTo: dsContainer.bottomAnchor),
])
doubleSidedPVC.didMove(toParent: self)
// let's add pages to each controller
let colors: [UIColor] = [
.systemRed,
.systemGreen,
.systemBlue,
.red,
.green,
.blue,
]
var pvcControllers: [UIViewController]!
pvcControllers = []
for i in 0..<colors.count {
let vc = MyExamplePageViewVC()
vc.theLabel.text = "Page: \(i)"
vc.view.backgroundColor = colors[i]
pvcControllers.append(vc)
}
singleSidedPVC.pageViewControllers = pvcControllers
pvcControllers = []
for i in 0..<colors.count {
let vc = MyExamplePageViewVC()
vc.theLabel.text = "Page: \(i)"
vc.view.backgroundColor = colors[i]
pvcControllers.append(vc)
// for double-sided controller, we're inserting
// a "blank" page VC after every "real" page VC
// so *that* is what shows on the back of the curl
let blankVC = UIViewController()
blankVC.view.backgroundColor = .darkGray
pvcControllers.append(blankVC)
}
doubleSidedPVC.pageViewControllers = pvcControllers
}
}
SamplePageViewController - 非常标准:
class SamplePageViewController: UIPageViewController {
// this will be set by the parent controller
var pageViewControllers: [UIViewController] = [] {
didSet {
setViewControllers([pageViewControllers[0]], direction: .forward, animated: false, completion: nil)
}
}
override init(transitionStyle style: UIPageViewController.TransitionStyle, navigationOrientation: UIPageViewController.NavigationOrientation, options: [UIPageViewController.OptionsKey : Any]? = nil) {
super.init(transitionStyle: style, navigationOrientation: navigationOrientation, options: options)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override func viewDidLoad() {
super.viewDidLoad()
dataSource = self
}
}
extension SamplePageViewController: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = pageViewControllers.firstIndex(of: viewController) else { return nil }
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else { return nil }
return pageViewControllers[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = pageViewControllers.firstIndex(of: viewController) else { return nil }
let nextIndex = viewControllerIndex + 1
guard nextIndex < pageViewControllers.count else { return nil }
return pageViewControllers[nextIndex]
}
}
MyExamplePageViewVC - 同样,非常标准......每个页面都会有一个标签来填充大部分框架:
class MyExamplePageViewVC: UIViewController {
let theLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .yellow
v.textAlignment = .center
v.font = .systemFont(ofSize: 36.0, weight: .light)
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
view.addSubview(theLabel)
NSLayoutConstraint.activate([
theLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
theLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
theLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.9),
theLabel.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.9),
])
}
}
运行时的样子: