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
1 Answer
Reset to default 0When 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条)