preface

The introduction to Flutter for Android developers (1) explained the general process of developing a simple news app with Flutter and the implementation of its main functions. The implementation details of some features are omitted. This article will elaborate on these details. The following points are involved:

The splash screen page

Custom layout

The drop-down refresh

Pull up to load more

The use of Assets

Routing (page hopping)

Embedded WebView

The splash screen page

Since a Flutter app needs to be initialized when it is started. That’s a long time. Therefore, a splash screen is required when developing a Flutter app. Adding a splash screen to a Flutter app running on Android is the same as adding a splash screen to a normal Android app.

First, in androidmanifest.xml,

MainActivity
meta-data

Here’s the LaunchTheme:

drawable

For details on how to get a splash screen on ios, see here.

Custom layout

We all know that in Android, if the layout control provided by the system does not meet our needs, we will customize the layout control to achieve. Flutter also provides the ability to customize layout controls. In this news app, the list items on the home page are displayed as shown in the picture below, which is achieved by using custom layout controls.

The code is in news_item.dart.

class NewsItem extends StatelessWidget {
 ...
  @override
  Widget build(BuildContext context) {
   ...
  returnnew InkWell( onTap: enabled ? onTap : null, onLongPress: enabled ? onLongPress : null, child: Semantics( selected: selected, enabled: enabled, child: ConstrainedBox( constraints: // This is a custom Layout child: CustomMultiChildLayout(// This Delegate is used to do the actual layout Delegate: ItemLayoutDelegate(), // Children: children,)),); }}Copy the code

CustomMultiChildLayout is a control that allows you to create your own custom layout. You need a Delegate as the parameter. This Delegate needs to be implemented by ourselves. The other argument, children, is the child control that needs to be laid out. The children of custom layout controls need to be wrapped in a LayoutId control. This is one of the interesting things about Flutter. A lot of things that we use as properties in Android, Flutter is wrapped around as a class. This is one of the reasons why the UI code is ugly.

The id here is usually represented by an enumeration, for example

enum _Block {
  bg,
  text,
}
Copy the code

Bg stands for news picture and text stands for news headline. The child controls you pass to CustomMultiChildLayout should look like this, each wrapped in LayoutId:

final List<Widget> children = <Widget>[]; Children. Add (LayoutId(// header id id: _block. bg, child: fadeinimage.assetNetwork (),)); Children. Add (LayoutId(// title id id: _block. text, child: Container()));Copy the code

Finally, let’s take a look at the actual layout and look at the ItemLayoutDelegate code:

class ItemLayoutDelegate extends MultiChildLayoutDelegate {
  @override
  void performLayout(Size size) {
    if (hasChild(_Block.bg)) {
      layoutChild(_Block.bg, new BoxConstraints.tight(size));
      positionChild(_Block.bg, Offset.zero);
    }

    if(hasChild(_block. text)) {layoutChild(_block. text, new BoxConstraints. Tight (Size(sie.width, sie.height * 0.4))); PositionChild (_block. text, new Offset(0.0, size.height-size. Height * 0.4)); } } @override bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) =>false;
}
Copy the code

The custom layout is done in the function performLayout. The input parameter is Size, which is the width and height of the parent control. Function body is based on the id of the child control, different child control first call the constraint layoutChild, then call the positionChild position, custom layout is complete, isn’t it very simple?

The drop-down refresh

It’s easy to add a Material Design-style drop-down refresh, just give the list pack a RefreshIndicator

 returnRefreshIndicator(// onRefresh: _onRefresh, Child: ListView.Builder ())Copy the code

The pulldown refresh triggers the callback through the onRefresh parameter setting. In _onRefesh, the refresh logic is implemented. Note that _onRefresh needs to return a Future of type Null. After this Future complete. The refreshed icon will disappear by itself. The effect is as follows:

Pull up to load more

Flutter does not have system-provided overloading controls, so we tried to make a rough implementation here. The idea is to add a load control at the end of the list and trigger the load action when sliding to the bottom of the list.

ItemCount: _articles. Length + 1, itemBuilder: (context, index) {if(index == _articles.length) {// If it is the last one, return to load more controlreturn LoadingFooter(
                        retry: () {
                          loadMore();
                        },
                        state: _footerStatus);
                  } else{// Returns the normal list itemreturnNewsItem(); }}, // check list rolling state controller: _controller);Copy the code

We increase the length of the list by one when we create it, return to load more controls when we get to the last item, and monitor the scrolling status of the list through the Controller. So we’re adding a pull-up load function to the list. The effect is as follows:

The use of Assets

Add Assets

The concept of Assets is different from that of Assets in Android. In a sense, Assets of Flutter are more like Resources in Android. All assets added to Flutter need to be declared in pubspec.yaml. For example, if I need to add an image to use as a placeholder for loading web images, I just need to make the following declaration.

flutter:
  assets:
  - images/news_cover.png
Copy the code

The Resources folder of Android can be named according to certain rules, so that the system can select the most suitable Resources. Similarly, the Asset of Flutter can also be named. The following declaration provides ICONS in three different resolutions.

. /my_icon.png ... / 2.0 x/my_icon. PNG... / 3.0 x/my_icon. PNGCopy the code

Access to Assets

Access to Assets in Flutter is flexible. Basically, you can access Assets in the following ways:

import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;

Future<String> loadAsset() async {
  return await rootBundle.loadString('assets/config.json');
}
Copy the code

But many controls also provide a more convenient way, see here for details.

Routing (page hopping)

In Android, we use startActivity or a third-party routing library to jump to pages. In Flutter, we use the built-in Navigator to jump to pages. Navigator is a stack. When a new page needs to be opened, Navigator. Push is called, and when a new page needs to be returned, navigator.pop is called. The code is as follows:

Navigator.push(
              context,
              MaterialPageRoute(
                 builder: (context) => WebviewScaffold(),
             )));
Copy the code

Embedded WebView

Flutter itself does not support embedded WebViews. This can be done using the third-party plugin library Flutter_webview_plugin.

Start by introducing this library in pubspec.yaml:

dependencies:
     flutter_webview_plugin: "^ 0.1.5"
Copy the code

Just pass in the URL and appBar

WebviewScaffold(
      url: '${_articles[index].url}',
      appBar:
              AppBar(title: Text("News Detail")))Copy the code

conclusion

This is the end of my first discussion of the Flutter app. I believe that you will have an understanding of some basic technical points of developing the Flutter app. I have just started to learn, there may be mistakes in the article, welcome to correct. In general, developing apps with Flutter feels a lot different from Android native app development. It is of great value for us to broaden our technical thinking. There is still a long way to go to understand all aspects of Flutter development, but it will be interesting to read more code and practice.