Blog background

Schritt-für-Schritt-Anleitung für deine erste Flutter-App

Lerne mit dieser Schritt-für-Schritt-Anleitung eine Flutter-App zur Einheitenumrechnung zu entwickeln und starte noch heute in die mobile App-Entwicklung!

Dieser Blogpost wurde von einer Maschine aus dem Englischen übersetzt. Die Originalversion finden Sie hier: Step-by-Step Guide to Creating your First Flutter App

Bitte kontaktiere uns , wenn etwas nicht eindeutig beschrieben ist, nicht funktioniert, fehlerhaft wirkt oder wenn du Unterstützung benötigst.

Inhaltsverzeichnis

Die Reise zur Entwicklung deiner ersten Flutter-App kann eine aufregende, aber auch entmutigende Aufgabe sein. Flutter sticht mit seiner Multiplattform-Unterstützung, schnellen Entwicklungszeiten und der Hot-Reload-Funktion als leistungsstarkes Toolkit für die App-Entwicklung hervor. Die anfängliche Lernkurve kann für Anfänger jedoch steil erscheinen. Diese Anleitung soll den Prozess vereinfachen und dich durch die Erstellung einer Einheitenumrechnungs-App führen.

Dieses Projekt dient nicht nur als praktische Einführung in Flutter, sondern demonstriert auch die Vorteile des Frameworks in einer realen Anwendung.

Schritt 1: Das neue Projekt erstellen

Zuerst installiere Flutter:

sudo snap install flutter --classic

Um zu überprüfen, ob Flutter korrekt funktioniert:

flutter doctor

Beginne damit, ein neues Flutter-Projekt zu erstellen. Öffne dein Terminal und führe aus:

flutter create unit_converter

Dieser Befehl erstellt die Standard-Flutter-App.

Schritt 2: Den Einheitendatentyp definieren

Erstelle zunächst eine neue Datei mit dem Namen unit.dart im lib-Verzeichnis des Projekts.

Definiere in der Datei zunächst eine Enumeration für Einheitentypen:

enum Type { weight, length, time }

Führe dann eine Klasse ein, die verschiedene Einheiten repräsentiert und einen Namen, einen Typ (aus dem Enum) und einen Wert relativ zu Standard-SI-Einheiten enthält:

class Unit {
  String name;
  Type type;
  double valSiUnits;

  Unit(this.name, this.valSiUnits, this.type);
}

Füge für die Einheitenumrechnungsfunktionalität hinzu:

  double? convert(double? val, Unit to) {
    if (type != to.type) {
      throw Exception("Trying to convert between incompatible types");
    }
    if (val == null) return null;
    return val * valSiUnits / to.valSiUnits;
  }

Diese Methode prüft, ob die Einheiten kompatibel sind (d. h. vom selben Typ), behandelt Null-Eingaben elegant, indem sie null zurückgibt, wenn der Eingabewert null ist, und führt die Umrechnung mithilfe des Verhältnisses der SI-Werte der Einheiten durch.

Schritt 3: Einheiten definieren

Da die physikalischen Konstanten, mit denen wir arbeiten, unveränderlich sind und der Umfang unserer Anwendung definiert ist, können wir unsere Einheiten als globale Konstanten in unit.dart definieren:

final Map> units = {
  Type.weight: [
    Unit("Kilogram", 1.0, Type.weight), // SI unit
    Unit("Gram", 0.001, Type.weight),
    Unit("Pound", 0.453592, Type.weight),
    Unit("Stone", 6.35029, Type.weight),
  ],
  Type.length: [
    Unit("Meter", 1.0, Type.length), // SI unit
    Unit("Centimeter", 0.01, Type.length),
    Unit("Inch", 0.0254, Type.length),
    Unit("Mile", 1609.34, Type.length),
    Unit("Kilometer", 1000, Type.length),
  ],
  Type.time: [
    Unit("Second", 1.0, Type.time), // SI unit
    Unit("Minute", 60.0, Type.time),
    Unit("Hour", 3600.0, Type.time),
    Unit("Day", 3600 * 24, Type.time),
    Unit("Week", 3600 * 24 * 7, Type.time)
  ],
};

Du kannst dies einfach erweitern, indem du neue Einheiten und Einheitentypen hinzufügst.

Schritt 4: Mit dem Aufbau der Benutzeroberfläche beginnen

Navigiere zurück zur main.dart-Datei, um mit dem Aufbau der Benutzeroberfläche zu beginnen.

Stelle sicher, dass unit.dart importiert ist:

import 'package:unit_converter/unit.dart';

Bearbeite die build-Funktion der MyApp-Klasse, um das Theme und den Titel der App anzupassen. Hier legst du das globale Erscheinungsbild deiner App und ihren Titel fest, wie er im Task-Switcher angezeigt wird.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Unit Converter',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.lightGreen),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Unit Converter'),
    );
  }

Du kannst damit experimentieren, um besser zu sehen, wie es die App verändert.

Führe in _MyHomePageState Variablen ein, die die Umrechnungslogik repräsentieren, einschließlich der beteiligten Einheiten und Werte sowie Controller für Texteingaben.

  Type unitType = Type.weight;
  Unit fromUnit = units[Type.weight]![0];
  Unit toUnit = units[Type.weight]![1];
  double? valueFrom = 0;
  double? valueTo = 0;
  final controllerFrom = TextEditingController();
  final controllerTo = TextEditingController();

Wir müssen den Benutzern die Möglichkeit geben, Einheitentypen auszuwählen. Eine Möglichkeit, dies zu erreichen, besteht darin, ein PopupMenuButton in der Appbar zu verwenden. Hier ist eine unkomplizierte Implementierung davon:

      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
        actions: [
          PopupMenuButton(
            itemBuilder: (BuildContext context) {
              return [
                PopupMenuItem(
                  onTap: () {
                    unitType = Type.weight;
                  },
                  child: const Text("Weight"),
                ),
                PopupMenuItem(
                  onTap: () {
                    unitType = Type.weight;
                  },
                  child: const Text("Length"),
                ),
                PopupMenuItem(
                  onTap: () {
                    unitType = Type.time;
                  },
                  child: const Text("Time"),
                )
              ];
            },
          ),
        ],
      ),

Während diese Methode für unsere kleine App gut funktioniert, ist es vorteilhaft, die Erstellung von Popup-Menüelementen zu automatisieren, um die Wartbarkeit und Skalierbarkeit zu verbessern, insbesondere wenn die Entwicklung voranschreitet und die App wächst. Dies vermeidet die manuelle Deklaration von Elementen und macht das Hinzufügen neuer Einheitentypen viel einfacher:

              List items = [];
              for (final type in Type.values) {
                items.add(PopupMenuItem(
                  onTap: () {
                    if (unitType == type) return;
                    unitType = type;
                    fromUnit = units[type]![0];
                    toUnit = units[type]![1];
                    setVal(valueFrom, from: true);
                  },
                  child: Text(type.name),
                ));
              }
              return items;

Durch die Iteration über Type.values generiert dieser Ansatz dynamisch Menüelemente für jeden Einheitentyp.

Die Bedeutung dieses Ansatzes zeigt sich, wenn wir die onTap-Funktion aktualisieren, um die ausgewählten Einheiten an den Einheitentyp anzupassen. Mit der ursprünglichen Methode hätte dies zu übermäßiger Redundanz geführt.

Beachte beim Debuggen, dass das Debug-Banner das Menüsymbol verdecken kann. Diese Erfahrung unterstreicht die Wichtigkeit, deine Benutzeroberfläche sowohl im Entwicklungs- als auch im Produktionsmodus zu testen, um die Benutzerfreundlichkeit sicherzustellen.

Schritt 5: Das Dropdown-Menü zur Auswahl der Einheiten erstellen

Beim Erstellen einer Einheitenumrechner-App ist es wichtig, dass sich die Textfelder bei jeder Änderung der Einheitenmenge oder der ausgewählten Einheiten automatisch aktualisieren. Dies erfordert eine Funktion speziell für die Verwaltung dieser Aktualisierungen, wodurch die App reaktionsschneller und benutzerfreundlicher wird.

  void setVal(double? val, {required bool from, bool modifyChanged = true}) {
    if (from) {
      valueFrom = val;
      valueTo = fromUnit.convert(val, toUnit);
    } else {
      valueTo = val;
      valueFrom = toUnit.convert(val, fromUnit);
    }

    if (modifyChanged || !from) {
      controllerFrom.text =
          (valueFrom == null) ? "" : valueFrom!.toStringAsFixed(4);
    }
    if (modifyChanged || from) {
      controllerTo.text = (valueTo == null) ? "" : valueTo!.toStringAsFixed(4);
    }
    setState(() {});
  }

Diese Funktion verarbeitet die neue Einheitenmenge und einen booleschen Wert, der angibt, ob wir den ‘from’- oder ’to’-Wert ändern. Sie aktualisiert dann sowohl die Umrechnungswerte als auch ihre entsprechenden Textfelder entsprechend.

Um die Einheitenauswahl in unserer Umrechner-App zu implementieren, können wir Dropdown-Menüs verwenden, damit Benutzer die Einheiten auswählen können, zwischen denen sie umrechnen möchten. Die Nutzung des DropdownSearch-Widgets bietet eine verbesserte Benutzererfahrung mit durchsuchbaren und auswählbaren Einheitenoptionen. Bevor du DropdownSearch einbindest, stelle sicher, dass es deinem Projekt hinzugefügt wurde, indem du ausführst:

flutter pub add dropdown_search

und importiere es in deine Dart-Datei:

import 'package:dropdown_search/dropdown_search.dart';

Um Redundanz zu vermeiden, erstellen wir eine Funktion, getUnitSelectorWidget, um diese Dropdown-Menüs dynamisch zu generieren. Diese Funktion ist so konzipiert, dass sie anpassungsfähig ist und sowohl “from”- als auch “to”-Einheitsauswahlszenarien basierend auf einem booleschen Parameter bedient. Die Implementierung sieht wie folgt aus:

  Widget getUnitSelectorWidget({required bool from}) {
    return DropdownSearch(
      filterFn: (item, filter) {
        return item.name.toLowerCase().startsWith(filter.toLowerCase());
      },
      compareFn: (item1, item2) {
        return item1.name == item2.name;
      },
      popupProps: const PopupPropsMultiSelection.modalBottomSheet(
        searchDelay: Duration.zero,
        showSelectedItems: true,
        showSearchBox: true,
      ),
      onChanged: (var newValue) {
        if (newValue == null) return;
        if (from) {
          fromUnit = newValue;
        } else {
          toUnit = newValue;
        }
        // Update the converted values by calling setVal
        setVal(valueFrom, from: true);
      },
      selectedItem: from ? fromUnit : toUnit,
      items: units[unitType]!,
      itemAsString: (item) => item.name,
    );
  }

In diesem Setup stellen filterFn und compareFn sicher, dass Einheiten während der Suche leicht gefunden und korrekt zugeordnet werden. popupProps passen die interaktiven Funktionen des Dropdowns an, wie z. B. Suchverzögerung und Anzeigeeinstellungen. Schließlich aktualisiert der onChanged-Callback den App-Status basierend auf der Benutzerauswahl und sorgt für Echtzeit-Reaktionsfähigkeit. Durch diesen Ansatz schaffen wir eine benutzerfreundliche Oberfläche zur Auswahl von Umrechnungseinheiten und verbessern die Gesamtfunktionalität unserer App.

Schritt 6: Textfelder für die Eingabe der Einheitenmengen erstellen

Die Erstellung einer reaktionsschnellen und benutzerfreundlichen Oberfläche für unsere Einheitenumrechner-App beinhaltet, dass Benutzer Mengen zur Umrechnung eingeben können. Dieser Schritt führt eine Funktion ein, um die Erstellung von Eingabefeldern zu rationalisieren, wodurch das Design der App konsistent wird und die Redundanz entfernt wird, die durch separate Definition der “from”- und “to”-Textfelder entstehen würde.

  Widget getQuantityInputWidget({required bool from, double width = 200}) {
    return SizedBox(
      width: width,
      child: TextField(
        keyboardType: TextInputType.number,
        controller: from ? controllerFrom : controllerTo,
        onChanged: (value) {
          double? valueNum = double.tryParse(value);
          if (valueNum == null) {
            setVal(null, from: from);
          }
          setVal(valueNum, from: from, modifyChanged: false);
          setState(() {});
        },
      ),
    );
  }

In diesem Setup konfigurieren wir ein Textfeld, um nur numerische Werte zu akzeptieren, und verknüpfen es mit dem richtigen Controller. Dann stellen wir sicher, dass bei Eingabe eines neuen Werts dieser automatisch umgerechnet wird und der entsprechende Wert im anderen Textfeld aktualisiert wird. Um zu verhindern, dass das aktuell aktive Textfeld während der Eingabe neu formatiert wird, verwenden wir den Parameter modifyChanged: false.

Schritt 7: Alles zusammenfügen

Nachdem alle wesentlichen Komponenten erstellt wurden, ist es an der Zeit, unsere Einheitenumrechner-App innerhalb der build-Funktion zusammenzusetzen. Durch effektive Organisation unserer Widgets erstellen wir eine benutzerfreundliche Oberfläche. So kann das Layout innerhalb des body des Scaffold strukturiert werden:

Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Row(
              children: [
                const Spacer(),
                Expanded(child: getUnitSelectorWidget(from: true)),
                const SizedBox(width: 20),
                Expanded(child: getUnitSelectorWidget(from: false)),
                const Spacer(),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                getQuantityInputWidget(from: true),
                const SizedBox(width: 20),
                getQuantityInputWidget(from: false),
              ],
            ),
          ],
        ),
      ),

Dieses Layout verwendet ein Center-Widget, um die Hauptspalte in der Mitte des Bildschirms auszurichten. Wir führen zwei Zeilen innerhalb dieser Spalte ein: Die erste Zeile enthält unsere Einheitsauswahl-Dropdowns, und die zweite Zeile enthält die Mengeneingabefelder. Spacer und SizedBox sind strategisch platziert, um sicherzustellen, dass ausreichend Abstand vorhanden ist, wodurch die Oberfläche ästhetisch ansprechend und einfach zu navigieren ist.

Mit diesem Setup haben wir erfolgreich eine einfache Einheitenumrechner-App erstellt, die Einheitenumrechnungen über verschiedene Dimensionen wie Masse, Länge und Zeit effizient verarbeitet und Funktionalität mit Benutzerfreundlichkeit verbindet.