gpt4 book ai didi

ios - UIPageViewController 可以返回错误的索引

转载 作者:行者123 更新时间:2023-12-01 15:21:06 25 4
gpt4 key购买 nike

正如标题所述,有一种方法可以返回错误的索引。这会弄乱页面底部的索引表示点。完成此操作的方法是在不从屏幕上松开手指的情况下跳过一页。如果发生这种情况,它会弄乱其余的演示点。

here是它在行动中的样子。

这是用于 UIPageViewController 的代码。

    import UIKit

class PageViewController: UIPageViewController {

override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.LightContent
}

private(set) lazy var orderedViewControllers: [UIViewController] = {
return [self.newColoredViewController("Green"),
self.newColoredViewController("Red"),
self.newColoredViewController("Blue")]

}()

private func newColoredViewController(color: String) -> UIViewController {
return UIStoryboard(name: "Main", bundle: nil) .
instantiateViewControllerWithIdentifier("\(color)ViewController")
}

override func viewDidLoad() {
super.viewDidLoad()

dataSource = self

if let firstViewController = orderedViewControllers.first {
setViewControllers([firstViewController],
direction: .Forward,
animated: true,
completion: nil)
}

// Do any additional setup after loading the view.
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}


/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/

}

//MARK: UIPageViewControllerDataSource

extension PageViewController: UIPageViewControllerDataSource {

func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.indexOf(viewController) else {
return nil
}

let previousIndex = viewControllerIndex - 1

guard previousIndex >= 0 else {
return nil
}

guard orderedViewControllers.count > previousIndex else {
return nil
}

return orderedViewControllers[previousIndex]
}

func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.indexOf(viewController) else {
return nil
}

let nextIndex = viewControllerIndex + 1

let orderedViewControllersCount = orderedViewControllers.count

guard orderedViewControllersCount != nextIndex else {
return nil
}

guard orderedViewControllersCount > nextIndex else {
return nil
}

return orderedViewControllers[nextIndex]
}

func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return orderedViewControllers.count
}

func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
guard let firstViewController = viewControllers?.first,
firstViewControllerIndex = orderedViewControllers.indexOf(firstViewController) else {
return 0
}

return firstViewControllerIndex
}

}

对此的任何帮助将不胜感激,谢谢。

最佳答案

我做了一个解决方法,因为这仍然没有解决!已经4年多了。
类到子类而不是 UIPageViewController :

import UIKit

class PageController: UIPageViewController {
lazy var pages: [UIViewController] = []

var newOffset: CGFloat = 20

var showReal = true
var pageControlX: CGFloat = 0 // 0 is the middle of the screen
var pageControlY: CGFloat = 200

private var scrollView: UIScrollView?
private var scrollPoints: [UIView] = []
private var oldScrollPoints: [UIView] = []

private var indexKeeper = IndexKeeper()

private var selectedColor = UIColor(white: 1, alpha: 1)
private var unselectedColor = UIColor(white: 1, alpha: 0.2)

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

// whole screen scroll
scrollView = view.subviews.filter{ $0 is UIScrollView }.first! as? UIScrollView
scrollView!.frame = UIScreen.main.bounds

// get pageControl and scroll view from view's subviews
let pageControl = view.subviews.filter{ $0 is UIPageControl }.first! as! UIPageControl
oldScrollPoints = pageControl.subviews

// remove all constraint from view that are tied to pageControl
let const = view.constraints.filter { $0.firstItem as? NSObject == pageControl || $0.secondItem as? NSObject == pageControl }
view.removeConstraints(const)

// customize pageControl
pageControl.translatesAutoresizingMaskIntoConstraints = false
pageControl.frame = CGRect(x: pageControlX, y: pageControlY,
width: view.frame.width, height: 0)

DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
self.replacePoints()
self.updateIndex()
}
}

private func replacePoints() {
for point in scrollPoints {
point.removeFromSuperview()
}
scrollPoints = []
for oldPoint in oldScrollPoints {
let newPoint = UIView(frame: oldPoint.frame)
// make rounded
newPoint.layer.borderWidth = 0
newPoint.layer.masksToBounds = false
newPoint.layer.cornerRadius = newPoint.frame.height / 2
newPoint.clipsToBounds = true

newPoint.center = CGPoint(x: oldPoint.center.x, y: newOffset)
newPoint.backgroundColor = oldPoint.backgroundColor
oldPoint.superview?.addSubview(newPoint)
scrollPoints.append(newPoint)
oldPoint.alpha = showReal ? 1 : 0
}
}

private func offsetFromFirstPage() -> CGFloat {
var coordinates: [CGFloat] = []
for (index, page) in pages.enumerated() {
let offset = scrollView!.convert(scrollView!.bounds.origin, to: page.view!)
coordinates.append(offset.x + CGFloat(index) * view.frame.width)
}

let duplicates: [CGFloat] = coordinates.enumerated().map
{ current in
if coordinates.firstIndex(of: current.element) != coordinates.lastIndex(of: current.element) {
return current.element
} else {
return .nan
}
}

return duplicates.first(where: { !$0.isNaN }) ?? 0
}

private var lastIndex: Int = 0
private func pageIndexFrom(offset: CGFloat, visibleRatio: CGFloat=0.6) -> Int {
let adjustedOffset = (offset / view.frame.width)

if adjustedOffset > CGFloat(lastIndex) + visibleRatio {
if lastIndex + 1 < pages.count {
lastIndex += 1
}
} else if adjustedOffset < CGFloat(lastIndex) - visibleRatio {
if lastIndex - 1 >= 0 {
lastIndex -= 1
}
}
return lastIndex
}

private func updateIndex() {
let fastIndex = pages.firstIndex(of: viewControllers!.first!)!
indexKeeper.fastIndexUpdate(index: fastIndex)

let offset = offsetFromFirstPage()
let slowIndex = pageIndexFrom(offset: offset)
indexKeeper.slowIndexUpdate(index: slowIndex)

for (index, point) in scrollPoints.enumerated() {
if index == indexKeeper.finalIndex {
point.backgroundColor = selectedColor
} else {
point.backgroundColor = unselectedColor
}
}

DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
self.updateIndex()
}
}
}

class IndexKeeper {
var finalIndex = 0
private var slowIndex = 0
private var fastIndex = 0

func slowIndexUpdate(index: Int) {
if index != slowIndex {
slowIndex = index
finalIndex = slowIndex
}
}

func fastIndexUpdate(index: Int) {
if index != fastIndex {
fastIndex = index
finalIndex = fastIndex
}
}
}
使用示例:
import UIKit

class PageViewController: PageController, UIPageViewControllerDataSource {

private func pageInstance(name:String) -> UIViewController {
return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: name)
}

override func viewDidLoad() {
super.viewDidLoad()

pages = [
pageInstance(name: "FirstPage"),
pageInstance(name: "SecondPage"),
pageInstance(name: "ThirdPage"),
pageInstance(name: "FourthPage")
]

dataSource = self

setViewControllers([pages.first!], direction: .forward, animated: false, completion: nil)
}

// get page before current page
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let index = pages.firstIndex(of: viewController), index > 0 else {
return nil
}

return pages[index - 1]
}

// get page after current page
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let index = pages.firstIndex(of: viewController), index + 1 < pages.count else {
return nil
}

return pages[index + 1]
}

func presentationCount(for pageViewController: UIPageViewController) -> Int {
return pages.count
}

func presentationIndex(for pageViewController: UIPageViewController) -> Int {
if let vc = viewControllers?.first {
return pages.firstIndex(of: vc)!
}
return 0
}
}

关于ios - UIPageViewController 可以返回错误的索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36853129/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com