A value of type 'Widget' can't be assigned to a variable of type 'PreferredSizeWidget'

Viewed 2371

Error 1

Error 2

THERE ARE 2 ERRORS IN THIS PROGRAM WHICH HAVE BEEN SHOWN IN THE IMAGES ABOVE

Main.dart file

void main() {
 
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Personal Expenses ',
      theme: ThemeData(
        primarySwatch: Colors.green,
        accentColor: Colors.amber,
        //errorColor: Colors.red[700],
        fontFamily: 'Quicksand',
        textTheme: ThemeData.light().textTheme.copyWith(
            title: TextStyle(
              fontFamily: 'OpenSans',
              fontWeight: FontWeight.bold,
              fontSize: 18,
            ),
            button: TextStyle(color: Colors.amber)),
        appBarTheme: AppBarTheme(
          textTheme: ThemeData.light().textTheme.copyWith(
                title: TextStyle(
                  fontFamily: 'OpenSans',
                  fontSize: 20,
                  fontWeight: FontWeight.bold,
                ),
              ),
        ),
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
 
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final List<Transaction> _userTransactions = [
   
  ];
  bool _showChart = false;
  List<Transaction> get _recentTransactions {
    return _userTransactions.where((tx) {
      return tx.date.isAfter(
        DateTime.now().subtract(
          Duration(days: 7),
        ),
      );
    }).toList();
  }

  void _addNewTransaction(
      String txTitle, double txAmount, DateTime chosenDate) {
    final newTx = Transaction(
      title: txTitle,
      amount: txAmount,
      date: chosenDate,
      id: DateTime.now().toString(),
    );

    setState(() {
      _userTransactions.add(newTx);
    });
  }

  void _startAddNewTransaction(BuildContext ctx) {
    showModalBottomSheet(
      context: ctx,
      builder: (_) {
        return GestureDetector(
          onTap: () {},
          child: NewTransaction(_addNewTransaction),
          behavior: HitTestBehavior.opaque,
        );
      },
    );
  }

  void _deleteTransaction(String id) {
    setState(() {
      _userTransactions.removeWhere((tx) => tx.id == id);
    });
  }

  @override
  Widget build(BuildContext context) {
    final mediaQuery = MediaQuery.of(context);
    final isLandscape = mediaQuery.orientation == Orientation.landscape;
    final PreferredSizeWidget appbar = Platform.isIOS 

A value of type 'Widget' can't be assigned to a variable of type 'PreferredSizeWidget'.

        ? CupertinoNavigationBar(
            middle: Text(
              'Personal Expenses ',
            ),
            trailing: Row(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                GestureDetector(
                  child: Icon(CupertinoIcons.add),
                  onTap: () => _startAddNewTransaction(context),
                )
              ],
            ),
          )
        : AppBar(
            title: Text(
              'Personal Expenses ',
              style: TextStyle(fontFamily: 'OpenSans'),
            ),
            actions: <Widget>[
              IconButton(
                icon: Icon(Icons.add),
                onPressed: () => _startAddNewTransaction(context),
              ),
            ],
          );
    final txListWidget = Container(
      height: (mediaQuery.size.height -
              appbar.preferredSize.height -
              mediaQuery.padding.top) *
          0.7,
      child: TransactionList(
        _userTransactions,
        _deleteTransaction,
      ),
    );
    final pageBody = SingleChildScrollView(
      child: Column(
        
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          if (isLandscape)
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text('Show Chart'),
                Switch.adaptive(
                  activeColor: Theme.of(context).accentColor,
                  value: _showChart,
                  onChanged: (val) {
                    setState(() {
                      _showChart = val;
                    });
                  },
                ),
              ],
            ),
         
        ],
      ),
    );

return Platform.isIOS ? CupertinoPageScaffold( child: pageBody, navigationBar: appbar,

The argument type 'PreferredSizeWidget' can't be assigned to the parameter type 'ObstructingPreferredSizeWidget?'.

          )
        : Scaffold(
            .........,
                  ),
          );
  }
}
3 Answers

Your code works in non-null safe versions of Flutter. I do not know why the null safe version now objects to:

final PreferredSizeWidget appbar = Platform.isIOS ...

If you omit the type:

final appbar = Platform.isIOS ...

Then appbar is interpreted as a Widget and gives an error on appbar.preferredSize.

You can force the type to be examined at runtime:

final dynamic appbar = Platform.isIOS ...

This works for me testing with my Android device. However, I have not tested with an Apple device.

I created this flutter issue for the change in behaviour with the null-safe version of flutter. You can subscribe to the issue to get update notifications.

Edit: The Flutter team raised a Dart issue which explains the new bahaviour and suggests using:

final PreferredSizeWidget appbar = (Platform.isIOS ? CupertinoNavigationBar() : AppBar()) 
                                   as PreferredSizeWidget;

the issue is , appBar accept widget that implements PreferredSize

and CupertinoPageScaffold accept widget the implements ObstructingPreferredSizeWidget

so don't determine the datatype of the appbar

and let it be determine at the runtime

simply make it like this

final appBar = Platform.IOS ? CupertinoNavigationBar() : AppBar()

and add the CupertinoNavigationBar in CupertinoPageScaffold

and add the AppBar in Scaffold

I faced the same issue, this is due to the null safety feature of Dart

Solution

final dynamic appBar = Platform.isIOS
    ? CupertinoNavigationBar() : AppBar()

Or you can use

final PreferredSizedWidget appBar = Platform.isIOS
        ? CupertinoNavigationBar() as ObstructingPreferredSizedWidget : AppBar()
Related