Flutter - Rendering a HTML Unordered List

2,259

Solution 1

You don't forget two rules:

  • You can create custom widget so rich-text set to false (default True)
  • You have custom widget options need page margin like item spacing.

Look at this code:

 Html(
    data: data,
    useRichText: false,
    customRender: htmlCustomRenderer,
  )

enter image description here

If you detail look at this.(lib/html-parser)

Result: enter image description here

Solution 2

The package has been updated (v1.0.0) and it has been changed but it's now easier to do:

Html(
  data: {html}
  customRender: {
    "li": (RenderContext context, Widget child, attributes, dom.Element element) {
      return this.customListItem(element);
     },
  },
),
Wrap customListItem(dom.Element node) {
  return Wrap(
    crossAxisAlignment: WrapCrossAlignment.center,
    spacing: 4,
    children: [
      Padding(
        padding: EdgeInsets.only(left: 10),
        child: CircleAvatar(
          radius: 2,
        ),
      ),
      Text(node.text)
    ],
  );
}
Share:
2,259
elvinas
Author by

elvinas

Casually infiltrating.

Updated on December 20, 2022

Comments

  • elvinas
    elvinas over 1 year

    I’m trying to represent HTML code in Flutter (ul to be specific) and minimally style it. I tried using the flutter_html package, and I see there’s a customRender option.

    Basically, what I’m trying to do:

    • Add a space under every li element.
    • Take away the left margin (it's there by default on flutter_html).
    • Change the color of the bullet point. Not, necessary, but would be nice.

    I'm pretty new to Flutter and Dart, so I can't manage to make the customRender work. Perhaps someone knows how to go around it? Or maybe there's a better way to do it?


    Adding some code fore reference.

    import 'package:flutter_html/flutter_html.dart';
    
    // ... Some non-essential code ...
    
    Align(
      alignment: Alignment.centerLeft,
      child: Html(
        data: """${unorderedList}""",
        customRender: (node, children) {
          if (node is dom.Element) {
            switch (node.localName) {
              case "li":
                return Column(children: children);
            }
          }
          return null;
        },
      )
    )
    

    Note: taking out the customRender block produces a left margin.


    EDIT: Addition to the vb10 solution that allows multiline list item texts.

    Wrap customListItem(dom.Element node) {
      return Wrap(
        spacing: 25.0,
        children: [
          Row(
            crossAxisAlignment: CrossAxisAlignment.start, 
            children: [
              Padding(
                // Top padding adjusts for text offset, set it to the font size.
                padding: const EdgeInsets.only(top: 18.0, right: 15.0), 
                child: CircleAvatar(radius: 4)
              ),
              Expanded(child: Text(node.text)),
            ]
          ),
          SizedBox(height: 25.0),
        ]
      );
    }
    
    • Simone Rossaini
      Simone Rossaini almost 4 years
      Can you show your code?
    • elvinas
      elvinas almost 4 years
      @SimoneRossaini Edited. The input for the HTML is just a regular <ul> with a bunch of <li>. The list or the list items don't have any attributes.
  • elvinas
    elvinas almost 4 years
    It's nearly exactly what I was looking for! But it seems that the Wrap widget forces the node.text to jump to the next line if it spans more than one line. Perhaps there's a widget that would work better in this case?
  • vb10
    vb10 almost 4 years
    This situation, need a test case. if you have more line, you need custom parser method but more advanced. I think you can have more line, fix the HTML body on the backend side after sending fix body.
  • elvinas
    elvinas almost 4 years
    Managed to fix it with Rows and Expanded and playing around with some padding.
  • Joel Broström
    Joel Broström about 3 years
    Don't forget to add dom as dom to get access to element: import 'package:html/dom.dart' as dom;