Datenaggregation

Datenaggregation

–> Daten aus verschiedenen Quellen sammeln, zusammenfassen und organisieren.

In Bezug auf App-Entwicklung mit Dart und Flutter können Informationen von APIs, Datenbanken, Sensoren oder anderen externen Quellen umfasst werden.

  • Definition von Datenquellen
  • HTTP-Anfragen und APIs
  • Erstellung von Datenmodellen
  • State-Management
  • Behandlung von Lade- und Fehlerzustände
  • etc.

Data Persistence

Persistence

aus Chat GPT:

Fähigkeit, Daten über einen längeren Zeitraum zu speichern und wiederherzustellen. Es geht darum, Daten so zu persistieren, dass sie zwischen den verschiedenen Laufzeiten der Anwendung erhalten bleiben. Das bedeutet, dass Daten auch nach dem Schließen der App oder dem Neustart des Geräts weiterhin verfügbar sind.

Es gibt verschiedene Arten von Persistenz in Dart und Flutter:

  1. Lokale Persistenz:
    • SharedPreferences: Eine einfache Möglichkeit, Schlüssel-Wert-Paare lokal zu speichern, die für kleine Mengen von Daten wie App-Einstellungen geeignet ist.
    • sqflite: Eine SQLite-Datenbank für Flutter, die eine relationale lokale Datenbank ermöglicht, ideal für größere Mengen strukturierter Daten.
    • Hive: Eine leichtgewichtige NoSQL-Datenbank, die für Flutter optimiert ist und sowohl lokale als auch plattformübergreifende Persistenz bietet.
  2. Cloud-Persistenz:
    • Firebase (Cloud Firestore, Realtime Database): Firebase bietet eine Cloud-basierte Lösung für die Persistenz von Daten. Cloud Firestore ist eine NoSQL-Datenbank, während die Realtime Database eine JSON-Datenbank ist. Beide ermöglichen die Synchronisation von Daten über verschiedene Plattformen hinweg.
  3. Dateisystem-Persistenz:
    • Arbeiten mit Dateien: Flutter ermöglicht den Zugriff auf das lokale Dateisystem des Geräts, wodurch Daten in Dateien gespeichert und gelesen werden können.
  4. HTTP-Persistenz:
    • Dio: Dio ist eine HTTP-Client-Bibliothek für Dart und Flutter. Durch die Kommunikation mit einem Server können Daten über das Netzwerk persistiert werden.
  5. Zustandspersistenz:
    • Provider + SharedPreferences/Hive: Der Zustand einer Flutter-App kann mithilfe von State-Management-Lösungen wie Provider und der Kombination mit SharedPreferences oder Hive persistiert werden.

Der Einsatz von Persistenz ist entscheidend, um Daten zwischen den verschiedenen Zuständen einer Flutter-App zu übertragen und sicherzustellen, dass wichtige Informationen nicht verloren gehen, wenn die App geschlossen oder das Gerät neu gestartet wird. Je nach den spezifischen Anforderungen deiner Anwendung kannst du die am besten geeignete Persistenzmethode auswählen.

Datenbankintegration

Datenbankintegration

Es gibt verschiedene Wege um Daten in DBs zu integrieren:

  • Daten lokal auf dem Gerät speichern (sqflite, moor)
  • mit einem entfernten Server abfragen (dart.io, dart.html, http-library, hive, dio)
  • kostenpflichtige Services nutzen (firebase, amazon, azure etc.)

Die Integration einer Datenbank in eine Dart- und Flutter-App = strukturierte Daten zu speichern und abzurufen.

Grundschritte:

  1. Datenbank auswählen
  2. Paket zu App hinzufügen (pubspec.yaml)
  3. DB erstellen und konfigurieren
  4. CRUD-Operationen implementieren (Erstellen, Lesen, Aktualisieren und Löschen)
  5. Datenverbindungen überlegen (Lifecyle-Events etc., (?) moor)
  6. State-Management (über z.B. Provider Zustände mit DB verwalten)
  7. UI aktualisieren
  8. Datenabfragen im Bezug auf Sicherheit und Leistung optimieren

Links zu verwandten Themas aus offizieller Dokumentation:

Testen & Debuggen

Testen von Flutter Apps

Überblick –> https://docs.flutter.dev/testing/overview

Services:

Debugging Tools

  • Dart DevTools
  • Flutter Inspector
  • print-Anweisungen
  • Logging mit dart:developer
  • Visual Studio Code Debugger
  • Assertions
  • Flutter-Befehle (flutter doctor etc.)

Debugging Techniken

–> https://docs.flutter.dev/testing/code-debugging

  • Logging
  • Setting breakpoints
  • Debug flags: application layers
  • Debug flags: performance
  • etc.

Lokaler Cache

Lokaler Cache

–> Speicherung von Daten auf dem Gerät des Users. Zweck: schneller Zugriff auf diese Daten. Besonders, wenn es um häufig abgerufenen Daten geht, um wiederholte Netzwerkanfragen zu vermeiden oder damit die App funktionsfähig ist, wenn keine Netzwerkverbindung besteht.

Techniken:

Schlüsselfarben

Farben für App

Die spezifische Anwendung von Farben kann je nach dem spezifischen Kontext und den Anforderungen der App variieren.

Allgemeine Leitlinien, wie verschiedene Schlüsselfarben in App-Designs verwendet werden können:

Primärfarben:
App-Header und Navigationsleisten: Primärfarben werden oft für die Hauptelemente wie App-Header, Navigationsleisten und Schaltflächen verwendet, um wichtige Funktionen oder Aktionen hervorzuheben.

Sekundärfarben:
Akzentfarben und Call-to-Action-Elemente: Sekundärfarben können für Akzentuierungen und Call-to-Action-Elemente verwendet werden, um wichtige Interaktionspunkte hervorzuheben. Zum Beispiel für Schaltflächen, Links oder Benachrichtigungen.

Neutralfarben:
Hintergründe und Text: Neutralfarben eignen sich gut für Hintergründe, insbesondere wenn du möchtest, dass Inhalte oder andere Elemente darauf hervorstechen. Sie werden auch häufig für Text verwendet, um die Lesbarkeit zu verbessern.

Tertiärfarben:
Akzentuierung und Variation: Tertiärfarben können dazu verwendet werden, bestimmte Elemente hervorzuheben und Variationen innerhalb der Farbpalette zu schaffen. Dies könnte zum Beispiel für spezielle Grafiken, Icons oder kleine Designakzente sein.

Richtlinien der Material Design 3:

Schlüsselfarben werden aus dem Farbton der Eingabefarbe erstellt, indem Chroma und Ton angepasst werden.

(1) Primär kann Ihre Hauptmarkenfarbe oder die am häufigsten verwendete primäre Akzentfarbe sein.
Die primäre Schlüsselfarbe wird als Quellfarbe verwendet, ähnlich wie die Quellfarbe in der dynamischen Einstellung, und überschreibt alle anderen Schlüsselfarben. Legen Sie diese daher zuerst fest. Das bedeutet, dass keine zusätzlichen Farben hinzugefügt werden müssen

(2) Sekundäre Rollen werden für weniger prominente Komponenten in der Benutzeroberfläche verwendet und erweitern gleichzeitig die Möglichkeiten zur Farbdarstellung.

(3) Neutrale Rollen werden für Oberflächen und Hintergründe sowie für stark hervorgehobene Texte und Symbole verwendet. Ihre Markenfarben werden nun in das Kernfarbschema aufgenommen, das an den M3-Farbraum angepasst ist, vollständig zugänglich ist und als Design im Code exportiert und implementiert werden kann.

(4) Tertiärrollen werden für kontrastierende Akzente verwendet, die dazu dienen können, Primär- und Sekundärfarben auszugleichen oder die Aufmerksamkeit auf ein Element zu lenken.

App Icon für Android

Es gibt zwei Möglichkeiten, das App-Icon zu ändern:
1. Verwenden eines Pakets, das automatisch alle Größen von Icons in Android- und IOS-Ordnern hinzufügt.
2. Manuelles Ändern der Icondateien im Android- und IOS-Ordner durch Hochladen aller erforderlichen Icongrößen.

Manuele Variante für Android:

1. Logo erstellen
2. Icons für Logo mit einem Online Generator (z.B. AppIcon AI) in verschiedenen Größen generieren.
3. Zu android/app/src/main/res navigieren und auf res mit rechtem Click im Kontextmenü > “reveal in Explorer”.
4. Alle mipmap Ordner im res entfernen und die neue (generierte aus AppIcon/android) mipmap hineinkopieren.

Application Launcher Icon für Android (aus offizieller Doku)

Navigieren Sie im Stammverzeichnis Ihres Flutter-Projekts zu …/android/app/src/main/res.
Die verschiedenen Bitmap-Ressourcenordner wie mipmap-hdpi enthalten bereits Platzhalterbilder mit dem Namen ic_launcher.png.
Ersetzen Sie sie durch Ihre gewünschten Assets und beachten Sie dabei die empfohlene Symbolgröße pro Bildschirmdichte, wie im Android Developer Guide angegeben.

Hinweis: Wenn Sie die PNG-Dateien umbenennen, müssen Sie auch den entsprechenden Namen im <application> tag’s android:icon Attribut im AndroidManifest.xml aktualisieren.

Startbildschirm mit Icon für Android (aus offizieller Doku)

Um Ihrer Flutter-App einen Startbildschirm („auch als „“Begrüßungsbildschirm“) hinzuzufügen, navigieren Sie zu …/android/app/src/main. Verwenden Sie in res/drawable/launch_background.xml die  layer list drawable  XML-Ebenenliste, um das Aussehen Ihres Startbildschirms anzupassen. Die aktuelle Template bietet ein Beispiel für das Hinzufügen eines Bildes in der Mitte eines weißen Begrüßungsbildschirms in kommentiertem Code. Sie können den Kommentar entfernen oder andere drawables in die Code eingeben, um einen gewünschten Effekt zu bekommen.

Weitere Einzelheiten finden Sie unter Hinzufügen eines Begrüßungsbildschirms zu Ihrer Android-App.

Hinweis: runApp() soll in der main()-Funktion Ihrer App aufrufen werden. Sonst beim Appstarten bleibt Icon für immer.

Zusätzliche Resource zum Thema

–> offizielle Dokumentation: Updating the app icon

–> flutter_launcher_icons: ^0.13.1

–> Artikel Eigenes App Icon in Flutter einbinden

–> Anleitung auf StackOverflow

–> YT Tutorial: How to Change App Icon and App Name | The Right Way | Android & iOS

–> App Icon Generator Appicon AI

–> App Icon Generator IconKitchen

Pixel Density (DIP oder DP)

Pixeldichte

DIP (Density-Independent Pixel) und DPI (Dots Per Inch) sind Begriffe, die in der Grafik- und Bildschirmtechnologie verwendet werden, insbesondere im Kontext von Mobilgeräten. Hier sind die Unterschiede zwischen DIP und DPI:

DIP (Density-Independent Pixel):

  1. Definition: DIP ist eine Einheit, die in der Softwareentwicklung verwendet wird, um grafische Elemente unabhängig von der Pixeldichte eines Bildschirms zu beschreiben.
  2. Unabhängigkeit von der Pixeldichte: Ein DIP repräsentiert eine Einheit der Größe, die unabhängig von der tatsächlichen Pixeldichte ist. Dies bedeutet, dass ein DIP auf verschiedenen Bildschirmen gleich groß erscheint, unabhängig davon, ob es sich um einen hochauflösenden Bildschirm mit hoher Pixeldichte oder einen Bildschirm mit niedriger Pixeldichte handelt.
  3. Verwendung in der Softwareentwicklung: Entwickler verwenden DIPs, um die Größe von Benutzeroberflächenelementen festzulegen, ohne sich um die spezifische Pixeldichte des Geräts kümmern zu müssen. Dies ermöglicht eine konsistente Darstellung auf verschiedenen Geräten.

DPI (Dots Per Inch):

  1. Definition: DPI ist eine Maßeinheit, die die Anzahl der Bildpunkte (Pixel) pro Zoll auf einem Bildschirm oder Druckmedium angibt.
  2. Pixeldichte: DPI gibt an, wie dicht die Pixel auf einem Bildschirm platziert sind. Ein höherer DPI-Wert bedeutet eine höhere Pixeldichte, was zu einer schärferen Anzeige führt.
  3. Verwendung: DPI wird oft im Druckwesen und in der Bildschirmtechnologie verwendet, um die Qualität von Ausdrucken oder die Schärfe von Bildschirmdarstellungen zu beschreiben. In der Regel wird es in Bezug auf die Hardware und die physikalischen Eigenschaften eines Bildschirms verwendet.

Zusammenfassung:

  • DIP: Einheiten in der Softwareentwicklung zur Größenangabe von Benutzeroberflächenelementen, unabhängig von der Pixeldichte.
  • DPI: Eine Maßeinheit, die die Anzahl der Pixel pro Zoll auf einem Bildschirm oder Druckmedium angibt, und wird oft verwendet, um die Pixeldichte eines Bildschirms zu beschreiben.

In der Praxis sind DIPs und DPI eng miteinander verbunden, da DIPs dazu dienen, eine konsistente Benutzeroberfläche über verschiedene Pixeldichten hinweg zu ermöglichen. Entwickler verwenden DIPs, um die Größe von UI-Elementen zu definieren, und die Plattform passt diese dann entsprechend der Pixeldichte des Geräts an.

adaptiv vs. responsive

adaptiv vs. responsive

Sie können eine adaptive App haben, die nicht responsive ist, oder umgekehrt.
Und natürlich kann eine App beides oder keines von beidem sein.

Adaptives Design:

  • Es werden separate Designs für Desktop-Computer, Tablets und Mobilgeräte erstellt
  • Media Queries oder andere Techniken, um das Gerät zu identifizieren etc. Mit Media Queries werden Breakpoints gesetzt.
  • Bessere Leistung, da nur das Layout für erkanntes Gerät geladen wird

Responsive Design:

  • Einheitliches Layout für alle Geräte. Dynamische Anppasung an verschiedenen Bildschirmgrößen
  • Flüssige Raster und flexible Elemente. Skalierung proportional zw. UI-Elementen und Bildschirmabmessungen
  • Schwerpunkt in Verwendung von Media Queries liegt darauf, dass das Layout dynamisch auf verschiedene Bildschirmgrößen reagiert, ohne spezielle Designs für bestimmte Geräte vorzusehen.

Beide Ansätze haben jedoch gemeinsame Ziele:

  • Benutzerfreundlichkeit: eine gute UX, unabhängig vom verwendeten Gerät.
  • Optimierung für verschiedene Geräte: die Benutzeroberfläche auf einer Vielzahl von Geräten und Bildschirmgrößen gut dargestellt wird.

Kurze Einführung in Responsive Design (EN) ca. 6 min.: https://www.linkedin.com/learning/mapping-the-modern-web-design-process/responsive-web-design-as-a-process-14881664?u=36053084

Rx = Reactive Extensions

Rx

Reactive Extensions (Rx) ist ein Programmierparadigma, das auf dem Observer-Pattern basiert und es ermöglicht, asynchrone und ereignisbasierte Programmierung auf eine konsistente und leicht verständliche Weise zu behandeln.

In Flutter wird Rx Dart häufig verwendet, um reaktive Programmierkonzepte zu implementieren, insbesondere wenn es um die Verwaltung von Streams und Ereignissen geht. Mit Rx Dart können Entwickler auf elegante Weise auf Ereignisse reagieren und mit Streams arbeiten, indem sie Funktionen wie map, filter, merge und andere verwenden, um Datenströme zu manipulieren.

Es gibt verschiedene Pakete und Bibliotheken in Dart, die Rx Dart implementieren, und Entwickler können diese verwenden, um reaktive Programmiermuster in ihren Flutter-Anwendungen zu integrieren. Rx Dart ist nicht Teil des Flutter-Frameworks, sondern eine separate Bibliothek.

Ein einfaches Beispiel in Dart mit dem rxdart-Paket für Flutter vom GPT:

import ‚package:flutter/material.dart‘;
import ‚package:rxdart/rxdart.dart‘;

void main() {
  runApp(MyApp());
}

class CounterBloc {
  final BehaviorSubject<int> _counterSubject = BehaviorSubject<int>.seeded(0);

  Observable<int> get counterStream => _counterSubject.stream;

  void incrementCounter() {
    _counterSubject.add(_counterSubject.value + 1);
  }

  void dispose() {
    _counterSubject.close();
  }
}

class MyApp extends StatelessWidget {
  final CounterBloc _counterBloc = CounterBloc();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text(‚Rx Dart Beispiel‘),
        ),
        body: Center(
          child: StreamBuilder<int>(
            stream: _counterBloc.counterStream,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(‚Counter: ${snapshot.data}‘);
              } else {
                return Text(‚Loading…‘);
              }
            },
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            _counterBloc.incrementCounter();
          },
          child: Icon(Icons.add),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _counterBloc.dispose();
    super.dispose();
  }
}
 

In diesem Beispiel verwendet der CounterBloc das BehaviorSubject ausrxdart, um den aktuellen Counter-Wert zu speichern und als Stream bereitzustellen. Die Benutzeroberfläche reagiert auf Änderungen des Streams und aktualisiert den dargestellten Counter-Wert. Der Counter wird jedes Mal erhöht, wenn auf den FloatingActionButton geklickt wird. Beachten Sie auch die Verwendung der dispose-Methode, um sicherzustellen, dass der BLoC korrekt freigegeben wird.

BLoC

BLoC

Der BLoC (Business Logic Component) selbst ist eine Klasse oder ein Objekt, das die Logik Ihrer Anwendung enthält. Es kann die Datenverarbeitung, Validierung, API-Aufrufe und andere relevante Logik umfassen.

BLoCs verwenden normalerweise Streams, um Daten zu verwalten. Ein Stream ist eine Sequenz von Ereignissen oder Datenwerten im Laufe der Zeit. Der BLoC stellt einen Stream für die UI bereit, und die UI kann auf Änderungen des Streams reagieren.

Die UI interagiert mit dem BLoC durch das Senden von Ereignissen (Events) an den BLoC. Der BLoC verarbeitet diese Ereignisse und gibt den aktuellen Zustand (State) zurück. Die UI reagiert auf State-Änderungen und aktualisiert sich entsprechend.

Normalerweise wird Provider-Paket verwendet, um BLoCs zu verwalten. Der Provider hilft, Abhängigkeiten zu injizieren und den Zugriff auf den BLoC in der Anwendung zu organisieren.

..weiter so eine 8-Kseislauf:

  1. BLoC -> Async Request zu Data (oben)
  2. Async Responce zurück zum BLoC
  3. dann sendet BLoC  State zu UI (oben)
  4. von UI kommen Events wiederum zum BLoC

Ein Beispiel für BLoC von Chat-GPT:

// BLoC
class CounterBloc {​
  final _counterController = StreamController<int>.broadcast();
  int _counter = 0;

  Stream<int> get counterStream => _counterController.stream;

  void increment() {​
    _counter++;
    _counterController.add(_counter);
  }​

  void dispose() {​
    _counterController.close();
  }​
}​

// UI
class CounterApp extends StatelessWidget {​
  @override
  Widget build(BuildContext context) {​
    final CounterBloc counterBloc = Provider.of<CounterBloc>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text(‚BLoC Beispiel‘),
      ),
      body: StreamBuilder<int>(
        stream: counterBloc.counterStream,
        builder: (context, snapshot) {​
          return Center(
            child: Text(‚Counter: ${​snapshot.data}​‘),
          );
        }​,
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {​
          counterBloc.increment();
        }​,
        child: Icon(Icons.add),
      ),
    );
  }​
}​
 

In diesem Beispiel wird ein einfacher Zähler-BLoC erstellt und in der Benutzeroberfläche verwendet. Der BLoC erhöht den Zählerwert und informiert die Benutzeroberfläche über den aktualisierten Wert.

Redux

Redux

In Flutter gibt es nicht direkt „Redux“, wie es in der JavaScript-Welt der Fall ist.
Redux ist ein Konzept für die State-Management, das oft mit React-Anwendungen und anderen JavaScript-Frameworks verwendet wird.
In Flutter gibt es jedoch ein vergleichbares Konzept für die State-Management —> Provider.

Bild

Hier sind die drei Grundsätze von Redux in der JavaScript-Welt.

  1. Single source of truth: Der gesamte Anwendungsstatus wird in einem einzigen zentralen Speicher, dem sogenannten „Store“, gespeichert. Dadurch wird die Datenverwaltung vereinfacht und die Konsistenz erleichtert.
  2. State is read-only (Der Zustand ist schreibgeschützt): Der Zustand kann nicht direkt von Komponenten oder anderen Teilen der Anwendung geändert werden. Änderungen am Zustand erfolgen stattdessen durch „Actions“, einfache JavaScript-Objekte, die die Absicht anzeigen, den Zustand zu ändern.
  3. Changes are made with pure functions (Änderungen werden mit reinen Funktionen vorgenommen): Um Änderungen am Zustand vorzunehmen, werden „Reducer“ verwendet, die reine Funktionen sind. Reducer erhalten den aktuellen Zustand und eine Aktion als Parameter und geben einen neuen Zustand zurück, ohne den vorhandenen Zustand zu ändern.

23 Layout-Widgets

23 Layout-Widgets

  1. Container: Ein rechteckiger Bereich mit Anpassungsoptionen wie Breite, Höhe, Farbe und mehr.
  2. Row: Ordnet seine Kinder in einer horizontalen Zeile an.
  3. Column: Ordnet seine Kinder in einer vertikalen Spalte an.
  4. Stack: Stapelt Kinder-Widgets übereinander.
  5. Expanded: Weist einem Kind-Widget in einer Flex-Widget-Hierarchie den verbleibenden verfügbaren Platz zu.
  6. Flexible: Steuert die Flexibilität von Kind-Widgets in einer Flex-Widget-Hierarchie.
  7. ListView: Zeigt eine scrollbare Liste von Widgets an.
  8. GridView: Zeigt eine scrollbare Rasteranordnung von Widgets an.
  9. Card: Zeigt Informationen in einer Karte mit abgerundeten Ecken und Schatten an.
  10. SizedBox: Erstellt ein festes Höhe-Breite-Layout.
  11. Padding: Fügt Polsterung zu seinen Kindern hinzu.
  12. Align: Positioniert sein Kind innerhalb des übergeordneten Widgets.
  13. Wrap: Ordnet seine Kinder in einer Zeile oder Spalte an und kann automatisch umbrechen.
  14. Positioned: Positioniert ein Kind-Widget in einem Stack an einer bestimmten Position.
  15. AspectRatio: Setzt das Verhältnis von Breite zu Höhe für ein Widget.
  16. ListView.builder: Erstellt dynamisch eine Liste von Kindern basierend auf einem Generator.
  17. GridView.builder: Erstellt dynamisch ein Raster von Kindern basierend auf einem Generator.
  18. Spacer: Erzeugt in einer Flex-Widget-Hierarchie leeren Raum.
  19. Divider: Erstellt eine horizontale oder vertikale Trennlinie zwischen Elementen.
  20. FittedBox: Passt ein Kind in die verfügbare Größe, indem es es proportional oder nicht proportional verkleinert oder vergrößert.
  21. ConstrainedBox: Beschränkt die Größe seines Kindes auf eine bestimmte Mindest- oder Höchstgröße.
  22. IntrinsicHeight und IntrinsicWidth: Passen die Höhe bzw. Breite ihrer Kinder an, um ihre intrinsischen Größen beizubehalten.
  23. Flow: Ordnet Kinder in einer nicht einschränkenden Weise an.

Projekt als Web auf GitHub publizieren

Projekt als Web auf GitHub publizieren

  1. ein Repo auf GitHub erstellen (public und mit READ.ME)
  2. Lokal, in den 2build“-Ordner des Flutter-Projektes navigieren:
    % cd build
  3. Ein Ordner im Flutter-Projekt mit Namen „repo.name“ erstellen und dorthin Inhalt vom Repo auf GitHub kopieren:
    % git clone https://github.com/username/repo.name
  4. Inhalte mit aus Projekt App mit web-Version in den erstellten Ordner kopieren
  5. Zum erstellten „repo.name“-Ordner navigieren:
    % cd repo.name

In weiteren drei Schritten Inhalt des lokalen „repo.name“ auf dem „repo.name“ auf GitHub synchronisieren:

  1. % git add –all
  2. % git commit -m ‚initial commit‘
  3. % git push -u origin master

Auf GitHub –> Repo / Settings / Pages / Branch –> master –> save

Git Befehle

git cheat sheet als PDF

https://education.github.com/git-cheat-sheet-education.pdf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
% git clone https://github.com/your-ount-name/reopo_name.io.git

% git add --all
% git commit -m 'initial commit'
% git push -u origin master


% git init // neues Repositorium
% git status //aktuellen Status prüfen
% rm -rf .git // lokanes Repo löschen
% rm -rf .git*

% git config --global user.name
% git reset
% git reset --hard
% git remote -v
% git remote set-url origin https://github.com/your-ount-name/reopo_name.io.git

%rm -rf drhuva.io
% git init
% git remote add origin https://github.com/your-ount-name/reopo_name.io.git
% git pull origin master

% git status //aktuellen Status prüfen
% git add .// alle Dateien einfügen
% git add index.html // index.html einfügen
% git add /logs //Ordner "log" einfügen
% git rm --caсhed <Deiteiname>

Bild als Background anbinden

Bild als Background anbinden

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Container(
    decoration: BoxDecoration(
        image: DecorationImage(
            image: AssetImage('assets/background_image.jpg'), // Pfad zu Ihrem Bild
            fit: BoxFit.cover, // Anpassen, um den Bildschirm zu füllen
            ),
        ),
        child: // Ihr weiterer Inhalt hier
        Center(
             child: Text('Ihr Inhalt hier',
            style: TextStyle(color: Colors.white),
        ),
    ),
),

Navigation

Die Flutter Anwendungen zeigen ihre Inhalte in einer Art „Fullscreen-Containers“ auf einem Bildschirm – pages (oder screens, oder views).
Diese pages und screens werden in Flutter als Routs (Routen) bezeichnet.
In Android werden diese pages/screens als Activity bezeichnet, und in iOS als ViewController. Aber im Flatter sind die Routen auch Widgets.
Ein einzelnes Widget kann Route sein, wenn er einen vollständigen Layout darstellt.

Eine Route (ein Bildschirm) kann in Dart – im Sinne des OOP-Konzeptes – als eine „Klasse“ beschrieben werden.
Deswegen kann jede Route – als eine separate Klasse – über eigene Inhalte und eine eigene UI (Benutzeroberfläche) verfügen.

Möglichkeiten für Navigation in Flutter:
(A) einfache Navigation zwischen zwei Routen (push & pop)
(B) Navigation zwischen zwei benannten Routen (named Routs)
(C) Navigation zwischen zwei Routen mit onGenerateRoute()
(D) Navigation mit weichen Übergang zwischen zwei Routen (animiert)
(E) deep Links

Link zu offizieller Documentation –> über Navigation in Flutter
Link zum thematischen Artikel —> Navigation System in Flutter

(A) einfache Navigation zwischen zwei Routen:
1. Erstellen Sie zwei Routen.
2. Navigieren Sie mit der Methode Navigator.push() zur zweiten Route.

1
2
3
4
5
6
7
8
onPressed: () {
    Navigator.of(context).push(
            context,
            MaterialPageRoute(
                builder: (context) => SecondScreen();
            ),
    ),
}

3. Kehren Sie mit der Methode Navigator.pop() zur ersten Route zurück.

1
onPressed: () => Navigator.pop(context)

Ein weiteres Beispiel für Verwendung des Navigator-Widgets ist hier: https://www.geeksforgeeks.org/routes-and-navigator-in-flutter/?ref=rp

(B) Navigation zwischen zwei benannten Routen:
1. Erstellen Sie zwei Routen.
2. Die Eigenschaft home des Widgets MaterialApp mit der Eigenschaft initialRoute (mit dem Wert ‚/‘) ersetzen . Darunter eine weitere Eigenschaft route mit Wert verwenden:

1
2
3
4
5
6
//alternativ:
initialRoute: 'A',
    routes: {
      'A': (context) => const FirstScreen(),
      'B': (context) => const SecondScreen(),
    },

3. Im Navigator mit benannten Routen rufen wir MaterialPageRoute nicht mehr auf, sondern verwenden direkt die Methode .pushNamed(context, ‚route‘).

onPressed: () => Navigator.pushNamed(context, ‚/second‘),
// alternativ: Navigator.of(context).pushNamed(‚B‘);

4. Und wie bei einfachen Navigator mit Navigator.pop() zur ersten Route zurückkehren.

onPressed: () => Navigator.pop(context),

 

 

comming soon:

(C) Navigation zwischen zwei Routen mit onGenerateRoute()
(D) Navigation mit weichen Übergang zwischen zwei Routen (animiert)
(E) deep Links

Projekt erstellen

Projekt erstellen

  1. VS Code öffnen
  2. Commando-Zeile öffnen –> „CTRL+SHIFT+P“ (Mac users replace CTRL with CMD)
  3. „Flutter“ eintippen
  4. Die Option „Flutter: New Project“ auswählen
  5. „Application“-Option aus der Liste auswählen
  6. Ordner für Projekt auswählen –> Enter
  7. Namen für Projekt geben (kleine Buchstaben und Unterstriche) –> Enter