{"id":21877519,"url":"https://github.com/erabossid/flutter-fix","last_synced_at":"2025-03-10T14:23:22.927Z","repository":{"id":63901014,"uuid":"531930417","full_name":"erabosscode/flutter-fix","owner":"erabosscode","description":"Flutter Fix Practical Flutter App development code problems and solutions","archived":false,"fork":false,"pushed_at":"2023-02-16T13:47:01.000Z","size":260,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-07T02:22:54.194Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/erabosscode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-02T13:10:07.000Z","updated_at":"2023-01-31T20:18:59.000Z","dependencies_parsed_at":"2024-06-13T20:09:29.131Z","dependency_job_id":null,"html_url":"https://github.com/erabosscode/flutter-fix","commit_stats":null,"previous_names":["logixmaster/flutter-fix","mydigita/flutter-fix","erabossid/flutter-fix","erabosstt/flutter-fix","erabosscode/flutter-fix"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erabosscode%2Fflutter-fix","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erabosscode%2Fflutter-fix/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erabosscode%2Fflutter-fix/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erabosscode%2Fflutter-fix/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/erabosscode","download_url":"https://codeload.github.com/erabosscode/flutter-fix/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242865171,"owners_count":20197845,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-28T08:09:30.798Z","updated_at":"2025-03-10T14:23:22.904Z","avatar_url":"https://github.com/erabosscode.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Flutter Fix\nPractical Flutter App development code problems and solutions\n\n## Automatic flutter app icon launcher \n\n* Add flutter_launcher_icons as dev_dependencies\n* Put your icons in a folder and configure it as shown below with the icon path\n```yaml\n\ndev_dependencies:\n\n  flutter_launcher_icons: ^0.11.0\n\nflutter_icons:\n  android: true\n  ios: true\n  image_path: \"dev_assets/flatchat.png\"\n  adaptive_icon_background: \"#ffffff\"\n  adaptive_icon_foreground: \"dev_assets/flatchat_adaptive.png\"\n\n```\n* run this command `flutter pub run flutter_launcher_icons`\n\n\n## Flutter form validation (login / signup screen)\n\n```dart\nimport 'package:flutter/material.dart';\n\nclass AuthForm extends StatefulWidget {\n  const AuthForm({super.key});\n\n  @override\n  State\u003cAuthForm\u003e createState() =\u003e _AuthFormState();\n}\n\nclass _AuthFormState extends State\u003cAuthForm\u003e {\n  final _formKey = GlobalKey\u003cFormState\u003e();\n  var _isLogin = true;\n  var _userEmail = '';\n  var _userName = '';\n  var _userPassword = '';\n  void _trySubmit() {\n    final isValid = _formKey.currentState!.validate();\n    FocusScope.of(context).unfocus();\n    if (isValid) {\n      _formKey.currentState!.save();\n    }\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Center(\n      child: Card(\n        margin: const EdgeInsets.all(20),\n        child: SingleChildScrollView(\n          child: Padding(\n            padding: const EdgeInsets.all(14),\n            child: Form(\n              key: _formKey,\n              child: Column(\n                mainAxisSize: MainAxisSize.min,\n                children: [\n                  TextFormField(\n                    key: const ValueKey('email'),\n                    validator: (value) {\n                      if (value!.isEmpty ||\n                          !value.contains('@') ||\n                          !value.contains('.') ||\n                          value.length \u003c 6) {\n                        return 'Please enter a valid email address';\n                      }\n                      return null;\n                    },\n                    keyboardType: TextInputType.emailAddress,\n                    decoration:\n                        const InputDecoration(labelText: 'Email address'),\n                    onSaved: (newValue) {\n                      _userEmail = newValue!;\n                    },\n                  ),\n                  if (!_isLogin)\n                    TextFormField(\n                      key: const ValueKey('username'),\n                      validator: (value) {\n                        if (value!.isEmpty || value.length \u003c 5) {\n                          return 'Username should be min 6 chars long';\n                        }\n                        return null;\n                      },\n                      decoration: const InputDecoration(labelText: 'Username'),\n                      onSaved: (newValue) {\n                        _userName = newValue!;\n                      },\n                    ),\n                  TextFormField(\n                    key: const ValueKey('password'),\n                    validator: (value) {\n                      if (value!.isEmpty || value.length \u003c 7) {\n                        return 'Please enter min 8 char long password';\n                      }\n                      return null;\n                    },\n                    decoration: const InputDecoration(labelText: 'Password'),\n                    obscureText: true,\n                    onSaved: (newValue) {\n                      _userPassword = newValue!;\n                    },\n                  ),\n                  const SizedBox(height: 14),\n                  TextButton(\n                    onPressed: _trySubmit,\n                    child: Text(_isLogin ? 'Login' : 'Signup'),\n                  ),\n                  TextButton(\n                    onPressed: () {\n                      setState(() {\n                        _isLogin = !_isLogin;\n                      });\n                    },\n                    child: Text(_isLogin\n                        ? 'Create a new account'\n                        : 'I already have an account'),\n                  )\n                ],\n              ),\n            ),\n          ),\n        ),\n      ),\n    );\n  }\n}\n\n```\n\n## Getting data from firestore\n\n```dart\n floatingActionButton: FloatingActionButton(\n        child: const Icon(Icons.add),\n        onPressed: () async {\n          await Firebase.initializeApp();\n          FirebaseFirestore.instance\n              .collection('/chat/5eUgK6qd6YABtD2Pt723/messages/')\n              .snapshots()\n              .listen((QuerySnapshot querySnapshot) {\n            print('I am here');\n            print(querySnapshot.docs.map((e) =\u003e e['text']));\n            // 'text' is a document field stored in database\n          });\n        },\n      ),\n```\n\n## Use of Camera in flutter \n```dart\nimport 'dart:io';\nimport 'package:flutter/material.dart';\nimport 'package:image_picker/image_picker.dart';\n\nclass ImageInput extends StatefulWidget {\n  const ImageInput({super.key});\n\n  @override\n  State\u003cImageInput\u003e createState() =\u003e _ImageInputState();\n}\n\nclass _ImageInputState extends State\u003cImageInput\u003e {\n  File? _storedImage;\n  Future\u003cvoid\u003e _takePicture() async {\n    final imagePicker = ImagePicker();\n    final imageFile = await imagePicker.pickImage(\n      source: ImageSource.camera,\n      maxWidth: 600,\n    );\n\n    // this will prevent app crash when you'll cancel the camera\n    // without taking image\n    if (imageFile == null) {\n      return;\n    }\n\n    // update _storedImage immediately after taking a photo\n    setState(() {\n      _storedImage = File(imageFile.path);\n    });\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Row(\n      children: [\n        Container(\n          width: 150,\n          height: 100,\n          decoration: BoxDecoration(\n            border: Border.all(width: 1, color: Colors.grey),\n          ),\n          alignment: Alignment.center,\n          child: _storedImage != null\n              ? Image.file(\n                  _storedImage!,\n                  fit: BoxFit.cover,\n                  width: double.infinity,\n                )\n              : const Text(\n                  'No image taken',\n                  textAlign: TextAlign.center,\n                ),\n        ),\n        const SizedBox(\n          height: 12.0,\n        ),\n        Expanded(\n          child: TextButton.icon(\n            onPressed: _takePicture,\n            icon: const Icon(Icons.camera_alt),\n            label: const Text('Take Photo'),\n          ),\n        ),\n      ],\n    );\n  }\n}\n\n```\n\n## Signup with email and password Firebase api endpoint\n```dart\nfinal url = Uri.parse('https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=here_is_your_project_api_key');\n\n// final url = Uri.parse('https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=here_is_your_project_api_key');\n```\n\n## Firebase Database Rules only authenticated users can read- write\n\n```javascript{\n  \"rules\": {\n    \".read\": \"auth !=null\",  \n    \".write\": \"auth !=null\",  \n  }\n}\n```\n\n## Update only required field in Firebase realtimedatabase with flutter\n```dart\nimport 'dart:convert';\nimport 'package:flutter/material.dart';\nimport 'package:http/http.dart' as http;\n\nclass Product with ChangeNotifier {\n  final String id;\n  final String title;\n  final String description;\n  final double price;\n  final String imageUrl;\n  bool isFavorite;\n\n  Product({\n    required this.id,\n    required this.title,\n    required this.description,\n    required this.price,\n    required this.imageUrl,\n    this.isFavorite = false,\n  });\n\n  void _setFavoriteValue(bool newValue) {\n    isFavorite = newValue;\n    notifyListeners();\n  }\n\n  Future\u003cvoid\u003e toggleFavoriteStatus() async {\n    final oldStatus = isFavorite;\n    isFavorite = !isFavorite;\n    notifyListeners();\n    try {\n      final url =\n          'https://your_own_url_here.firebaseio.com/products/$id.json';\n\n      final response = await http.patch(Uri.parse(url),\n          body: json.encode({\n            'isFavorite': isFavorite,\n          }));\n\n      if (response.statusCode != 200) {\n        _setFavoriteValue(oldStatus);\n      }\n    } catch (error) {\n      _setFavoriteValue(oldStatus);\n    }\n  }\n}\n\n\n```\n\n\n## Handle invalid network image loading in flutter (404)\n\n```dart\nImage.network(\n            product.imageUrl,\n            fit: BoxFit.cover,\n\n            // if image url does not work, load a sample image from app assets\n            errorBuilder:\n                (BuildContext context, Object error, StackTrace? stackTrace) {\n              return Image.asset(\n                'assets/images/image_not_found.jpg',\n                fit: BoxFit.cover,\n              );\n            },\n          ),\n\n```\n\n\n## Rebuild only required or update data consumed widget with Provider\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:provider/provider.dart';\nimport '../pages/product_details.page.dart';\nimport '../providers/product.model.dart';\n\nclass ProductItem extends StatelessWidget {\n  const ProductItem({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n  \n  //don't listen for whole widgets - listen false\n  // but it will listen where required through Consumer\n    final product = Provider.of\u003cProduct\u003e(context, listen: false);\n    return ClipRRect(\n      borderRadius: BorderRadius.circular(10),\n      child: GridTile(\n        header: Text(\n          'Product ID: ${product.id.toUpperCase()}',\n        ),\n        footer: GridTileBar(\n            backgroundColor: Colors.black87,\n            \n            // consume updates only where you want \n            //and only this widget will be rebuilt\n            \n            leading: Consumer\u003cProduct\u003e(\n              builder: (ctx, prod, child) =\u003e IconButton(\n                onPressed: () {\n                  product.toggleFavoriteStatus();\n                },\n                color: Theme.of(context).primaryColor,\n                icon: Icon(product.isFavorite\n                    ? Icons.favorite\n                    : Icons.favorite_border),\n              ),\n            ),\n            trailing: IconButton(\n                onPressed: () {},\n                color: Theme.of(context).primaryColor,\n                icon: const Icon(Icons.shopping_cart)),\n            title: Text(\n              product.title,\n              textAlign: TextAlign.center,\n            )),\n        child: GestureDetector(\n          onTap: () {\n            Navigator.of(context).pushNamed(\n              ProductDetailsPage.routeName,\n              arguments: product.id,\n            );\n          },\n          child: Image.network(\n            product.imageUrl,\n            fit: BoxFit.cover,\n          ),\n        ),\n      ),\n    );\n  }\n}\n\n```\n\n## Use of LinearGradient in flutter\n\n```dart\nCard(\n        elevation: 5,\n        child: Container(\n          padding: const EdgeInsets.all(10),\n          decoration: BoxDecoration(\n            borderRadius: BorderRadius.circular(5),\n            gradient: LinearGradient(\n              colors: [color.withOpacity(0.7), color],\n              begin: Alignment.topLeft,\n              end: Alignment.bottomLeft,\n            ),\n          ),\n          child: Center(\n            child: Text(\n              title,\n              style:\n                  const TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold),\n            ),\n          ),\n        ),\n      )\n```\n\n## Use of flutter InkWell\n\n```dart\nWidget build(BuildContext context) {\n    return InkWell(\n      onTap: () =\u003e selectCategory(context),\n      splashColor: Theme.of(context).primaryColor,\n      borderRadius: BorderRadius.circular(20),\n      child: Card(\n        elevation: 5,\n        child: Container(\n          padding: const EdgeInsets.all(10),\n          decoration: BoxDecoration(\n            borderRadius: BorderRadius.circular(5),\n            gradient: LinearGradient(\n              colors: [color.withOpacity(0.7), color],\n              begin: Alignment.topLeft,\n              end: Alignment.bottomLeft,\n            ),\n          ),\n          child: Center(\n            child: Text(\n              title,\n              style:\n                  const TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold),\n            ),\n          ),\n        ),\n      ),\n    );\n  }\n}\n```\n\n## Use of flutter didChangeDependencies\n* widget. call does not work in state class, so to use in initState is ok, but\n* ModalRoute does not work in initState(), so to use all in didChangeDependencies\n\n```dart\nvoid didChangeDependencies() {\n    if (!_loadedInitData) {\n      final routeArgs =\n          ModalRoute.of(context)?.settings.arguments as Map\u003cString, String\u003e;\n      categoryTitle = routeArgs['title']!;\n      final categoryId = routeArgs['id'];\n      displayedMeals = widget.availableMeals.where((meal) {\n        return meal.categories.contains(categoryId);\n      }).toList();\n\n      _loadedInitData = true;\n    }\n\n    super.didChangeDependencies();\n  }\n\n\n```\n\n## Use of flutter GridView\n\n```dart\n  Widget build(BuildContext context) {\n    return SafeArea(\n      child: GridView(\n        padding: const EdgeInsets.all(16),\n        gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(\n          maxCrossAxisExtent: 180,\n          childAspectRatio: 1,\n          crossAxisSpacing: 12,\n          mainAxisSpacing: 12,\n          mainAxisExtent: 75,\n        ),\n        children: listOfCategories\n            .map((data) =\u003e CategoryItem(data.id, data.title, data.color))\n            .toList(),\n      ),\n    );\n  }\n\n```\n\n## Use of flutter SwitchListTile\nFull code in [flutter-meals-app](https://github.com/tradecoder/flutter-meals-app) in filter_screen.dart\n\n```dart\n\nimport 'package:flutter/material.dart';\nimport '../widgets/main_drawer.dart';\n\nclass FilterScreen extends StatefulWidget {\n  static const routeName = '/filters';\n  const FilterScreen({super.key});\n\n  @override\n  State\u003cFilterScreen\u003e createState() =\u003e _FilterScreenState();\n}\n\nclass _FilterScreenState extends State\u003cFilterScreen\u003e {\n  bool _glutenFree = false;\n  bool _vegetarian = false;\n  bool _vegan = false;\n  bool _lactoseFree = false;\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: const Text('Filtered'),\n      ),\n      drawer: const MainDrawer(),\n      body: Column(\n        children: [\n          Container(\n            padding: const EdgeInsets.all(14),\n            child: const Text('Filtered meals'),\n          ),\n          Expanded(\n            child: ListView(\n              children: [\n                SwitchListTile(\n                  title: const Text('Gluten free'),\n                  subtitle: const Text('Show gluten free meal'),\n                  value: _glutenFree,\n                  onChanged: ((newValue) {\n                    setState(() {\n                      _glutenFree = newValue;\n                    });\n                  }),\n                ),\n                SwitchListTile(\n                  title: const Text('Vegetarian'),\n                  subtitle: const Text('Show vegetarian meals'),\n                  value: _vegetarian,\n                  onChanged: ((newValue) {\n                    setState(() {\n                      _vegetarian = newValue;\n                    });\n                  }),\n                ),\n                SwitchListTile(\n                  title: const Text('Vegan'),\n                  subtitle: const Text('Show Vegan meals'),\n                  value: _vegan,\n                  onChanged: ((newValue) {\n                    setState(() {\n                      _vegan = newValue;\n                    });\n                  }),\n                ),\n                SwitchListTile(\n                  title: const Text('Lactose free'),\n                  subtitle: const Text('Show Lactose free meals'),\n                  value: _lactoseFree,\n                  onChanged: ((newValue) {\n                    setState(() {\n                      _lactoseFree = newValue;\n                    });\n                  }),\n                ),\n              ],\n            ),\n          )\n        ],\n      ),\n    );\n  }\n}\n\n```\n\n\n## Use of flutter pushReplacementNamed() and Drawer()\nFull code in [flutter-meals-app](https://github.com/tradecoder/flutter-meals-app) in main_drawer.dart \n```dart\nimport 'package:flutter/material.dart';\nimport '../screens/filter_screen.dart';\n\nclass MainDrawer extends StatelessWidget {\n  Widget buildListTile(String title, IconData icon, VoidCallback tapHandler) {\n    return ListTile(\n      leading: Icon(\n        icon,\n        size: 24,\n      ),\n      title: Text(\n        title,\n        style: const TextStyle(fontWeight: FontWeight.bold),\n      ),\n      onTap: tapHandler,\n    );\n  }\n\n  const MainDrawer({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return Drawer(\n      child: Column(\n        children: [\n          Container(\n            height: 100,\n            width: double.infinity,\n            padding: const EdgeInsets.all(14),\n            alignment: Alignment.centerLeft,\n            child: const Text(\n              'Cooking up!',\n              style: TextStyle(fontSize: 20),\n            ),\n          ),\n          const SizedBox(height: 16),\n          buildListTile(\n            'Meals',\n            Icons.restaurant,\n            () {\n              Navigator.of(context).pushReplacementNamed('/');\n            },\n          ),\n          buildListTile(\n            'Filters',\n            Icons.settings,\n            () {\n              Navigator.of(context)\n                  .pushReplacementNamed(FilterScreen.routeName);\n            },\n          ),\n        ],\n      ),\n    );\n  }\n}\n\n\n```\n\n## Flutter Drawer()\nFull code in [flutter-meals-app](https://github.com/tradecoder/flutter-meals-app) in TabScreen\n```dart\nWidget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(_pages[_selectedPageIndex]['title']),\n      ),\n      drawer: const Drawer(\n        child: Text('Drawer'),\n      ),\n      body: _pages[_selectedPageIndex]['page'],\n      bottomNavigationBar: BottomNavigationBar(\n        onTap: _selectPage,\n        unselectedItemColor: Colors.white,\n        selectedItemColor: Colors.yellow,\n        currentIndex: _selectedPageIndex,\n        type: BottomNavigationBarType.shifting,\n        items: [\n          BottomNavigationBarItem(\n            backgroundColor: Theme.of(context).primaryColor,\n            icon: const Icon(Icons.category),\n            label: 'Category',\n          ),\n          BottomNavigationBarItem(\n            backgroundColor: Theme.of(context).primaryColor,\n            icon: const Icon(Icons.star),\n            label: 'Favorite',\n          ),\n        ],\n      ),\n    );\n  }\n\n```\n\n## Flutter dynamic BottomNavigationBar \nFull code in [flutter-meals-app](https://github.com/tradecoder/flutter-meals-app)\n\n```dart\nimport 'package:flutter/material.dart';\nimport '../screens/categories_screen.dart';\nimport '../screens/favorite_screen.dart';\n\nclass TabScreen extends StatefulWidget {\n  const TabScreen({super.key});\n\n  @override\n  State\u003cTabScreen\u003e createState() =\u003e _TabScreenState();\n}\n\nclass _TabScreenState extends State\u003cTabScreen\u003e {\n  final List\u003cMap\u003cString, dynamic\u003e\u003e _pages = [\n    {\n      'page': const CategoriesScreen(),\n      'title': 'Categories',\n    },\n    {\n      'page': const FavoriteScreen(),\n      'title': 'Your favorite meal',\n    },\n  ];\n  int _selectedPageIndex = 0;\n  void _selectPage(int index) {\n    setState(() {\n      _selectedPageIndex = index;\n    });\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(_pages[_selectedPageIndex]['title']),\n      ),\n      body: _pages[_selectedPageIndex]['page'],\n      bottomNavigationBar: BottomNavigationBar(\n        onTap: _selectPage,\n        unselectedItemColor: Colors.white,\n        selectedItemColor: Colors.yellow,\n        currentIndex: _selectedPageIndex,\n        type: BottomNavigationBarType.shifting,\n        items: [\n          BottomNavigationBarItem(\n            backgroundColor: Theme.of(context).primaryColor,\n            icon: const Icon(Icons.category),\n            label: 'Category',\n          ),\n          BottomNavigationBarItem(\n            backgroundColor: Theme.of(context).primaryColor,\n            icon: const Icon(Icons.star),\n            label: 'Favorite',\n          ),\n        ],\n      ),\n    );\n  }\n}\n\n```\n\n\n## Flutter Bottom Navigation Bar with active Tab color\nFull code in [flutter-meals-app](https://github.com/tradecoder/flutter-meals-app)\n\n```dart\n\n\nimport 'package:flutter/material.dart';\nimport '../screens/categories_screen.dart';\nimport '../screens/favorite_screen.dart';\n\nclass TabScreen extends StatefulWidget {\n  const TabScreen({super.key});\n\n  @override\n  State\u003cTabScreen\u003e createState() =\u003e _TabScreenState();\n}\n\nclass _TabScreenState extends State\u003cTabScreen\u003e {\n  final List\u003cWidget\u003e _pages = const [\n    CategoriesScreen(),\n    FavoriteScreen(),\n  ];\n  int _selectedPageIndex = 0;\n  void _selectPage(int index) {\n    setState(() {\n      _selectedPageIndex = index;\n    });\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: const Text('Meals'),\n      ),\n      body: _pages[_selectedPageIndex],\n      bottomNavigationBar: BottomNavigationBar(\n        onTap: _selectPage,\n        unselectedItemColor: Colors.grey,\n        selectedItemColor: Theme.of(context).primaryColor,\n        currentIndex: _selectedPageIndex,\n        items: const [\n          BottomNavigationBarItem(\n            icon: Icon(\n              Icons.category,\n            ),\n            label: 'Category',\n          ),\n          BottomNavigationBarItem(\n            icon: Icon(Icons.star),\n            label: 'Favorite',\n          ),\n        ],\n      ),\n    );\n  }\n}\n\n\n\n```\n\n\n## Flutter Tab Screen ViewTabBar\nFull code in [flutter-meals-app](https://github.com/tradecoder/flutter-meals-app)\n\n```dart\nimport 'package:flutter/material.dart';\nimport '../screens/categories_screen.dart';\nimport '../screens/favorite_screen.dart';\n\nclass TabScreen extends StatefulWidget {\n  const TabScreen({super.key});\n\n  @override\n  State\u003cTabScreen\u003e createState() =\u003e _TabScreenState();\n}\n\nclass _TabScreenState extends State\u003cTabScreen\u003e {\n  @override\n  Widget build(BuildContext context) {\n    return DefaultTabController(\n      length: 2,\n      initialIndex: 0,\n      child: Scaffold(\n        appBar: AppBar(\n          title: const Text('Meals'),\n          bottom: const TabBar(\n            tabs: \u003cWidget\u003e[\n              Tab(\n                icon: Icon(Icons.category),\n                text: 'Categories',\n              ),\n              Tab(\n                icon: Icon(Icons.star),\n                text: 'Favorite',\n              ),\n            ],\n          ),\n        ),\n        body: const TabBarView(\n          children: \u003cWidget\u003e[\n            CategoriesScreen(),\n            FavoriteScreen(),\n          ],\n        ),\n      ),\n    );\n  }\n}\n\n\n```\n\n## Options of registering flutter page routes/ navigation, fall back routes for unregistered or unknown routes\nFull code in [flutter-meals-app](https://github.com/tradecoder/flutter-meals-app/commit/888580c12e7334090f03ebf33c5e88417b352f02#diff-e61eb31d013d12616f5532636a88cfa63631dda8f7829e5424e68542214d1608)\n```dart\n\nimport 'package:flutter/material.dart';\nimport '../screens/meal_detail_screen.dart';\nimport './screens/category_meals_screen.dart';\nimport './screens/categories_screen.dart';\n\nvoid main() {\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: \"Flutter Meals App\",\n      theme: ThemeData(primarySwatch: Colors.pink),\n      initialRoute: '/',\n      routes: {\n        '/': (context) =\u003e const CategoriesScreen(),\n        CategoryMealsScreen.routeName: (context) =\u003e const CategoryMealsScreen(),\n        MealDetailScreen.routeName: (context) =\u003e const MealDetailScreen(),\n      },\n      onGenerateRoute: (settings) {\n        return MaterialPageRoute(builder: (ctx) =\u003e const CategoriesScreen());\n      },\n      onUnknownRoute: (settings) {\n        return MaterialPageRoute(builder: (ctx) =\u003e const CategoriesScreen());\n      },\n    );\n  }\n}\n\n```\n\n\n\n\n## Allow device only portrait mode- flutter\n```dart\nvoid main() {\n  WidgetsFlutterBinding.ensureInitialized();\n  SystemChrome.setPreferredOrientations([\n    DeviceOrientation.portraitUp,\n    DeviceOrientation.portraitDown,\n  ]);\n  runApp(const MyApp());\n}\n\n\n```\n\n\n## Fix double.parse() / int.parse() problems when string contains both numbers and text, and remove leading whitespace from a text\n\n```dart\nimport 'package:flutter/material.dart';\n\nclass NewTransaction extends StatefulWidget {\n  final Function txnDetails;\n  const NewTransaction({super.key, required this.txnDetails});\n\n  @override\n  State\u003cNewTransaction\u003e createState() =\u003e _NewTransactionState();\n}\n\nclass _NewTransactionState extends State\u003cNewTransaction\u003e {\n  final TextEditingController titleController = TextEditingController();\n  final TextEditingController amountController = TextEditingController();\n\n  void submitData() {\n    // .trim() will remove leading whitespace if any\n\n    final enteredTitle = titleController.text.trim();\n    double? enteredAmount = 0;\n\n    // before applying double.parse(), first check if it really has numbers\n    // then remove everything from the string but keep only numbers and a dot\n    if (amountController.text.contains(RegExp('[1-9]'))) {\n      enteredAmount = double.parse(\n          amountController.text.trim().replaceAll(RegExp('[^0-9.]'), ''));\n    }\n\n    if (!titleController.text.contains(RegExp('[a-zA-Z0-9]')) ||\n        amountController.text.isEmpty ||\n        enteredAmount \u003c= 0 ||\n        amountController.text.contains(RegExp('[a-zA-Z,]'))) {\n      return;\n    }\n\n    widget.txnDetails(\n      enteredTitle,\n      enteredAmount,\n    );\n    Navigator.of(context).pop();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Container(\n      color: null,\n      child: Card(\n        elevation: 5,\n        child: Container(\n          color: null,\n          padding: const EdgeInsets.all(12.0),\n          child: Column(\n            crossAxisAlignment: CrossAxisAlignment.end,\n            children: \u003cWidget\u003e[\n              TextField(\n                decoration: const InputDecoration(labelText: 'Title'),\n                controller: titleController,\n              ),\n              TextField(\n                decoration: const InputDecoration(labelText: 'Amount'),\n                controller: amountController,\n                keyboardType: TextInputType.number,\n              ),\n              TextButton(\n                  onPressed: submitData, child: const Text('Add Transaction'))\n            ],\n          ),\n        ),\n      ),\n    );\n  }\n}\n```\n\n\n## Add and open external link / hyperlink in flutter\n```dart\nimport 'package:flutter/material.dart';\n// add url_launcher and import\nimport 'package:url_launcher/url_launcher.dart';\n\n\n//use _openLink(\"your_url_here\") //\n//for an action to open a link where required\nFuture\u003cvoid\u003e _openLink(myUrl) async {\n  if (!await launchUrl(Uri.parse(myUrl))) {\n    throw 'could not open link';\n  }\n}\n//////////////////\n\nvoid main() {\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: \"my app\",\n      home: Scaffold(\n          body: Center(\n        child: ElevatedButton(\n            onPressed: () {\n              // use of url opener : _openLink()\n              _openLink(\"https://flutter.dev/\");\n            },\n            child: const Text('Test link opener')),\n      )),\n    );\n  }\n}\n```\n\n\n## Flutter App ListView builder\n\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:english_words/english_words.dart';\n\nvoid main() {\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({Key? key}) : super(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: \"Flutter App List View\",\n      theme: ThemeData(primarySwatch: Colors.red),\n      home: Scaffold(\n          appBar: AppBar(title: const Text(\"Flutter App ListView\")),\n          body: const Center(\n            child: RandomWords(),\n          )),\n    );\n  }\n}\n\nclass RandomWords extends StatefulWidget {\n  const RandomWords({Key? key}) : super(key: key);\n\n  @override\n  State\u003cRandomWords\u003e createState() =\u003e _RandomWordsState();\n}\n\nclass _RandomWordsState extends State\u003cRandomWords\u003e {\n  final _suggestions = \u003cWordPair\u003e[];\n  final _titleFont = const TextStyle(fontSize: 20);\n  @override\n  Widget build(BuildContext context) {\n    // lazyloaded ListView builder in flutter\n    return ListView.builder(itemBuilder: (context, index) {\n      if (index.isOdd) {\n        return const Divider();\n      }\n      final i = index ~/ 2;\n      if (i \u003e= _suggestions.length) {\n        _suggestions.addAll(generateWordPairs().take(5));\n      }\n\n      return ListTile(\n          title: Text(\n        _suggestions[i].asSnakeCase,\n        style: _titleFont,\n      ));\n    });\n  }\n}\n\n```\n\n## Flutter ListView - ListTile with trailing Icon\n\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:english_words/english_words.dart';\n\nvoid main() {\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({Key? key}) : super(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    return const MaterialApp(\n      title: \"Flutter ListView with Trailing Icon\",\n      home: ViewWordList(),\n    );\n  }\n}\n\nclass ViewWordList extends StatefulWidget {\n  const ViewWordList({Key? key}) : super(key: key);\n\n  @override\n  State\u003cViewWordList\u003e createState() =\u003e _ViewWordListState();\n}\n\nclass _ViewWordListState extends State\u003cViewWordList\u003e {\n  final _wordCollection = \u003cWordPair\u003e[];\n  final _titleFont = const TextStyle(fontSize: 20, color: Colors.blue);\n  final _saved = \u003cWordPair\u003e[];\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: const Text(\"Flutter ListView with trailing Icon\"),\n      ),\n      body: ListView.builder(itemBuilder: (context, index) {\n        if (index.isOdd) {\n          return const Divider();\n        }\n        final i = index ~/ 2;\n        if (i \u003e= _wordCollection.length) {\n          _wordCollection.addAll(generateWordPairs().take(10));\n        }\n\n        final isSaved = _saved.contains(_wordCollection[i]);\n\n        return ListTile(\n          title: Text(\n            _wordCollection[i].asSnakeCase,\n            style: _titleFont,\n          ),\n          trailing: Icon(\n            isSaved ? Icons.favorite : Icons.favorite_border,\n            color: isSaved ? Colors.red : null,\n            semanticLabel: isSaved ? \"remove\" : \"save\",\n          ),\n          onTap: () {\n            setState(() {\n              isSaved\n                  ? _saved.remove(_wordCollection[i])\n                  : _saved.add(_wordCollection[i]);\n            });\n          },\n        );\n      }),\n    );\n  }\n}\n\n\n```\n\n\n## Flutter Menu - Open a new page\n\n```dart\nimport 'package:flutter/material.dart';\n\nvoid main() {\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return const MaterialApp(\n      title: \"Fluter menu- opening new page\",\n      home: HomePage(),\n    );\n  }\n}\n\nclass HomePage extends StatefulWidget {\n  const HomePage({super.key});\n\n  @override\n  State\u003cHomePage\u003e createState() =\u003e _HomePageState();\n}\n\nclass _HomePageState extends State\u003cHomePage\u003e {\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: const Text(\"Home page\"),\n        actions: [\n          IconButton(\n            onPressed: _newPage,\n            icon: const Icon(Icons.list),\n          ),\n        ],\n      ),\n      body: Container(\n        padding: const EdgeInsets.all(16.0),\n        child: Column(\n          mainAxisAlignment: MainAxisAlignment.center,\n          children: [\n            const Text(\n              \"Press the Menu icon to open a new page. Also you can open the new page with this button.\",\n            ),\n            const Divider(),\n            const Padding(padding: EdgeInsets.all(10.0)),\n            ElevatedButton(\n              onPressed: _newPage,\n              child: const Text(\"Also can use this button\"),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n\n  void _newPage() {\n    Navigator.of(context).push(\n      MaterialPageRoute(\n        builder: (context) {\n          return Scaffold(\n            appBar: AppBar(\n              title: const Text(\"New page\"),\n            ),\n            body: const Center(\n              child: Text(\"New page contents here\"),\n            ),\n          );\n        },\n      ),\n    );\n  }\n}\n\n```\n\n## View saved items in a new page in Flutter\n\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:english_words/english_words.dart';\n\nvoid main() {\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return const MaterialApp(\n      title: \"View saved items in a new page in Flutter\",\n      home: HomePage(),\n    );\n  }\n}\n\nclass HomePage extends StatefulWidget {\n  const HomePage({super.key});\n\n  @override\n  State\u003cHomePage\u003e createState() =\u003e _HomePageState();\n}\n\nclass _HomePageState extends State\u003cHomePage\u003e {\n  final _wordCollection = \u003cWordPair\u003e[];\n  final _savedItems = \u003cWordPair\u003e[];\n  final _titleFont = const TextStyle(\n    fontSize: 20,\n    color: Colors.blue,\n  );\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: const Text(\"Home page: view all\"),\n        actions: [\n          IconButton(\n            onPressed: _viewSavedItems,\n            icon: const Icon(Icons.list),\n          ),\n        ],\n      ),\n      body: Column(\n        crossAxisAlignment: CrossAxisAlignment.start,\n        children: [\n          Padding(\n            padding: const EdgeInsets.all(15.0),\n            child: _savedItems.isNotEmpty\n                ? const Text(\"Press menu icon to see all your saved items.\")\n                : const Text(\n                    \"You haven't any saved collection. To save an item, just tap it.\"),\n          ),\n          const Divider(),\n          Expanded(\n            child: ListView.builder(\n              itemBuilder: (context, index) {\n                if (index.isOdd) {\n                  return const Divider();\n                }\n                final i = index ~/ 2;\n                if (i \u003e= _wordCollection.length) {\n                  _wordCollection.addAll(generateWordPairs().take(10));\n                }\n                final isItemSaved = _savedItems.contains(_wordCollection[i]);\n\n                return ListTile(\n                  title: Text(\n                    _wordCollection[i].asSnakeCase,\n                    style: _titleFont,\n                  ),\n                  subtitle: isItemSaved\n                      ? const Text(\"You like it\")\n                      : const Text(\"Like? Tap to save\"),\n                  trailing: Icon(\n                    isItemSaved ? Icons.favorite : Icons.favorite_border,\n                    color: isItemSaved ? Colors.red : null,\n                  ),\n                  onTap: () {\n                    setState(() {\n                      isItemSaved\n                          ? _savedItems.remove(_wordCollection[i])\n                          : _savedItems.add(_wordCollection[i]);\n                    });\n                  },\n                );\n              },\n            ),\n          )\n        ],\n      ),\n    );\n  }\n\n  void _viewSavedItems() {\n    Navigator.of(context).push(\n      MaterialPageRoute\u003cvoid\u003e(\n        builder: ((context) {\n          final tiles = _savedItems.map((e) {\n            return ListTile(\n              title: Text(\n                e.asSnakeCase,\n                style: _titleFont,\n              ),\n            );\n          });\n\n          final viewSelectedItems = tiles.isNotEmpty\n              ? ListTile.divideTiles(\n                  context: context,\n                  tiles: tiles,\n                ).toList()\n              : \u003cWidget\u003e[];\n          return Scaffold(\n            appBar: AppBar(\n              title: const Text(\"Your saved items\"),\n            ),\n            body: ListView(\n              children: viewSelectedItems,\n            ),\n          );\n        }),\n      ),\n    );\n  }\n}\n\n```\n\n## Full width button setup in Flutter\n\n```dart\nimport 'package:flutter/material.dart';\n\nvoid main() {\n  runApp(const MyApp());\n}\n\nconst _titleFont = TextStyle(fontSize: 20, color: Colors.blue);\n\nclass MyApp extends StatelessWidget {\n  const MyApp({Key? key}) : super(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: \"Full width button setup in Flutter\",\n      theme: ThemeData(\n        appBarTheme: const AppBarTheme(\n          backgroundColor: Colors.blue,\n          foregroundColor: Colors.white,\n        ),\n      ),\n      home: Scaffold(\n          appBar: AppBar(\n            title: const Text(\"Sign up\"),\n          ),\n          body: Container(\n            color: Colors.white54,\n            padding: const EdgeInsets.all(16.0),\n            child: Column(\n              mainAxisAlignment: MainAxisAlignment.start,\n              crossAxisAlignment: CrossAxisAlignment.start,\n              children: [\n                Container(\n                  padding: null,\n                  child: const Center(\n                    child: Text(\n                      \"Please sign up\",\n                      style: _titleFont,\n                    ),\n                  ),\n                ),\n                const SizedBox(\n                  height: 30.0,\n                ),\n                Container(\n                  color: null,\n                  child: TextFormField(\n                    decoration: const InputDecoration(\n                      border: OutlineInputBorder(),\n                      labelText: \"First name\",\n                    ),\n                  ),\n                ),\n                const SizedBox(\n                  height: 10,\n                ),\n                Container(\n                  color: null,\n                  child: TextFormField(\n                    decoration: const InputDecoration(\n                      border: OutlineInputBorder(),\n                      labelText: \"Last name\",\n                    ),\n                  ),\n                ),\n                const SizedBox(height: 10),\n                Container(\n                  color: null,\n                  child: TextFormField(\n                    decoration: const InputDecoration(\n                      border: OutlineInputBorder(),\n                      labelText: \"Email\",\n                    ),\n                  ),\n                ),\n                const SizedBox(height: 10),\n                Container(\n                  color: null,\n                  child: TextFormField(\n                    decoration: const InputDecoration(\n                      border: OutlineInputBorder(),\n                      labelText: \"Mobile number\",\n                    ),\n                  ),\n                ),\n                const SizedBox(height: 10),\n                const SizedBox(\n                  height: 50,\n                  //this will make the button full width        \n                  width: double.infinity,\n                  child: ElevatedButton(\n                    onPressed: _onSubmitSignupData,\n                    child: Text(\"Submit\"),\n                  ),\n                ),\n                const SizedBox(\n                  height: 30.0,\n                ),\n                const Text(\n                  \"Have an account? Login here\",\n                  style: TextStyle(\n                    color: Colors.blue,\n                    decoration: TextDecoration.underline,\n                  ),\n                ),\n              ],\n            ),\n          )),\n    );\n  }\n}\n\nvoid _onSubmitSignupData() {}\n\n```\n\n## Set full screen background image in Flutter\n\n```dart\nimport 'package:flutter/material.dart';\n\nvoid main() {\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: \"Set full screen background image in Flutter\",\n      theme: ThemeData(primarySwatch: Colors.pink),\n      home: const Homepage(),\n    );\n  }\n}\n\nclass Homepage extends StatefulWidget {\n  const Homepage({super.key});\n  @override\n  State\u003cHomepage\u003e createState() =\u003e _HomepageState();\n}\n\nclass _HomepageState extends State\u003cHomepage\u003e {\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: const Text(\"Full screen background image\"),\n      ),\n      body: Container(\n        padding: const EdgeInsets.all(16.0),\n        color: null,\n\n        //this will set background image\n        decoration: const BoxDecoration(\n          image: DecorationImage(\n            image: AssetImage(\"assets/images/bg-image-1.jpg\"),\n            // use BoxFit to size background image\n            // BoxFit.fill / BoxFit.cover / and other options you can use\n            // based on your requirement\n            fit: BoxFit.fill,\n          ),\n        ),\n        child: const Center(\n            child: Text(\"To setup full screen background image, \"\n                \"use DecorationImage and set required size with BoxFit\")),\n      ),\n    );\n  }\n}\n\n```\n\n## Flutter page navigation create and clear routes\n### Main app\n```dart\nimport 'package:flutter/material.dart';\nimport 'home_page.dart';\nimport 'product_page.dart';\nimport 'cart_page.dart';\n\nvoid main() {\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: \"Flutter Navigation\",\n      theme: ThemeData(primarySwatch: Colors.orange),\n      initialRoute: '/',\n      routes: {\n        '/': (context) =\u003e const HomePage(),\n        '/products': (context) =\u003e const ProductPage(),\n        '/cart': (context) =\u003e const CartPage(),\n      },\n    );\n  }\n}\n\n```\n### Home page\n\n```dart\nimport 'package:flutter/material.dart';\n\nclass HomePage extends StatelessWidget {\n  const HomePage({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text(\"Home\")),\n      body: Center(\n        child: Center(\n          child: ElevatedButton(\n            onPressed: () {\n              Navigator.pushNamed(context, '/products');\n            },\n            child: const Text(\"See all products\"),\n          ),\n        ),\n      ),\n    );\n  }\n}\n\n```\n### Product page\n\n```dart\nimport 'package:flutter/material.dart';\n\nclass ProductPage extends StatelessWidget {\n  const ProductPage({super.key});\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text(\"Shop\")),\n      body: Center(\n        child: ElevatedButton(\n          onPressed: () {\n            Navigator.pushNamed(context, '/cart');\n          },\n          child: const Text(\"View cart\"),\n        ),\n      ),\n    );\n  }\n}\n\n```\n\n### Cart page\n\n```dart\nimport 'package:flutter/material.dart';\n\nclass CartPage extends StatelessWidget {\n  const CartPage({super.key});\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text(\"Cart\")),\n      body: Center(\n        child: ElevatedButton(\n          onPressed: () {\n            // this will go back upto the given route name\n            Navigator.of(context).popUntil(ModalRoute.withName('/'));\n\n            // and this will go back to the first route\n            // Navigator.popUntil(context, (route) =\u003e route.isFirst);\n          },\n          child: const Text(\"Clear all routes and back to Homepage\"),\n        ),\n      ),\n    );\n  }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferabossid%2Fflutter-fix","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ferabossid%2Fflutter-fix","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferabossid%2Fflutter-fix/lists"}