Remove the card-like design for food entries and make the 'delete' button dynamically appear

This commit is contained in:
Marco 2024-09-06 02:23:47 +02:00
parent 1db4e5e351
commit 6552756702
6 changed files with 150 additions and 91 deletions

View File

@ -34,7 +34,10 @@ class _EnterFoodWidgetState extends State<EnterFoodWidget> {
return TextFormField(
controller: controller,
focusNode: focusNode,
decoration: const InputDecoration(label: Text("Name")));
decoration: const InputDecoration(
label: Text("Name"),
),
);
},
optionsBuilder: (TextEditingValue textEditingValue) {
if (textEditingValue.text == '') {
@ -57,30 +60,54 @@ class _EnterFoodWidgetState extends State<EnterFoodWidget> {
});
var massWidget = TextField(
decoration: const InputDecoration(label: Text("Menge")),
textAlign: TextAlign.end,
decoration: const InputDecoration(
label: Align(alignment: Alignment.centerRight, child: Text("Menge")),
),
keyboardType: TextInputType.number,
controller: massController,
onSubmitted: (value) => onSubmitAction(),
);
var kcalPerMassWidget = TextField(
decoration: const InputDecoration(label: Text("kcal pro")),
textAlign: TextAlign.end,
decoration: const InputDecoration(
label:
Align(alignment: Alignment.centerRight, child: Text("kcal pro"))),
keyboardType: TextInputType.number,
controller: kcalPerMassController);
controller: kcalPerMassController,
onSubmitted: (value) => onSubmitAction(),
);
var enterButton = ElevatedButton(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.zero,
),
onPressed: () {
onPressed: () => onSubmitAction(),
child: const Icon(Icons.add));
return Padding(
padding: const EdgeInsets.only(left: 8.0, right: 4.0),
child: RowWidget(
nameWidget,
massWidget,
kcalPerMassWidget,
Padding(
padding: const EdgeInsets.only(left: 16.0),
child: enterButton,
),
),
);
}
void onSubmitAction() {
double massAsNumber = 0.0;
double kcalPerMassAsNumber = 0.0;
try {
massAsNumber =
double.parse(massController.text.replaceAll(",", "."));
massAsNumber = double.parse(massController.text.replaceAll(",", "."));
} catch (e) {
var snackbar =
const SnackBar(content: Text("Menge muss eine Zahl sein"));
var snackbar = const SnackBar(content: Text("Menge muss eine Zahl sein"));
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(snackbar);
return;
@ -90,18 +117,16 @@ class _EnterFoodWidgetState extends State<EnterFoodWidget> {
kcalPerMassAsNumber =
double.parse(kcalPerMassController.text.replaceAll(",", "."));
} catch (e) {
var snackbar = const SnackBar(
content: Text("'kcal pro 100g' muss eine Zahl sein"));
var snackbar =
const SnackBar(content: Text("'kcal pro 100g' muss eine Zahl sein"));
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(snackbar);
return;
}
try {
massAsNumber =
double.parse(massController.text.replaceAll(",", "."));
massAsNumber = double.parse(massController.text.replaceAll(",", "."));
} catch (e) {
var snackbar =
const SnackBar(content: Text("Menge muss eine Zahl sein"));
var snackbar = const SnackBar(content: Text("Menge muss eine Zahl sein"));
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(snackbar);
return;
@ -113,18 +138,5 @@ class _EnterFoodWidgetState extends State<EnterFoodWidget> {
kcalPerMass: kcalPerMassAsNumber);
widget.onAdd(context, entry);
},
child: const Icon(Icons.add));
return Padding(
padding: const EdgeInsets.only(left: 8.0, right: 4.0),
child: RowWidget(
nameWidget,
massWidget,
kcalPerMassWidget,
null,
enterButton,
),
);
}
}

View File

@ -2,38 +2,94 @@ import 'package:flutter/material.dart';
import 'package:calodiary/food_entry_bloc.dart';
import 'package:calodiary/row_with_spacers_widget.dart';
class FoodEntryWidget extends StatelessWidget {
class FoodEntryWidget extends StatefulWidget {
final FoodEntry entry;
final Function(BuildContext context, String id) onDelete;
const FoodEntryWidget(
{super.key, required this.entry, required this.onDelete});
@override
State<FoodEntryWidget> createState() => _FoodEntryWidgetState();
}
class _FoodEntryWidgetState extends State<FoodEntryWidget> {
late bool showCancelAndDelete;
@override
void initState() {
showCancelAndDelete = false;
super.initState();
}
@override
Widget build(BuildContext context) {
return Dismissible(
key: ValueKey(entry.id),
onDismissed: (direction) {
onDelete(context, entry.id);
return GestureDetector(
onTap: () {
setState(() {
showCancelAndDelete = !showCancelAndDelete;
});
},
child: Card(
elevation: 5.0,
child: Stack(
children: [
Positioned.fill(
child: Stack(children: [
Positioned.fill(
child: Padding(
padding: const EdgeInsets.only(left: 4.0),
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: RowWidget(
Text(entry.name),
Text(entry.mass.ceil().toString()),
Text(entry.kcalPerMass.ceil().toString()),
Text((entry.mass * entry.kcalPerMass / 100).ceil().toString()),
IconButton(
style: IconButton.styleFrom(padding: EdgeInsets.zero),
onPressed: () {
onDelete(context, entry.id);
},
icon: const Icon(Icons.delete_forever_rounded)),
Text(widget.entry.name),
Text(widget.entry.mass.ceil().toString(),
textAlign: TextAlign.end),
Text(widget.entry.kcalPerMass.ceil().toString(),
textAlign: TextAlign.end),
Opacity(
opacity: showCancelAndDelete ? 0.0 : 1.0,
child: Text(
(widget.entry.mass * widget.entry.kcalPerMass / 100)
.ceil()
.toString(),
textAlign: TextAlign.end),
),
),
),
),
Opacity(
opacity: showCancelAndDelete ? 0.66 : 0.0,
child: Container(
color: Theme.of(context).colorScheme.secondary)),
]),
),
Opacity(
opacity: showCancelAndDelete ? 1.0 : 0.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
SizedBox(
child: IconButton(
padding: EdgeInsets.all(0.0),
icon: const Icon(Icons.cancel),
onPressed: showCancelAndDelete
? () => setState(() {
showCancelAndDelete = false;
})
: null,
),
),
SizedBox(
child: IconButton(
padding: EdgeInsets.all(0.0),
iconSize: 24,
icon: const Icon(Icons.delete),
color: Colors.redAccent,
onPressed: showCancelAndDelete
? () => widget.onDelete(context, widget.entry.id)
: null),
),
],
),
),
],
),
);
}
}

View File

@ -68,6 +68,7 @@ class MainApp extends StatelessWidget {
Locale('de'),
],
theme: ThemeData(
dividerTheme: const DividerThemeData(space: 2),
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.lightBlue,
brightness: newBrightness,

View File

@ -94,6 +94,7 @@ class _PerDateWidgetState extends State<PerDateWidget> {
return Column(
children: [
FoodEntryWidget(
key: ValueKey(state.foodEntries[entryIndex].id),
entry: state.foodEntries[entryIndex],
onDelete: (callbackContext, id) {
callbackContext
@ -103,7 +104,6 @@ class _PerDateWidgetState extends State<PerDateWidget> {
));
},
),
if (listIndex != state.foodEntries.length - 1)
const Divider(),
],
);

View File

@ -1,31 +1,22 @@
import 'package:flutter/material.dart';
class RowWidget extends StatefulWidget {
class RowWidget extends StatelessWidget {
final Widget? widget1;
final Widget? widget2;
final Widget? widget3;
final Widget? widget4;
final Widget? widget5;
const RowWidget(
this.widget1, this.widget2, this.widget3, this.widget4, this.widget5,
const RowWidget(this.widget1, this.widget2, this.widget3, this.widget4,
{super.key});
@override
State<RowWidget> createState() => _RowWidgetState();
}
class _RowWidgetState extends State<RowWidget> {
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(flex: 10, child: widget.widget1 ?? Container()),
Expanded(flex: 6, child: widget.widget2 ?? Container()),
Expanded(flex: 6, child: widget.widget3 ?? Container()),
Expanded(flex: 8, child: widget.widget4 ?? Container()),
Expanded(flex: 3, child: widget.widget5 ?? Container()),
Expanded(flex: 10, child: widget1 ?? Container()),
Expanded(flex: 6, child: widget2 ?? Container()),
Expanded(flex: 6, child: widget3 ?? Container()),
Expanded(flex: 6, child: widget4 ?? Container()),
],
);
}

View File

@ -33,7 +33,6 @@ class _SumWidgetState extends State<SumWidget> {
null,
null,
null,
null,
);
},
);