XML Layout for Flutter. Brings Angular's style to Flutter!

Overview

Imagine that you can do this :

<Container width="50 | widthPercent"
           height="50 | heightPercent"
           color="blue"
           :text="'Hello world!'"
           :opacity=".9"
           :center
           :if="ctrl.textVisible | behavior" />

Instead of this:

    final size = MediaQuery.of(context).size;
    final __widget = StreamBuilder(
      initialData: ctrl.textVisible.value,
      stream: ctrl.textVisible,
      builder: (BuildContext context, snapshot) {
        if (snapshot.data) {
          return Opacity(
            opacity: .9,
            child: Center(
              child: Container(
                color: Colors.blue,
                height: (size.height * 50) / 100.0,
                width: (size.width * 50) / 100.0,
                child: Text(
                  'Hello world!'
                )
              )
            )
          );
        }
        else {
          return Container(width: 0, height: 0);
        }
      }
    );
    return __widget;

Which is about 20 lines of code, and if you just updated the :text property to use a stream variable :text="ctrl.myTextStream | stream" that will add another 4 lines of code for the StreamBuilder.

Extension features:

  • Separates UI code (widget and widget's state) from the business logic.
  • Brings some Angular's features like pipes, conditionals...
  • Provides built-in properties & pipes to make the coding much easier.
  • Generates localization code depending on json files.
  • Forms & animation made easy.
  • Customizable! so developers can add their own properties and modify some features.
  • Supports Code completion, hover information, Go to Definition, diagnostics and code actions.

Example

Here is a working example

Get Started

  1. Install the extension from vscode marketplace
  2. Create a new flutter project
  3. Install prerequisites packages:
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  provider: ^3.0.0+1
  flutter_xmllayout_helpers: ^0.0.9
  1. Apply one of the following steps:
    • Clear all main.dart content then use fxml_app snippet to create the app.
    • Modify main.dart to use MultiProvider from provider package:
      • Register PipeProvider (from flutter_xmllayout_helpers package) as a provider.
      • Register RouteObserver<Route> as a provider (only if you want to use RouteAware events in your widgets' controllers).

Localization:

  1. Create i18n folder inside lib folder and add JSON files named with locale codes e.g. en.json.
  2. Import i18n/gen/delegate.dart in the main file.
  3. Register AppLocalizationsDelegate() in localizationsDelegates parameter of the MaterialApp.
  4. To use localized text in the UI see Pipes docs.

XML layout:

  1. Create a new folder and name it as your page/widget name e.g. home.
  2. Then create home.xml file inside home folder.
  3. Use fxml_widget snippet to create the starter layout, modify it as you want then save it. the extension will generate a file named home.xml.dart which contains UI code, and home.ctrl.dart file (if not exists) that contains the controller class which is the place you should put your code in (will be generated only if you added controller property).

Example:

<HomePage controller="HomeController" routeAware
    xmlns:cupertino="package:flutter/cupertino.dart">

  <Scaffold>

    <appBar>
      <AppBar>
        <title>
          <Text text="'Home'" />
        </title>
      </AppBar>
    </appBar>

    <body>
      <Column mainAxisAlignment="center" crossAxisAlignment="center">
        <Image :use="asset" source="'assets/my_logo.png'" />
        <Text text="'Hello world!'" />
        <Icon icon="CupertinoIcons.home" />
      </Column>
    </body>
  </Scaffold>
</HomePage>

HomePage (root element) the name of your widget. controller an optional property, the controller name you want to generate. routeAware an optional property, which generates navigation events (didPush(), didPop(), didPushNext() and didPopNext()). xmlns:* an optional property(s) used to import packges and files to be used in HomePage class. (in this example we imported cupertino.dart to use CupertinoIcons).

Controller:

If you added a controller property to your widget then will be generated (if not exists), the file looks like this:

import 'package:flutter/widgets.dart';
import 'home.xml.dart';

class HomeController extends HomeControllerBase {

  //
  // here you can add you own logic and call the variables and methods
  // within the XML file. e.g. <Text text="ctrl.myText" />
  //

  @override
  void didLoad(BuildContext context) {
  }

  @override
  void onBuild(BuildContext context) {
  }

  @override
  void afterFirstBuild(BuildContext context) {
  }

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

Features documentation

1. Wrapper properties

2. Pipes

3. Custom properties

4. Injecting providers

5. Parameters

6. Adding controllers to widgets

7. Adding mixin to widget's states

8. Localization

9. Developer customization

Comments
  • Extension contains analytics code from Dart-Code

    Extension contains analytics code from Dart-Code

    Hi!

    I noticed this extension has a copy of some of the code from the Dart extension - including the analytics code:

    https://github.com/waseemdev/vscode-flutter.xml-layout/blob/master/src/dart/extension/analytics.ts

    I don't know if the code is actually called, but sending analytics to this account from your extension could be confusing - is it possible you can remove the analytics code (or change the ID for the anlytics account?).

    Thanks!

    opened by DanTup 13
  • How can I return a value from the controller to an xml file?

    How can I return a value from the controller to an xml file?

    I need to return an error from the server and write an errorText response, I understand I can do this using (stream) but unfortunately it does not work. Please tell me the correct path.

    Here is the error and my code:

    
    <Container height="70" >
     <TextField  controller="ctrl.emailController"
          decoration="ctrl.decorations.getBaseTextField1('Email', ctrl.errorEmail | stream ) " />
    </Container>
    
    
    
    InputDecoration getBaseTextField1(String hintText, String errorText) {
        return InputDecoration(
            filled: true,
            fillColor: Colors.white70,
            enabledBorder: OutlineInputBorder(
                borderRadius: BorderRadius.all(Radius.circular(8.0)),
                borderSide: BorderSide(
                    color: ColorsApp.borderFrame,
                    width: 2,
                    style: BorderStyle.solid)),
            focusedBorder: OutlineInputBorder(
              borderRadius: BorderRadius.all(Radius.circular(4)),
              borderSide:
                  BorderSide(width: 1, color: ColorsApp.borderFrame_focused),
            ),
            focusedErrorBorder: OutlineInputBorder(
                borderRadius: BorderRadius.all(Radius.circular(4)),
                borderSide: BorderSide(width: 1, color: Colors.redAccent)),
            hintText: hintText,
            errorText: errorText,
            hintStyle: Styles.hintStyle);
      }
    
    
    
    Compiler message:
    lib/ui/sign_up/sign_up.xml.dart:158:34: Error: Place positional arguments before named arguments.
    Try moving the positional argument before the named arguments, or add a name to the argument.
                    stream: 'Email', ctrl.errorEmail,
                                     ^^^^
    lib/ui/sign_up/sign_up.xml.dart:158:39: Error: Expected named argument.
                    stream: 'Email', ctrl.errorEmail,
                                          ^
    lib/ui/sign_up/sign_up.xml.dart:156:35: Error: No named parameter with the name '#2'.
                  child: StreamBuilder(
                                      ^^...
    /E:/Android/Dart/flutter/packages/flutter/lib/src/widgets/async.dart:465:9: Context: Found this candidate, but the arguments don't match.
      const StreamBuilder({
    
    opened by Gensjava 4
  • xml auto import library doesn't work with the latest vscode(1.60.1) & Dart Code(v3.26.0) extension

    xml auto import library doesn't work with the latest vscode(1.60.1) & Dart Code(v3.26.0) extension

    2 issues found after debugging with this extension:

    1. the result of executeCommand('vscode.executeCodeActionProvider') not longer returns a 'Import library' titled Command, instead it returns a CodeAction with title 'Import library';

    2. got "command '_dart.applySourceChange' not found" when executing the source change command.

    opened by Jamesweng 3
  • I don't understand how to use this technology.

    I don't understand how to use this technology.

    This library is a great idea, but I have difficulty understanding how to work with it.I follow these instructions, but I don't understand everything.Please explain in more detail or maybe there is an example. I use Android Studio and I follow these instructions https://marketplace.visualstudio.com/items?itemName=WaseemDev.flutter-xml-layout

    but I do not understand where to use this "fxml_app" how do I call this command?

    Apply one of the following steps: Clear all main.dart content then use fxml_app snippet to create the app. Modify main.dart to use MultiProvider from provider package: Register PipeProvider (from flutter_xmllayout_helpers package) as a provider. Register RouteObserver as a provider (only if you want to use RouteAware events in your widgets' controllers).

    opened by Gensjava 3
  • Working Example

    Working Example

    Interesting work.

    Do you have working sample/example Flutter Application (with XML Layouts)?

    One that illustrates the concepts covered in the Docs would be awesome.

    Thanks!

    opened by lilkren 3
  • Failed to generate controller file when there's '.' character in the middle of filepath

    Failed to generate controller file when there's '.' character in the middle of filepath

    Hello Waseemdev,

    This extension is awesome and we would love to have a try in our projects. When playing with this extension, we find an issue here:

    The extension failed to generate the controller file if we have a character '.' in the middle of file path, e.g.,

    for file: /Users/firstname.lastname/workspace/test-vscode-flutter.xml-layout/home/home.xml

    It will try to import 'firstname.ctrl.dart' instead of 'home.ctrl.dart'. It looks like the extension splits on the first '.' on the path instead of the last one to generate the filename.

    Could you please have a look here?

    Thank You! -James

    opened by Jamesweng 2
  • How do I use other libraries?

    How do I use other libraries?

    Hi, I need help, I need to create a carousel I found a library but I don't understand how I can use it I always get an error like this in the screenshot, please help me find solutions. https://github.com/serenader2014/flutter_carousel_slider

    1 2

    opened by Gensjava 2
  • 0.0.33 upgrade issue on the repeat attribute

    0.0.33 upgrade issue on the repeat attribute

    Hi Waseem,

    Thanks for releasing the 0.0.33 update.

    After updgrading to 0.0.33, we found one issue and would like to confirm with you -

    the following xml (where cities is a List) -

    <LabeledCheckbox :repeat="item of widget.cities.take(5)"

    in 0.0.32, the generated code is -

    ...WidgetHelpers.mapToWidgetList(widget.cities.take(5), (item, index) {

    in 0.0.33, the generated code becomes -

    ...widget.cities.take(5).asMap().map((index, item)) {

    is this change expected? it breaks build since the take(5) method returns an iterator that doesn't has a asMap() method

    Thanks

    opened by Jamesweng 1
  • FlutterError: This widget has been unmounted, so the State no longer has a context

    FlutterError: This widget has been unmounted, so the State no longer has a context

    Hi, we got some error reports(collected from Crashlytics) as following on our App -

    "This widget has been unmounted, so the State no longer has a context (and should be considered defunct). Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.. Error thrown during a scheduler callback.

    Non-fatal Exception: FlutterError 0 ??? 0x0 State.context. + 942 (framework.dart:942) 1 ??? 0x0 State.context + 948 (framework.dart:948) 2 ??? 0x0 _ActionButtonWidgetState.initState. + 41 (action_button_widget.xml.dart:41) 3 ??? 0x0 SchedulerBinding._invokeFrameCallback + 1144 (binding.dart:1144) 4 ??? 0x0 SchedulerBinding.handleDrawFrame + 1089 (binding.dart:1089) 5 ??? 0x0 SchedulerBinding.scheduleWarmUpFrame. + 862 (binding.dart:862)"

    which is related to the following line of generated code which may access the context getter after widget unmounted - void initState() { ... WidgetsBinding.instance.addPostFrameCallback((_) => ctrl.afterFirstBuild(context)); }

    And I'm trying to submit a PR to fix this line.

    opened by Jamesweng 1
  • itemBuilder for listView generates null item for empty array

    itemBuilder for listView generates null item for empty array

    Hi Waseemdev,

    The following xml code -

    <ListView :use="builder" :itemBuilder="item of ctrl.data | behavior">
          <Card margin="24" >
         ...
    
    

    will generate codes like this -

     StreamBuilder(
          initialData: ctrl.data.value,
          stream: ctrl.data,
          builder: (BuildContext context, ctrlDataSnapshot) {
            final ctrlDataValue = ctrlDataSnapshot.data;
            if (ctrlDataValue == null) {
              return Container(width: 0, height: 0);
            }
            return ListView.builder(
              itemBuilder: (BuildContext context, int index) {
                final item = ctrlDataValue == null || ctrlDataValue.length <= index || ctrlDataValue.length == 0 ? null : ctrlDataValue[index];
              ...
    

    when ctrl.data is an empty array (init value), we get item=null here which may break logic that assumes no code inside the loop will be executed when looping through an empty array, can we handle empty array the same as null array which returns an empty Container(), does this make sense?

    Currently to workaround this null item we can add ':if' check inside the loop -

    <ListView :use="builder" :itemBuilder="item of ctrl.data | behavior">
          <Card margin="24" :if="item!=null" >
         ...
    

    Thanks, -James

    opened by Jamesweng 1
  • migrate to null-safety codes and Flutter 3.3.0

    migrate to null-safety codes and Flutter 3.3.0

    Hi Waseemdev,

    Would like to update you that we have updated this extension to generate null-safety codes and having running our apps with Flutter 3.3.0 for weeks. Here I'm creating the pull request to merge back changes. Similarly we have updated the flutter_xmllayout_helpers lib to null-safety and Flutter 3.3.0

    Thanks, -James

    opened by Jamesweng 1
  • Snippet definitions missing 'description'

    Snippet definitions missing 'description'

    This extension's snippet definitions

    ~/.vscode/extensions/waseemdev.flutter-xml-layout-0.0.31/snippets/dart.json
    ~/.vscode/extensions/waseemdev.flutter-xml-layout-0.0.31/snippets/xml.json
    

    are missing the required description field in the JSON, which can break some snippet scanners. It should at least be defined and set to an empty string. For example

    {
    	"fxml_widget": {
    		"prefix": "fxml_widget",
    		"body": [
    			"<${1:My}Page controller=\"${1:My}Controller\">",
    			"  <Scaffold>",
    			"    <appBar>",
    			"      <AppBar>",
    			"        <title>",
    			"          <Text text=\"'${2:PageTitle}'\" />",
    			"        </title>",
    			"      </AppBar>",
    			"    </appBar>",
    			"    <body>",
    			"      <Container>",
    			"      </Container>",
    			"    </body>",
    			"  </Scaffold>",
    			"</${1:My}Page>"
    		]
    	}
    }
    

    should be

    {
    	"fxml_widget": {
    		"prefix": "fxml_widget",
    		"body": [
    			"<${1:My}Page controller=\"${1:My}Controller\">",
    			"  <Scaffold>",
    			"    <appBar>",
    			"      <AppBar>",
    			"        <title>",
    			"          <Text text=\"'${2:PageTitle}'\" />",
    			"        </title>",
    			"      </AppBar>",
    			"    </appBar>",
    			"    <body>",
    			"      <Container>",
    			"      </Container>",
    			"    </body>",
    			"  </Scaffold>",
    			"</${1:My}Page>"
    		],
                   "description": ""
    	}
    }
    
    opened by abulka 0
  • How to define and use generic typed widget in xml?

    How to define and use generic typed widget in xml?

    Hi,

    I would like to know if there's a way to use generic typed widget in xml? e.g., how to rewrite the following code in xml? where RadioListTile is a generic typed widget.

    @override
      Widget build(BuildContext context) {
        return Column(
          children: <Widget>[
            RadioListTile<SingingCharacter>(
              title: const Text('Lafayette'),
              value: SingingCharacter.lafayette,
              groupValue: _character,
              onChanged: (SingingCharacter? value) {
                setState(() {
                  _character = value;
                });
              },
            ),
            RadioListTile<SingingCharacter>(
              title: const Text('Thomas Jefferson'),
              value: SingingCharacter.jefferson,
              groupValue: _character,
              onChanged: (SingingCharacter? value) {
                setState(() {
                  _character = value;
                });
              },
            ),
          ],
        );
      }
    

    and moreover, is there a way to define new generic typed widget like RadioListTile in xml?

    Appreciate for any info help. -James

    opened by Jamesweng 0
  • What are your plans for the Get package?

    What are your plans for the Get package?

    Get package is very popular, more than 2k likes already. https://pub.dev/packages/get

    But this library is tied to the Provider package. This is the only thing that prevents many users from using it.

    opened by alexkharech 0
Owner
Waseem
Senior Full Stack & Mobile Developer
Waseem
A grid-based layout system for Flutter, inspired by CSS Grid Layout

Flutter Layout Grid A powerful grid layout system for Flutter, optimized for complex user interface design. Click images to see their code ✨ Featuring

Felt 307 Dec 24, 2022
Flutter RSS feed parsing - A demo application of flutter which parse RSS XML contents to the flutter application

Flutter RSS feed parsing demo This is demo application of flutter which shows ho

Nyakuri Levite 3 Nov 15, 2022
Plist parser - A Plist parser for Flutter supports XML and binary Apple Property list (plist) formats

Plist Parser for Flutter ?? A Flutter Plugin for Plist parser supporting XML and

dirablue ( gaku ) 4 Nov 17, 2022
A plugin that brings native iOS keyboard behavior to Flutter.

iKeyboard A plugin that brings native iOS keyboard behavior to Flutter. Getting Started Just put IKeyboard as MaterialApp ancestor and put IKeyboard.b

Jonny Borges 1 May 4, 2022
A flutter plugin that brings an in-background android app to the foreground

bg_launcher A flutter plugin that brings an in-background android app to the foreground (Android only) Restrictions on starting activities from the ba

Iheb Briki 5 Nov 25, 2022
Ruqe brings the convenient types and methods found in Rust into Dart, such as the Result, Option, pattern-matching, etc.

ruqe Ruqe brings the convenient types and methods found in Rust into Dart, such as the Result, Option, pattern-matching, etc. Additionally, the librar

Alexander Nitiola 12 Dec 28, 2022
Neumorphic style - Example app with Flutter that displays a neumorphic style container

Flutter Neumorphic Style Example App Example app with Flutter that displays a ne

Piyush Nagpal 2 Mar 24, 2022
A quick and powerful Flutter layout with a bottom navbar.

What is bottom_nav_layout? It is a quick flutter app layout for building an app with a bottom nav bar. You can get an app with fluent behavior running

Mustafa Azyoksul 31 Dec 21, 2022
Example de layout in Flutter inspiration in Netflix App + Woody Woodpecker Characters

PicFlix Example de layout in Flutter inspiration in Netflix App + Woody Woodpecker Characters Cover extracted of https://twitter.com/winemcbride/statu

Tiago Danin 3 May 17, 2021
flutter development bootcamp layout challenge #2.1

MiCard App Challenge Hey folks! This app is the continuation of the layout_challenge_app. I coded this app from scratch because unfortunate things hap

Damla Çim 1 Jan 6, 2022
Layout of the flutter example.such as Row,Comlun,listview,Just for learning.

Just for learning ❤️ Star ❤️ the repo to support the project or ?? Follow Me.Thanks! Facebook Page Facebook Group QQ Group Developer Flutter Open Flut

Flutter开源社区 308 Nov 29, 2022
Application developed in Flutter with inspired layout in the Tinder

flutter_tinder_template This is an template implementation of the Tinder App with Flutter. How to Run the Project Ensure that you have the flutter ins

Gildson 41 Sep 21, 2021
Learn to build a basic app layout using only Flutter & Dart

basic-flutter-layout Created by Thai Duong Do (Tad Wilson) for non-commercial pu

TAD 5 Oct 12, 2022
Layout of the flutter example.such as Row,Comlun,listview,Just for learning.

Just for learning ❤️ Star ❤️ the repo to support the project or ?? Follow Me.Thanks! Facebook Page Facebook Group QQ Group Developer Flutter Open Flut

Flutter开源社区 308 Nov 29, 2022
Package to select layout per orientation or device size like mobile vs tablet layouts or portrait vs landscape

proxy_layout Package to select layout per orientation or device size like mobile vs tablet layouts or portrait vs landscape Usage You have two widgets

Jimmy Aumard 8 Apr 18, 2021
Create a Grid Layout of IoT (Internet of Things) devices in a particular house.

Create a Grid Layout of IoT (Internet of Things) devices in a particular house. Keep it simple to just 4-6 devices. Each device will have an icon on its own. When you press the icon, toggle the image and toggle the text underneath between on and off.

null 0 Dec 30, 2021
Achieve ~60 FPS, no matter how heavy the tree is to build/layout

flutter_smooth Achieve ~60 FPS, no matter how heavy the tree is to build/layout. ?? 3-second video output_small.mp4 (left = without smooth, right = sm

fzyzcjy 1k Jan 9, 2023
Flutter cupertino style date picker.

Flutter Cupertino Date Picker [pub packages] | 中文说明 Flutter cupertino date picker. Usage 1. Depend Add this to you package's pubspec.yaml file: depend

Dylan Wu 333 Dec 26, 2022
Flutter cupertino style date picker.

Flutter Cupertino Date Picker [pub packages] | 中文说明 Flutter cupertino date picker. Usage 1. Depend Add this to you package's pubspec.yaml file: depend

Dylan Wu 333 Dec 26, 2022