1

I am building an authentication system using the Firebase prebuilt UI, and I want to customize the UI to fit the program. Say I want to set the background color to black and change the corner radius of the buttons, is there any way I can do this? I've tried sub-classing the authPickerViewController but somehow it didn't work. I did some searching, but couldn't find any tutorial or recent problems related to this either.

Here's what I have in my MainViewController

class LoginViewController: UIViewController, FUIAuthDelegate{

  override func viewDidLoad() {
    super.viewDidLoad()

    let authUI = FUIAuth.defaultAuthUI()
    authUI?.delegate = self
    let providers: [FUIAuthProvider] = [
      FUIEmailAuth(),
      FUIGoogleAuth(),
      FUIPhoneAuth(authUI:FUIAuth.defaultAuthUI()!)]
    authUI?.providers = providers

    let authViewController = authUI?.authViewController()
    authViewController!.modalPresentationStyle = .fullScreen
    authViewController!.setNavigationBarHidden(true, animated: false)

    self.present(authViewController!, animated: false, completion: nil)
  }

  func application(_ app: UIApplication, open url: URL,
    options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool {
    let sourceApplication = options[UIApplicationOpenURLOptionsKey.sourceApplication]
    if FUIAuth.defaultAuthUI()?.handleOpen(url, sourceApplication: sourceApplication as? String) ?? false {
      return true
    }
    return false
  }
}

And here is the subclass I created:

class FUICustomAuthPickerViewController: FUIAuthPickerViewController,FUIAuthDelegate {

  override func viewDidLoad() {
    super.viewDidLoad()

    self.view.backgroundColor = .black
  }

  func authPickerViewController(forAuthUI authUI: FUIAuth) -> FUIAuthPickerViewController {
    return FUICustomAuthPickerViewController(nibName: "FUICustomAuthPickerViewController",
      bundle: Bundle.main,
      authUI: authUI)
  }
}

On the Firebase documentation for customization, they say that:

You can customize the sign-in screens by subclassing FirebaseUI's view controllers and specifying them in FUIAuth's delegate methods.

I am a beginner, how can I do that?

Edited:

So by following the instructions on this link I managed to add stuff to the pre-built UI by creating an extension to the FUIAuthDelegate.

extension LoginViewController:FUIAuthDelegate {
  func application(_ app: UIApplication, open url: URL,
    options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool {
    let sourceApplication = options[UIApplicationOpenURLOptionsKey.sourceApplication]
    if FUIAuth.defaultAuthUI()?.handleOpen(url, sourceApplication: sourceApplication as? String) ?? false {
      return true
    }
    return false
  }

  func authPickerViewController(forAuthUI authUI: FUIAuth) -> FUIAuthPickerViewController {
    let vc = FUIAuthPickerViewController(authUI: authUI)

    let view = UIView(frame: .zero)
    view.backgroundColor = .black
    view.translatesAutoresizingMaskIntoConstraints = false
    vc.view.addSubview(view)

    NSLayoutConstraint.activate([
      view.heightAnchor.constraint(equalTo: vc.view.heightAnchor, multiplier: 1),
      view.widthAnchor.constraint(equalTo: vc.view.widthAnchor, multiplier: 1)])

    return vc
  }
}

Turns out subclass is not necessarily needed. However, I can't seem to make this view I created to be the background, it either covers everything or nothing at all.I tried changing the background color of the view directly, didn't work. Anyone knows how to do this?

Peter Friese
  • 6,709
  • 31
  • 43
Timmy Mi
  • 33
  • 7
  • Please read [Under what circumstances may I add “urgent” or other similar phrases to my question, in order to obtain faster answers?](//meta.stackoverflow.com/q/326569) - the summary is that this is not an ideal way to address volunteers, and is probably counterproductive to obtaining answers. Please refrain from adding this to your questions. – halfer Jun 11 '20 at 21:33
  • @halfer Yes Sir! Noted with thanks. – Timmy Mi Jun 12 '20 at 05:07
  • @TimmyMi - check out the FirebaseUI-iOS repo for a complete sample that shows how to customise the different view controllers: https://github.com/firebase/FirebaseUI-iOS/tree/master/samples/swift/FirebaseUI-demo-swift/Samples/Auth. Also, I was wondering if you wanted to actually use `black` as the background color, or rather support light mode / dark mode - can you comment? – Peter Friese Jun 12 '20 at 07:57
  • @PeterFriese I was using black as an example here, so no worries about that. Anyway, thanks for the repo, I’ll check it out and get back to you. – Timmy Mi Jun 12 '20 at 09:06
  • @PeterFriese do you mind explaining in more detail? How do I implement this in my project? Thanks a lot! – Timmy Mi Jun 12 '20 at 12:20
  • Happy to explain, but I need more context. What exactly are you trying to achieve? Change the background colour, add a logo,...? Which authentication providers do you want to use? – Peter Friese Jun 12 '20 at 12:35
  • @peter Apart from what you mentioned, I would also like to add another button which allows the user to skip the log in process. I am using email, google, and phone number authentication. Later, I might need to customize the email sign-in and phone verification view as well, but they are not my concern just yet. After signing in with any method, the user should be navigated to a specific view controller. – Timmy Mi Jun 12 '20 at 12:55
  • @peter do I need to use both the xib and the subclass? – Timmy Mi Jun 12 '20 at 15:18
  • That's right - that's one way to do it. You can also try the solution suggested in this discussion over at Github: https://github.com/firebase/FirebaseUI-iOS/issues/628#issuecomment-479530155 - essentially, you find the scrollview in the `FUIAuthPickerViewController`, and customize it. – Peter Friese Jun 12 '20 at 15:39
  • @peter thanks for the help, I solved the problem and posted the answer below. The information you provided was useful :D – Timmy Mi Jun 12 '20 at 21:05

1 Answers1

2

Solved the problem using the method and one of the comments provided in this link. Turns out, apart from subclassing, you have to add the following two methods to your subclass for it to work.

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?, authUI: FUIAuth?) {
        super.init(nibName: nil, bundle: Bundle.main, authUI: authUI!)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

However, the approach I used (not sure if other approaches raise the same problem) also caused another problem - the email sign-in button stopped responding - which is addressed in this link by presenting the view controller with a navigationViewController because the email sign-in button works together with the navigation bar, you can get rid of it once you have presented the view with a navigationViewController.

Now the complete subclass looks like this:

import UIKit
import FirebaseUI

class FUICustomAuthPickerViewController: FUIAuthPickerViewController {

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?, authUI: FUIAuth?) {
        super.init(nibName: nil, bundle: Bundle.main, authUI: authUI!)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let width = UIScreen.main.bounds.size.width
        let height = UIScreen.main.bounds.size.height

        let imageViewBackground = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
        imageViewBackground.backgroundColor = .eatstrOrange

        view.insertSubview(imageViewBackground, at: 0)
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.setNavigationBarHidden(true, animated: animated)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.setNavigationBarHidden(false, animated: animated)
    }
}

And here's the main view controller:

import UIKit
import FirebaseUI

class LoginViewController: UIViewController{

    override func viewDidLoad() {
        super.viewDidLoad()

        let authUI = FUIAuth.defaultAuthUI()
        let delegate = authUI?.delegate
        authUI?.delegate = delegate
        let providers: [FUIAuthProvider] = [
          FUIGoogleAuth(),
          FUIEmailAuth(),
          FUIPhoneAuth(authUI:FUIAuth.defaultAuthUI()!)]
        authUI?.providers = providers

        let authViewController = FUICustomAuthPickerViewController(authUI: authUI!)
        authViewController.modalPresentationStyle = .fullScreen
        navigationController?.pushViewController(authViewController, animated: false)
    }
}

Final outcome

Timmy Mi
  • 33
  • 7