2

I am making an app with a page view and a custom bottom navigation bar CustomBottomNavigator. The icons change color when pages are changed but whenever I implement Ontap method for the individual CustomBottomNavigatorItem it gives a null check operator used on a null value.The error is attached after the code.I can't understand null safety even after watching several videos and looking in the documentation

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart'as firebase_auth;

import 'package:flutter_fashion/main.dart';


class CustomBottomNavigator extends StatefulWidget {

  final int tab;
  final Function(int) tabPressed;
  const CustomBottomNavigator({Key? key, required this.tab, required this.tabPressed}) : super(key: key);

  @override
  _CustomBottomNavigatorState createState() => _CustomBottomNavigatorState();
}

class _CustomBottomNavigatorState extends State<CustomBottomNavigator> {
  int _selectedTab=0;
  @override
  Widget build(BuildContext context) {
    _selectedTab=widget.tab;
    return Container(
      decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.only(
              topLeft: Radius.circular(12), topRight: Radius.circular(12)),
          boxShadow: [
            BoxShadow(
                color: Colors.black.withOpacity(0.05),
                spreadRadius: 1.0,
                blurRadius: 30.0)
          ]),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          CustomBottomNavigatorItem(
            icon: Icons.home_outlined,
            selected: _selectedTab==0?true:false,
            onPressed: () {
              widget.tabPressed(0);
            },
          ),
          CustomBottomNavigatorItem(
            icon: Icons.code_rounded,
            selected: _selectedTab==1?true:false,
            onPressed: () {
              widget.tabPressed(1);
            },
          ),
          CustomBottomNavigatorItem(
            icon: Icons.bookmark_border_rounded,
            selected: _selectedTab==2?true:false,
            onPressed: () {
              widget.tabPressed(2);
            },
          ),
          CustomBottomNavigatorItem(
            icon: Icons.logout_rounded,
            selected: _selectedTab==3?true:false,
            onPressed: () {
              firebase_auth.FirebaseAuth.instance.signOut();
              Navigator.pushAndRemoveUntil(
                  context,
                  MaterialPageRoute(
                      builder: (builder) => MyApp()),
                      (route) => false);
            },
          ),
        ],
      ),
    );
  }
}


class CustomBottomNavigatorItem extends StatelessWidget {
  final IconData icon;
  final bool selected;
  final Function onPressed;
  CustomBottomNavigatorItem(
      {required this.icon, required this.selected, required this.onPressed,});
  @override
  Widget build(BuildContext context) {
    bool _selected = selected;
    return GestureDetector(
      onTap: () => onPressed,
      child: Container(
        padding: EdgeInsets.symmetric(horizontal: 24, vertical: 28),
        decoration: BoxDecoration(
            border: Border(
                top: BorderSide(
                    color: _selected
                        ? Theme.of(context).accentColor
                        : Colors.transparent,
                    width: 2.0))),
        child: Icon(
          icon,
          size: 24,
          color: _selected ? Theme.of(context).accentColor : Colors.black,
        ),
      ),
    );
  }
}

HomePage

import 'package:flutter/material.dart';
import 'package:flutter_fashion/Views/Widgets/bottom_navigator.dart';
import 'package:flutter_fashion/Views/Widgets/page_view_tabs/ml_page_tab.dart';
import 'package:flutter_fashion/Views/Widgets/page_view_tabs/saved_page_tab.dart';
import 'package:flutter_fashion/Views/Widgets/page_view_tabs/home_page_tab.dart';


class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  late final PageController _tabPageController;
  late int _selectedTab=0;

  @override
  void initState() {
    _tabPageController=PageController();
    super.initState();
  }

  @override
  void dispose() {
    _tabPageController.dispose();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Expanded(
              child: PageView(
                controller: _tabPageController,
                onPageChanged: (num){
                  setState(() {
                    _selectedTab=num;
                  });
                },
                children: [
                  HomeTab(),
                  MachineLearningTab(),
                  SavedTab(),
                ],
              ),
            ),
            CustomBottomNavigator(tab: _selectedTab,tabPressed: (num){
              _tabPageController.animateToPage(num, duration: Duration(milliseconds: 300), curve: Curves.easeOutCubic);
            },)
          ],
        ),
      ),
    );
  }
}
  • The problem appears not to be in the code you've posted, but rather in your home page code, perhaps from using some kind of custom scrolling widget. I've found similar errors coming out of the flutter library since null-safety, and have had to find ways to use the Flutter provided scrollable widgets to get the job done. See this issue for more details: https://github.com/flutter/flutter/issues/66250 – Michael Horn Jun 13 '21 at 16:49
  • See I added the homePage after the error msg I don't think it happened due to homepage, if you notice the app signs out also that is all the gesture detectors are getting tapped on intialization – hamza hasan Jun 13 '21 at 18:47

2 Answers2

1

Null check operator used on a null value exception usually happens when you use null check operator (!) on the nullable identifier, I suspect cause of the error are in this line:

class CustomBottomNavigatorItem extends StatelessWidget {
...
  @override
  Widget build(BuildContext context) {
...
      onTap: onPressed(),
...
}

which is supposed to be:

class CustomBottomNavigatorItem extends StatelessWidget {
...
  @override
  Widget build(BuildContext context) {
...
      onTap: onPressed,
...
}

notice I omit the '()' on onPressed function, since adding it would simply mean invoking it, thereof you are passing the value of the result of onPressed function and not the function itself.

landfire13224
  • 337
  • 4
  • 12
0

Change onPressed() to () => onPressed

  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => onPressed,
      child: Container(
        padding: EdgeInsets.symmetric(horizontal: 24, vertical: 28),
        decoration: BoxDecoration(
          border: Border(
            top: BorderSide(width: 2.0),
          ),
        ),
        child: Icon(
          Icons.send,
          size: 24,
        ),
      ),
    );
  }

Try updating the CustomBottomNavigatorItem that manages the sign out functionality to something like this:

CustomBottomNavigatorItem(
            icon: Icons.logout_rounded,
            selected: _selectedTab==3?true:false,
            onPressed: () {
              WidgetsBinding.instance.addPostFrameCallback(
              (_) {
                Navigator.of(context)
                    .pushReplacementNamed("You Route Name");
              },
            ),
            firebase_auth.FirebaseAuth.instance.signOut();
            },
          ),
Jaime Ortiz
  • 1,089
  • 10
  • 14