dart - I am unable to fix the overflow issue in my app that I am practicing with flutter from a course - Stack Overflow

The problem is that whenever I open the model bottom sheet and when the keyboard appears on pressing a

The problem is that whenever I open the model bottom sheet and when the keyboard appears on pressing a text field the chart widget behind the ModalBottomSheet overflows and this only happens when I switch to landscape mode.

link to a clip of the problem .gif

Below is the code for BottomSheet Widget and The Widget that wraps everything:

BottomSheet.dart

import 'package:expense_tracker/model/expense.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class ExpenseAdd extends StatefulWidget {
 const ExpenseAdd({required this.addExpense,required this.removeExpense ,super.key});
 final void Function(Expense expense) addExpense;
 final void Function(Expense expense) removeExpense;

 

 @override
 State<ExpenseAdd> createState() => _ExpenseAddState();
}

class _ExpenseAddState extends State<ExpenseAdd> {
 final TextEditingController _titleController = TextEditingController();
 final TextEditingController _amountController = TextEditingController();
 Category category = Category.leisure;
 DateTime? daTe;

 void _datePickerOverlay() {
   final date = DateTime.now();
   final firstDate = DateTime(date.year - 1);
   

   showDatePicker(
     context: context,
     firstDate: firstDate,
     lastDate: date,
     initialDate: date,
   ).then((selectedDate) {
     setState(() {
       daTe = selectedDate;
     });
   });
 }

 void _checkSubmittion() {
   final String title = _titleController.text;
   final String amount = _amountController.text;

   if (title.trim().isEmpty || amount.trim().isEmpty || daTe == null) {
     showDialog(
       context: context,
       builder: (ctx) {
         return AlertDialog(
           title: Text('Alert'),
           content: Text(
             'Make sure you have entered correct input and left no required fields empty.',
           ),
         );
       },
     );
     return;
   }
   widget.addExpense(Expense(title: title, amount: double.parse(amount), date: daTe!, category: category,),);
   Navigator.pop(context);
   return;

 }

 @override
 void dispose() {
   _titleController.dispose();
   _amountController.dispose();
   super.dispose();
 }

 @override
 Widget build(context) {
 
   return 
      SizedBox(
       height: double.infinity,
        child: SingleChildScrollView(
          child: Padding(
             padding: EdgeInsets.fromLTRB(16, 48, 16, 0),
             child: Column(
               children: [
                 const SizedBox(height: 20),
                 Text('Add New Expense'),
                 const SizedBox(height: 20),
                 TextField(
                   
                   controller: _titleController,
                   decoration: InputDecoration(
                      prefixIcon: Icon(Icons.edit),
                     label: Text('Title'),
                     border: OutlineInputBorder(),
                   ),
                 ),
                 const SizedBox(height: 20),
                Row(
                     children: [
                       Expanded(
                         child: TextField(
                           keyboardType: TextInputType.number,
                           controller: _amountController,
                           decoration: InputDecoration(
           
                             prefixIcon: Icon(Icons.monetization_on_sharp),
                             label: Text('Amount'),
                             border: OutlineInputBorder(
                               
                             ),
                           ),
                         ),
                       ),
                       const SizedBox(width: 20),
                       Flexible(
                         child: Row(
                           children: [
                             Spacer(),
                             Flexible(
                               child: Text(
                                 (daTe == null
                                     ? 'No date selected'
                                     : formatter.format(daTe!)),
                               ),
                             ),
                             IconButton(
                               onPressed: () {
                                 _datePickerOverlay();
                               },
                               icon: Icon(Icons.calendar_month),
                             ),
                           ],
                         ),
                       ),
                     ],
                   ),
                 
                 const SizedBox(height: 20),
                Row(
                     children: [
                       const SizedBox(width: 10),
                       DropdownButton(
                         value: category,
                         items:
                             Category.values.map((category) {
                               return DropdownMenuItem(
                                 value: category,
                                 child: Text(category.name.toString()),
                               );
                             }).toList(),
                         onChanged: (value) {
                           setState(() {
                             category = value!;
                           });
                         },
                       ),
                       Flexible(
                         child: Row(
                           children: [
                             Spacer(),
                             TextButton(
                               onPressed: () {
                                 Navigator.pop(context);
                               },
                               child: Text('Cancel'),
                             ),
                             const SizedBox(width: 10),
                             FilledButton(onPressed: () {
                               _checkSubmittion();
                             }, child: Text('Save')),
                           ],
                         ),
                       ),
                     ],
                   ),
                 
               ],
             ),
           
                
              ),
        ),
      );
 }
}

expense_tracker.dart

import 'package:expense_tracker/model/expense.dart';
import 'package:expense_tracker/widget/chart.dart';
import 'package:expense_tracker/widget/expense_add.dart';
import 'package:expense_tracker/widget/list_of_expense.dart';
import 'package:flutter/material.dart';

class ExpenseTracker extends StatefulWidget {
  const ExpenseTracker({super.key});

  @override
  State<ExpenseTracker> createState() => _ExpenseTrackerState();
}

class _ExpenseTrackerState extends State<ExpenseTracker> {
  final List<Expense> expenses = [
   
  ];

  void _addExpenseOverlay() {
    showModalBottomSheet(
      useSafeArea: true,
      isScrollControlled: true,
      context: context,
      builder: (ctx) {
        return ExpenseAdd(
          addExpense: _addExpense,
          removeExpense: _removeExpense,
        );
      },
    );
  }

  void _addExpense(Expense expense) {
    setState(() {
      expenses.add(expense);
    });
  }

  void _removeExpense(Expense expense) {
    setState(() {
      expenses.remove(expense);
    });
  }

  void _undoDelete(Expense expense, index) {
    setState(() {
      expenses.insert(index, expense);
    });
  }

  @override
  Widget build(context) {
    final width  = MediaQuery.of(context).size.width;
    return Scaffold(
      resizeToAvoidBottomInset: true,
      appBar: AppBar(
        title: Text('XP Tracker'),
        actions: [
          IconButton(
            onPressed: () {
              _addExpenseOverlay();
            },
            icon: Icon(Icons.add),
          ),
        ],
      ),
      body: Center(
        child: width < 600 ? Column(
          children: [
            Chart(expenses: expenses),
            (expenses.isEmpty
                ? Center(child: Text('No Expense found.'))
                : Expanded(
                  child: ListOfExpense(
                    expenses: expenses,
                    removeExpense: _removeExpense,
                    undoDelete: _undoDelete,
                  ),
                )),
          ],
        ) : Row(
          children: [
            Expanded(child: Chart(expenses: expenses)),
            (expenses.isEmpty
                ? Center(child: Text('No Expense found.'))
                : Expanded(
                  child: ListOfExpense(
                    expenses: expenses,
                    removeExpense: _removeExpense,
                    undoDelete: _undoDelete,
                  ),
                )),
          ],
        ),
      ),
    );
  }
}

The problem is that whenever I open the model bottom sheet and when the keyboard appears on pressing a text field the chart widget behind the ModalBottomSheet overflows and this only happens when I switch to landscape mode.

link to a clip of the problem https://s1.ezgif/tmp/ezgif-1680ad1de76705.gif

Below is the code for BottomSheet Widget and The Widget that wraps everything:

BottomSheet.dart

import 'package:expense_tracker/model/expense.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class ExpenseAdd extends StatefulWidget {
 const ExpenseAdd({required this.addExpense,required this.removeExpense ,super.key});
 final void Function(Expense expense) addExpense;
 final void Function(Expense expense) removeExpense;

 

 @override
 State<ExpenseAdd> createState() => _ExpenseAddState();
}

class _ExpenseAddState extends State<ExpenseAdd> {
 final TextEditingController _titleController = TextEditingController();
 final TextEditingController _amountController = TextEditingController();
 Category category = Category.leisure;
 DateTime? daTe;

 void _datePickerOverlay() {
   final date = DateTime.now();
   final firstDate = DateTime(date.year - 1);
   

   showDatePicker(
     context: context,
     firstDate: firstDate,
     lastDate: date,
     initialDate: date,
   ).then((selectedDate) {
     setState(() {
       daTe = selectedDate;
     });
   });
 }

 void _checkSubmittion() {
   final String title = _titleController.text;
   final String amount = _amountController.text;

   if (title.trim().isEmpty || amount.trim().isEmpty || daTe == null) {
     showDialog(
       context: context,
       builder: (ctx) {
         return AlertDialog(
           title: Text('Alert'),
           content: Text(
             'Make sure you have entered correct input and left no required fields empty.',
           ),
         );
       },
     );
     return;
   }
   widget.addExpense(Expense(title: title, amount: double.parse(amount), date: daTe!, category: category,),);
   Navigator.pop(context);
   return;

 }

 @override
 void dispose() {
   _titleController.dispose();
   _amountController.dispose();
   super.dispose();
 }

 @override
 Widget build(context) {
 
   return 
      SizedBox(
       height: double.infinity,
        child: SingleChildScrollView(
          child: Padding(
             padding: EdgeInsets.fromLTRB(16, 48, 16, 0),
             child: Column(
               children: [
                 const SizedBox(height: 20),
                 Text('Add New Expense'),
                 const SizedBox(height: 20),
                 TextField(
                   
                   controller: _titleController,
                   decoration: InputDecoration(
                      prefixIcon: Icon(Icons.edit),
                     label: Text('Title'),
                     border: OutlineInputBorder(),
                   ),
                 ),
                 const SizedBox(height: 20),
                Row(
                     children: [
                       Expanded(
                         child: TextField(
                           keyboardType: TextInputType.number,
                           controller: _amountController,
                           decoration: InputDecoration(
           
                             prefixIcon: Icon(Icons.monetization_on_sharp),
                             label: Text('Amount'),
                             border: OutlineInputBorder(
                               
                             ),
                           ),
                         ),
                       ),
                       const SizedBox(width: 20),
                       Flexible(
                         child: Row(
                           children: [
                             Spacer(),
                             Flexible(
                               child: Text(
                                 (daTe == null
                                     ? 'No date selected'
                                     : formatter.format(daTe!)),
                               ),
                             ),
                             IconButton(
                               onPressed: () {
                                 _datePickerOverlay();
                               },
                               icon: Icon(Icons.calendar_month),
                             ),
                           ],
                         ),
                       ),
                     ],
                   ),
                 
                 const SizedBox(height: 20),
                Row(
                     children: [
                       const SizedBox(width: 10),
                       DropdownButton(
                         value: category,
                         items:
                             Category.values.map((category) {
                               return DropdownMenuItem(
                                 value: category,
                                 child: Text(category.name.toString()),
                               );
                             }).toList(),
                         onChanged: (value) {
                           setState(() {
                             category = value!;
                           });
                         },
                       ),
                       Flexible(
                         child: Row(
                           children: [
                             Spacer(),
                             TextButton(
                               onPressed: () {
                                 Navigator.pop(context);
                               },
                               child: Text('Cancel'),
                             ),
                             const SizedBox(width: 10),
                             FilledButton(onPressed: () {
                               _checkSubmittion();
                             }, child: Text('Save')),
                           ],
                         ),
                       ),
                     ],
                   ),
                 
               ],
             ),
           
                
              ),
        ),
      );
 }
}

expense_tracker.dart

import 'package:expense_tracker/model/expense.dart';
import 'package:expense_tracker/widget/chart.dart';
import 'package:expense_tracker/widget/expense_add.dart';
import 'package:expense_tracker/widget/list_of_expense.dart';
import 'package:flutter/material.dart';

class ExpenseTracker extends StatefulWidget {
  const ExpenseTracker({super.key});

  @override
  State<ExpenseTracker> createState() => _ExpenseTrackerState();
}

class _ExpenseTrackerState extends State<ExpenseTracker> {
  final List<Expense> expenses = [
   
  ];

  void _addExpenseOverlay() {
    showModalBottomSheet(
      useSafeArea: true,
      isScrollControlled: true,
      context: context,
      builder: (ctx) {
        return ExpenseAdd(
          addExpense: _addExpense,
          removeExpense: _removeExpense,
        );
      },
    );
  }

  void _addExpense(Expense expense) {
    setState(() {
      expenses.add(expense);
    });
  }

  void _removeExpense(Expense expense) {
    setState(() {
      expenses.remove(expense);
    });
  }

  void _undoDelete(Expense expense, index) {
    setState(() {
      expenses.insert(index, expense);
    });
  }

  @override
  Widget build(context) {
    final width  = MediaQuery.of(context).size.width;
    return Scaffold(
      resizeToAvoidBottomInset: true,
      appBar: AppBar(
        title: Text('XP Tracker'),
        actions: [
          IconButton(
            onPressed: () {
              _addExpenseOverlay();
            },
            icon: Icon(Icons.add),
          ),
        ],
      ),
      body: Center(
        child: width < 600 ? Column(
          children: [
            Chart(expenses: expenses),
            (expenses.isEmpty
                ? Center(child: Text('No Expense found.'))
                : Expanded(
                  child: ListOfExpense(
                    expenses: expenses,
                    removeExpense: _removeExpense,
                    undoDelete: _undoDelete,
                  ),
                )),
          ],
        ) : Row(
          children: [
            Expanded(child: Chart(expenses: expenses)),
            (expenses.isEmpty
                ? Center(child: Text('No Expense found.'))
                : Expanded(
                  child: ListOfExpense(
                    expenses: expenses,
                    removeExpense: _removeExpense,
                    undoDelete: _undoDelete,
                  ),
                )),
          ],
        ),
      ),
    );
  }
}

Share Improve this question asked Mar 25 at 11:14 Sameer AhmedSameer Ahmed 31 bronze badge
Add a comment  | 

1 Answer 1

Reset to default 0

When the keyboard appears, the Row that contains your Chart does not have a sufficient height, and a layout error occurs in your Chart. We don't know what the chart looks like, but one of its children requires more height than available with the keyboard present in landscape mode.

In such a case, a possible solution can be to wrap your Scaffold body in a SingleChildScrollView, so that when the space becomes too small, it will automatically scroll. But again, it really depends on what's actually going on in your Chart widget.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744201226a4562886.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信