juanpablofernandez / SwiftyOnboard

A swifty iOS framework that allows developers to create beautiful onboarding experiences.
MIT License
1.25k stars 105 forks source link

Page Control doesn't synchronize with a swipe action #16

Closed alan-d-haller closed 7 years ago

alan-d-haller commented 7 years ago

Dear developer, I tried to install this SwiftyOnboard pod into my project, but its page control doesn't synchronize with a swipe action. For example, even if I swipe the display to the next page, the dot point of page control doesn't move. Plus, even if I tap the dot, the display doesn't move to the designated page. In order to synchronize page control and swipe and tap actions like the demo, where and which code should I add? My environment is Xcode 9 beta 6, macOS Sierra. I'm a beginner who started learning of iOS development 2 months ago, so I wonder if you cloud explain a solution to me simply. Thanks in advance from Japan.

juanpablofernandez commented 7 years ago

Hey there @y-hara1031 I'll try to guide you so that you can solve this as soon as possible :)

Plus, even if I tap the dot, the display doesn't move to the designated page.

For example, even if I swipe the display to the next page, the dot point of page control doesn't move.

Could you send over a code snippet of your implementation of the onboarding?

Cheers.

alan-d-haller commented 7 years ago

@juanpablofernandez Thanks for your reply and help. No, I didn't edit the files so much. Basically, I followed the guidance of this pod and write the code. Anyway, I'll send you the snippets that I wrote. I wonder if you could correct that. Thanks in advance.

alan-d-haller commented 7 years ago

ViewController.swift

`import UIKit import SwiftyOnboard

class ViewController: UIViewController,SwiftyOnboardDelegate, SwiftyOnboardDataSource {

@IBOutlet var swiftyOnboard: SwiftyOnboard!

override func viewDidLoad() {
    super.viewDidLoad()

    swiftyOnboard.style = .light
    swiftyOnboard.delegate = self
    swiftyOnboard.dataSource = self
    swiftyOnboard.fadePages = true
    swiftyOnboard.backgroundColor = UIColor(red: 46/256, green: 46/256, blue: 76/256, alpha: 1)

}
@objc func handleSkip() {
    swiftyOnboard?.goToPage(index: 2, animated: true)

}

@objc func handleContinue(sender: UIButton) {
    let index = sender.tag
    swiftyOnboard?.goToPage(index: index + 1, animated: true)
}
func swiftyOnboardNumberOfPages(_ swiftyOnboard: SwiftyOnboard) -> Int {
    return 3
}

func swiftyOnboardPageForIndex(_ swiftyOnboard: SwiftyOnboard, index: Int) -> SwiftyOnboardPage? {
    let view = CustomPage.instanceFromNib() as? CustomPage
    view?.image.image = UIImage(named: "\(index).png")
    if index == 0 {
        //On the first page, change the text in the labels to say the following:
        view?.titleLabel.text = "このアプリでは"
        view?.subTitleLabel.text = "いろんな事をシェアしよう"
    } else if index == 1 {
        //On the second page, change the text in the labels to say the following:
        view?.titleLabel.text = "出かけた場所の上空に"
        view?.subTitleLabel.text = "写真を保存したり、落書きをしたり"
    } else {
        //On the thrid page, change the text in the labels to say the following:
        view?.titleLabel.text = "さあはじめましょう!"
        view?.subTitleLabel.text = "楽しい世界へようこそ!"
    }
    return view
}

func swiftyOnboardViewForOverlay(_ swiftyOnboard: SwiftyOnboard) -> SwiftyOnboardOverlay? {
    let overlay = CustomOverlay.instanceFromNib() as? CustomOverlay
    overlay?.skip.addTarget(self, action: #selector(handleSkip), for: .touchUpInside)
    overlay?.buttonContinue.addTarget(self, action: #selector(handleContinue), for: .touchUpInside)
    return overlay
}

func swiftyOnboardOverlayForPosition(_ swiftyOnboard: SwiftyOnboard, overlay: SwiftyOnboardOverlay, for position: Double) {
    let overlay = overlay as! CustomOverlay
    let currentPage = round(position)
    overlay.pageControl.currentPage = Int(currentPage)
    overlay.buttonContinue.tag = Int(position)
    if currentPage == 0.0 || currentPage == 1.0 {
        overlay.buttonContinue.setTitle("続ける", for: .normal)
        overlay.skip.setTitle("スキップ", for: .normal)
        overlay.skip.isHidden = false
    } else {
        overlay.buttonContinue.setTitle("はじめる!", for: .normal)
        overlay.skip.isHidden = true
    }
}

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

}`

alan-d-haller commented 7 years ago

CustomPage.swift

`import Foundation import SwiftyOnboard

class CustomPage: SwiftyOnboardPage {

@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var image: UIImageView!
@IBOutlet weak var subTitleLabel: UILabel!

class func instanceFromNib() -> UIView {
    return UINib(nibName: "CustomPage", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! UIView
}

}`

alan-d-haller commented 7 years ago

CustomOverlay.swift

`import Foundation import SwiftyOnboard

class CustomOverlay: SwiftyOnboardOverlay {

@IBOutlet weak var skip: UIButton!
@IBOutlet weak var buttonContinue: UIButton!
@IBOutlet weak var contentControl: UIPageControl!

override func awakeFromNib() {
    super.awakeFromNib()

    buttonContinue.layer.borderColor = UIColor.white.cgColor
    buttonContinue.layer.borderWidth = 1
    buttonContinue.layer.cornerRadius = buttonContinue.bounds.height / 2
}

class func instanceFromNib() -> UIView {
    return UINib(nibName: "CustomOverlay", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! UIView
}

}`

alan-d-haller commented 7 years ago

That's all.

juanpablofernandez commented 7 years ago

@y-hara1031 The first issue has been fixed, I just updated the pod.

The reason you are getting these issues is because you are using a custom overlay. When doing this you must handle the logic for the UIPageControl just like you are handling the logic for the continue/skip buttons, when using the default Overlay this logic is handled for you.

Does your CustomOverlay succeed in showing?

juanpablofernandez commented 7 years ago

I think I know the source of your problem

In the DataSource Method: swiftyOnboardOverlayForPosition you are updating the PageControl's current page overlay.pageControl.currentPage = Int(currentPage) this however is the default UIPageControl that belongs to the class SwiftyOnboardOverlay. You are subclassing SwiftyOnboardOverlay and creating your own UIPageControl which is named contentControl as you can see here: @IBOutlet weak var contentControl: UIPageControl! therefore setting the currentPage for pageControl isn't going to display the changes since it's a different UIPageControl.

Replace overlay.pageControl.currentPage = Int(currentPage) with overlay.contentControl.currentPage = Int(currentPage) and it should do the trick.

As for the first issue, you will need to add an action to contentControl self.overlay?.contentControl.addTarget(self, action: #selector(didTapPageControl), for: .allTouchEvents)

Then proceed to create the following function in your ViewController:

func didTapPageControl(_ sender: Any) {
        let pageControl = sender as! UIPageControl
        let page = pageControl.currentPage
        self.goToPage(index: page, animated: true)
    }

Adding both these things should allow you to tap on the pageControl bubble and navigate to that page.

Let me know how it works out! Cheers,

alan-d-haller commented 7 years ago

Yes, my CustomOverlay succeed normally except for page control.

I appreciate your guide. I'll try to modify my project file.

Thank you very much!

alan-d-haller commented 7 years ago

Firstly, I replace the code overlay.pageControl.currentPage = Int(currentPage) with overlay.contentControl.currentPage = Int(currentPage) in the ViewController.swift. Then my page control gets to work normally. In other words, when I swipe the display, the bubble moves to the next.

Secondly, in CustomOverlay.swift, I created IBAction of contentConrol and added self.overlay?.contentControl.addTarget(self, action: #selector(didTapPageControl), for: .allTouchEvents). And added the method below. func didTapPageControl(_ sender: Any) { let pageControl = sender as! UIPageControl let page = pageControl.currentPage self.goToPage(index: page, animated: true) }

However, these error messages appeared like the below. Value of type 'CustomOverlay' has no member 'overlay' Value of type 'CustomOverlay' has no member 'goToPage'

Did I mistake the place to add the method?

juanpablofernandez commented 7 years ago

I'm glad the first issue was resolved!

You are getting the second issue because self.goToPage(index: page, animated: true) is a method that belongs to the SwiftyOnboard class. The CustomOverlay class doesn't have it, so you are getting the error, the same goes for the 'overlay' error.

That's why I said above to add the target programmatically to the PageControl, inside your viewController and under the swiftyOnboardViewForOverlay method. I also made a mistake, once you add the action programmatically and add the didTapPageControl function replace self.goToPage(index: page, animated: true) with swiftyOnboard.goToPage(index: page, animated: true) this should fix the issues.

Good luck!

alan-d-haller commented 7 years ago

Thank you very much for your courteous guide again! I misunderstood the place where I had to add the method.

Thanks to your guide, now the all functions of the pod gets to work normally in my project.

Firstly, I added overlay?.contentControl.addTarget(self, action: #selector(didTapPageControl), for: .allTouchEvents) in swiftyOnboardViewForOverlay method in ViewController.swift.

Secondly, I added the method func didTapPageControl(_ sender: Any) { let contentControl = sender as! UIPageControl let page = contentControl.currentPage swiftyOnboard.goToPage(index: page, animated: true) }.

Then Xcode instructed me to add @objc in the front of didTapPageControl method.

After that, build succeeded and finally the page control got to work perfectly.

Anyway, I really appreciate your repeated support. I will make the most of your pod for my project.

Muchas gracias!

juanpablofernandez commented 7 years ago

I'm glad everything is now working. Happy Coding!