I subclassed FUIAuthPickerViewController in order to add a background image (UIImageView) behind the Google / FB sign-in buttons but I can't get it to display. This started happening after updating Firebase pods to the latest version (was working fine on the previous versions). See Details section for info.
Issue description, code snippets, pod & sdk versions & screenshots on StackOverflow, since I initially didn't think it could be a bug.
If you print out the view hierarchy of the auth picker controller's view, what does it look like?
Background seems to be hiding in the back, behind a scrollview(?);


Ah, that sounds like it was introduced in https://github.com/firebase/FirebaseUI-iOS/pull/590. We can fix this by exposing the scroll view publicly so subclasses can add and remove subviews as they desire.
Sounds good! Will this come out in the next release?
If you are creating a subview and inserting it, you can also insert it at 1 instead of 0 which is a temporary fix until the scrollview is explicitly exposed.
view.insertSubview(subview, at: 1) }
Tried that; I can see the background but not the sign in buttons. See my SO link for a screenshot.
Sorry, my use case was slightly different. I think if you do view.subviews[0].insertSubview(subview, at: 0), that should work. I also needed to set the background to clear as well for the UI View that houses the auth buttons.
let selectorView = view.subviews[0].subviews[0]
selectorView.backgroundColor = UIColor.clear
Before:

After:

Thank you, this actually works as a temp fix;
self.view.subviews[0].subviews[0].backgroundColor = UIColor.clear
self.view.subviews[0].insertSubview(imgView, at: 0)
The top area of the scrollbarview is still visible though.
Any thoughts? I initially thought it was the status bar.



@polis80cy The new auth picker selector has a scrollview while previous version doesn't. The scrollview is added because some apps cannot display all their sign in options (such as horizontal mode). We added the scroll view with backward compatibility in mind, and should be able to make most of developers' custom views work. But in case a developer is doing something we didn't expect (such as utilizing some internal behaviors of our previous code), it may cause layout issues.
In your case, as far as I understand, you're trying to make a custom view with a background image. I believe you are fully able to do that with the new version. In our sample app, we have a FUICustomAuthPickerViewController (and you can test that by using the Demo app, and turn "Custom Authorization UI" switch on in the setting section). That view has a "knobColor" background.
To do add an image background manually, you can add the following code to the custom class (I closely mimics your swift code):
@implementation FUICustomAuthPickerViewController {
UIView * _backgroundView;
}
- (void)viewDidLoad {
[super viewDidLoad];
_backgroundView = [[UIView alloc] initWithFrame:CGRectZero];
_backgroundView.layer.contents = (id)[UIImage imageNamed:@"img.png"].CGImage;
[self.view insertSubview:_backgroundView atIndex:0];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
_backgroundView.frame = self.view.bounds;
}
I just tested and it correctly renders the image as the custom background.

Perhaps your custom xib file is different and use some assumptions from the previous version, but with the vanilla xib file from the sample app, and the above ObjC code, I don't see any issue with the layout.
@Yue-Wang-Google I tried that and it still doesn't work I'm afraid.
This is on the latest version and all I'm doing is subclassing FUIAuthPickerViewController as per the readme file on GH. I'm not utilizing anything from previous codebase versions.
It's in Swift, no custom xib files.
Trying your suggestion:
class AuthViewController: FUIAuthPickerViewController {
var backgView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let backgroundImage = #imageLiteral(resourceName: "MainBackground")
backgView = UIView(frame: CGRect.zero)
backgView.layer.contents = backgroundImage.cgImage
self.view.insertSubview(backgView, at: 0)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
backgView.frame = self.view.bounds
}
}
And this is my delegate (which triggers the above class to fire) in AppDelegate.swift:
func authPickerViewController(forAuthUI authUI: FUIAuth) -> FUIAuthPickerViewController {
return AuthViewController(authUI: authUI)
}
The result:

Trying the little hack as suggested by @cwoolum works but leaves that top grey scrollbar area visible as you can see from the screenshots in my previous comment. This is how:
class AuthViewController: FUIAuthPickerViewController {
var imgView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let backgroundImage = #imageLiteral(resourceName: "MainBackground")
imgView = UIImageView(image: backgroundImage)
imgView.contentMode = .scaleAspectFill
self.view.subviews[0].subviews[0].backgroundColor = UIColor.clear
self.view.subviews[0].insertSubview(imgView, at: 0)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
imgView.frame = self.view.bounds
}
}
And this is the result (you can see the grey top part):

If there's a way to get rid of that grey top part (I've added some screenshots about that in my previous comment), I can definitely live with this. That's all I need at this point.
@polis80cy please try the samples in /samples/objc/FirebaseUI-demo-objc/Samples/Auth/FUICustomAuthPickerViewController.{xib,h,m}. They should work well.
I tried the sample code with the latest FirebaseUI (6.2.1), without custom .xib file:
@implementation FUICustomAuthPickerViewController {
UIView * _backgroundView;
}
- (void)viewDidLoad {
[super viewDidLoad];
_backgroundView = [[UIView alloc] initWithFrame:CGRectZero];
_backgroundView.layer.contents = (id)[UIImage imageNamed:@"img.png"].CGImage;
[self.view insertSubview:_backgroundView atIndex:0];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
_backgroundView.frame = self.view.bounds;
}
And still does not work. The _backgroundView is behind the _scrollView.
@polis80cy try this workaround:
override func viewDidLoad() {
super.viewDidLoad()
let scrollView = view.subviews[0]
scrollView.backgroundColor = .clear
let contentView = scrollView.subviews[0]
contentView.backgroundColor = .clear
let background = UIImage(named: "image")
backgroundImageView = UIImageView(image: background)
backgroundImageView.contentMode = .scaleToFill
view.insertSubview(backgroundImageView, at: 0)
}
And set backgroundImageView's constraints to the superview's edges. It worked in my case.
@zhanetpaneva this works beautifully, thank you!
@polis80cy try this workaround:
override func viewDidLoad() { super.viewDidLoad() let scrollView = view.subviews[0] scrollView.backgroundColor = .clear let contentView = scrollView.subviews[0] contentView.backgroundColor = .clear let background = UIImage(named: "image") backgroundImageView = UIImageView(image: background) backgroundImageView.contentMode = .scaleToFill view.insertSubview(backgroundImageView, at: 0) }And set backgroundImageView's constraints to the superview's edges. It worked in my case.
this caused error for me when cancling on email authui screen
Does anyone know how to make it full screen?
Even If I try to make the Nav Transparent the image doesn't cover the UIScreen.main.bounds.height of the screen, making it cut at the navBar.
I got this:
at LoginVC
/// Delegate function that allows us to create a custom FUIAuthPickerViewController
///
/// - Parameter authUI: FUIAuth instance
/// - Returns: The custom FUIAuthPickerViewController
func authPickerViewController(forAuthUI authUI: FUIAuth) -> FUIAuthPickerViewController {
// Create an instance of the FirebaseAuth login view controller
let customLoginViewController = FUIAuthPickerViewController(authUI: authUI)
customLoginViewController.navigationItem.leftBarButtonItem = nil
// Use the previous values to build a CGRect for the drawable's view's frame
let drawableFrame = CGRect(x: self.view.frame.origin.x, y: self.view.frame.origin.y, width: self.view.frame.width, height: UIScreen.main.bounds.height)
let drawableImageView = UIImageView(frame: drawableFrame)
drawableImageView.image = UIImage(named: "Logging")
drawableImageView.contentMode = .scaleAspectFill
customLoginViewController.view.subviews[0].subviews[0].backgroundColor = UIColor.clear
customLoginViewController.view.subviews[0].insertSubview(drawableImageView, at: 0)
return customLoginViewController
}
This at AppDelegate:
didFinishLaunchingWithOptions.... {
window?.rootViewController = LoginViewController()
// Remove the bottom line for the UINavigationBar
UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
//Clear NavBar for a fullscreen ImageView
UINavigationBar.appearance().isTranslucent = true
}


How I disable the scrolling or the bounce? how can I remove the navBar title?
I have tried this code
/// Delegate function that allows us to create a custom FUIAuthPickerViewController
///
/// - Parameter authUI: FUIAuth instance
/// - Returns: The custom FUIAuthPickerViewController
func authPickerViewController(forAuthUI authUI: FUIAuth) -> FUIAuthPickerViewController {
// Create an instance of the FirebaseAuth login view controller
let customLoginVC = FUIAuthPickerViewController(authUI: authUI)
customLoginVC.navigationItem.leftBarButtonItem = nil
customLoginVC.navigationController?.isToolbarHidden = true
customLoginVC.navigationController?.isNavigationBarHidden = true
//Original Frame
let drawableFrame = CGRect(x: 0, y: -44, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
let drawableImageView = UIImageView(frame: drawableFrame)
drawableImageView.image = UIImage(named: "pdf2")
drawableImageView.contentMode = .scaleAspectFill
//vc
customLoginVC.view.subviews[0].subviews[0].backgroundColor = UIColor.clear
customLoginVC.view.subviews[0].insertSubview(drawableImageView, at: 0)
customLoginVC.view.backgroundColor = .black
let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView
statusBar?.backgroundColor = UIColor.clear
return customLoginVC
}
Unfortunately, toolBar is not hidden, navBar is not hidding or setting it's text even if I set another title e.g. navBar.title = "hi" or even nil. background also doesn't change and it is white.
The unique thing that I'm able to modify is the back button which I'm already setting in up as nil and it works but the remaning code it is just like ignoring it... any thoughts? I'm all ears.
Most helpful comment
@polis80cy try this workaround:
And set backgroundImageView's constraints to the superview's edges. It worked in my case.