Flutter - Webseiten
Die Erstellung von Webseiten und PWAs ist bereit seit einer ganzen Weile in der Beta-Phase, heute zeigen wir dir ein kleines produktives Beispiel.
Inhaltsverzeichnis
Flutter for Web ist nun schon seit einer ganzen Weile in der Beta-Phase. Wir wollen uns im heutigen Artikel einmal anschauen, wie weit das Framework für die Entwicklung im Web taugt und ob bereits die wichtigsten Features funktionieren. Dabei werden wir noch auf kleinere Bugs und Gaps eingehen, die uns bei der Entwicklung aufgefallen sind.
Beta
Als Erstes noch der wichtige Hinweis, dass das Flutter Team nicht empfiehlt Flutter for Web für komplexe produktive Webseiten zu nutzen, da sich das Modul noch in der Beta-Phase befindet und es Bugs geben kann. Wir haben die Chance trotzdem genutzt, um eine einfache Webseite zu gestalten und zu launchen.
Webseite
Die Webseite ist ein One-Pager bzw. eine Landing-Page und ihr könnt sie euch über den folgenden Link ansehen. Hierbei gibt es vor allem eine Hauptseite und zwei kleinere Unterseiten, um rechtliche Inhalte zur Verfügung zu stellen.
Features
Welche Features haben wir im Projekt verwendet, welche Pakete stecken dahinter oder wie funktioniert das Ganze genau in Flutter, dazu mehr in diesem Abschnitt.
Hover Effekte
Die bekannten Hover Effekte aus dem Web, sind auf mobilen Geräten nicht so einfach umsetzbar oder gar nicht erst implementiert, da man mit dem Finger meistens direkt einen Klick auslöst und nicht erst über die Element fährt. Am Computer ist dies natürlich wieder anders herum, die User sind gewonht, dass etwas passiert, wenn man mit der Maus über ein Element fährt. Die einfachste Form der Implementierung hier in einem kleinen Beispiel.
MouseRegion(
onHover: (event) {
setState(() {
containerColor = Colors.blueGrey.withOpacity(0.6);
});
},
onExit: (event) {
setState(() {
containerColor = Colors.transparent;
});
},
child: InkWell(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 8),
decoration: BoxDecoration(
color: containerColor,
borderRadius: BorderRadius.circular(15),
),
child: Text(''),
),
onTap: () {
// Call an action
},
),
);
Das Widget MouseRegion hilft bei der Umsetzung dieser Funktionalität. Das Event "onHover" wird ausgelöst, wenn die Maus das Element berührt und "onExit" wird die Aktion wieder beendet. Hier hast du die Möglichkeit per "setState" verschiedene Attribute neu zu setzen und so für den Hover-Effekt zu sorgen.
Anker
Eigentlich Standard in der Webentwicklung, doch noch nicht so leicht einsetzbar, sind die Anker auf der Webseite. Das heißt, du klickst auf einen Link und springst an eine bestimmte Position auf der Webseite. Im ersten Schritt müssen wir dazu einen Schlüssel erzeugen, dies geht am besten über den globalen Schlüssel.
final keyShop = new GlobalKey();
Diesen Schlüssel können wir dann einem WIdget über das Key Attribut zuweisen. Damit besitzt das Element einen eindeutigen Schlüssel und kann von uns angesteuert werden. Als zweiten Schritt musst du dann noch die Navigation zum Element implementieren. Dies kann zum Beispiel in der MEthode "onPressed" eines Buttons geschehen. Damit gehen wir sich, dass das Element nach dem Klick auch wirklich sichtbar ist.
Scrollable.ensureVisible(keyAbout.currentContext);
Slideshow
Für die Implementierung haben wir auf den beliebten Carousel Slider zurückgegriffen, der sich auch sehr einfach implementieren und konfigurieren lässt. Damit ließen sich die drei Slider auf der Webseite einfach implementieren und laufen nun völlig automatisch ab.
Videos
Für die Implementierung des Videos und der Steuerung haben wir auf das Paket vom Flutter Team, den Video Player, gesetzt. Dieser ist mittlerweile auch für die Webversion verfügbar und es lassen sich einfach Steuerelemente für das entsprechende Video einfach implementieren.
import 'package:diy_landing_page/helper/constants.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
class VideoArea extends StatefulWidget {
final String filePath;
VideoArea(this.filePath);
@override
_VideoAreaState createState() => _VideoAreaState();
}
class _VideoAreaState extends State<VideoArea>
with SingleTickerProviderStateMixin {
VideoPlayerController _videoController;
AnimationController _animationController;
bool _isPlaying = false;
@override
void initState() {
super.initState();
_videoController = VideoPlayerController.asset(widget.filePath);
_videoController.initialize().then((value) {
setState(() {});
});
_videoController.setLooping(true);
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 500),
);
}
@override
void dispose() {
_videoController.dispose();
_animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Stack(
children: [
Positioned(
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Container(
width: 300,
child: _videoController.value.initialized
? AspectRatio(
aspectRatio: _videoController.value.aspectRatio,
child: VideoPlayer(_videoController),
)
: Container(),
),
),
),
Positioned(
bottom: 10,
left: 140,
child: CircleAvatar(
radius: 20,
backgroundColor: kMainColor,
child: IconButton(
icon: AnimatedIcon(
icon: AnimatedIcons.play_pause,
progress: _animationController,
color: Colors.white,
),
onPressed: () {
if (_isPlaying == false) {
_videoController.play();
_animationController.forward();
_isPlaying = true;
} else {
_videoController.pause();
_animationController.reverse();
_isPlaying = false;
}
},
),
),
),
],
),
);
}
}
Als Beispiel das Widget, welches für jedes Video verwendet wird. Es wird das Widget aufgebaut und bekommt als Content den Pfad zum Video übergeben. Das Video befinet sich dabei im Asset Ordner und wird "lokal" später vom Server geladen.
Navigation
Wenn wir über Navigation auf der Webseite reden, meinen wir natürlich den Navigator innerhalb von Flutter. Um von der Seite auf eine Unterseite zu navigieren, verwenden wir Named-Routes. Dies ist der einfachste Weg zur Navigation auf die nächste Seite. Entsprechend der Route, ändert sich auch die Url für die Unterseite und kann somit auch als Link verschickt werden.
Interessant ist auch, dass beim direkten Aufruf der URL und die Navigation über den Floating-Action-Button, man wieder auf der Startseite landet, obwohl man nicht direkt über diese eingestiegen ist.
Mobile
Wie du oben siehst, gibt es ein großes Menü auf der Webseite, welches für die Navigation in die Abschnitte verantwortlich ist. Wenn du dir die Webseite als Mobileversion anschaust oder auf dem Smartphone öffnest, dann wird sich dieses Menü in eine kompakte Version verwandeln. Das Hamburger Symbol erscheint ...
... und beim Öffnen des Menüs werden die Navigationen untereinander angezeigt.
Im ersten Schritt prüfen wir die aktuell verfügbare Breite der Seite und ob das Menü überhaupt auf die komplette Breite passt. Dann können wir entscheiden, ob wir das mobile oder Desktop-Menü laden.
static bool isWidth(BuildContext context, double checkWidth) {
var screenSize = MediaQuery.of(context).size;
if (screenSize.width <= checkWidth) {
return true;
} else {
return false;
}
}
Welches Menü angezeigt wird, entscheidet über die Anzeige auf der fertigen Seite und gibt uns die Möglichkeit für jede unterschiedliche Seitenbreite ein anderes Menü anzuzeigen.
Bugs
Bisher sind uns bei der Entwicklung nur kleinere Fehler untergekommen, die wir dir hier noch einmal etwas genauer auflisten wollen:
- URL Anzeige - Aktuell befindet sich in der URL immer ein Hashtag (#), welches aber nur optisch stört
- Texte - Aufbereitung und Ausgabe von großen Textmengen (Rechtstexte) ist etwas umständlich
Fazit
Flutter for Web ist heute bereits für Webseiten ausgereift und bietet viele Voreile gegenüber einem geringen Teil an Nachteilen. Das Design und das Handling der Webseiten ist einfach und eignet sich hervorragend für ein Headless CMS zur Anzeige des Frontend.