32

Using HTML I can add a bullet points to a paragraph like this:

<ul>
   <li> example </li>
   <li> example </li>
   <li> example </li>
<ul>

How can I write bullet point form in Flutter?

new Text(''),
Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
lesego finger
  • 321
  • 1
  • 3
  • 4

11 Answers11

45

If you don't want to download another library (e.g. flutter_markdown), and one or more of your list items have lengthy text that spans several rows, I'd go with Raegtime's answer. However, since it assumes a string with line breaks, I want to make a version for a list with strings, which is a more common scenario. In the code below, Column makes the list items come on different rows, and Row makes the bullet points have empty space below themselves.

import 'package:flutter/material.dart';

class UnorderedList extends StatelessWidget {
  UnorderedList(this.texts);
  final List<String> texts;

  @override
  Widget build(BuildContext context) {
    var widgetList = <Widget>[];
    for (var text in texts) {
      // Add list item
      widgetList.add(UnorderedListItem(text));
      // Add space between items
      widgetList.add(SizedBox(height: 5.0));
    }

    return Column(children: widgetList);
  }
}

class UnorderedListItem extends StatelessWidget {
  UnorderedListItem(this.text);
  final String text;

  @override
  Widget build(BuildContext context) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Text("• "),
        Expanded(
          child: Text(text),
        ),
      ],
    );
  }
}

We can use it as such:

UnorderedList([
    "What conclusions can we draw from the implementation?",
    "Are there any changes that need to be introduced permanently?"
])

And get the result: Picture of example result

Mjaustro
  • 727
  • 8
  • 11
19

Using markdown for this is overkill. Using character is by far easier.

If you're too lazy to copy paste the character, here's a custom Text that does it for you:

class Bullet extends Text {
  const Bullet(
    String data, {
    Key key,
    TextStyle style,
    TextAlign textAlign,
    TextDirection textDirection,
    Locale locale,
    bool softWrap,
    TextOverflow overflow,
    double textScaleFactor,
    int maxLines,
    String semanticsLabel,
  }) : super(
          '• ${data}',
          key: key,
          style: style,
          textAlign: textAlign,
          textDirection: textDirection,
          locale: locale,
          softWrap: softWrap,
          overflow: overflow,
          textScaleFactor: textScaleFactor,
          maxLines: maxLines,
          semanticsLabel: semanticsLabel,
        );
}
surtyaar
  • 2,532
  • 1
  • 18
  • 13
Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432
  • 2
    It does not align long text message to right side of bullet icon. Any suggestion for long text? Thanks. – Kamlesh May 29 '21 at 07:21
16

I would better use utf-code. For list I think more comfortably will be something like:

class DottedText extends Text {
  const DottedText(String data, {
    Key key,
    TextStyle style,
    TextAlign textAlign,
    TextDirection textDirection,
    Locale locale,
    bool softWrap,
    TextOverflow overflow,
    double textScaleFactor,
    int maxLines,
    String semanticsLabel,
  }) : super(
    '\u2022 $data',
    key: key,
    style: style,
    textAlign: textAlign,
    textDirection: textDirection,
    locale: locale,
    softWrap: softWrap,
    overflow: overflow,
    textScaleFactor: textScaleFactor,
    maxLines: maxLines,
    semanticsLabel: semanticsLabel,);
}
Andrii Turkovskyi
  • 27,554
  • 16
  • 95
  • 105
12

I tried using flutter_markdown and it seems to work. And of course you can change it to numbered/ordered or unordered list as you want.

enter image description here

import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:flutter/material.dart';
void main() => runApp(Demo());


class Demo extends StatelessWidget {
  final testData = ["Example1", "Example2", "Example3", "Example100"];



  @override
  Widget build(BuildContext context) {
    final _markDownData = testData.map((x) => "- $x\n").reduce((x, y) => "$x$y");

    return MaterialApp(
        home: Scaffold(
      body: Container(
        margin: EdgeInsets.all(40.0),
        child: Markdown(data: _markDownData)),
    ));
  }
}
dragonfly02
  • 3,403
  • 32
  • 55
  • It does not align long text message to right side of bullet icon. Any suggestion for long text? Thanks. – Kamlesh May 29 '21 at 07:21
2

@Snurrig - Excellent answer. Works great! Thanks a lot!

Modified it to create an ordered/numbered list, as well. See below:

class OrderedList extends StatelessWidget {
  OrderedList(this.texts);
  final List<dynamic> texts;

  @override
  Widget build(BuildContext context) {
    var widgetList = <Widget>[];
    int counter = 0;
    for (var text in texts) {
      // Add list item
      counter++;
      widgetList.add(OrderedListItem(counter, text));
      // Add space between items
      widgetList.add(SizedBox(height: 5.0));
    }

    return Column(children: widgetList);
  }
}

class OrderedListItem extends StatelessWidget {
  OrderedListItem(this.counter, this.text);
  final int counter;
  final String text;

  @override
  Widget build(BuildContext context) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Text("$counter. "),
        Expanded(
          child: Text(text),
        ),
      ],
    );
  }
}

enter image description here

d410
  • 68
  • 1
  • 12
2

you can use like this:

Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                '\u2022',
                style: TextStyle(
                  fontSize: 16,
                  height: 1.55,
                ),
              ),
              SizedBox(
                width: 5,
              ),
              Expanded(
                child: Container(
                  child: Text(
                    str,
                    textAlign: TextAlign.left,
                    softWrap: true,
                    style: TextStyle(
                      fontSize: 16,
                      color: Colors.black.withOpacity(0.6),
                      height: 1.55,
                    ),
                  ),
                ),
              ),
            ],
          );
samin
  • 482
  • 5
  • 9
1

You can use LineSplitter, Row, Column, and the ASCII bullet point. All u need is a String with linebreaks.

String myStringWithLinebreaks = "Line 1\nLine 2\nLine 3";

Example in a ListTile

 ListTile(
                  title: Text("Title Text"),
                  subtitle: 
                    Column(
                      children: LineSplitter.split(myStringWithLinebreaks).map((o) {
                    return Row(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text("• "),
                        Expanded(
                          child: Text(o),
                        )
                      ],
                    );
                  }).toList())),
iDecode
  • 22,623
  • 19
  • 99
  • 186
Maurice Raguse
  • 4,437
  • 2
  • 29
  • 46
1

If you do not require markdowns everywhere, and just want to use them in one or two places, then adding a package or writing that much code for it is not a suitable idea.

You can copy the DOT from websites like emojipedia and paste it in front of your text.

here is an example:

Text("⚈ Provide, operate, and maintain our website"),
Ali Murtaza
  • 414
  • 4
  • 9
1

This will add bullet. Use it in a row with text.

Container(width: 10, height: 10, decoration: 
BoxDecoration(shape: BoxShape.circle, color: Colors.black),),
Anees
  • 99
  • 7
0
 Row(
   children: [
             _buildBullet(),
              const SizedBox(width: 5),
              _buildText(),
              ],
  ),

  SizedBox _buildBullet() {
    return SizedBox(
      height: 7,
      width: 7,
      child: TextButton(
        style: TextButton.styleFrom(
          backgroundColor: Color(0xFFF8B407),
          shape: const CircleBorder(),
        ),
        child: const Text(''),
        onPressed: () {},
      ),
    );
  }

  Text _buildText() {
    return const Text(
      'Lorem Ipsum is simply dummy text of the printing and typesetting',
      style: TextStyle(fontSize: 24, color: Colors.white),
    );
  }
0

We can create one widget which will take take and return bullet text. you can use this widget.

class BulletText extends StatelessWidget {
  final String text;
  const BulletText({
    super.key,
    required this.text,
  });

  @override
  Widget build(BuildContext context) {
    return Text(
      "• $text",
      style: TextStyle(
        color: Colors.black,
        fontWeight: FontWeight.normal,
        
        
      ),
    );
  }
}

You can Use This anywhere you want like this

BulletText(text: "Scrap cars"),
Shailendra Rajput
  • 2,131
  • 17
  • 26