0

I created one reusable multi line text component. I am using TextSpan widget.

code:

/// Creates multi line styled widget which displays list of items with bullet
class AppMultiLineText extends StatelessWidget {
  final List<CustomStyledText> items;
  final String semanticsText;

  const AppMultiLineText({@required this.items, this.semanticsText}) : assert(items != null);

  @override
  Widget build(BuildContext context) {
    final style = context.appThemeData.bodyCopyDefault.appTextStyle;
    final styleBold = context.appThemeData.bodyCopyBold.appTextStyle;
    return MergeSemantics(
      child: Padding(
        padding: context.appThemeData.multilineDisplay.padding,
        child: Column(
          children: [
            _buildRow(context, items, style, styleBold, semanticsText),
          ],
        ),
      ),
    );
  }
}

Widget _buildRow(BuildContext context, List<CustomStyledText> styledText, AppTextStyle style, AppTextStyle styleBold,
    String semanticsText) {
  final _padding = EdgeInsets.symmetric(vertical: context.appThemeData.bulletStyle.spaceBetweenLines);
  return Semantics(
    child: Padding(
      padding: _padding,
      child: Row(
        children: [
          _buildBulletSection(context),
          _styledWidget(context, styledText, style, styleBold, semanticsText),
          
        ],
      ),
    ),
  );
}

Widget _buildBulletSection(BuildContext context) {
  // final textScaleFactor = _textScaleFactor(context);
  final _bulletPadding = EdgeInsets.only(
      top: context.appThemeData.bulletStyle.bulletOffset, right: context.appThemeData.bulletStyle.spaceAfterBullet);

  return Text.rich(
    TextSpan(
      children: [
        WidgetSpan(
          child: Padding(
            padding: _bulletPadding,
            child: _drawBullet(context),
          ),
        ),
      ],
    ),
    //textScaleFactor: textScaleFactor,
  );
}

Widget _drawBullet(BuildContext context) {
  final _bulletDiameter = context.appThemeData.bulletStyle.bulletDiameter;
  return Container(
    width: _bulletDiameter,
    height: _bulletDiameter,
    decoration: BoxDecoration(
      color: context.appThemeData.bodyCopyDefault.appTextStyle.textStyle.color,
      shape: BoxShape.circle,
    ),
  );
}
Widget _styledWidget(BuildContext context, List<CustomStyledText> styledText, AppTextStyle style,
    AppTextStyle styleBold, String semanticsText) {
  final scaleFactor = context.calculateScaleFactor(
    style.textStyle.fontSize,
    style.maximumFontSize,
    style.minimumScalingFactor,
  );

  return Expanded(
    child: Text.rich(
      TextSpan(
        style: style.textStyle,
        children: styledText.map((e) {
          return TextSpan(
            text: e.text,
            style: e.isBold
                ? styleBold.textStyle.copyWith(
                    letterSpacing: e.isNumeric ? PresentationConstants.numericLetterSpacing : null,
                  )
                : style.textStyle.copyWith(
                    letterSpacing: e.isNumeric ? PresentationConstants.numericLetterSpacing : null,
                  ),
          );
        }).toList(),
      ),
      style: style.textStyle,
      textScaleFactor: scaleFactor,
      textAlign: style.textAlign,
      semanticsLabel: semanticsText,
    ),
  );
}

class CustomStyledText {
  final String text;
  final String styleText;
  final bool isBold;
  final bool isNumeric;

  CustomStyledText(
    this.text, {
    this.styleText,
    this.isBold = false,
    this.isNumeric = false,
  });
}


class:
 AppMultiLineText(
              items: [
                CustomStyledText(context.appLocalization.listOfRequirementsBodyCopy1),
                CustomStyledText(context.appLocalization.listOfRequirementsBodyCopy2),
                
              ],
            ),
          ],
        ),

[![enter image description here][1]][1]

This is the expected design [1]: https://i.sstatic.net/AZF3w.png

But I am getting all items as paragraph.

2 Answers 2

1

It is best to use the RichText widget. Details are available here

Sign up to request clarification or add additional context in comments.

Comments

0

May I propose another solution?

import 'package:flutter/material.dart';

class CustomList extends StatelessWidget {
  final List<Widget> children;

  const CustomList({
    Key key,
    this.children = const [],
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        for (final child in children)
          Container(
            padding: EdgeInsets.all(10.0),
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Padding(
                  padding: const EdgeInsets.all(5.0),
                  child: Icon(
                    Icons.circle,
                    size: 4.0,
                  ),
                ),
                SizedBox(width: 10.0),
                Expanded(child: child),
              ],
            ),
          ),
      ],
    );
  }
}

Pass any widget you like in to it's children and it will append the dots automatically:

CustomList(
            children: [
              Text('My first line of text'),
              Text(
                'My second line of text which is long enough, long enough,  long enough,  long enough,  long enough,  long enough',
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                  color: Colors.orange,
                  fontSize: 20.0,
                ),
              ),
            ],
          ),

----------- Addon -----------

You can go even further and add a "type" to switch from unordered to ordered style.

import 'package:flutter/material.dart';

enum CustomListType { Unordered, Ordered }

class CustomList extends StatelessWidget {
  final List<Widget> children;
  final CustomListType type;

  const CustomList({
    Key key,
    this.children = const [],
    this.type = CustomListType.Unordered,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final _children = <Widget>[];
    for (var i = 0; i < children.length; i++) {
      _children.add(Container(
        padding: EdgeInsets.all(10.0),
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            type == CustomListType.Ordered
                ? Text('${i + 1}.')
                : Padding(
                    padding: const EdgeInsets.all(5.0),
                    child: Icon(
                      Icons.circle,
                      size: 4.0,
                    ),
                  ),
            SizedBox(width: 10.0),
            Expanded(child: children.elementAt(i)),
          ],
        ),
      ));
    }
    return Column(
      children: _children,
    );
  }
}
CustomList(
            type: CustomListType.Ordered,
            children: [
              Text('My first line of text'),
              Text(
                'My second line of text which is long enough, long enough,  long enough,  long enough,  long enough,  long enough',
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                  color: Colors.orange,
                  fontSize: 20.0,
                ),
              ),
            ],
          ),

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.