Changed features
parent
b791a4b69f
commit
473db9335e
Binary file not shown.
After Width: | Height: | Size: 300 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.6 MiB |
|
@ -0,0 +1,35 @@
|
||||||
|
import 'package:flutter_application_1/enums.dart';
|
||||||
|
|
||||||
|
// Berechnet das investierte Geld über eine bestimmte Zeit
|
||||||
|
double calculateInvestedMoney(double initialCapital, double monthlySavingsRate, double time, List<double> investedMoneyList) {
|
||||||
|
double investedMoney = initialCapital;
|
||||||
|
investedMoneyList.clear();
|
||||||
|
for (int i = 0; i < time; i++) {
|
||||||
|
investedMoney += monthlySavingsRate * 12; // Jährliche Sparrate hinzufügen
|
||||||
|
investedMoney = investedMoney.roundToDouble();
|
||||||
|
investedMoneyList.add(investedMoney); // Investierten Betrag zur Liste hinzufügen
|
||||||
|
}
|
||||||
|
return investedMoney;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berechnet den Zinseszins über eine bestimmte Zeit.
|
||||||
|
double calculateCompoundInterest(double initialCapital, double monthlySavingsRate, double interestRate, double time, PayoutInterval payoutInterval, List<double> investedMoneyList, List<double> compoundInterestList) {
|
||||||
|
double compoundInterest = initialCapital;
|
||||||
|
compoundInterestList.clear();
|
||||||
|
if (payoutInterval == PayoutInterval.yearly) { // Berechnung für jährliche Auszahlung
|
||||||
|
for (int i = 0; i < time; i++) {
|
||||||
|
compoundInterest += compoundInterest * (interestRate / 100) + monthlySavingsRate * 12; // Zinsen und jährliche Sparrate hinzufügen
|
||||||
|
compoundInterest = compoundInterest.roundToDouble();
|
||||||
|
compoundInterestList.add(compoundInterest - investedMoneyList[i]); // Zinseszins zur Liste hinzufügen
|
||||||
|
}
|
||||||
|
} else { // Berechnung für monatliche Auszahlung
|
||||||
|
for (int i = 0; i < time; i++) {
|
||||||
|
for (int j = 0; j < 12; j++) {
|
||||||
|
compoundInterest += compoundInterest * ((interestRate / 100) / 12) + monthlySavingsRate; // Monatliche Zinsen und Sparrate hinzufügen
|
||||||
|
compoundInterest = compoundInterest.roundToDouble();
|
||||||
|
}
|
||||||
|
compoundInterestList.add(compoundInterest - investedMoneyList[i]); // Zinseszins zur Liste hinzufügen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return compoundInterest; // Gesamtkapital nach Zinseszinsberechnung zurückgeben
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter_application_1/calculator.dart';
|
||||||
import 'package:flutter_application_1/enums.dart';
|
import 'package:flutter_application_1/enums.dart';
|
||||||
import 'package:flutter_application_1/translations.dart';
|
import 'package:flutter_application_1/translations.dart';
|
||||||
import 'package:flutter_application_1/utils.dart';
|
import 'package:flutter_application_1/utils.dart';
|
||||||
|
@ -122,17 +123,15 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
_timeController.text = '10';
|
_timeController.text = '10';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double _initialCapital = 0.0; // Das anfängliche Kapital
|
||||||
double _initialCapital = 0.0; // Anfangskapital
|
double _monthlySavingsRate = 0.0; // Der monatliche Sparbetrag
|
||||||
double _monthlySavingsRate = 0.0; // Monatliche Sparrate
|
double _interestRate = 0.0; // Der jährliche Zinssatz
|
||||||
double _interestRate = 0.0; // Jährlicher Zinssatz
|
double _time = 0.0; // Der Anlagezeitraum in Jahren
|
||||||
double _time = 0.0; // Anlagezeitraum in Jahren
|
double _investedMoney = 0.0; // Das investierte Geld
|
||||||
double _investedMoney = 0.0; // Investiertes Geld ohne Zinsen
|
final List<double> _investedMoneyList = []; // Liste, die das investierte Geld pro Jahr speichert
|
||||||
final List<double> _investedMoneyList = []; // Investiertes Geld ohne Zinsen (pro Jahr)
|
PayoutInterval _payoutInterval = PayoutInterval.yearly; // Das Auszahlungsintervall (jährlich oder monatlich)
|
||||||
PayoutInterval _payoutInterval = PayoutInterval.yearly; // Standardwert für das Ausschüttungsintervall
|
double _compoundInterest = 0.0; // Der Zinseszins
|
||||||
double _compoundInterest = 0.0; // Investiertes Geld mit Zinsen
|
final List<double> _compoundInterestList = []; // Liste, die den Zinseszins pro Jahr speichert
|
||||||
final List<double> _compoundInterestList = []; // Investiertes Geld mit Zinsen (pro Jahr)
|
|
||||||
bool _calculationPerformed = false;
|
|
||||||
|
|
||||||
// Methoden zum Festlegen der Werte aus den Eingabefeldern
|
// Methoden zum Festlegen der Werte aus den Eingabefeldern
|
||||||
void setInitialCapital() {
|
void setInitialCapital() {
|
||||||
|
@ -159,44 +158,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methode zum Berechnen des investierten Geldes
|
bool calculationPerformed = false;
|
||||||
void _calculateInvestedMoney() {
|
|
||||||
setState(() {
|
|
||||||
_investedMoneyList.clear();
|
|
||||||
_investedMoney = _initialCapital;
|
|
||||||
for (int i = 0; i < _time; i++) {
|
|
||||||
_investedMoney += _monthlySavingsRate * 12;
|
|
||||||
_investedMoney = _investedMoney.roundToDouble();
|
|
||||||
_investedMoneyList.add(_investedMoney);
|
|
||||||
}
|
|
||||||
_calculationPerformed = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methode zum Berechnen der Zinsen
|
|
||||||
void _calculateCompoundInterest() {
|
|
||||||
setState(() {
|
|
||||||
_compoundInterestList.clear();
|
|
||||||
_compoundInterest = _initialCapital;
|
|
||||||
if(_payoutInterval == PayoutInterval.yearly){
|
|
||||||
for(int i = 0; i < _time; i++){
|
|
||||||
_compoundInterest += _compoundInterest * (_interestRate / 100) + _monthlySavingsRate * 12;
|
|
||||||
_compoundInterest = _compoundInterest.roundToDouble();
|
|
||||||
_compoundInterestList.add(_compoundInterest - _investedMoneyList[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
for(int i = 0; i < _time; i++){
|
|
||||||
for(int j = 0; j < 12; j++){
|
|
||||||
_compoundInterest += _compoundInterest * ((_interestRate / 100) / 12) + _monthlySavingsRate;
|
|
||||||
_compoundInterest = _compoundInterest.roundToDouble();
|
|
||||||
}
|
|
||||||
_compoundInterestList.add(_compoundInterest - _investedMoneyList[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_calculationPerformed = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -227,12 +189,18 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
setMonthlySavingsRate();
|
setMonthlySavingsRate();
|
||||||
setInterestRate();
|
setInterestRate();
|
||||||
setTime();
|
setTime();
|
||||||
_calculateInvestedMoney();
|
_investedMoney = calculateInvestedMoney(_initialCapital, _monthlySavingsRate, _time, _investedMoneyList);
|
||||||
_calculateCompoundInterest();
|
_compoundInterest = calculateCompoundInterest(_initialCapital, _monthlySavingsRate, _interestRate, _time, _payoutInterval, _investedMoneyList, _compoundInterestList);
|
||||||
|
calculationPerformed = true;
|
||||||
},
|
},
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
backgroundColor: MaterialStateProperty.all<Color>(CupertinoColors.black),
|
backgroundColor: MaterialStateProperty.all<Color>(CupertinoColors.black),
|
||||||
foregroundColor: MaterialStateProperty.all<Color>(CupertinoColors.white),
|
foregroundColor: MaterialStateProperty.all<Color>(CupertinoColors.white),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Berechnen',
|
'Berechnen',
|
||||||
|
@ -242,8 +210,8 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
if(_calculationPerformed)
|
if (calculationPerformed)
|
||||||
buildResultWidget('$_compoundInterest', '$_investedMoney', '$_time', '$_monthlySavingsRate', '$_interestRate', _payoutInterval, _investedMoneyList, _compoundInterestList),
|
buildResultWidget(context, '$_compoundInterest', '$_investedMoney', '$_time', '$_monthlySavingsRate', '$_interestRate', _payoutInterval, _investedMoneyList, _compoundInterestList),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:syncfusion_flutter_charts/charts.dart';
|
import 'package:syncfusion_flutter_charts/charts.dart';
|
||||||
|
|
||||||
// Widget für ein gestapeltes Säulendiagramm
|
// Widget zur Erstellung eines gestapelten Säulendiagramms
|
||||||
class StackedColumnChart extends StatelessWidget {
|
class StackedColumnChart extends StatelessWidget {
|
||||||
final List<double> lowerValues;
|
final List<double> lowerValues; // Liste der unteren Werte für das Diagramm
|
||||||
final List<double> upperValues;
|
final List<double> upperValues; // Liste der oberen Werte für das Diagramm
|
||||||
|
|
||||||
const StackedColumnChart({
|
const StackedColumnChart({
|
||||||
super.key,
|
super.key,
|
||||||
|
@ -16,8 +16,8 @@ class StackedColumnChart extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SfCartesianChart(
|
return SfCartesianChart(
|
||||||
legend: const Legend(
|
legend: const Legend(
|
||||||
isVisible: true, // Legende anzeigen
|
isVisible: true,
|
||||||
position: LegendPosition.top, // Legende unterhalb des Diagramms platzieren
|
position: LegendPosition.top,
|
||||||
),
|
),
|
||||||
primaryXAxis: const CategoryAxis(
|
primaryXAxis: const CategoryAxis(
|
||||||
title: AxisTitle(text: 'Jahr'),
|
title: AxisTitle(text: 'Jahr'),
|
||||||
|
@ -26,24 +26,24 @@ class StackedColumnChart extends StatelessWidget {
|
||||||
title: AxisTitle(text: 'Euro'),
|
title: AxisTitle(text: 'Euro'),
|
||||||
),
|
),
|
||||||
series: <CartesianSeries>[
|
series: <CartesianSeries>[
|
||||||
// Untere Teil der Säule
|
// Serie für die Einzahlungen (untere Werte)
|
||||||
StackedColumnSeries<SalesData, int>(
|
StackedColumnSeries<SalesData, int>(
|
||||||
dataSource: _getLowerChartData(),
|
dataSource: _getLowerChartData(),
|
||||||
xValueMapper: (SalesData sales, _) => sales.year,
|
xValueMapper: (SalesData sales, _) => sales.year,
|
||||||
yValueMapper: (SalesData sales, _) => sales.value,
|
yValueMapper: (SalesData sales, _) => sales.value,
|
||||||
name: 'Einzahlungen',
|
name: 'Einzahlungen',
|
||||||
color: CupertinoColors.systemRed.highContrastColor,
|
color: CupertinoColors.systemGrey.darkHighContrastColor,
|
||||||
),
|
),
|
||||||
// Obere Teil der Säule
|
// Serie für die Zinsen (obere Werte)
|
||||||
StackedColumnSeries<SalesData, int>(
|
StackedColumnSeries<SalesData, int>(
|
||||||
dataSource: _getUpperChartData(),
|
dataSource: _getUpperChartData(),
|
||||||
xValueMapper: (SalesData sales, _) => sales.year,
|
xValueMapper: (SalesData sales, _) => sales.year,
|
||||||
yValueMapper: (SalesData sales, _) => sales.value,
|
yValueMapper: (SalesData sales, _) => sales.value,
|
||||||
name: 'Zinsen',
|
name: 'Zinsen',
|
||||||
color: CupertinoColors.systemBlue.highContrastColor,
|
color: CupertinoColors.systemGreen.highContrastColor,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
// Trackball für Hover-Interaktion
|
// Konfiguration für die Interaktivität des Diagramms
|
||||||
trackballBehavior: TrackballBehavior(
|
trackballBehavior: TrackballBehavior(
|
||||||
enable: true,
|
enable: true,
|
||||||
tooltipSettings: const InteractiveTooltip(enable: true),
|
tooltipSettings: const InteractiveTooltip(enable: true),
|
||||||
|
@ -53,7 +53,7 @@ class StackedColumnChart extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methode zum Erstellen der Daten für den unteren Teil der Säule (Investiertes Geld)
|
// Methode zur Erstellung der Daten für die untere Serie (Einzahlungen)
|
||||||
List<SalesData> _getLowerChartData() {
|
List<SalesData> _getLowerChartData() {
|
||||||
List<SalesData> chartData = [];
|
List<SalesData> chartData = [];
|
||||||
for (int i = 0; i < lowerValues.length; i++) {
|
for (int i = 0; i < lowerValues.length; i++) {
|
||||||
|
@ -61,7 +61,8 @@ class StackedColumnChart extends StatelessWidget {
|
||||||
}
|
}
|
||||||
return chartData;
|
return chartData;
|
||||||
}
|
}
|
||||||
// Methode zum Erstellen der Daten für den oberen Teil der Säule (Investiertes Geld mit Zinsen)
|
|
||||||
|
// Methode zur Erstellung der Daten für die obere Serie (Zinsen)
|
||||||
List<SalesData> _getUpperChartData() {
|
List<SalesData> _getUpperChartData() {
|
||||||
List<SalesData> chartData = [];
|
List<SalesData> chartData = [];
|
||||||
for (int i = 0; i < upperValues.length; i++) {
|
for (int i = 0; i < upperValues.length; i++) {
|
||||||
|
@ -71,6 +72,7 @@ class StackedColumnChart extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Klasse zur Modellierung der Datenpunkte im Diagramm
|
||||||
class SalesData {
|
class SalesData {
|
||||||
final int year;
|
final int year;
|
||||||
final double value;
|
final double value;
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class CustomImageButton extends StatelessWidget {
|
||||||
|
final VoidCallback onPressed;
|
||||||
|
final Widget child;
|
||||||
|
final String backgroundImage;
|
||||||
|
|
||||||
|
const CustomImageButton({
|
||||||
|
super.key,
|
||||||
|
required this.onPressed,
|
||||||
|
required this.child,
|
||||||
|
required this.backgroundImage,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: onPressed,
|
||||||
|
child: Container(
|
||||||
|
height: 150,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage(backgroundImage),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,72 +0,0 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
// Widget für eine erweiterbare Box
|
|
||||||
class ExpandableBox extends StatefulWidget {
|
|
||||||
final String headerText;
|
|
||||||
final Widget expandedContent;
|
|
||||||
|
|
||||||
const ExpandableBox({super.key, required this.headerText, required this.expandedContent});
|
|
||||||
|
|
||||||
@override
|
|
||||||
// ignore: library_private_types_in_public_api
|
|
||||||
_ExpandableBoxState createState() => _ExpandableBoxState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ExpandableBoxState extends State<ExpandableBox> {
|
|
||||||
bool _isExpanded = false;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
// GestureDetector zum Erfassen von Klicks zum Erweitern oder Verkleinern der Box
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
setState(() {
|
|
||||||
_isExpanded = !_isExpanded;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: CupertinoColors.extraLightBackgroundGray,
|
|
||||||
borderRadius: _isExpanded ? const BorderRadius.only(topLeft: Radius.circular(5), topRight: Radius.circular(5),) : BorderRadius.circular(5),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
||||||
child: Text(
|
|
||||||
widget.headerText,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontWeight: FontWeight.bold
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Icon(
|
|
||||||
_isExpanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down,
|
|
||||||
size: 30,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (_isExpanded)
|
|
||||||
Container(
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
color: CupertinoColors.extraLightBackgroundGray,
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
bottomLeft: Radius.circular(5),
|
|
||||||
bottomRight: Radius.circular(5),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(20), // Hier kannst du den gewünschten Padding-Wert festlegen
|
|
||||||
child: widget.expandedContent,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
// Funktion zum Erstellen eines Eingabe-Widgets
|
// Erstellt ein Widget für die Eingabe mit einem Label, einem Texteingabefeld, einer Validierungsanzeige und einem Tooltip
|
||||||
Widget buildInputWidget(String label, TextEditingController controller, FocusNode focusNode, bool isValid, String suffixText, String tooltipText) {
|
Widget buildInputWidget(String label, TextEditingController controller, FocusNode focusNode, bool isValid, String suffixText, String tooltipText) {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
@ -9,11 +9,11 @@ Widget buildInputWidget(String label, TextEditingController controller, FocusNod
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
// Zeile für das Label und den Tooltip
|
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
|
// Label für das Eingabefeld
|
||||||
Text(
|
Text(
|
||||||
label,
|
label,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
|
@ -22,6 +22,7 @@ Widget buildInputWidget(String label, TextEditingController controller, FocusNod
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 5),
|
const SizedBox(width: 5),
|
||||||
|
// Tooltip-Icon mit Erklärungstext
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message: tooltipText,
|
message: tooltipText,
|
||||||
triggerMode: TooltipTriggerMode.tap,
|
triggerMode: TooltipTriggerMode.tap,
|
||||||
|
@ -39,6 +40,7 @@ Widget buildInputWidget(String label, TextEditingController controller, FocusNod
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
// Icon zur Anzeige der Validierung (grün für gültig, rot für ungültig)
|
||||||
isValid
|
isValid
|
||||||
? const Icon(
|
? const Icon(
|
||||||
CupertinoIcons.check_mark_circled_solid,
|
CupertinoIcons.check_mark_circled_solid,
|
||||||
|
@ -53,7 +55,7 @@ Widget buildInputWidget(String label, TextEditingController controller, FocusNod
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
// Textfeld für die Eingabe
|
// Texteingabefeld mit Suffix-Text
|
||||||
CupertinoTextField(
|
CupertinoTextField(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
|
|
|
@ -3,27 +3,28 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_application_1/enums.dart';
|
import 'package:flutter_application_1/enums.dart';
|
||||||
import 'package:flutter_application_1/translations.dart';
|
import 'package:flutter_application_1/translations.dart';
|
||||||
|
|
||||||
// Widget zur Auswahl des Ausschüttungsintervalls
|
|
||||||
class IntervalWidget extends StatefulWidget {
|
class IntervalWidget extends StatefulWidget {
|
||||||
final String selectedInterval;
|
final String selectedInterval;
|
||||||
final Function(String) onChanged;
|
final Function(String) onChanged;
|
||||||
|
|
||||||
const IntervalWidget({super.key, required this.selectedInterval, required this.onChanged});
|
const IntervalWidget({
|
||||||
|
super.key,
|
||||||
|
required this.selectedInterval,
|
||||||
|
required this.onChanged
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
// ignore: library_private_types_in_public_api
|
IntervalWidgetState createState() => IntervalWidgetState();
|
||||||
_IntervalWidgetState createState() => _IntervalWidgetState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _IntervalWidgetState extends State<IntervalWidget> {
|
class IntervalWidgetState extends State<IntervalWidget> {
|
||||||
bool isExpanded = false;
|
bool isExpanded = false; // Zustand, ob das Intervall-Auswahlfenster erweitert ist
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
// Überschrift für das Dropdown-Menü
|
|
||||||
const Row(
|
const Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
|
@ -34,6 +35,7 @@ class _IntervalWidgetState extends State<IntervalWidget> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 5),
|
SizedBox(width: 5),
|
||||||
|
// Tooltip mit Erklärung zum Ausschüttungsintervall
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message: 'Das Ausschüttungsintervall bezieht sich darauf, wie oft die Erträge aus Ihrer Investition ausgeschüttet werden.',
|
message: 'Das Ausschüttungsintervall bezieht sich darauf, wie oft die Erträge aus Ihrer Investition ausgeschüttet werden.',
|
||||||
triggerMode: TooltipTriggerMode.tap,
|
triggerMode: TooltipTriggerMode.tap,
|
||||||
|
@ -49,19 +51,19 @@ class _IntervalWidgetState extends State<IntervalWidget> {
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
// Dropdown-Menü
|
|
||||||
CupertinoTextField(
|
CupertinoTextField(
|
||||||
placeholder: 'Ausschüttungsintervall auswählen',
|
placeholder: 'Ausschüttungsintervall auswählen',
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
// Öffnet das ModalBottomSheet zur Auswahl des Ausschüttungsintervalls
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
backgroundColor: CupertinoColors.white,
|
backgroundColor: CupertinoColors.black,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
// Liste von Auswahlmöglichkeiten
|
// ListTile für jährliches Ausschüttungsintervall
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
|
@ -69,17 +71,17 @@ class _IntervalWidgetState extends State<IntervalWidget> {
|
||||||
translateInterval(PayoutInterval.yearly),
|
translateInterval(PayoutInterval.yearly),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
color: CupertinoColors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
hoverColor: Colors.transparent,
|
trailing: widget.selectedInterval == translateInterval(PayoutInterval.yearly) ? const Icon(CupertinoIcons.checkmark_alt, color: CupertinoColors.white,) : null,
|
||||||
trailing: widget.selectedInterval == translateInterval(PayoutInterval.yearly) ? const Icon(CupertinoIcons.checkmark_alt) : null,
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// Auswahl des jährlichen Intervalls und Schließen des Bottom Sheets
|
|
||||||
widget.onChanged(translateInterval(PayoutInterval.yearly));
|
widget.onChanged(translateInterval(PayoutInterval.yearly));
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// ListTile für monatliches Ausschüttungsintervall
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
|
@ -87,12 +89,11 @@ class _IntervalWidgetState extends State<IntervalWidget> {
|
||||||
translateInterval(PayoutInterval.monthly),
|
translateInterval(PayoutInterval.monthly),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
color: CupertinoColors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
hoverColor: Colors.transparent,
|
trailing: widget.selectedInterval == translateInterval(PayoutInterval.monthly) ? const Icon(CupertinoIcons.checkmark_alt, color: CupertinoColors.white,) : null,
|
||||||
trailing: widget.selectedInterval == translateInterval(PayoutInterval.monthly) ? const Icon(CupertinoIcons.checkmark_alt) : null,
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// Auswahl des monatlichen Intervalls und Schließen des Bottom Sheets
|
|
||||||
widget.onChanged(translateInterval(PayoutInterval.monthly));
|
widget.onChanged(translateInterval(PayoutInterval.monthly));
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
|
@ -103,18 +104,19 @@ class _IntervalWidgetState extends State<IntervalWidget> {
|
||||||
},
|
},
|
||||||
).then((value) {
|
).then((value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
isExpanded = false;
|
isExpanded = false; // Setzt den Zustand auf nicht erweitert zurück, wenn das Modal geschlossen wird
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
setState(() {
|
setState(() {
|
||||||
isExpanded = true;
|
isExpanded = true; // Setzt den Zustand auf erweitert
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// Suffix-Icon, das den Zustand anzeigt (erweitert oder nicht)
|
||||||
suffix: Padding(
|
suffix: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
||||||
child: Icon(isExpanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down),
|
child: Icon(isExpanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down),
|
||||||
),
|
),
|
||||||
controller: TextEditingController(text: widget.selectedInterval),
|
controller: TextEditingController(text: widget.selectedInterval), // Setzt den Text des Textfeldes auf das ausgewählte Intervall
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: CupertinoColors.extraLightBackgroundGray,
|
color: CupertinoColors.extraLightBackgroundGray,
|
||||||
borderRadius: BorderRadius.circular(5),
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
// Erstellt eine Zeitleiste für Meilensteine
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
|
Widget buildMilestoneTimeline(List<Map<String, dynamic>> milestones, double totalInterest) {
|
||||||
|
return SizedBox(
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: List.generate(milestones.length, (index) {
|
||||||
|
double milestoneValue = milestones[index]['value'];
|
||||||
|
String milestoneEmoji = milestones[index]['emoji'];
|
||||||
|
String milestoneText = milestones[index]['text'];
|
||||||
|
bool milestoneReached = totalInterest >= milestoneValue; // Überprüfen, ob Meilenstein erreicht wurde
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
if (index > 0)
|
||||||
|
Container(
|
||||||
|
height: 25,
|
||||||
|
width: 2,
|
||||||
|
color: milestoneReached ? CupertinoColors.systemGreen : CupertinoColors.black, // Linie zwischen Meilensteinen
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
milestoneEmoji,
|
||||||
|
style: const TextStyle(fontSize: 20), // Emoji für Meilenstein
|
||||||
|
),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
Text(
|
||||||
|
milestoneText,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||||
|
child: Icon(
|
||||||
|
milestoneReached ? CupertinoIcons.check_mark_circled_solid : CupertinoIcons.circle_fill,
|
||||||
|
size: 20,
|
||||||
|
color: milestoneReached ? CupertinoColors.systemGreen : CupertinoColors.black, // Icon, das den Status des Meilensteins anzeigt
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,44 +1,79 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_application_1/enums.dart';
|
import 'package:flutter_application_1/enums.dart';
|
||||||
import 'package:flutter_application_1/translations.dart';
|
import 'package:flutter_application_1/translations.dart';
|
||||||
import 'package:flutter_application_1/widgets/expandable_widget.dart';
|
import 'package:flutter_application_1/widgets/second_page_widget.dart';
|
||||||
|
import 'package:flutter_application_1/widgets/custom_image_button_widget.dart';
|
||||||
import 'package:flutter_application_1/widgets/chart_widget.dart';
|
import 'package:flutter_application_1/widgets/chart_widget.dart';
|
||||||
|
import 'package:flutter_application_1/widgets/milestone_timeline_widget.dart';
|
||||||
|
|
||||||
// Erstellt das Widget für das Ergebnis der Berechnungen
|
// Erstellt ein Widget, das die Berechnungsergebnisse anzeigt
|
||||||
Widget buildResultWidget(String compoundInterest, String investedMoney, String time, String monthlySavingsRate, String interestRate, PayoutInterval payoutInterval, List<double> investedMoneyList, List<double> compoundInterestList) {
|
Widget buildResultWidget(BuildContext context, String compoundInterest, String investedMoney, String time, String monthlySavingsRate, String interestRate, PayoutInterval payoutInterval, List<double> investedMoneyList, List<double> compoundInterestList) {
|
||||||
// Liste von Meilensteinen mit Werten, Bildern und Texten.
|
// Liste von Meilensteinen mit Werten, Emojis und Beschreibungen
|
||||||
List<Map<String, dynamic>> milestoneList = [
|
List<Map<String, dynamic>> milestoneList = [
|
||||||
{'value': 1329.0, 'emoji': '📱', 'text': 'iPhone 15 Pro Max\nPreis: 1329€'},
|
{'value': 700.0, 'emoji': '📱', 'text': 'Smartphone\nPreis: 700€'},
|
||||||
{'value': 3071.0, 'emoji': '🚲', 'text': 'Flyer Gotour6 3.40\nPreis: 3071€'},
|
{'value': 3250.0, 'emoji': '🚲', 'text': 'eBike\nPreis: 3250€'},
|
||||||
{'value': 248157.0, 'emoji': '🏎️', 'text': 'Porsche 992 GT3 RS\nPreis: 248157€'},
|
{'value': 20000.0, 'emoji': '🌎', 'text': 'Weltreise\nPreis: 20000€'},
|
||||||
{'value': 450000.0, 'emoji': '🏡', 'text': '150qm Einfamilienhaus\nPreis: ca. 450000€'},
|
{'value': 100000.0, 'emoji': '🏎️', 'text': 'Sportwagen\nPreis: 100000€'},
|
||||||
|
{'value': 350000.0, 'emoji': '🏡', 'text': '150qm Einfamilienhaus\nPreis: 350000€'},
|
||||||
];
|
];
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
CustomImageButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => SecondPage(
|
||||||
|
title: 'Grafik',
|
||||||
|
widgetToShow: StackedColumnChart(
|
||||||
|
lowerValues: investedMoneyList,
|
||||||
|
upperValues: compoundInterestList,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
backgroundImage: 'assets/images/button_bg1.jpg',
|
||||||
|
child: const Text(
|
||||||
|
'Grafik',
|
||||||
|
style: TextStyle(color: CupertinoColors.white, fontSize: 20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
CustomImageButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => SecondPage(
|
||||||
|
title: 'Meilensteine',
|
||||||
|
widgetToShow: buildMilestoneTimeline(milestoneList, double.parse(compoundInterest) - double.parse(investedMoney))
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
backgroundImage: 'assets/images/button_bg2.jpg',
|
||||||
|
child: const Text(
|
||||||
|
'Meilensteine',
|
||||||
|
style: TextStyle(color: CupertinoColors.white, fontSize: 20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
_buildResultRow('Endkapital:', '$compoundInterest€'),
|
_buildResultRow('Endkapital:', '$compoundInterest€'),
|
||||||
_buildResultRow('Einzahlungen:', '$investedMoney€'),
|
_buildResultRow('Einzahlungen:', '$investedMoney€'),
|
||||||
_buildResultRow('Erhaltene Zinsen:', '${double.parse(compoundInterest) - double.parse(investedMoney)}€'),
|
_buildResultRow('Erhaltene Zinsen:', '${double.parse(compoundInterest) - double.parse(investedMoney)}€'),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 10),
|
||||||
Text(
|
Text(
|
||||||
'Wenn du über einen Zeitraum von $time Jahren ${translateInterval(payoutInterval)} $monthlySavingsRate€ mit einem Zinssatz von $interestRate% investierst, erreichst du am Ende ein Endkapital von $compoundInterest€. Dieses setzt sich aus Einzahlungen von $investedMoney€ und Zinsen bzw. Kapitalerträgen in Höhe von ${double.parse(compoundInterest) - double.parse(investedMoney)}€ zusammen.'
|
'Wenn du über einen Zeitraum von $time Jahren ${translateInterval(payoutInterval)} $monthlySavingsRate€ mit einem Zinssatz von $interestRate% investierst, erreichst du am Ende ein Endkapital von $compoundInterest€. Dieses setzt sich aus Einzahlungen von $investedMoney€ und Zinsen bzw. Kapitalerträgen in Höhe von ${double.parse(compoundInterest) - double.parse(investedMoney)}€ zusammen.'
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
|
||||||
ExpandableBox(
|
|
||||||
headerText: 'Grafik',
|
|
||||||
expandedContent: StackedColumnChart(
|
|
||||||
lowerValues: investedMoneyList,
|
|
||||||
upperValues: compoundInterestList,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 5),
|
|
||||||
ExpandableBox(
|
|
||||||
headerText: 'Meilensteine',
|
|
||||||
expandedContent: buildMilestoneTimeline(milestoneList, double.parse(compoundInterest) - double.parse(investedMoney)),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Erstellt eine Zeile mit einem Label und einem Wert
|
||||||
Widget _buildResultRow(String label, String value) {
|
Widget _buildResultRow(String label, String value) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
|
@ -68,62 +103,3 @@ Widget _buildResultRow(String label, String value) {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Erstellt die Meilenstein-Timeline.
|
|
||||||
Widget buildMilestoneTimeline(List<Map<String, dynamic>> milestones, double totalInterest) {
|
|
||||||
return SizedBox(
|
|
||||||
child: Center(
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: List.generate(milestones.length, (index) {
|
|
||||||
// Werte aus dem Meilenstein-Objekt extrahieren
|
|
||||||
double milestoneValue = milestones[index]['value'];
|
|
||||||
String milestoneEmoji = milestones[index]['emoji'];
|
|
||||||
String milestoneText = milestones[index]['text'];
|
|
||||||
bool milestoneReached = totalInterest >= milestoneValue;
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
if (index > 0) // Zeigt eine vertikale Linie an zwischen den Meilensteinen
|
|
||||||
Container(
|
|
||||||
height: 50,
|
|
||||||
width: 2,
|
|
||||||
color: milestoneReached ? CupertinoColors.systemGreen : CupertinoColors.black,
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
milestoneEmoji,
|
|
||||||
style: const TextStyle(fontSize: 25),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 5),
|
|
||||||
Text(
|
|
||||||
milestoneText,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// Zeigt ein Häkchen oder einen Kreis je nach Erreichen des Meilensteins an
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
|
||||||
child: Icon(
|
|
||||||
milestoneReached ? CupertinoIcons.check_mark_circled_solid : CupertinoIcons.circle_fill,
|
|
||||||
size: 20,
|
|
||||||
color: milestoneReached ? CupertinoColors.systemGreen : CupertinoColors.black,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SecondPage extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final Widget widgetToShow;
|
||||||
|
|
||||||
|
const SecondPage({
|
||||||
|
super.key,
|
||||||
|
required this.title,
|
||||||
|
required this.widgetToShow
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: CustomScrollView(
|
||||||
|
slivers: <Widget>[
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.only(left: 10, right: 10, top: MediaQuery.of(context).padding.top + 10),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(CupertinoIcons.chevron_left, size: 15), // Zurück-Pfeil
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 40), // Platzhalter für zentrierte Ausrichtung
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: widgetToShow, // Anzeigen des mitgegebenen Widgets
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,8 +60,9 @@ flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
|
||||||
# To add assets to your application, add an assets section, like this:
|
# To add assets to your application, add an assets section, like this:
|
||||||
# assets:
|
assets:
|
||||||
# - assets/images/
|
- assets/images/button_bg1.jpg
|
||||||
|
- assets/images/button_bg2.jpg
|
||||||
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||||
|
|
Loading…
Reference in New Issue