xml_layout 2.3.14 copy "xml_layout: ^2.3.14" to clipboard
xml_layout: ^2.3.14 copied to clipboard

outdated

XML layout for flutter. Layout your widgets with xml at runtime.

xml_layout #

XML layout for flutter. Layout your UI via xml at runtime. and support extending any customer widget. Here is a online preview.

Getting Started #

write xml layout file like:

xml

<Text mainAxisAlignment="center">
    <for count="6">
        <Text>$item, You have pushed the button this many times:</Text>
    </for>
    <Text id="text-id">
        <attr:style>
            <TextStyle color="red"/>
        </attr:style>
        $counter
    </Text>
</Column>

dart

XMLLayout(
    temp: snapshot.data,
    objects: {
        "counter": _counter
    },
)

In this case

$counter for passing argument to the layout.

id attribute for selecting the widget or state.

XMLLayoutState state = ...;
// find the key of the Text 
GlobalKey key = state.find('text-id');

Registers #

  • register
    • description: Register a constructor. It could convert a xml element to target object.
/**
 * Register a constructor
 * 
 * xml:
 * <MyClass width="10" height="10" />
 * 
 */
XMLLayout.register('MyClass', (node, key) {
    return MyClass(
        key: key,
        child: node.child<Widget>(),
        width: node.s<double>("width"),
        height: node.s<double>("height"),
    );
});
  • registerEnum
    • description: A shortcat to register a enum class. It could convert a attribute to the enum.
/**
* Register a enum type
* 
* xml:
* <Text textAlign="center">str</Text>
*/
XMLLayout.registerEnum(TextAlign.values);
  • registerInline(Type type, String name, bool field, InlineItemConstructor constructor)
    • description: Register a constructor which could convert a attribute to target type.
    • arguments:
      • field this constructor is for a static field or a constructor.
/**
 * <Text fontWeight="w200">str</Text>
 */
XmlLayout.registerInline(FontWeight, "w200", true, (node, method) {
  return FontWeight.w200;
});

/**
 * <Text textHeightBehavior="fromEncoded(20)">str</Text>
 */
XmlLayout.registerInline(TextHeightBehavior, "fromEncoded", false,
      (node, method) {
  return TextHeightBehavior.fromEncoded(int.tryParse(method[0]));
});

node.s<T>("name"), node.attribute<T>("name") convert subnode to target type

node.t<T>(), node.convert<T>() convert this node to target type

node.v<T>("value"), node.value<T>("value") convert text to target type

Widget Builder #

<ListView.separated itemCount="$itemCount">
    <attr:itemBuilder>
        <Function returnType="Widget">
            <!-- get arguments of function via args -->
            <SetArgument return="index" argument="${args[1]}"/>
            <Call function="$getItem" return="itemData">
                <!-- pass argument to getItem function -->
                <Argument value="$index"/>
            </Call>
            <!-- The last element of Function tag would be the final result -->
            <Text>${itemData.title}</Text>
        </Function>
    </attr:itemBuilder>
</ListView.separated>

Script #

<Function>
    <Script>
        set("index", ${args[1]})
        set("itemData", getItem($index))
    </Script>
    <!-- same as -->
    <SetArgument return="index" argument="${args[1]}"/>
    <Call function="$getItem" return="itemData">
        <Argument value="$index"/>
    </Call>
    <!-- end(same as) -->

    <Text>${itemData.title}</Text>
</Function>

Method #

Method could be registerd via XmlLayout.registerInlineMethod, and can be used in a Xml attribute or Script tag.

Default methods:

  • isEmpty(a) => a.isEmpty()
  • isNotEmpty(a) => a.isNotEmpty()
  • equal(a, b, ...) => a == b ...
  • net(a, b) => a != b
  • mod(a, b) => a % b
  • div(a, b) => a / b
  • set(name, a) => env[name] = a
  • not(a) => !a
  • lt(a, b) => a < b
  • nlt(a, b) => a >= b
  • gt(a, b) => a > b
  • ngt(a, b) => a <= b
  • plus(a, b, ...) => a + b ...
  • minus(a, b, ...) => a - b ...
  • multiply(a, b, ...) => a * b ...
  • divide(a, b, ...) => a / b ...

Control Flow #

A util to control the rendering logic. like:

<for count="$counter">
    <Text>$item, You have pushed the button this many times:</Text>
    <if candidate="equal(1, mod($item, 2))">
        <Text>Test text</Text>
    </if>
</for>
  • if tag is a if control flow.
    • attributes:
      • candidate a Boolean value, if true the children would be rendered, otherwise not be rendered.
  • else tag is a else control flow, could be placed after if or another else tag.
    • attributes:
      • candidate same as if tag.
  • for tag is a loop control flow.
    • attributes:
      • array a List value, iterates over array elements, each element for children one time.
      • count a Integer value, iterates children the value times. It is mutually exclusive with the array attribute.
      • item a String value, the name of each element, default is item.
      • index a String value, the name of the index of element, default is index.

Builder #

You can write a script to generate the constructor code. In the example test.dart is the builder script.

Builder options:

  • entry_name
    • default: types
    • type: List<Type>
    • description: types in this list which will be processed.
  • collections_name
    • default: collections
    • type: List<Collection>
    • description: Collection type is used to process the collection class, such as: Colors and Icons.

ps: Colors and Icons is preprocessed just import it via:

import 'package:xml_layout/types/colors.dart' as colors;
import 'package:xml_layout/types/icons.dart' as icons;

// ...

colors.register();
icons.register();
  • coverts_name
    • default: converts
    • type: Map<String, String>
    • description: Every import uri will be test by the key value pair in this variable. if a import source uri is start with the key then it will be convert to the value.
  • imports_name
    • default: imports
    • type: List<String>
    • description: Extension import uris which will be write to the generated code.

Example

lib/test.dart

import 'package:flutter/material.dart';

const List<Type> types = [
  Text,
];

build.yaml

targets:
  $default:
    builders:
      xml_layout:
        generate_for:
          - lib/test.dart

Create the files above, then just run flutter pub run build_runner build. And you will get the generated code in lib/test.xml_layout.dart.

21
likes
70
points
230
downloads

Publisher

unverified uploader

Weekly Downloads

XML layout for flutter. Layout your widgets with xml at runtime.

Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

analyzer, build, dart_style, flutter, xml

More

Packages that depend on xml_layout