Home > Mobile >  I am trying to use a bottom sheet modal in flutter conditionally only when users are not subscribed
I am trying to use a bottom sheet modal in flutter conditionally only when users are not subscribed

Time:09-01

Problem: I have a flutter application that after loging in, i want to show a bottom sheet modal popup only when users of the app is not subscribed and restricts them from using the app and is clickable to take them straight to the subscription widget/page.

but i get an error saying "The argument type "Future" can't be assigned to the parameter type 'Widget'

Solution i tried:

  1. I tried removing the Future and Async function i passed in the FloatingModal Class but it still gives same errors on runtime

  2. i converted my stateless widget 'Dashboard' to stateful to see if it does the trick but it didn't work.

  3. If this approach is completely wrong, what better approach would you recommend for me for the usecase/problem

Please note i am using the modal_bottom_sheet flutter package by Jaimeblasco. This app is also using a backend in laravel.

The 3 widget actively responsible are dashboard.dart subscription_notice.dart and floating_modal.dart which i'll provide the code snippets.

Please i'll really need help as it's a project i'm working on at this time. Thank you :)

class Dashboard extends StatelessWidget {
  const Dashboard({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    HomeController homeController = Get.find();
    ServicesController servicesController = Get.find();
    VerificationController verificationController = Get.find();
    PlayersController playersController = Get.find();
    var user =
        UserModel.fromJson(jsonDecode(homeController.userData.value)).user!;
        
        Widget content(context) {
      return Obx(() => Column(
            children: [
              Expanded(
                child: ListView(
                    padding: const EdgeInsets.only(
                        top: 40, left: 20, right: 20, bottom: 20),
                    children: [
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          Text(
                              AppLocalizations.of(context)!.welcome  
                                  " ${user.firstName}",
                              style: const TextStyle(fontSize: 20)),
                              
                              if (servicesController.subscription.isEmpty &&
                          !servicesController.loading &&
                          user.userType != "club_official")
                          FloatingModal(child: showFloatingModalBottomSheet(context: context, builder: (context) => const SubscriptionNotice())),
                          ]);
                           ),
              const HorizontalAdvertBanner()
            ],
          ));
    }

class SubscriptionNotice extends StatelessWidget {
  const SubscriptionNotice({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    ServicesController servicesController = Get.find();
    var user =
        UserModel.fromJson(jsonDecode(servicesController.userData.value)).user!;

    return Material(
      child: SafeArea(
        top: false,
        child: Column(
          children: [
            const SizedBox(
              height: 20,
            ),
            CardItem(
                icon: SvgPicture.asset("assets/images/warning_icon.svg"),
                content: RichText(
                  text: TextSpan(
                      children: user.userType == "player"
                          ? [
                              TextSpan(
                                  text:
                                      "you need to subscribe to a plan. Click on this ",
                                  style: TextStyle(
                                      fontSize: 14,
                                      color: Get.isDarkMode
                                          ? AppColors.textLigth
                                          : AppColors.textDark,
                                      fontFamily: "Avenir")),
                              const TextSpan(
                                  text: "link",
                                  style: TextStyle(
                                      color: Color(0xffFF9432),
                                      fontSize: 14,
                                      fontWeight: FontWeight.w600,
                                      fontFamily: "Avenir")),
                              TextSpan(
                                  text: " and subscribe now",
                                  style: TextStyle(
                                      fontSize: 14,
                                      color: Get.isDarkMode
                                          ? AppColors.textLigth
                                          : AppColors.textDark,
                                      fontFamily: "Avenir"))
                            ]
                          : [
                              TextSpan(
                                  text:
                                      " you need to subscribe.  Click on this",
                                  style: TextStyle(
                                      fontSize: 14,
                                      color: Get.isDarkMode
                                          ? AppColors.textLigth
                                          : AppColors.textDark,
                                      fontFamily: "Avenir")),
                              const TextSpan(
                                  text: " link",
                                  style: TextStyle(
                                      color: Color(0xffFF9432),
                                      fontSize: 14,
                                      fontWeight: FontWeight.w600,
                                      fontFamily: "Avenir")),
                              TextSpan(
                                  text: ", and subscribe",
                                  style: TextStyle(
                                      fontSize: 14,
                                      color: Get.isDarkMode
                                          ? AppColors.textLigth
                                          : AppColors.textDark,
                                      fontFamily: "Avenir"))
                            ]),
                ),
                onPressed: () {
                  TabRouting().pushScreen(context, const Services());
                }),
          ],
        ),
      ),
    );
  }
}

class FloatingModal extends StatelessWidget {
  final Widget child;
  final Color? backgroundColor;

  const FloatingModal({Key? key, required this.child, this.backgroundColor})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 20),
        child: Material(
          color: backgroundColor,
          clipBehavior: Clip.antiAlias,
          borderRadius: BorderRadius.circular(12),
          child: child,
        ),
      ),
    );
  }
}

Future<T> showFloatingModalBottomSheet<T>({
  required BuildContext context,
  required WidgetBuilder builder,
  Color? backgroundColor,
}) async {
  final result = await showCustomModalBottomSheet(
      context: context,
      builder: builder,
      containerWidget: (_, animation, child) => FloatingModal(
            child: child,
          ),
      expand: false);

  return result;
}

CodePudding user response:

On your FloatingModal it seeks a widget as a child. But showFloatingModalBottomSheet is a future method.

You can use a tappable widget and on it tap event use this method.

 FloatingModal(
    child: ElevatedButton(
  onPressed: () async {
     showFloatingModalBottomSheet(context: context, builder: (context) => const SubscriptionNotice());
  },
  child: Text("showX"),
  ),
)

To show dialog directly after widget build on StatelessWidget

  @override
  Widget build(BuildContext context) {
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
      //condition if needed 
await showFloatingModalBottomSheet(context: context, builder: (context) => const SubscriptionNotice());
    });
  • Related