控制UIPageControl中的“活动”点

时间:2015-10-20 21:37:25

标签: ios swift uipageviewcontroller uipagecontrol

我的设计师要求我在UIPageViewController中为10个视图显示3个点。

当显示前3个视图控制器时,应突出显示第0个点;当接下来的4个视图控制器显示时,应突出显示第1个点;当最后3个视图控制器显示时,应突出显示第2个点。

到目前为止,我可以在UIPageControl中显示3个点,但指针点只是旋转,表明n%3位置处于活动状态。

func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
    return 3
}

我还没有看到任何关于如何使用UIPageControl控制索引的文档是活动索引,所以我不确定这是Apple希望你能够覆盖的东西。

如果有办法完成我想要做的事情,我会很感激帮助。

1 个答案:

答案 0 :(得分:0)

事实证明,我尝试完成的工作无法通过UIPageViewController完成。默认情况下,不能直接覆盖此类中的UIPageControl。

相反,我能够使用UICollectionView(一个允许它在其页面更改效果中类似于UIPageViewController的hack)和一个UIPageControl的组合,作为相同的总体UIViewController的子视图。

class MyPageViewController : UIViewController {
    // MARK: subviews
    private var collectionView:UICollectionView!
    /// the collection layout controls the scrolling behavior of the collection view
    private var collectionLayout = MyLayout()
    private var pageControl = UIPageControl()

    let CollectionViewCellReuseIdentifer = "CollectionViewCellReuseIdentifier"

    // MARK: autolayout
    private var autolayoutConstraints:[NSLayoutConstraint] = [NSLayoutConstraint]()



    // MARK: constructors
    init() {
        super.init(nibName: nil, bundle: nil)
    }



    // MARK: UIViewController lifecycle methods
    override func viewDidLoad() {
        super.viewDidLoad()
        self.setupView()
    }



    /**
    Set up the collection view, page control, skip & log in buttons
    */
    func setupView() {
        self.setupCollectionView()
        self.setupPageControl()

        self.setupConstraints()

        self.view.addConstraints(self.autolayoutConstraints)
    }

    /**
    Set up the collection view
    */
    func setupCollectionView() {
        self.collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: self.collectionLayout)
        self.collectionView.translatesAutoresizingMaskIntoConstraints = false
        self.collectionView.registerClass(MyPageView.self, forCellWithReuseIdentifier: self.CollectionViewCellReuseIdentifer)
        self.collectionView.dataSource = self
        self.collectionView.delegate = self
        self.collectionView.backgroundColor = UIColor.whiteColor()
        self.collectionView.scrollEnabled = true
        self.collectionView.decelerationRate = UIScrollViewDecelerationRateFast;


        self.collectionLayout.minimumInteritemSpacing = 1
        self.collectionLayout.minimumLineSpacing = 1
        self.collectionLayout.scrollDirection = .Horizontal
        self.collectionLayout.delegate = self

        self.view.addSubview(self.collectionView)
    }

    /**
    Set up view showing pagination dots for slideshow items
    */
    func setupPageControl() {
        self.pageControl.translatesAutoresizingMaskIntoConstraints = false
        self.pageControl.numberOfPages = 3
        self.pageControl.backgroundColor = UIColor.whiteColor()

        self.view.addSubview(self.pageControl)
    }

    func setupConstraints() {
        let views:[String:AnyObject] = [
            "collectionView" : self.collectionView,
            "pageControl" : self.pageControl,
        ]

        self.autolayoutConstraints.appendContentsOf(
            NSLayoutConstraint.constraintsWithVisualFormat(
                "V:|[collectionView][pageControl]|",
                options: .AlignAllCenterX,
                metrics: nil,
                views: views
            )
        )

        self.autolayoutConstraints.appendContentsOf(
            NSLayoutConstraint.constraintsWithVisualFormat(
                "H:|[collectionView]|",
                options: .AlignAllCenterY,
                metrics: nil,
                views: views
            )
        )

        self.autolayoutConstraints.appendContentsOf(
            NSLayoutConstraint.constraintsWithVisualFormat(
                "H:|[pageControl]|",
                options: NSLayoutFormatOptions(),
                metrics: nil,
                views: views
            )
        )
    }
}

extension MyPageViewController : MyPageViewControllerDelegate {
    func didSwitchToPage(imageIndex: Int) {
        if imageIndex < 3 {
            self.pageControl.currentPage = 0
        } else if imageIndex < 7 {
            self.pageControl.currentPage = 1
        } else {
            self.pageControl.currentPage = 2
        }

        self.pageControl.setNeedsDisplay()
    }
}

布局类源自我的同事在研究类似问题时发现的答案。 http://karmadust.com/centered-paging-with-preview-cells-on-uicollectionview/

/**
*  Delegate for slide interactions
*/
protocol MyPageViewControllerDelegate {
    /**
    Triggered when a new page has been 'snapped' into place

    - parameter imageIndex: index of the image that has been snapped to
    */
    func didSwitchToPage(imageIndex: Int)

}

class MyLayout : UICollectionViewFlowLayout {
    var delegate:MyPageViewControllerDelegate?

    /*
    Allows different items in the collection to 'snap' onto the current screen section.
    Based off of http://karmadust.com/centered-paging-with-preview-cells-on-uicollectionview/
    */
    override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {

        if let cv = self.collectionView {

            let cvBounds = cv.bounds
            let halfWidth = cvBounds.size.width * 0.5;
            let proposedContentOffsetCenterX = proposedContentOffset.x + halfWidth;

            if let attributesForVisibleCells = self.layoutAttributesForElementsInRect(cvBounds) {

                var candidateAttributes : UICollectionViewLayoutAttributes?
                // the index of the image selected
                var index:Int = 0

                for attributes in attributesForVisibleCells {

                    // == Skip comparison with non-cell items (headers and footers) == //
                    if attributes.representedElementCategory != UICollectionElementCategory.Cell {
                        index++
                        continue
                    }

                    if let candAttrs = candidateAttributes {

                        let a = attributes.center.x - proposedContentOffsetCenterX
                        let b = candAttrs.center.x - proposedContentOffsetCenterX

                        if fabsf(Float(a)) < fabsf(Float(b)) {
                            candidateAttributes = attributes;
                        }

                    }
                    else { // == First time in the loop == //

                        candidateAttributes = attributes;
                        index++
                        continue;
                    }

                }

                // Beautification step , I don't know why it works!
                if(proposedContentOffset.x == -(cv.contentInset.left)) {
                    return proposedContentOffset
                }

                if let delegate = self.delegate {
                    delegate.didSwitchToPage((candidateAttributes?.indexPath.row)!)
                }

                return CGPoint(x: floor(candidateAttributes!.center.x - halfWidth), y: proposedContentOffset.y)

            }


        }

        // fallback
        return super.targetContentOffsetForProposedContentOffset(proposedContentOffset)
    }
}

注意:我删除了我使用的实际代码,并替换了一堆名称,使其更适合示例。我没有运行这个特定的代码,也没有在我的IDE中测试错误。话虽这么说,代码背后的方法是可靠的。