Firebase UI for Flutter

repository·main·Indexed 41 days ago

https://github.com/firebase/firebaseui-flutter

A suite of specialized plugins providing ready-made UI components to rapidly integrate Firebase services into Flutter applications. Includes firebase_ui_auth for authentication flows (Email, Phone, OAuth), as well as plugins for Firestore, Realtime Database, and Storage. Features pre-built widgets like SignInScreen and ProfileScreen, and support for multiple languages via the firebase_ui_localizations package.

Tokens
40K
Snippets
102
Records
143
Agent score
100%

What's inside Firebase UI for Flutter

  1. Overview of Firebase UI for Flutter plugins

    main
    Firebase UI for Flutter is a collection of plugins designed to quickly connect common Flutter UI elements to Firebase APIs. Instead of building complex authentication, database, or storage interfaces from scratch, you can use these specialized plugins to implement standard Firebase features with pre-built UI components.
  2. Explore Firebase UI for Flutter plugins

    main

    Firebase UI for Flutter provides a collection of specialized plugins to simplify common Firebase integrations. The available plugins include:

    Firebase UI Auth

    Provides pre-built authentication flows and UI components. Supported authentication methods include:

    • Email: Standard email/password authentication.
    • Email link: Passwordless authentication via email links.
    • Universal Email Sign In: Simplified email-based sign-in.
    • Phone: SMS-based phone number authentication.
    • OAuth: Social authentication providers (e.g., Google, Facebook).
    • Email verification: Flows for verifying user email addresses.
    • Navigation & Theming: Customization options for auth flow navigation and visual styles.

    Firebase UI Database

    Provides UI components and integrations for Firebase database services.

    Firebase UI Storage

    Provides UI components and integrations for Firebase Storage services.

  3. Use Firebase UI OAuth providers

    main

    The firebase_ui_oauth package serves as the base package for various Firebase UI OAuth provider plugins. To implement specific OAuth authentication flows, you must install the specific provider package required for your target service:

    • Apple Sign In: firebase_ui_oauth_apple
    • Google Sign In: firebase_ui_oauth_google
    • Facebook Sign In: firebase_ui_oauth_facebook
    • Twitter Sign In: firebase_ui_oauth_twitter
  4. Customize the loading state of StorageImage

    main

    The StorageImage widget allows you to define different visual behaviors while the image is being fetched from Firebase Storage using the loadingState property.

    Available variants via LoadingStateVariant include:

    • solidColor: Displays a solid color placeholder (default).
    • loadingIndicator: Displays a progress indicator (CircularProgressIndicator for Material or CupertinoActivityIndicator for Cupertino).
    • shimmer: Displays a shimmering animation over a solid color.
    • blurHash: Displays a blurred version of the image using a BlurHash string.
    StorageImage(
      ref: FirebaseStorage.instance.ref('images/dash_and_sparky.png'),
      fit: BoxFit.cover,
      loadingState: LoadingStateVariant.solidColor(), // Example variant
    );
  5. How navigation works in Firebase UI

    main

    Firebase UI uses standard Flutter navigation by default, specifically using Navigator 1.0 (e.g., Navigator.push(context, route)).

    • Standard Apps: If your application uses standard Flutter navigation APIs, Firebase UI works out of the box without configuration.
    • Custom Routing Apps: If you use a custom routing package or named routes, you must override the default navigation actions using the actions property on Firebase UI widgets to integrate with your routing strategy.
  6. PaginatedLoadingController states

    main

    The PaginatedLoadingController uses a state object to communicate the current status of the data fetch. You can use a switch expression on ctrl.state to render different UI components:

    • InitialPageLoading: The very first request for the first page is in progress.
    • PageLoading: A subsequent page is being fetched.
    • PageLoadError: An error occurred during fetching. The error details are available via the error property.
    • PageLoadComplete: Data has been successfully loaded. The loaded items are available via the items property.
  7. Advanced configuration with FirestoreQueryBuilder

    main

    If you need more control than FirestoreListView provides (for example, using a GridView instead of a ListView), use FirestoreQueryBuilder.

    Unlike FirestoreListView, FirestoreQueryBuilder does not provide a built-in list implementation. Instead, its builder returns a QueryBuilderSnapshot which represents the entire state of the query. You are responsible for:

    1. Handling loading states via snapshot.isFetching.
    2. Handling error states via snapshot.hasError.
    3. Implementing the UI (e.g., GridView.builder).
    4. Manually triggering more data fetches by calling snapshot.fetchMore() when the user reaches the end of the current list and snapshot.hasMore is true.
    FirestoreQueryBuilder<Map<String, dynamic>>(
      query: usersQuery,
      builder: (context, snapshot, _) {
        if (snapshot.isFetching) {
          return const CircularProgressIndicator();
        }
    
        if (snapshot.hasError) {
          return Text('Something went wrong! ${snapshot.error}');
        }
    
        return GridView.builder(
          itemCount: snapshot.docs.length,
          itemBuilder: (context, index) {
            // Manual infinite scroll trigger
            if (snapshot.hasMore && index + 1 == snapshot.docs.length) {
              snapshot.fetchMore();
            }
    
            final user = snapshot.docs[index].data();
            return Text(user['name']);
          },
        );
      },
    );
  8. Theme Firebase UI widgets using MaterialApp or CupertinoApp

    main

    Firebase UI widgets are built on top of Flutter's Material and Cupertino design patterns. They do not have their own independent styling system; instead, they inherit their appearance from the ThemeData (for MaterialApp) or CupertinoThemeData (for CupertinoApp) provided in your application's root widget.

    For example, a SignInScreen using an EmailAuthProvider will automatically use standard Material widgets like TextFormField, TextButton, and OutlinedButton. To change the look of these components, you must override the corresponding theme properties in your MaterialApp.

    class FirebaseAuthUIExample extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          home: SignInScreen(
            providers: [
              EmailAuthProvider(),
            ],
          ),
        );
      }
    }
  9. Advanced configuration with FirebaseDatabaseQueryBuilder

    main

    If you need more control than FirebaseDatabaseListView provides (for example, if you want to use a GridView instead of a ListView), use FirebaseDatabaseQueryBuilder.

    Unlike the list view widget, FirebaseDatabaseQueryBuilder does not provide a UI implementation. Instead, it provides a FirebaseQueryBuilderSnapshot via its builder callback. This snapshot contains the state of the entire query, including:

    • isFetching: Boolean indicating if data is currently being loaded.
    • hasError: Boolean indicating if an error occurred.
    • error: The error object if hasError is true.
    • docs: A list of the documents currently loaded.
    • hasMore: Boolean indicating if there are more items available to fetch.
    • fetchMore(): A method to trigger the loading of the next page of data.

    Note: When using a custom implementation like GridView.builder, you must manually call snapshot.fetchMore() when the user reaches the end of the current list to enable infinite scrolling.

    final usersQuery = FirebaseDatabase.instance.ref('users').orderByChild('name');
    
    FirebaseDatabaseQueryBuilder(
      query: usersQuery,
      builder: (context, snapshot, _) {
        if (snapshot.isFetching) {
          return const CircularProgressIndicator();
        }
    
        if (snapshot.hasError) {
          return Text('Something went wrong! ${snapshot.error}');
        }
    
        return GridView.builder(
          itemCount: snapshot.docs.length,
          itemBuilder: (context, index) {
            // Manually trigger fetchMore when reaching the end of the current batch
            if (snapshot.hasMore && index + 1 == snapshot.docs.length) {
              snapshot.fetchMore();
            }
    
            final user = snapshot.docs[index].value as Map<String, dynamic>;
            return Text("User name is ${user['name']}");
          },
        );
      },
    );