Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Allow fully customized XML layouts for the AuthMethodPickerActivity #1477

Closed
samtstern opened this issue Oct 9, 2018 · 27 comments
Closed

Comments

@samtstern
Copy link
Contributor

Proposal

Allow developers to pass their own XML resource for the main login screen:

AuthUI.getInstance().createSignInIntentBuilder()
    // ...
    .setTheme(...)
    .setMainLayout(R.xml.my_custom_layout) // If not provided, default used
    .build()

We would define an implicit public API specifying which resource IDs need to be present in that XML screen in order for us to add controls to it, such as:

  • A ViewGroup for us to add the sign-in provider buttons
  • A TextView for the Terms of Service and Privacy Policy disclosure
  • A ProgressBar to show loading operations
  • An option to use your own sign-in buttons and just let us add click listeners.

Note that this proposal only affects the first screen. The rest would still be governed by the setTheme() attribute. There are too many other screens, and their functionality is too complex, to allow for full user customization of every one.

Rationale

We have gotten many requests to be able to customize the main UI more such as:
#1383, #753, #619, #266, #236, #229

When looking at popular Android apps, the sign-in method selection screen is often a showcase for the brand and the UI varies from app to app. There's no way to add more "options" to our system to encompass all use cases.

Here are some examples of screens from other apps that I like and would like to enable. While we can't enable every single feature shown in these screenshots, we can at least allow developers to get most of the way there and create an immersive look and feel without writing anything besides XML.




cc @bojeil-google @morganchen12 @lsirac @SUPERCILEX

@SUPERCILEX
Copy link
Collaborator

I think you're right. The main issue I see is that all those screenshots have data which would probably be downloaded dynamically. If we really wanted to support as many use cases as possible, we'd probably have to create a service which gives devs access to the view hierarchy so they can do animations, dynamic stuff, whatever. I'm using a service for the full account linking PR and I've been wanting to do something similar for the email sign-up page to allow custom field add/removal and validation.

In any case, this seems like a step in the right direction to me. 👍

@cutiko
Copy link

cutiko commented Oct 12, 2018

Greetings

I think this is a great improvement, is what I would expect as customization. I would like to suggest something about this:

which resource IDs need to be present in that XML

That seems prone to human error, a formal structure that represents the layout could be useful:

public class AuthLayout {
       @LayoutRes
        private int layout;
        @IdRes
        private int facebookBtn, googleBtn, emailBtn;
        //Constructors, getters and setters...
}

This way we have to only be careful to have one id for each provider

@dimipaun
Copy link
Contributor

In addition to this, we should export the building blocks of this screen so that users can easily recreate it -- this would solve all these problems and more!

For example, we want to add additional login buttons (e.g. Login with XYZ) which is basically impossible to do right now as the building blocks of this page are not public.

@samtstern
Copy link
Contributor Author

@cutiko that's a good idea! It would avoid having XML as an implicit API and use something more explicit.

@dimipaun we'd love to do something like that but right now it's really hard because we're managing a whole stack of Activities. Without owning the root activity, there are some things we can't do. It may be possible to define an interface so that anyone could make their own root activity, but that's a non-goal right now.

@samtstern
Copy link
Contributor Author

@iamyaoxi has started working on this using the suggestions of everyone here.

@yos1p
Copy link
Contributor

yos1p commented Oct 22, 2018

Yes! And thanks everyone for those great ideas! And if possible, please review the PR and give your opinion on it.

@samtstern
Copy link
Contributor Author

Just merged the initial implementation for this by @iamyaoxi, so this should be ready to go for 4.3.0

@cutiko
Copy link

cutiko commented Nov 15, 2018

Greetings

I have a doubt, what if someone does something like this:

 <FrameLayout>

     <Button
        text="Facebook"/>

    <fragment
      id="coolFragment"
      name="com.package.project.CoolFragment"/>

</FrameLayout>

We can pass a Fragment and then in onActivityCreated access to whatever we want. I can think of plenty cool things I would like to do, but, can this create a conflict in anyhow?

@samtstern
Copy link
Contributor Author

@cutiko that's actually a pretty interesting idea! There's nothing that will break right away (that I can think of off the top of my head), however we're not going to make any guarantees about the Activity lifecycle or what other Fragments may be present so make sure to do a lot of testing if you go down that road.

@cutiko
Copy link

cutiko commented Nov 20, 2018

Greetings

I'm working on this basing my self on this.

  • Builder seems intuitive
  • I wouldn't mind about highlighting the mismatch between providers, the log seems fairly obvious

I'm having some problems as well:

  • If smart lock is not disable .setIsSmartLockEnabled(false) then the Google account chooser dialog is showed before seen the kickoff activity
  • if there is only Email sign-in method, then the kickoff activity is skipped, going directly to the specific method activity
  • If only Google is available and the smart lock is disabled, then nothing happens

@samtstern
Copy link
Contributor Author

@cutiko thanks for trying this! Are you using the 4.3.0-SNAPSHOT builds?

If smart lock is not disable .setIsSmartLockEnabled(false) then the Google account chooser dialog is showed before seen the kickoff activity

Are you sure that's the Google account picker and not just the SmartLock hint selector? They look very very similar. Screenshot would help.

if there is only Email sign-in method, then the kickoff activity is skipped, going directly to the specific method activity

This is intended behavior. If you want to always show the sign-in screen, call setAlwaysShowSignInMethodScreen(true) on the builder.

If only Google is available and the smart lock is disabled, then nothing happens

Is there anything in the logs here? This sounds like a bug!

@cutiko
Copy link

cutiko commented Nov 20, 2018

repositories {
    maven { url "https://oss.jfrog.org/artifactory/oss-snapshot-local" }
}

dependencies {
    ...
    implementation 'com.firebaseui:firebase-ui-auth:4.3.0-SNAPSHOT'
    ...
}

Screenshot as requested
SCREENSHOT

Video can be seen here

Ok, that fixes a lot, sorry was not aware of the method.

Couldn't find anything relevant on the logs this is the current repo branch

@samtstern
Copy link
Contributor Author

@cutiko glad that helped! I will look into the thing about SmartLock exiting, that's a bug.

@samtstern
Copy link
Contributor Author

@cutiko hmm once I dismiss the SmartLock dialog I get this (the Google sign in dialog):
screen shot 2018-11-20 at 4 31 21 pm

So I am a little stuck on how to reproduce your error. But I will keep trying!

@cutiko
Copy link

cutiko commented Nov 20, 2018

@samtstern can you take a look at this file found something on the logcat is commented there.

Google is enabled on the console, SHA is set on the project settings...

I think I found something else:

  • If the account is created the problem is presented only sometimes :/
  • If the account is created and .setAlwaysShowSignInMethodScreen(true) closing smart-lock move to the next activity
  • If the account is not created closing smart-lock prompt the account selector
  • If the account is not created and .setAlwaysShowSignInMethodScreen(true) closing smart-lock move to the next activity

I'm confused, I was able to reproduce the error, then deleting the account and trying to reproducing it again and I can't.

I'm afraid it could be me doing something wrong, but someone else on SO had the same problem

@cutiko
Copy link

cutiko commented Nov 21, 2018

I think is working, you can see the first version of the demo here

SEE VIDEO

In case anyone wants to take a look more closely, this is the repo

For the moment I want to make a dirty demo just trying to push the layout customization to the max. I'm planning to clean up the code and add some others later, I want to see what happens with a service binding and more than one fragment and using broadcast. All of that should end up being a juicy example of how far this new release can be pushed.

In my regards, I only have kind words to everyone who works on this project, this next release is going to completely blow everyone mind Thanks everybody this is awesome

@samtstern
Copy link
Contributor Author

@cutiko that's so cool! I am gonna share that with the whole team. And hopefully we can get to the bottom of your SmartLock/Google issues.

@samtstern
Copy link
Contributor Author

This has been released in version 4.3.0.

@sipersso
Copy link

@samtstern Is it possible to have a separate theme for the AuthMethodPickerActivity and the rest of the screens. I am using the customization, which is great, but I don't want the toolbar och the AuthMethodPicker. If I remove it using the them, it will also remove the toolbar from all other activities, like the email sign in flow, where the toolbars are actually useful.

Is there any way to achieve this?

@samtstern
Copy link
Contributor Author

@sipersso there's no way to do this right now but you may be able to do this in a hacky way.

Use the custom layout to put an invisible <fragment> into the custom UI. Then inside the Fragment do something like getSupportActionBar().hide() and make the toolbar disappear at runtime.

@sipersso
Copy link

@samtstern thank you! As you said, very hacky, but I think it might work. I'll give that a try.

@sipersso
Copy link

@samtstern works perfectly. Thank you!

@nathanvogel
Copy link

Hacky but works :) Here's the full code for the lazy ones like me:

class DisableActionBarFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.empty, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        activity?.actionBar?.hide()
        (activity as? AppCompatActivity)?.supportActionBar?.hide()
    }
}

@thestch
Copy link

thestch commented Mar 10, 2020

@samtstern Hi, is it possible to register listeners into the UI elements of the layout used by AuthMethodPickerLayout? The reason is that while I'm using a custom layout, I would also need to register listeners to EditText etc. to get other user details such as their name, instead of launching a new activity to let them enter it.

@samtstern
Copy link
Contributor Author

samtstern commented Mar 10, 2020 via email

@cutiko
Copy link

cutiko commented Mar 10, 2020

@thestch take a look at this you might find a hack arround
https://github.com/cutiko/FirebaseUiAuth
Is old but worth the try

@mangeshghotage
Copy link

mangeshghotage commented Apr 24, 2020

I am trying to create a UI similar to what is shown in the last screenshot (TikTok) by OP. In my case FirebaseUI is not showing transparent background. How to achieve such UI having transparent background?
PS: Here is my detailed SO post

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants