6

I'd like to be able to place a background image behind the three sign-in buttons (for Google, Facebook, and Email) of the FirebaseUI login screen. FirebaseUI login is a drop-in authentication solution for iOS, Android, and Web. I'm having trouble with iOS.

There's a little bit of advice on Github, but not enough.

I first initialize my var customAuthPickerViewController : FIRAuthPickerViewController! near the top of the ViewController.swift file.

Then, this is the function in my ViewController.swift file, but it's not working. When I click the logout button, the app crashes, and no background image is ever shown.

// Customize the sign-in screen to have the Bizzy Books icon/background image

func authPickerViewController(for authUI: FIRAuthUI) -> FIRAuthPickerViewController {

    customAuthPickerViewController = authPickerViewController(for: authUI)
    backgroundImage = UIImageView(image: UIImage(named: "bizzybooksbee"))
    backgroundImage.contentMode = UIViewContentMode.scaleAspectFill
    customAuthPickerViewController.view.addSubview(backgroundImage)

    return customAuthPickerViewController
}

The background image "bizzybooksbee" is a Universal Image Set with 1x, 2x, and 3x images already loaded in my Assets.xcassets folder.

Here's a picture of what the login screen looks like without trying to implement the background image.

enter image description here

UPDATE: I'm able to get the image to show, with the code I gave in the comments below, but it shows OVER the sign-in buttons, as in the pic below.

enter image description here

Here's an image of the "heirarchy," with Jeffrey's help:

enter image description here

Brad Caldwell
  • 344
  • 2
  • 14
  • I've successfully added an image, but the image is now on top of the buttons, so now my question is, how do I get the image behind the buttons. – Brad Caldwell Oct 10 '16 at 17:08
  • What I did to get the image to show is detailed in my refined query [here](https://thenewboston.com/forum/topic.php?id=12907). Instead of having the func authPickerViewController stuff, I simply added the following lines to my login() function before presenting the authViewController: – Brad Caldwell Oct 10 '16 at 17:11
  • `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.image = UIImage(named: "bizzybooksbee") // you can change the content mode: imageViewBackground.contentMode = UIViewContentMode.scaleAspectFill authViewController?.view.insertSubview(imageViewBackground, at: 1)` – Brad Caldwell Oct 10 '16 at 17:11
  • Did you try inserting the imageView at: 0? authViewController?.view.insertSubview(imageViewBackground, at: 0) – Jeffrey Bergier Oct 11 '16 at 01:06
  • @JeffreyBergier Yes, I did that, and then the image gets hid behind the UITableView (so I am told) - at least you can't see the image when it's at position 0. Thanks for the attempt, though! – Brad Caldwell Oct 11 '16 at 01:07
  • Aw dang. If its a table view then that could get complicated. You can set the backgroundColor of the tableview itself to clearColor. But if the cells have their own backgroundColor, that won't help. Have you tried using Xcode view debugger to see how many cells are in the table? They might have build the screen so there are 4 cells. 3 are the 3 buttons and 1 is a big gray cell. You might be able to grab the contentView of that cell and insert your image view there. – Jeffrey Bergier Oct 11 '16 at 01:11
  • @JeffreyBergier Thanks! Let me give that a try. I am told there's a UITableView, but like I said, I really don't know. Let me try the debugger thing. – Brad Caldwell Oct 11 '16 at 01:14
  • You could also use an image that fits in the top section and is transparent on the bottom (so it doesn't cover the buttons) and then set .userInteractionEnabled to false so that it doesn't block touch events and they still go to the buttons. Its super hacky, but it might work. – Jeffrey Bergier Oct 11 '16 at 01:15
  • ah! I think I know the problem. The authViewController is actually a UINavigationController. This is quite common. What you need to do is cast it as a UINavigationController and then ask for its rootViewController and insert your image view in the rootViewController. So that looks like..... let navVC = authViewController as? UINavigationController; let rootVC = navVC?.rootViewController; rootVC?.view.insertSubview(imageView, at: 0); – Jeffrey Bergier Oct 11 '16 at 16:16
  • @JeffreyBergier I think you were headed in the right direction! I got some help, answered the Q below, and made a YouTube vid: https://youtu.be/d_byFfP3cTw Thanks! – Brad Caldwell Oct 11 '16 at 16:40

1 Answers1

9

Here's the solution!

Remove the junk that doesn't work from ViewController.swift:

func authPickerViewController(for authUI: FIRAuthUI) -> FIRAuthPickerViewController {

    customAuthPickerViewController = authPickerViewController(for: authUI)
    backgroundImage = UIImageView(image: UIImage(named: "bizzybooksbee"))
    backgroundImage.contentMode = UIViewContentMode.scaleAspectFill
    customAuthPickerViewController.view.addSubview(backgroundImage)

    return customAuthPickerViewController   
}

Create a .swift "subclass" of FIRAuthPickerViewController that you can name anything, and add your background image/customization there:

import UIKit
import FirebaseAuthUI

class BizzyAuthViewController: FIRAuthPickerViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        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.image = UIImage(named: "bizzybooksbee")

        // you can change the content mode:
        imageViewBackground.contentMode = UIViewContentMode.scaleAspectFill

        view.insertSubview(imageViewBackground, at: 0)
    }}

In your ViewController.swift (or whatever you call it), in the section where you login, change authViewController to equal your new subclass, add a line for the navigation controller, and pass it into the self.present:

let authViewController = BizzyAuthViewController(authUI: authUI!)

let navc = UINavigationController(rootViewController: authViewController)

self.present(navc, animated: true, completion: nil)

I also made a YouTube tutorial which shows how to do this in depth.

Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
Brad Caldwell
  • 344
  • 2
  • 14
  • Do you by any chance know how to change background image of email screen? It uses UITableView so just change background image is not enough. – Vitalii Ivanov Apr 19 '17 at 23:58
  • I think the email screen might be a little harder to do. I'd check in at code mentor i o website. – Brad Caldwell May 06 '17 at 19:05
  • @Brad Caldwell Hi I can see that you solved an issue similar / complementary to mine, can you have a look to it and tell me if you see what's wrong? Thank you! – Alex9494 Sep 06 '17 at 10:51
  • 1
    it is not working for the "func emailEntryViewController(forAuthUI authUI: FUIAuth) -> FUIEmailEntryViewController {". Is there any way to implement it – Sultan Ali Dec 10 '17 at 17:02
  • I get the error `Could not load NIB in bundle: NSBundle [...] with name [app name].[custom class name]` just by setting the custom view controller in their delegate. – sudo Oct 25 '18 at 04:53
  • 1
    You may have to also do this: override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?, authUI: FUIAuth?) { super.init(nibName: nil, bundle: Bundle.main, authUI: authUI!) } – sudo Oct 25 '18 at 04:58
  • 3
    As per latest Firebase UI version (5.x), one should subclass FUIAuthPickerViewController and not FIRAuthPickerViewController – Vineel Dec 25 '18 at 09:21