This is a test message to test the length of the message box.
Login

Flutter - Websites

The creation of websites and PWAs has been in beta for quite a while, today we're going to show you a small productive example.

Advertising

Flutter for Web has been in beta for quite a while now. In today's article, we want to take a look at how far the framework is suitable for development on the web and whether the most important features are already working. We will go into smaller bugs and gaps that we noticed during development.

 

Beta

First of all, the important note that the Flutter team does not recommend using Flutter for Web for complex productive websites, as the module is still in the beta phase and there may be bugs. Nevertheless, we took the chance to design and launch a simple website.

 

Website

The website is a one-pager or landing page and you can view it using this link. There is only a main page and two smaller sub-pages to provide legal content.

 

Features

Which features did we use in the project, which packages are behind them or how exactly does it work in Flutter? More on this in this section.

 

Hover Effects

The well-known hover effects from the web are not so easy to implement on mobile devices or not implemented at all, as you usually trigger a click with your finger and do not first run over the element. On the computer this is of course the other way around, the users are used to something happening when they move the mouse over an element. The simplest form of implementation here in a small example.

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
    },
  ),
);

 

The MouseRegion widget helps implement this functionality. The "onHover" event is triggered when the mouse touches the element and "onExit" terminates the action. Here you have the possibility to set different attributes with "setState" and thus ensure the hover effect.

 

Anchor

The anchors on websites are actually standard in web development, but not yet easy to use. That means you click on a link and jump to a certain position on the website. In the first step we have to generate a key, this is best done using the global key.


final keyShop = new GlobalKey();

 

We can then assign this key to a widget via the key attribute. This means that the element has a unique key and can be controlled by us. As a second step, you then have to implement the navigation to the element. This can be done, for example, in the "onPressed" method of a button. So we work to ensure that the element is really visible after the click.


Scrollable.ensureVisible(keyAbout.currentContext);

 

Slideshow

For the implementation, we used the popular Carousel Slider package, which is also very easy to implement and configure. This made it easy to implement the three sliders on the website and now they run completely automatically.

 

Videos

For the implementation of the video and the control, we relied on the package from the Flutter team, the video player. This is now also available for the web version and controls for the corresponding video can be easily implemented.


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;
                  }
                },
              ),
            ),
          ),
        ],
      ),
    );
  }
}

 

As an example, the widget that is used for each video. The widget is set up and the path to the video is transferred as content. The video is located in the asset folder and is later loaded "locally" from the server.

 

Navigation

When we talk about navigating the website, we naturally mean the navigator within Flutter. To navigate from the page to a sub-page, we use named routes. This is the easiest way to navigate to the next page. According to the route, the URL for the subpage also changes and can therefore also be sent as a link.

 

It is also interesting that when you call up the URL directly and navigate via the floating action button, you end up on the start page again, although you did not enter directly via it.

 

Mobile

As you can see above, there is a large menu on the website that is responsible for navigating through the sections. If you look at the website as a mobile version or open it on your smartphone, then this menu will turn into a compact version. The hamburger symbol appears ...

 

... and when opening the menu, the navigations are displayed one below the other.

 

In the first step, we check the currently available width of the page and whether the menu even fits the entire width. Then we can decide whether to load the mobile or desktop menu.


static bool isWidth(BuildContext context, double checkWidth) {
  var screenSize = MediaQuery.of(context).size;

  if (screenSize.width <= checkWidth) {
    return true;
  } else {
    return false;
  }
}

 

Which menu is displayed decides on the display on the finished page and gives us the option of displaying a different menu for each different page width.

 

Bugs

So far we have only encountered minor errors during development, which we would like to list again here in more detail:

  • URL display - Currently there is always a hashtag (#) in the URL, but it is only visually disturbing
  • Texts - preparing and outputting large amounts of text (legal texts) is a bit cumbersome

 

Conclusion

Flutter for Web is already fully developed for websites and offers many advantages over a small number of disadvantages. The design and handling of the website is simple and ideal for a headless CMS to display the frontend.


Included topics:
FlutterDevelop websitesPWAHummingbird
Comments (0)
Advertising

Flutter - #FlutterEngage

Category - Flutter

The FlutterEngage event is over and there was again a lot of helpful and interesting information for all Flutter developers among us. We want to briefly summarize the most important points here.

03/05/2021

Flutter - Learning source

Category - Flutter

In this article we want to introduce you to some current learning sources that you can use as inspiration and for further education. Here we will mainly deal with YouTube channels and present some.

01/29/2021

Flutter Day 2020

Category - Flutter

The Flutter Day 2020 is over and we will briefly summarize the most important of the day and provide you with the resources.

07/31/2020

Flutter - Game Development

Category - Flutter

Flutter has many advantages for the rapid development of simple apps, but can the framework also be used to develop games?

05/22/2020

Flutter - Develop own packages (Part 2)

Category - Flutter

In the continuation of the series, we deal with the testing and further development of our own darts package from the last article.

05/15/2020

We use cookies for our services and functions. More informations